Egret社区
本帖最后由 APICloud大神 于 2019-4-30 15:50 编辑

前两天开始做移动端APP的微信支付,过程中遇到了一些问题,比如支付的过程中返回值总是:-1 {status:false},这些问题已经得到了解决。前人栽树,后人尽管乘凉,那么分享一下整个支付过程(wxPay 方案一):
1、申请微信开发平台的账号、创建移动应用、申请开发者资质认证(整个过程APICLOUD官方网站已经给出了相当明确的操作步骤,与实际操作没有差异,按照文档一步一步来,是没有问题的),附带链接地址:http://docs.apicloud.com/Others/Open-SDK-Integration-Guide/weChat

2、配置移动应用中 config.xml 文件
<feature name="wxPay">    <param name="urlScheme" value="***"/>    <param name="apiKey" value="***"/>    <param name="apiSecret" value="***"/>  </feature>
复制代码

配置获取方式说明以及截图:从微信开发平台获取,登录微信开发平台 —>管理中心—>移动应用—>查看(urlScheme的值和apiKey相同)(微信开发平台链接:https://open.weixin.qq.com/
3、getOrderId(),将获取预支付订单号,建议将获取预支付订单号放置服务器端执行。(服务端代码如下:)
  • $dataArr = array(
  •     'appid' => $appId,
  •     'mch_id' => $mchId,
  •     'nonce_str' => getNonceStr(),
  •     'body' => $body,
  •     'attach' => $attach,
  •     'out_trade_no' => getNonceStr(),
  •     'total_fee' => $totalFee,
  •     'spbill_create_ip' => $cIp,
  •     'notify_url' => $url,
  •     'trade_type' => 'APP'
  • );
  • //转XML格式
  • function createXML($rootNode, $arr)
  • {
  •     //创建一个文档,文档时xml的,版本号为1.0,编码格式utf-8
  •     $xmlObj = new DOMDocument('1.0', 'UTF-8');
  •     //创建根节点
  •     $Node = $xmlObj->createElement($rootNode);
  •     //把创建好的节点加到文档中
  •     $root = $xmlObj->appendChild($Node);
  •     //开始把数组中的数据加入文档
  •     foreach ($arr as $key => $value) {
  •         //如果是$value是一个数组
  •         if (is_array($value)) {
  •             //先创建一个节点
  •             $childNode = $xmlObj->createElement($key);
  •             //将节点添加到$root中
  •             $root->appendChild($childNode);
  •             //循环添加数据
  •             foreach ($value as $key2 => $val2) {
  •                 //创建节点的同时添加数据
  •                 $childNode2 = $xmlObj->createElement($key2, $val2);
  •                 //将节点添加到$childNode
  •                 $childNode->appendChild($childNode2);
  •             }
  •         } else {
  •             //创建一个节点,根据键和值
  •             $childNode = $xmlObj->createElement($key, $value);
  •             //把节点加到根节点
  •             $root->appendChild($childNode);
  •         }
  •     }
  •     //把创建好的xml保存到本地
  •     $xmlObj->save('xml/log.xml');
  •     $str = $xmlObj->saveXML();
  • //        echo $str;
  •     //返回xml字符串
  •     return $str;
  • }
  • //封装签名算法
  • function MakeSign($arr)
  • {
  •     //签名步骤一:按字典序排序参数
  •     ksort($arr);
  •     $string = ToUrlParams($arr);
  •     //签名步骤二:在string后加入KEY
  •     $string = $string . "&key=" . $key;
  •     //签名步骤三:MD5加密
  •     $string = md5($string);
  •     //签名步骤四:所有字符转为大写
  •     $result = strtoupper($string);
  •     return $result;
  • }
  • /**
  • * 格式化参数格式化成url参数
  • */
  • function ToUrlParams($arr)
  • {
  •     $buff = "";
  •     foreach ($arr as $k => $v) {
  •         if ($k != "sign" && $v != "" && !is_array($v)) {
  •             $buff .= $k . "=" . $v . "&";
  •         }
  •     }
  •     $buff = trim($buff, "&");
  •     return $buff;
  • }
  • //随机字符串(不长于32位)
  • function getNonceStr($length = 32)
  • {
  •     $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
  •     $str = "";
  •     for ($i = 0; $i < $length; $i++) {
  •         $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  •     }
  •     return $str;
  • }
  • function curl($url, $post_data)
  • {
  •     $headerArray = array(
  •         'Accept:application/json, text/javascript, */*',
  •         'Content-Type:application/x-www-form-urlencoded',
  •         'Referer:https://mp.weixin.qq.com/'
  •     );
  •     $ch = curl_init();
  •     curl_setopt($ch, CURLOPT_URL, $url);
  •     // 对认证证书来源的检查,0表示阻止对证书的合法性的检查。
  •     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  •     // 从证书中检查SSL加密算法是否存在
  •     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  •     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//关闭直接输出
  •     curl_setopt($ch, CURLOPT_POST, 1);//使用post提交数据
  •     curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);//设置 post提交的数据
  •     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');//设置用户代理
  •     curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray);//设置头信息
  •     $loginData = curl_exec($ch);//这里会返回token,需要处理一下。
  •     return $loginData;
  •     $token = array_pop($token);
  •     curl_close($ch);
  • }
  • /**
  • * 解析xml文档,转化为对象
  • * @param  String $xmlStr xml文档
  • * @return Object         返回Obj对象
  • */
  • function xmlToObject($xmlStr)
  • {
  •     if (!is_string($xmlStr) || empty($xmlStr)) {
  •         return false;
  •     }
  •     // 由于解析xml的时候,即使被解析的变量为空,依然不会报错,会返回一个空的对象,所以,我们这里做了处理,当被解析的变量不是字符串,或者该变量为空,直接返回false
  •     libxml_disable_entity_loader(true);
  •     $postObj = json_decode(json_encode(simplexml_load_string($xmlStr, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
  •     //将xml数据转换成对象返回
  •     return $postObj;
  • }
  • //=====================执行=======================
  • $sign = MakeSign($dataArr);//签名生成
  • $dataArr['sign'] = $sign;
  • $xmlStr = createXML('xml', $dataArr);//统一下单xml数据生成
  • $reArr = explode('?>', $xmlStr);
  • $reArr = end($reArr);
  • $xml = curl('https://api.mch.weixin.qq.com/pay/unifiedorder', $reArr);//发送请求 统一下单数据
  • //解析返回的xml字符串
  • $re = xmlToObject($xml);
  • //判断统一下单是否成功
  • if ($re['result_code'] == 'SUCCESS') {
  •     //支付请求数据
  •     $payData = array(
  •         'appid' => $re['appid'],
  •         'partnerid' => $re['mch_id'],
  •         'prepayid' => $re['prepay_id'],
  •         'noncestr' => getNonceStr(),
  •         'package' => 'Sign=WXPay',
  •         'timestamp' => time()
  •     );
  •     //生成支付请求的签名
  •     $paySign = MakeSign($payData);
  •     $payData['sign'] = $paySign;
  •     //拼接成APICLOUD所需要支付数据请求
  •     $payDatas = array(
  •         'apiKey' => $re['appid'],
  •         'orderId' => $re['prepay_id'],
  •         'mchId' => $re['mch_id'],
  •         'nonceStr' => $payData['noncestr'],
  •         'package' => 'Sign=WXPay',
  •         'timeStamp' => $payData['timestamp'],
  •         'sign' => $paySign
  •     );
  •     //返回支付请求数据
  •     echo json_encode($payDatas);
  • } else {
  •     $re['payData'] = "error";
  •     echo json_encode($re);
  • }


复制代码

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

  • $.ajax({
  •             url:url,
  •             data:{
  •                 body:body,
  •                 attach:attach,
  •                 total_fee:total_fee
  •             },
  •             dataType:"json",
  •             type:"post",
  •             success:function(data){
  •                 if(data.payData != "error"){
  •                     var wxPay = api.require('wxPay');
  •                     wxPay.payOrder(data, function(ret, err) {
  •                         if (ret.status) {
  •                             //支付成功
  •                             alert('支付成功');
  •                             }
  •                         } else {
  •                             alert(err.code);

复制代码
复制代码
5、以上描述,已经亲测没有问题,如果代码或叙述有问题的,欢迎各位大神指教批评;如果有帮到各位初学者的不胜荣幸;另外说下我之前遇到过支付过程中返回-1的问题:参与第二次支付签名的参数是:appid、partnerid、prepayid、noncestr、package、timestamp,生成签名后,需要将payOrder()所需要的参数一一对应重新填写(appKey==appid、orderId==prepayid、mchId==partnerid、nonceStr==noncestr、package==package、timeStamp==timestamp)。
分享到 :
1 人收藏

1 个回复

倒序浏览
熊猫少女  圆转纯熟 | 2019-4-30 15:29:05
感谢分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|京网文[2014]0791-191号|京ICP证150115号|Egret社区 ( 京ICP备14025619号 )

Powered by Discuz! X3.4 © 2001-2019 Comsenz Inc.

返回顶部