### [微信小程序支付的流程问题解析(代码解析)](https://www.prosaas.cn/article/17132) **Published:** 2018-08-14T09:23:34 **Author:** 5201314 **Excerpt:** 本篇文章给大家带来的内容是关于微信小程序支付的流程问题解析(代码解析),有一定的参考价值,有需要的朋友可以参考… 本篇文章给大家带来的内容是关于微信小程序支付的流程问题解析(代码解析),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 这几天在做小程序的支付,没有用官方的SDK,这里就纯用官方的文档搞一发。 **\* 注:使用的PHP,不过支付流程都是这样** ## 开发前必读 ### 主要流程 - 小程序前端发送求参请求 - 接受请求封装 “统一下单” 获取`package` - 小程序接受 “统一下单” 获取的`package`值带入`wx.requestPayment`发起支付请求 ### 准备工具 - 申请小程序微信支付 - 拿到小程序微信支付的商户号及设置秘钥 **注意:小程序就只需要这两步,如果是web的话还需要设置支付目录授权域名,文档里面也有写的:https://pay.weixin.qq.com/wik..** ## 统一下单 > 官方文档:https://pay.weixin.qq.com/wik... /\*\*  \* 统一订单  \*/ public function unifiedorder(){     // 以下配置是必填项,如有其它需求请自行配置     $config = array(         'appid'         =>    'xxxxxxx',//这里是小程序appid         'mch\_id'        =>    'xxxxxxx',//商户ID         'nonce\_str'     =>    $this->getNonceStr(),//随机字符串         'body'          =>    '这里是测试 - 测试',//请按照文档要求填写合格名称         'out\_trade\_no'  =>    time().$this->getNonceStr(2),//流水单号         'total\_fee'     =>    '20',//金额,分为单位,这里是0.2元         'spbill\_create\_ip' => '123.123.123.123',//当前IP         'notify\_url'    =>    'http://xxxx.com',//请恕我愚昧,我没搞懂他有什么用         'trade\_type'    =>    'JSAPI',//必须填写JSAPI         'openid'        =>    'xxxxxxxx'//当前用户的openid,在trade\_type=JSAPI的时候,此项就变成必填项了     );     $config\['sign'\] = $this->getSignPay($config);     $xmlData = $this->ToXml($config);//转成xml数据     $postData = $this->http\_post($xmlData);     $arrayData = $this->FromXml($postData);     if($arrayData\['return\_code'\] == 'SUCCESS' || $arrayData\['result\_code'\] == 'SUCCESS'){         return $arrayData\['prepay\_id'\];//重点来了:走了这么多路,就为了这个值。到这一步就证明成功一多半了。     }else{         return $arrayData;//返回错误     } } /\*\*  \* 获取签名  \*/ public function getSignPay($config){     $key = 'xxxxxxx';//商户秘钥,就是自己生成的32位密码     $strA = 'appid='.$config\['appid'\].'&body='.$config\['body'\].'&mch\_id='.$config\['mch\_id'\].'&nonce\_str='.$config\['nonce\_str'\].'¬ify\_url='.$config\['notify\_url'\].'&spbill\_create\_ip'.$config\['spbill\_create\_ip'\].'&total\_fee='.$config\['total\_fee'\].'&trade\_type='.$config\['trade\_type'\];//ASCII 字典序     $strB = $strA.'&key='.$key;     $sign = strtoupper(md5($strB));//大写MD5     return $sign; } /\*\*  \* 随机字符串 32位  \*/ public 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; } /\*\* \* array转XML \*/ public function ToXml($data){ if(!is\_array($data) || count($data) <= 0){ throw new WxPayException("数组数据异常!"); } $xml = "";     foreach ($data as $key=>$val){         $xml.="<".$key.">".$val."";     }     $xml.="";     return $xml;  } /\*\*  \* xml转array  \*/ public function FromXml($xml){         if(!$xml){         throw new WxPayException("xml数据异常!");     }     libxml\_disable\_entity\_loader(true);     $this->values = json\_decode(json\_encode(simplexml\_load\_string($xml, 'SimpleXMLElement', LIBXML\_NOCDATA)), true);     return $this->values; } /\*\*  \* post 请求  \*/ public function http\_post($url,$param,$post\_file=false){     $oCurl = curl\_init();     if(stripos($url,"https://")!==FALSE){         curl\_setopt($oCurl, CURLOPT\_SSL\_VERIFYPEER, FALSE);         curl\_setopt($oCurl, CURLOPT\_SSL\_VERIFYHOST, false);         curl\_setopt($oCurl, CURLOPT\_SSLVERSION, 1); //CURL\_SSLVERSION\_TLSv1     }     if (PHP\_VERSION\_ID >= 50500 && class\_exists('\\CURLFile')) {         $is\_curlFile = true;     } else {         $is\_curlFile = false;         if (defined('CURLOPT\_SAFE\_UPLOAD')) {             curl\_setopt($oCurl, CURLOPT\_SAFE\_UPLOAD, false);         }     }     if (is\_string($param)) {         $strPOST = $param;     }elseif($post\_file) {         if($is\_curlFile) {             foreach ($param as $key => $val) {                 if (substr($val, 0, 1) == '@') {                 }             }         }         $strPOST = $param;     } else {         $aPOST = array();         foreach($param as $key=>$val){             $aPOST\[\] = $key."=".urlencode($val);         }         $strPOST =  join("&", $aPOST);     }     curl\_setopt($oCurl, CURLOPT\_URL, $url);     curl\_setopt($oCurl, CURLOPT\_RETURNTRANSFER, 1 );     curl\_setopt($oCurl, CURLOPT\_POST,true);     curl\_setopt($oCurl, CURLOPT\_POSTFIELDS,$strPOST);     $sContent = curl\_exec($oCurl);     $aStatus = curl\_getinfo($oCurl);     curl\_close($oCurl);     if(intval($aStatus\["http\_code"\])==200){         return $sContent;     }else{         return false;     } } 好了现在已经获取到了 `prepay_id` 的值,我们的统一下单就算完成了,其实我更乐意叫他数据封 ## 小程序微信支付 > 官方文档:https://developers.weixin.qq.... 先来一个插曲,首先我们小程序的前端需要去触发pay,实现的功能肯定是要点击小程序的一个触发,然后才能支付对吧, pay:function(e){     //这里面使用post去请求。然后通过我接下来要写的API支付代码获取小程序支付参数     success:function(res){          wx.requestPayment({              'timeStamp':toString(res.timeStamp),//这里转字符串,这里被坑过,不转的话可能会出现total\_fee为空              'nonceStr':toString(res.nonceStr),              'package':toString(res.package),              'signType':'MD5',              'paySign':toString(res.paySign),              success:function(res){                  console.log(res);//这里可以跳转到带参地址              },              fail:function(res){                  console.info('支付失败',res);              },              complete:function(){                  console.info('支付触发回调',res);              }          })       }         } ### api支付 也就是上面小程序代码的后端请求地址 /\*\*  \* api组装数据  \*/ public function payApiBlack(){     $appid = 'xxxxxx';//小程序appid,上面有重复,不过这样比较直观     $timeStamp = time();     $nonceStr = $this->getNonceStr();//这是调用统一下单里面的方法,为了直观,我把这些代码都写在了一个类里     $package = 'prepay\_id='.$this->unifiedorder();     $signType = 'MD5';     $key = 'xxxxxx';//这里是商户秘钥,32位,同上面也有     $strA = 'appId='.$appid.'&nonceStr='.$nonceStr.'package='.$package.'&= signType='.$signType.'&timeStamp='.$timeStamp.'&key='.$key;     $paySign = strtoupper(md5($strA));     $data = array(         'appid'=>$appid,         'timeStamp'=>$timeStamp,         'nonceStr'=>$nonceStr,         'package'=>$package,         'signType'=>$signType     );     return $data;//返回给小程序 } 以上就是全部代码,还有小程序的支付回调没有什么信息,所以,我的思路判断success后进行跳转带参 //此代码为wx.requestPayment success,部分代码省略 //res 回调参数包括用户uid及其他重要传递 success:function(res){     wx.redirect({         url:'pages/pay/done?uid='+res.uid     }) } 当然那个统一下单的 notify\_url 好像与回调有关,至于怎么用,试了几次回调的CURD都没反应,所以有空再研究啦。 以上代码仅作为支付流程解释,所以真正要用到项目上,还是去套官方的SDK吧,毕竟涉及到钱嘛 相关推荐: 微信小程序和支付宝小程序对比区别介绍 微信小程序如何从0开始进入支付 微信小程序微信支付接入开发 以上就是微信小程序支付的流程问题解析(代码解析)的详细内容,更多请关注知企PROSAAS其它相关文章! **Categories:** 后端开发 ---