APP开发平台 > Blog > 移动APP 微信支付完整过程

移动APP 微信支付完整过程

  前两天开始做移动端APP的微信支付,过程中遇到了一些问题,比如支付的过程中返回值总是:-1 {status:false},这些问题已经得到了解决。前人栽树,后人尽管乘凉,那么分享一下整个支付过程(wxPay 方案一):

  1、申请微信开发平台的账号、创建移动应用、申请开发者资质认证(整个过程APICLOUD官方网站已经给出了相当明确的操作步骤,与实际操作没有差异,按照文档一步一步来,是没有问题的),附带链接地址:http://docs.apicloud.com/Others/Open-SDK-Integration-Guide/weChat

  2、配置移动应用中 config.xml 文件

  复制代码

  配置获取方式说明以及截图:从微信开发平台获取,登录微信开发平台 —>管理中心—>移动应用—>查看(urlScheme的值和apiKey相同)(微信开发平台链接:https://open.weixin.qq.com/)

  3、getOrderId(),将获取预支付订单号,建议将获取预支付订单号放置服务器端执行。(服务端代码如下:)

  1. $dataArr = array(

  2.     'appid' => $appId,

  3.     'mch_id' => $mchId,

  4.     'nonce_str' => getNonceStr(),

  5.     'body' => $body,

  6.     'attach' => $attach,

  7.     'out_trade_no' => getNonceStr(),

  8.     'total_fee' => $totalFee,

  9.     'spbill_create_ip' => $cIp,

  10.     'notify_url' => $url,

  11.     'trade_type' => 'APP'

  12. );



  13. //转XML格式

  14. function createXML($rootNode, $arr)

  15. {

  16.     //创建一个文档,文档时xml的,版本号为1.0,编码格式utf-8

  17.     $xmlObj = new DOMDocument('1.0', 'UTF-8');

  18.     //创建根节点

  19.     $Node = $xmlObj->createElement($rootNode);

  20.     //把创建好的节点加到文档中

  21.     $root = $xmlObj->appendChild($Node);

  22.     //开始把数组中的数据加入文档

  23.     foreach ($arr as $key => $value) {

  24.         //如果是$value是一个数组

  25.         if (is_array($value)) {

  26.             //先创建一个节点

  27.             $childNode = $xmlObj->createElement($key);

  28.             //将节点添加到$root中

  29.             $root->appendChild($childNode);

  30.             //循环添加数据

  31.             foreach ($value as $key2 => $val2) {

  32.                 //创建节点的同时添加数据

  33.                 $childNode2 = $xmlObj->createElement($key2, $val2);

  34.                 //将节点添加到$childNode

  35.                 $childNode->appendChild($childNode2);

  36.             }

  37.         } else {

  38.             //创建一个节点,根据键和值

  39.             $childNode = $xmlObj->createElement($key, $value);

  40.             //把节点加到根节点

  41.             $root->appendChild($childNode);

  42.         }

  43.     }

  44.     //把创建好的xml保存到本地

  45.     $xmlObj->save('xml/log.xml');

  46.     $str = $xmlObj->saveXML();

  47. //        echo $str;

  48.     //返回xml字符串

  49.     return $str;

  50. }



  51. //封装签名算法

  52. function MakeSign($arr)

  53. {

  54.     //签名步骤一:按字典序排序参数

  55.     ksort($arr);

  56.     $string = ToUrlParams($arr);

  57.     //签名步骤二:在string后加入KEY

  58.     $string = $string . "&key=" . $key;

  59.     //签名步骤三:MD5加密

  60.     $string = md5($string);

  61.     //签名步骤四:所有字符转为大写

  62.     $result = strtoupper($string);

  63.     return $result;

  64. }


  65. /**

  66. * 格式化参数格式化成url参数

  67. */

  68. function ToUrlParams($arr)

  69. {

  70.     $buff = "";

  71.     foreach ($arr as $k => $v) {

  72.         if ($k != "sign" && $v != "" && !is_array($v)) {

  73.             $buff .= $k . "=" . $v . "&";

  74.         }

  75.     }


  76.     $buff = trim($buff, "&");

  77.     return $buff;

  78. }



  79. //随机字符串(不长于32位)

  80. function getNonceStr($length = 32)

  81. {

  82.     $chars = "abcdefghijklmnopqrstuvwxyz0123456789";

  83.     $str = "";

  84.     for ($i = 0; $i < $length; $i++) {

  85.         $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);

  86.     }

  87.     return $str;

  88. }



  89. function curl($url, $post_data)

  90. {



  91.     $headerArray = array(

  92.         'Accept:application/json, text/javascript, */*',

  93.         'Content-Type:application/x-www-form-urlencoded',

  94.         'Referer:https://mp.weixin.qq.com/'

  95.     );


  96.     $ch = curl_init();

  97.     curl_setopt($ch, CURLOPT_URL, $url);

  98.     // 对认证证书来源的检查,0表示阻止对证书的合法性的检查。

  99.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

  100.     // 从证书中检查SSL加密算法是否存在

  101.     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

  102.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//关闭直接输出

  103.     curl_setopt($ch, CURLOPT_POST, 1);//使用post提交数据

  104.     curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);//设置 post提交的数据

  105.     curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.69 Safari/537.36');//设置用户代理

  106.     curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray);//设置头信息



  107.     $loginData = curl_exec($ch);//这里会返回token,需要处理一下。



  108.     return $loginData;


  109.     $token = array_pop($token);

  110.     curl_close($ch);



  111. }


  112. /**

  113. * 解析xml文档,转化为对象

  114. * @param  String $xmlStr xml文档

  115. * @return Object         返回Obj对象

  116. */

  117. function xmlToObject($xmlStr)

  118. {

  119.     if (!is_string($xmlStr) || empty($xmlStr)) {

  120.         return false;

  121.     }

  122.     // 由于解析xml的时候,即使被解析的变量为空,依然不会报错,会返回一个空的对象,所以,我们这里做了处理,当被解析的变量不是字符串,或者该变量为空,直接返回false

  123.     libxml_disable_entity_loader(true);

  124.     $postObj = json_decode(json_encode(simplexml_load_string($xmlStr, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

  125.     //将xml数据转换成对象返回

  126.     return $postObj;

  127. }





  128. //=====================执行=======================

  129. $sign = MakeSign($dataArr);//签名生成

  130. $dataArr['sign'] = $sign;


  131. $xmlStr = createXML('xml', $dataArr);//统一下单xml数据生成

  132. $reArr = explode('?>', $xmlStr);

  133. $reArr = end($reArr);


  134. $xml = curl('https://api.mch.weixin.qq.com/pay/unifiedorder', $reArr);//发送请求 统一下单数据


  135. //解析返回的xml字符串

  136. $re = xmlToObject($xml);


  137. //判断统一下单是否成功

  138. if ($re['result_code'] == 'SUCCESS') {


  139.     //支付请求数据

  140.     $payData = array(

  141.         'appid' => $re['appid'],

  142.         'partnerid' => $re['mch_id'],

  143.         'prepayid' => $re['prepay_id'],

  144.         'noncestr' => getNonceStr(),

  145.         'package' => 'Sign=WXPay',

  146.         'timestamp' => time()

  147.     );



  148.     //生成支付请求的签名

  149.     $paySign = MakeSign($payData);


  150.     $payData['sign'] = $paySign;


  151.     //拼接成APICLOUD所需要支付数据请求

  152.     $payDatas = array(

  153.         'apiKey' => $re['appid'],

  154.         'orderId' => $re['prepay_id'],

  155.         'mchId' => $re['mch_id'],

  156.         'nonceStr' => $payData['noncestr'],

  157.         'package' => 'Sign=WXPay',

  158.         'timeStamp' => $payData['timestamp'],

  159.         'sign' => $paySign

  160.     );


  161.     //返回支付请求数据

  162.     echo json_encode($payDatas);

  163. } else {

  164.     $re['payData'] = "error";

  165.     echo json_encode($re);

  166. }


复制代码

  4、预支付下单成功后,将拼接好的支付请求数据返回,也就是上述代码中数组$payDatas(注意:第二次参与签名的字段是:appid、partnerid、prepayid、noncestr、package、timestamp),app端代码如下:

  1. $.ajax({

  2.             url:url,

  3.             data:{

  4.                 body:body,

  5.                 attach:attach,

  6.                 total_fee:total_fee

  7.             },

  8.             dataType:"json",

  9.             type:"post",

  10.             success:function(data){



  11.                 if(data.payData != "error"){

  12.                     var wxPay = api.require('wxPay');

  13.                     wxPay.payOrder(data, function(ret, err) {


  14.                         if (ret.status) {

  15.                             //支付成功

  16.                             alert('支付成功');

  17.                             }




  18.                         } else {

  19.                             alert(err.code);

复制代码

  5、以上描述,已经亲测没有问题,如果代码或叙述有问题的,欢迎各位大神指教批评;如果有帮到各位初学者的不胜荣幸;另外说下我之前遇到过支付过程中返回-1的问题:这个问题不得不说APICLOUD官网有那么一点点的坑,官网上面payOrder()的参数为:appKey、orderId、mchId、nonceStr、timeStamp、package,就会以为参与第二次支付签名的参数是这些,但其实并不是,那么参与第二次支付签名的参数是:appid、partnerid、prepayid、noncestr、package、timestamp,生成签名后,需要将payOrder()所需要的参数一一对应重新填写(appKey==appid、orderId==prepayid、mchId==partnerid、nonceStr==noncestr、package==package、timeStamp==timestamp)。

文地址:https://community.apicloud.com/bbs/thread-70594-1-1.html

   更多APP资讯,请关注www.apicloud.com

  提交App定制需求,了解报价和周期:https://app.apicloud.com/index?uzchannel=500


2018-05-18 来源:APICloud

An efficient app outsourcing platform that guarantees timely delivery!

Submit Requirements