JQuery/PHP

巧妙使用Native给网站对接微信支付功能

阿里云

我们制作网站后,如果网站上需要支付功能的话,就需要给我们的网站对接微信支付功能,方便用户在我们网站上直接支付。

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

  1. //APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
  2. public function GetAppId()
  3. {
  4. return '';
  5. }
  6.  
  7. //MCHID:商户号(必须配置,开户邮件中可查看)
  8. public function GetMerchantId()
  9. {
  10. return '';
  11. }
  12.  
  13. //KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置), 请妥善保管, 避免密钥泄露
  14. //设置地址:https://pay.weixin.qq.com/index.php/account/api_cert
  15. public function GetKey()
  16. {
  17. return '';
  18. }

模式二显示二维码 native.php 页

  1. /**
  2. * 流程:
  3. * 1、调用统一下单,取得code_url,生成二维码
  4. * 2、用户扫描二维码,进行支付
  5. * 3、支付完成之后,微信服务器会通知支付成功
  6. * 4、在支付成功通知中需要查单确认是否真正支付成功(见:notify.php)
  7. */
  8. $input = new WxPayUnifiedOrder();
  9. //商品描述
  10. $input->SetBody($title);
  11. //订单号
  12. $input->SetOut_trade_no($out_trade_no);
  13. //金额
  14. $input->SetTotal_fee($total_fee);
  15. $input->SetTime_start(date("YmdHis"));
  16. $input->SetTime_expire(date("YmdHis",time()+600));
  17. //支付回调设置
  18. $input->SetNotify_url("http://xxxxxx.com/weixin_pc/example/native_notify.php");
  19. //支付类型 扫码支付
  20. $input->SetTrade_type("NATIVE");
  21. //商品ID
  22. $input->SetProduct_id($product_id);
  23.  
  24. $notify = new NativePay();
  25. $result = $notify->GetPayUrl($input);
  26.  
  27. //var_dump($result);
  28.  
  29. $url2 = $result["code_url"];
  30. 定时获取是否付款
  31.  
  32. $(function(){
  33. var miao=600;
  34. var rs;
  35. timess();
  36.  
  37. function timess()
  38. {
  39. $.ajax({
  40. url: '获取是否付款数据',
  41. type: 'get',
  42. dataType: 'json',
  43. async:false,
  44. success: function (data) {
  45. rs=data;
  46. console.log(rs);
  47. }
  48. });
  49.  
  50. if(rs.status==1)
  51. {
  52. alert("付款成功,即将跳转!")
  53. window.location.href='跳转结果页';
  54. }
  55. else
  56. {
  57. miao--;
  58. $(".weixinbox .tit .ttt span").html(miao);
  59. if(miao==0)
  60. {
  61. clearInterval(timer);
  62. alert("二维码过期,即将刷新二维码!")
  63. window.location.reload();
  64. }
  65. setTimeout(function() {
  66. timess();
  67. },1000)
  68. }
  69. }
  70. });

异步通知页 native_notify.php

  1. public function NotifyProcess($objData, $config, &$msg)
  2. {
  3. $data = $objData->GetValues();
  4. //echo "处理回调";
  5. Log::DEBUG("call back:" . json_encode($data));
  6. //TODO 1、进行参数校验
  7. //DEMO中的这行注释,不判断产品ID,获取不到
  8. //if(!array_key_exists("openid", $data) || !array_key_exists("product_id", $data))
  9. if(!array_key_exists("openid", $data))
  10. {
  11. $msg = "回调数据异常";
  12. Log::DEBUG($msg . json_encode($data));
  13. return false;
  14. }
  15.  
  16. //...略
  17.  
  18. //==========================业务=========================
  19. $number=$data["out_trade_no"];//订单号
  20. $transaction_id=$data["transaction_id"];//交易号
  21.  
  22. $GLOBALS["number"]=$number;
  23. $GLOBALS["platform_number"]=$transaction_id;
  24. //=======================================================
  25.  
  26. return false
  27. }
  28.  
  29. $config = new WxPayConfig();
  30. Log::DEBUG("begin notify!");
  31. $notify = new NativeNotifyCallBack();
  32. $notify->Handle($config, true);
  33.  
  34. if(isset($GLOBALS["number"]) && isset($GLOBALS["platform_number"]) && $GLOBALS["number"] && $GLOBALS["platform_number"])
  35. {
  36. //业务代码
  37. }

注: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 页,代码如下

  1. $title="标题标题标题";
  2. $money=100; //充值金额 微信支付单位为分
  3. $product_id=1;//产品id
  4.  
  5. $userip = get_client_ip(); //获得用户设备 IP
  6. $appid = ""; //应用 APPID
  7. $mch_id = ""; //微信支付商户号
  8. $key = ""; //微信商户 API 密钥
  9. $out_trade_no="123456789000"; //平台内部订单号
  10. $nonce_str = createNoncestr();//随机字符串
  11. $body = $title;//内容
  12. $total_fee = $money; //金额
  13. $spbill_create_ip = $userip; //IP
  14. $notify_url = "http://xxxxxx.com/weixin_h5/pay/native_notify.php"; //回调地址
  15. $trade_type = 'MWEB';//交易类型 具体看 API 里面有详细介绍
  16. $scene_info ='{"h5_info":{"type":"Wap","wap_url":"http://xxxxxx.com","wap_name":"支付"}}';//场景信息 必要参数
  17. $signA ="appid=$appid&attach=$out_trade_no&body=$body&mch_id=$mch_id&nonce_str=$nonce_str&notify_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";
  18. $strSignTmp = $signA."&key=$key"; //拼接字符串 注意顺序微信有个测试网址 顺序按照他的来 直接点下面的校正测试 包括下面 XML 是否正确
  19. $sign = strtoupper(MD5($strSignTmp)); // MD5 后转换成大写
  20. $post_data = "<xml>
  21. <appid>$appid</appid>
  22. <mch_id>$mch_id</mch_id>
  23. <body>$body</body>
  24. <out_trade_no>$out_trade_no</out_trade_no>
  25. <total_fee>$total_fee</total_fee>
  26. <spbill_create_ip>$spbill_create_ip</spbill_create_ip>
  27. <notify_url>$notify_url</notify_url>
  28. <trade_type>$trade_type</trade_type>
  29. <scene_info>$scene_info</scene_info>
  30. <attach>$out_trade_no</attach>
  31. <nonce_str>$nonce_str</nonce_str>
  32. <sign>$sign</sign>
  33. </xml>";//拼接成 XML 格式
  34. $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信传参地址
  35. $dataxml = postXmlCurl($post_data,$url); //后台 POST 微信传参地址 同时取得微信返回的参数
  36. $objectxml = (array)simplexml_load_string($dataxml, 'SimpleXMLElement', LIBXML_NOCDATA); //将微信返回的 XML 转换成数组
  37. function createNoncestr( $length = 32 ){
  38. $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
  39. $str ="";
  40. for ( $i = 0; $i < $length; $i++ ) {
  41. $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
  42. }
  43. return $str;
  44. }
  45. function postXmlCurl($xml,$url,$second = 30){
  46. $ch = curl_init();
  47. //设置超时
  48. curl_setopt($ch, CURLOPT_TIMEOUT, $second);
  49. curl_setopt($ch,CURLOPT_URL, $url);
  50. curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
  51. curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
  52. //设置 header
  53. curl_setopt($ch, CURLOPT_HEADER, FALSE);
  54. //要求结果为字符串且输出到屏幕上
  55. curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  56. //post 提交方式
  57. curl_setopt($ch, CURLOPT_POST, TRUE);
  58. curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
  59. //运行 curl
  60. $data = curl_exec($ch);
  61. //返回结果
  62. if($data){
  63. curl_close($ch);
  64. return $data;
  65. }else{
  66. $error = curl_errno($ch);
  67. curl_close($ch);
  68. echo "curl 出错,错误码:$error"."<br>";
  69. }
  70. }
  71. function get_client_ip($type = 0) {
  72. $type = $type ? 1 : 0;
  73. $ip = 'unknown';
  74. if ($ip !== 'unknown') return $ip[$type];
  75. if($_SERVER['HTTP_X_REAL_IP']){//nginx 代理模式下,获取客户端真实 IP
  76. $ip=$_SERVER['HTTP_X_REAL_IP'];
  77. }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {//客户端的 ip
  78. $ip = $_SERVER['HTTP_CLIENT_IP'];
  79. }elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {//浏览当前页面的用户计算机的网关
  80. $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
  81. $pos = array_search('unknown',$arr);
  82. if(false !== $pos) unset($arr[$pos]);
  83. $ip = trim($arr[0]);
  84. }elseif (isset($_SERVER['REMOTE_ADDR'])) {
  85. $ip = $_SERVER['REMOTE_ADDR'];//浏览当前页面的用户计算机的 ip 地址
  86. }else{
  87. $ip=$_SERVER['REMOTE_ADDR'];
  88. }
  89. // IP 地址合法验证
  90. $long = sprintf("%u",ip2long($ip));
  91. $ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
  92. return $ip[$type];
  93. }
  94.  
  95. <a class="pay" href="<?php echo $objectxml['mweb_url'] ?>"><button class="pay">确认支付</button></a>
  96. 异步通知页 native_notify.php 修改NotifyProcess方法
  97.  
  98. public function NotifyProcess($objData, $config, &$msg)
  99. {
  100. $data = $objData->GetValues();
  101. //echo "处理回调";
  102. Log::DEBUG("call back:" . json_encode($data));
  103. //TODO 1、进行参数校验
  104. //if(!array_key_exists("openid", $data) || !array_key_exists("product_id", $data))
  105. if(!array_key_exists("openid", $data))
  106. {
  107. $msg = "回调数据异常";
  108. Log::DEBUG($msg . json_encode($data));
  109. return false;
  110. }
  111.  
  112. //TODO 2、进行签名验证
  113. try {
  114. $checkResult = $objData->CheckSign($config);
  115. if($checkResult == false){
  116. //签名错误
  117. Log::ERROR("签名错误...");
  118. return false;
  119. }
  120. } catch(Exception $e) {
  121. Log::ERROR(json_encode($e));
  122. }
  123.  
  124. //==========================业务=========================
  125. $number=$data["out_trade_no"];//订单号
  126. $transaction_id=$data["transaction_id"];//交易号
  127.  
  128. $GLOBALS["number"]=$number;
  129. $GLOBALS["platform_number"]=$transaction_id;
  130. //=======================================================
  131. return true;
  132. }
  133.  
  134. $config = new WxPayConfig();
  135. Log::DEBUG("begin notify!");
  136. $notify = new NativeNotifyCallBack();
  137. $notify->Handle($config, true);
  138.  
  139. if(isset($GLOBALS["number"]) && isset($GLOBALS["platform_number"]) && $GLOBALS["number"] && $GLOBALS["platform_number"])
  140. {
  141. //业务代码
  142. }

异步通知页 native_notify.php 如果不用官方的 demo 代码如下:

  1. $xml = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
  2.  
  3. if (empty($xml))
  4. {
  5. return false;
  6. }
  7.  
  8. //将 xml 格式转换成数组
  9. function xmlToArray($xml) {
  10. //禁止引用外部 xml 实体
  11. libxml_disable_entity_loader(true);
  12. $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
  13. $val = json_decode(json_encode($xmlstring), true);
  14. return $val;
  15. }
  16.  
  17. $attr = xmlToArray($xml);
  18.  
  19. $total_fee = $attr['total_fee'];
  20. $open_id = $attr['openid'];
  21. $out_trade_no = $attr['out_trade_no'];
  22. $time = $attr['time_end'];
  23.  
  24. //业务代码
  25.  
  26. //在异步回调取值的时候,异步回调一直在调用(如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。 (通知频率为 15/15/30/180/1800/1800/1800/1800/3600,单位:秒))
  27.  
  28. exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');

巧妙使用 Native 给网站对接微信支付功能

已有 314 人购买
查看演示升级 VIP立刻购买

收藏
(0)

发表回复

热销模板

Ashade - 作品展示摄影相册WordPress汉化主题
LensNews

本站承接 WordPress / PbootCMS / DedeCMS 等
系统建站、仿站、开发、定制等业务!