微信小程序支付+php后端

时间:2019-03-19
本文章向大家介绍微信小程序支付+php后端,主要包括微信小程序支付+php后端使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

  最近在做自有项目后端用的是thinkphp5.1框架,闲话不说直接上代码

  小程序代码

  

 1 wxpay: function(e){
 2     let thisid = e.currentTarget.dataset.id;       这个是订单的id
 3     var that = this;
 4     wx.request({
 5       url: URL +'need/requestPay',       这个是往后台传的地址
 6       data:{
 7         id : thisid
 8       },
 9       method:'post',
10       success(res){
11         var data = res.data;
12         console.log(data)
13         if (data.error == 0){
14           app.mistake(data.msg,'../../../');
15           return false;
16         }
17         wx.requestPayment({         //调起支付
18           //下边参数具体看微信小程序官方文档
19           timeStamp: data.data.timeStamp,
20           nonceStr: data.data.nonceStr,
21           package: data.data.package,
22           signType: data.data.signType,
23           paySign: data.data.paySign,
24           success(res) {
25             if (res.errMsg == "requestPayment:ok"){
26               wx.request({      //这个是支付成功后改变订单状态的代码
27                 url: URL+'need/payok',
28                 data:{
29                   id : thisid
30                 },
31                 method:'post',
32                 success(r){
33                   console.log(r);
34                   if(r.data.error == 1){
35                     app.ok('支付成功', '../../../');     这个是支付成功后的弹窗
36                     that.onLoad();
37                   }
38                 }
39               })
40             }
41           },
42           fail(res) { }
43         })
44       }
45     })
46   }        

后台代码

  使用前先引入WeixinPay.php

 1 public function requestPay()
 2     {
 3         if(!Request::instance()->isPost()){
 4             return $this -> re(0,'请用POST获取数据');
 5         }
 6         $id = input('id');
 7         $rs = Db::name('表名') -> field('id,openid,order_amount,order_payment,order_number') -> where(['id' => $id,'order_payment' => 1]) -> find();
 8         if(empty($rs)){
 9             return $this -> re(0,'未找到此订单');
10         }
11         // halt($rs);
12         $a = new WeixinPay($rs['openid'],$rs['order_number'],'订单支付',$rs['order_amount']);
13         $pay = $a -> pay();  //下单获取返回值
14         // halt($pay);
15         return $this -> re(1,'下单成功',$pay);
16     }
17 
18     //支付成功
19     public function payok()
20     {
21         if(!Request::instance()->isPost()){
22             return $this -> re(0,'请用POST获取数据');
23         }
24         $id = input('id');
25         $rs = Db::name('表名') -> where('id',$id) -> update(['order_payment' => 0,'order_fi' => 3]);    //修改表中字段状态
26         if(empty($rs)){
27             return $this -> re(0,'失败');
28         }else{
29             return $this -> re(1,'成功');
30         }
31     }

WeixinPay.php

  1 <?php 
  2 namespace app\library;
  3   
  4 /* 
  5  * 小程序微信支付 
  6  */
  7   
  8   
  9 class WeixinPay { 
 10   
 11   
 12   /*protected $appid; 
 13   protected $mch_id; 
 14   protected $key; 
 15   protected $openid; 
 16   protected $out_trade_no; 
 17   protected $body; 
 18   protected $total_fee; */
 19   function __construct($openid,$out_trade_no,$body,$total_fee) { 
 20     $this->appid = 'wx0aaaaaaaaa';//你的小程序appid 
 21     $this->openid = $openid;   //用户的openid我是直接存在表中的,若是你没有存,请百度查询如何获取用户openid
 22     // 商户号
 23     $this->mch_id = '888888';   //你的商户号。找不到的在你的小程序里边的微信支付里边找,前提是你必须先开启你的微信支付
 24     // 支付秘钥
 25     $this->key = '5555555555555';   //这个是你商户号的api秘钥,在产品中心里边找,
 26     //订单号
 27     $this->out_trade_no = $out_trade_no;   //这个我是用的我后台的订单号
 28     // 内容
 29     $this->body = $body;         //支付时显示的提示
 30     //金额
 31     $this->total_fee = floatval($total_fee)*100;    //这个块使用分为单位的所有要乘100
 32   } 
 33   
 34   
 35   public function pay() { 
 36     //统一下单接口 
 37     $return = $this->weixinapp(); 
 38     return $return; 
 39   } 
 40   
 41   
 42   //统一下单接口 
 43   private function unifiedorder() { 
 44     $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; 
 45     $parameters = array( 
 46       'appid' => $this->appid, //小程序ID 
 47       'mch_id' => $this->mch_id, //商户号 
 48       'nonce_str' => $this->createNoncestr(), //随机字符串  
 49       'body' => $this->body, //商品描述  
 50       'out_trade_no'=> $this->out_trade_no, //商户订单号 
 51       'total_fee' => $this->total_fee, //总金额 单位 分 
 52       'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], //终端IP 
 53       'notify_url' => 'http://www.weixin.qq.com/wxpay/pay.php', //通知地址 确保外网能正常访问 
 54       'openid' => $this->openid, //用户id 
 55       'trade_type' => 'JSAPI'//交易类型       //要是返回该产品权限未开通请在产品中心开通jsAPi他包含的小程序支付
 56     ); 
 57     //统一下单签名 
 58     $parameters['sign'] = $this->getSign($parameters); 
 59     $xmlData = $this->arrayToXml($parameters); 
 60     $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60)); 
 61     return $return; 
 62   } 
 63   
 64   
 65   private static function postXmlCurl($xml, $url, $second = 30)  
 66   { 
 67     $ch = curl_init(); 
 68     //设置超时 
 69     curl_setopt($ch, CURLOPT_TIMEOUT, $second); 
 70     curl_setopt($ch, CURLOPT_URL, $url); 
 71     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
 72     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验 
 73     //设置header 
 74     curl_setopt($ch, CURLOPT_HEADER, FALSE); 
 75     //要求结果为字符串且输出到屏幕上 
 76     curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 
 77     //post提交方式 
 78     curl_setopt($ch, CURLOPT_POST, TRUE); 
 79     curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); 
 80   
 81   
 82     curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20); 
 83     curl_setopt($ch, CURLOPT_TIMEOUT, 40); 
 84     set_time_limit(0); 
 85   
 86   
 87     //运行curl 
 88     $data = curl_exec($ch); 
 89     //返回结果 
 90     if ($data) { 
 91       curl_close($ch); 
 92       return $data; 
 93     } else { 
 94       $error = curl_errno($ch); 
 95       curl_close($ch); 
 96       throw new WxPayException("curl出错,错误码:$error"); 
 97     } 
 98   } 
 99     
100     
101     
102   //数组转换成xml 
103   private function arrayToXml($arr) { 
104     $xml = "<root>"; 
105     foreach ($arr as $key => $val) { 
106       if (is_array($val)) { 
107         $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">"; 
108       } else { 
109         $xml .= "<" . $key . ">" . $val . "</" . $key . ">"; 
110       } 
111     } 
112     $xml .= "</root>"; 
113     return $xml; 
114   } 
115   
116   
117   //xml转换成数组 
118   private function xmlToArray($xml) { 
119   
120   
121     //禁止引用外部xml实体  
122   
123   
124     libxml_disable_entity_loader(true); 
125   
126   
127     $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); 
128   
129   
130     $val = json_decode(json_encode($xmlstring), true); 
131   
132   
133     return $val; 
134   } 
135   
136   
137   //微信小程序接口 
138   private function weixinapp() { 
139     //统一下单接口 
140     $unifiedorder = $this->unifiedorder(); 
141     //print_r($unifiedorder);
142     // halt($unifiedorder);
143     // if($unifiedorder['err_code_des'] == '201 商户订单号重复'){
144     //   return ''
145     // }
146     $parameters = array( 
147       'appId' => $this->appid, //小程序ID 
148       'timeStamp' => '' . time() . '', //时间戳 
149       'nonceStr' => $this->createNoncestr(), //随机串 
150       'package' => 'prepay_id=' . $unifiedorder['prepay_id'], //数据包         要是返回201则要修改订单号,这个问题测试中容易出现,上线了基本不出现问题
151       'signType' => 'MD5'//签名方式 
152     ); 
153     //签名 
154     $parameters['paySign'] = $this->getSign($parameters); 
155     return $parameters;
156   } 
157   
158   
159   //作用:产生随机字符串,不长于32位 
160   private function createNoncestr($length = 32) { 
161     $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; 
162     $str = ""; 
163     for ($i = 0; $i < $length; $i++) { 
164       $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); 
165     } 
166     return $str; 
167   } 
168   
169   
170   //作用:生成签名 
171   private function getSign($Obj) { 
172     foreach ($Obj as $k => $v) { 
173       $Parameters[$k] = $v; 
174     } 
175     //签名步骤一:按字典序排序参数 
176     ksort($Parameters); 
177     $String = $this->formatBizQueryParaMap($Parameters, false); 
178     //签名步骤二:在string后加入KEY 
179     $String = $String . "&key=" . $this->key; 
180     //签名步骤三:MD5加密 
181     $String = md5($String);
182     //签名步骤四:所有字符转为大写 
183     $result_ = strtoupper($String); 
184     return $result_; 
185   } 
186   
187   
188   ///作用:格式化参数,签名过程需要使用 
189   private function formatBizQueryParaMap($paraMap, $urlencode) { 
190     $buff = ""; 
191     ksort($paraMap); 
192     foreach ($paraMap as $k => $v) { 
193       if ($urlencode) { 
194         $v = urlencode($v); 
195       } 
196       $buff .= $k . "=" . $v . "&"; 
197     } 
198     $reqPar; 
199     if (strlen($buff) > 0) { 
200       $reqPar = substr($buff, 0, strlen($buff) - 1); 
201     } 
202     return $reqPar; 
203   } 
204   
205   
206 } 

  然后微信支付基本上就这些问题了,若是还有其他的问题请留言,我看到会回复 的,转载请标明出处,谢谢