我们制作网站后,如果网站上需要支付功能的话,就需要给我们的网站对接微信支付功能,方便用户在我们网站上直接支付。
1、注册微信支付商家
2、PC 站申请【Native 支付】、手机站申请【H5 支付】;自适应网站 2 个都申请
3、下载微信支付 demo
Native 支付:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1。H5 支付:没找到官方 demo,可以用 Native 的 demo 改
4、Native 的 demo 目录下 example 目录就是示例,native.php 扫码支付页,native_notify.php 异步回调页。
配置页 WxPay.Config.php
//APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
public function GetAppId()
{
return '';
}
//MCHID:商户号(必须配置,开户邮件中可查看)
public function GetMerchantId()
{
return '';
}
//KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置), 请妥善保管, 避免密钥泄露
//设置地址:https://pay.weixin.qq.com/index.php/account/api_cert
public function GetKey()
{
return '';
}
模式二显示二维码 native.php 页
/**
* 流程:
* 1、调用统一下单,取得code_url,生成二维码
* 2、用户扫描二维码,进行支付
* 3、支付完成之后,微信服务器会通知支付成功
* 4、在支付成功通知中需要查单确认是否真正支付成功(见:notify.php)
*/
$input = new WxPayUnifiedOrder();
//商品描述
$input->SetBody($title);
//订单号
$input->SetOut_trade_no($out_trade_no);
//金额
$input->SetTotal_fee($total_fee);
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis",time()+600));
//支付回调设置
$input->SetNotify_url("http://xxxxxx.com/weixin_pc/example/native_notify.php");
//支付类型 扫码支付
$input->SetTrade_type("NATIVE");
//商品ID
$input->SetProduct_id($product_id);
$notify = new NativePay();
$result = $notify->GetPayUrl($input);
//var_dump($result);
$url2 = $result["code_url"];
定时获取是否付款
$(function(){
var miao=600;
var rs;
timess();
function timess()
{
$.ajax({
url: '获取是否付款数据',
type: 'get',
dataType: 'json',
async:false,
success: function (data) {
rs=data;
console.log(rs);
}
});
if(rs.status==1)
{
alert("付款成功,即将跳转!")
window.location.href='跳转结果页';
}
else
{
miao--;
$(".weixinbox .tit .ttt span").html(miao);
if(miao==0)
{
clearInterval(timer);
alert("二维码过期,即将刷新二维码!")
window.location.reload();
}
setTimeout(function() {
timess();
},1000)
}
}
});
异步通知页 native_notify.php
public function NotifyProcess($objData, $config, &$msg)
{
$data = $objData->GetValues();
//echo "处理回调";
Log::DEBUG("call back:" . json_encode($data));
//TODO 1、进行参数校验
//DEMO中的这行注释,不判断产品ID,获取不到
//if(!array_key_exists("openid", $data) || !array_key_exists("product_id", $data))
if(!array_key_exists("openid", $data))
{
$msg = "回调数据异常";
Log::DEBUG($msg . json_encode($data));
return false;
}
//...略
//==========================业务=========================
$number=$data["out_trade_no"];//订单号
$transaction_id=$data["transaction_id"];//交易号
$GLOBALS["number"]=$number;
$GLOBALS["platform_number"]=$transaction_id;
//=======================================================
return false
}
$config = new WxPayConfig();
Log::DEBUG("begin notify!");
$notify = new NativeNotifyCallBack();
$notify->Handle($config, true);
if(isset($GLOBALS["number"]) && isset($GLOBALS["platform_number"]) && $GLOBALS["number"] && $GLOBALS["platform_number"])
{
//业务代码
}
注:if(!array_key_exists("openid", $data) || !array_key_exists("product_id", $data)) 这行修改为 if(!array_key_exists("openid", $data)) 获取不到 product_id 这个值。
5、H5 支付,将 Native 的 demo 复制一份
先在微信支付产品中心 H5 支付中配置域名 就是下面的 XXXXXX.COM
原来的 native.php 页删除,新建 native.php 页,代码如下
$title="标题标题标题";
$money=100; //充值金额 微信支付单位为分
$product_id=1;//产品id
$userip = get_client_ip(); //获得用户设备 IP
$appid = ""; //应用 APPID
$mch_id = ""; //微信支付商户号
$key = ""; //微信商户 API 密钥
$out_trade_no="123456789000"; //平台内部订单号
$nonce_str = createNoncestr();//随机字符串
$body = $title;//内容
$total_fee = $money; //金额
$spbill_create_ip = $userip; //IP
$notify_url = "http://xxxxxx.com/weixin_h5/pay/native_notify.php"; //回调地址
$trade_type = 'MWEB';//交易类型 具体看 API 里面有详细介绍
$scene_info ='{"h5_info":{"type":"Wap","wap_url":"http://xxxxxx.com","wap_name":"支付"}}';//场景信息 必要参数
$signA ="appid=$appid&attach=$out_trade_no&body=$body&mch_id=$mch_id&nonce_str=$nonce_str¬ify_url=$notify_url&out_trade_no=$out_trade_no&scene_info=$scene_info&spbill_create_ip=$spbill_create_ip&total_fee=$total_fee&trade_type=$trade_type";
$strSignTmp = $signA."&key=$key"; //拼接字符串 注意顺序微信有个测试网址 顺序按照他的来 直接点下面的校正测试 包括下面 XML 是否正确
$sign = strtoupper(MD5($strSignTmp)); // MD5 后转换成大写
$post_data = "<xml>
<appid>$appid</appid>
<mch_id>$mch_id</mch_id>
<body>$body</body>
<out_trade_no>$out_trade_no</out_trade_no>
<total_fee>$total_fee</total_fee>
<spbill_create_ip>$spbill_create_ip</spbill_create_ip>
<notify_url>$notify_url</notify_url>
<trade_type>$trade_type</trade_type>
<scene_info>$scene_info</scene_info>
<attach>$out_trade_no</attach>
<nonce_str>$nonce_str</nonce_str>
<sign>$sign</sign>
</xml>";//拼接成 XML 格式
$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信传参地址
$dataxml = postXmlCurl($post_data,$url); //后台 POST 微信传参地址 同时取得微信返回的参数
$objectxml = (array)simplexml_load_string($dataxml, 'SimpleXMLElement', LIBXML_NOCDATA); //将微信返回的 XML 转换成数组
function createNoncestr( $length = 32 ){
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str ="";
for ( $i = 0; $i < $length; $i++ ) {
$str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
function postXmlCurl($xml,$url,$second = 30){
$ch = curl_init();
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
//设置 header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//post 提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//运行 curl
$data = curl_exec($ch);
//返回结果
if($data){
curl_close($ch);
return $data;
}else{
$error = curl_errno($ch);
curl_close($ch);
echo "curl 出错,错误码:$error"."<br>";
}
}
function get_client_ip($type = 0) {
$type = $type ? 1 : 0;
$ip = 'unknown';
if ($ip !== 'unknown') return $ip[$type];
if($_SERVER['HTTP_X_REAL_IP']){//nginx 代理模式下,获取客户端真实 IP
$ip=$_SERVER['HTTP_X_REAL_IP'];
}elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {//客户端的 ip
$ip = $_SERVER['HTTP_CLIENT_IP'];
}elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {//浏览当前页面的用户计算机的网关
$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$pos = array_search('unknown',$arr);
if(false !== $pos) unset($arr[$pos]);
$ip = trim($arr[0]);
}elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];//浏览当前页面的用户计算机的 ip 地址
}else{
$ip=$_SERVER['REMOTE_ADDR'];
}
// IP 地址合法验证
$long = sprintf("%u",ip2long($ip));
$ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
return $ip[$type];
}
<a class="pay" href="<?php echo $objectxml['mweb_url'] ?>"><button class="pay">确认支付</button></a>
异步通知页 native_notify.php 修改NotifyProcess方法
public function NotifyProcess($objData, $config, &$msg)
{
$data = $objData->GetValues();
//echo "处理回调";
Log::DEBUG("call back:" . json_encode($data));
//TODO 1、进行参数校验
//if(!array_key_exists("openid", $data) || !array_key_exists("product_id", $data))
if(!array_key_exists("openid", $data))
{
$msg = "回调数据异常";
Log::DEBUG($msg . json_encode($data));
return false;
}
//TODO 2、进行签名验证
try {
$checkResult = $objData->CheckSign($config);
if($checkResult == false){
//签名错误
Log::ERROR("签名错误...");
return false;
}
} catch(Exception $e) {
Log::ERROR(json_encode($e));
}
//==========================业务=========================
$number=$data["out_trade_no"];//订单号
$transaction_id=$data["transaction_id"];//交易号
$GLOBALS["number"]=$number;
$GLOBALS["platform_number"]=$transaction_id;
//=======================================================
return true;
}
$config = new WxPayConfig();
Log::DEBUG("begin notify!");
$notify = new NativeNotifyCallBack();
$notify->Handle($config, true);
if(isset($GLOBALS["number"]) && isset($GLOBALS["platform_number"]) && $GLOBALS["number"] && $GLOBALS["platform_number"])
{
//业务代码
}
异步通知页 native_notify.php 如果不用官方的 demo 代码如下:
$xml = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
if (empty($xml))
{
return false;
}
//将 xml 格式转换成数组
function xmlToArray($xml) {
//禁止引用外部 xml 实体
libxml_disable_entity_loader(true);
$xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
$val = json_decode(json_encode($xmlstring), true);
return $val;
}
$attr = xmlToArray($xml);
$total_fee = $attr['total_fee'];
$open_id = $attr['openid'];
$out_trade_no = $attr['out_trade_no'];
$time = $attr['time_end'];
//业务代码
//在异步回调取值的时候,异步回调一直在调用(如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。 (通知频率为 15/15/30/180/1800/1800/1800/1800/3600,单位:秒))
exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');
专业提供WordPress主题安装、深度汉化、加速优化等各类网站建设服务,详询在线客服!