微信小程式中實現微信支付
阿新 • • 發佈:2019-01-11
最近做小程式,涉及到微信支付,看了看微信小程式開發文件,儘管之前做過微信支付,還是有點懵逼,不過好在之前研究過,不然真的是無從下手。對比了一下發現,其實小程式中做支付比公眾號支付要省事很多,因為不需要支付授權目錄,也不需要授權域名,但是支付流程卻比公眾號多了一步,就是統一下單是預支付,然後需要對預支付的結果再次簽名之後,才調起支付。
前期準備:
1.開通了微信支付,並且小程式綁定了微信支付;
2.準備好小程式的appid,微信支付的商戶號,支付祕鑰。
商戶系統和微信支付系統主要互動:
1、小程式內呼叫登入介面,獲取到使用者的openid
此步驟在小程式內完成,也很簡單,方法見:【小程式登入API】
小程式端完整程式碼如下:
前期準備:
1.開通了微信支付,並且小程式綁定了微信支付;
2.準備好小程式的appid,微信支付的商戶號,支付祕鑰。
商戶系統和微信支付系統主要互動:
1、小程式內呼叫登入介面,獲取到使用者的openid
此步驟在小程式內完成,也很簡單,方法見:【小程式登入API】
2、呼叫商戶伺服器支付統一下單介面,進行預支付
3、呼叫商戶伺服器再次簽名介面,返回支付資料/** * 預支付請求介面(POST) * @param string $openid openid * @param string $body 商品簡單描述 * @param string $order_sn 訂單編號 * @param string $total_fee 金額 * @return json的資料 */ public function prepay(){ $config = $this->config; $openid = I('post.openid'); $body = I('post.body'); $order_sn = I('post.order_sn'); $total_fee = I('post.total_fee'); //統一下單引數構造 $unifiedorder = array( 'appid' => $config['appid'], 'mch_id' => $config['pay_mchid'], 'nonce_str' => self::getNonceStr(), 'body' => $body, 'out_trade_no' => $order_sn, 'total_fee' => $total_fee * 100, 'spbill_create_ip' => get_client_ip(), 'notify_url' => 'https://'.$_SERVER['HTTP_HOST'].'/Api/Wxpay/notify', 'trade_type' => 'JSAPI', 'openid' => $openid ); $unifiedorder['sign'] = self::makeSign($unifiedorder); //請求資料 $xmldata = self::array2xml($unifiedorder); $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $res = self::curl_post_ssl($url, $xmldata); if(!$res){ self::return_err("Can't connect the server"); } // 這句file_put_contents是用來檢視伺服器返回的結果 測試完可以刪除了 //file_put_contents(APP_ROOT.'/Statics/log1.txt',$res,FILE_APPEND); $content = self::xml2array($res); if(strval($content['result_code']) == 'FAIL'){ self::return_err(strval($content['err_code_des'])); } if(strval($content['return_code']) == 'FAIL'){ self::return_err(strval($content['return_msg'])); } self::return_data(array('data'=>$content)); //$this->ajaxReturn($content); }
4、小程式內完成支付,商戶伺服器接收支付回撥通知/** * 進行支付介面(POST) * @param string $prepay_id 預支付ID(呼叫prepay()方法之後的返回資料中獲取) * @return json的資料 */ public function pay(){ $config = $this->config; $prepay_id = I('post.prepay_id'); $data = array( 'appId' => $config['appid'], 'timeStamp' => time(), 'nonceStr' => self::getNonceStr(), 'package' => 'prepay_id='.$prepay_id, 'signType' => 'MD5' ); $data['paySign'] = self::makeSign($data); $this->ajaxReturn($data); }
小程式端程式碼:
wx.requestPayment({
'timeStamp': '',
'nonceStr': '',
'package': '',
'signType': 'MD5',
'paySign': '',
'success':function(res){
},
'fail':function(res){
}
})
伺服器回撥通知:我將完整的介面程式碼封裝成了一個類檔案,可以直接引入專案更改一下配置引數就可以使用的,原始碼下載:http://download.csdn.net/detail/sinat_35861727/9879682//微信支付回撥驗證 public function notify(){ $xml = $GLOBALS['HTTP_RAW_POST_DATA']; // 這句file_put_contents是用來檢視伺服器返回的XML資料 測試完可以刪除了 //file_put_contents(APP_ROOT.'/Statics/log2.txt',$res,FILE_APPEND); //將伺服器返回的XML資料轉化為陣列 $data = self::xml2array($xml); // 儲存微信伺服器返回的簽名sign $data_sign = $data['sign']; // sign不參與簽名演算法 unset($data['sign']); $sign = self::makeSign($data); // 判斷簽名是否正確 判斷支付狀態 if ( ($sign===$data_sign) && ($data['return_code']=='SUCCESS') && ($data['result_code']=='SUCCESS') ) { $result = $data; //獲取伺服器返回的資料 $order_sn = $data['out_trade_no']; //訂單單號 $openid = $data['openid']; //付款人openID $total_fee = $data['total_fee']; //付款金額 $transaction_id = $data['transaction_id']; //微信支付流水號 //更新資料庫 $this->updateDB($order_sn,$openid,$total_fee,$transaction_id); }else{ $result = false; } // 返回狀態給微信伺服器 if ($result) { $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; }else{ $str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[簽名失敗]]></return_msg></xml>'; } echo $str; return $result; }
小程式端完整程式碼如下:
/**
* 支付函式
* @param {[type]} _payInfo [description]
* @return {[type]} [description]
*/
pay:function(_payInfo,success,fail){
var payInfo = {
body:'',
total_fee:0,
order_sn:''
}
Object.assign(payInfo, _payInfo);
if(payInfo.body.length==0){
wx.showToast({
title:'支付資訊描述錯誤'
})
return false;
}
if(payInfo.total_fee==0){
wx.showToast({
title:'支付金額不能0'
})
return false;
}
if(payInfo.order_sn.length==0){
wx.showToast({
title:'訂單號不能為空'
})
return false;
}
var This = this;
This.getOpenid(function(openid){
payInfo.openid=openid;
This.request({
url:'api/pay/prepay',
data:payInfo,
success:function(res){
var data = res.data;
console.log(data);
if(!data.status){
wx.showToast({
title:data['errmsg']
})
return false;
}
This.request({
url:'api/pay/pay',
data:{prepay_id:data.data.data.prepay_id},
success:function(_payResult){
var payResult = _payResult.data;
console.log(payResult);
wx.requestPayment({
'timeStamp': payResult.timeStamp.toString(),
'nonceStr': payResult.nonceStr,
'package': payResult.package,
'signType': payResult.signType,
'paySign': payResult.paySign,
'success': function (succ) {
success&&success(succ);
},
'fail': function (err) {
fail&&fail(err);
},
'complete': function (comp) {
}
})
}
})
}
})
})
}