微信小程式支付流程,非同步回撥及訊息模板呼叫(php原始碼)
阿新 • • 發佈:2018-12-11
首先還是老樣子把流程圖給大家發一下
商戶系統和微信支付系統主要互動:
1、小程式內呼叫登入介面,獲取到使用者的openid,api參見公共api【小程式登入API】
2、商戶server呼叫支付統一下單,api參見公共api【統一下單API】
3、商戶server呼叫再次簽名,api參見公共api【再次簽名】
4、商戶server接收支付通知,api參見公共api【支付結果通知API】
5、商戶server查詢支付結果,api參見公共api【查詢訂單API】
獲取openid首先客戶端要呼叫wx.login()方法,得到code傳給伺服器端,伺服器接收code通過 wx.code2Session()獲取openid及其他引數,php程式碼如下:
public function login(Request $request){ $code = $request -> get('code'); $url = 'https://api.weixin.qq.com/sns/jscode2session'; $str = 'appid='.self::appid.'&secret='.self::secret.'&js_code='.$code.'&grant_type=authorization_code'; $new_url = $url.'?'.$str; $res = $this -> curlRequest($new_url); $res = json_decode($res,true); if(empty($res['openid'])){ return json_encode(['status'=>1,'content'=>$res['errmsg']]); } $openid = $res['openid']; $session_key = $res['session_key']; $token = uniqid(); $arr = [ 'openid' => $openid, 'session_key' => $session_key, 'token' => $token, 'money' => 0, 'status' => 1 ]; $data = DB::table('mobai_token')->where('openid',$openid)->first(); if(empty($data)){ DB::table('mobai_token')->insert($arr); return json_encode(['status'=>0,'content'=>$token]); } $token = $data->token; return json_encode(['status'=>0,'content'=>$token]); }
呼叫統一下單介面並返回wx.requestPayment()所需的引數(注意生成paySign的時候一定要按規則生成)
//調取統一下單介面 public function unpay(Request $request){ $order = $request->get('rtime'); $money = $request->get('money'); $data = DB::table('mobai_order')->where('rtime',$order)->first(); $openid = $data->openid; $unurl = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $params = [ 'appid' => self::appid, 'mch_id' => self::mch_id, 'nonce_str' => uniqid(), 'body' => '摩拜單車', 'out_trade_no' => $order, 'total_fee' => $money, 'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], 'notify_url' => 'https://mobai.xxxx.cn/notify',//此處寫你的回撥地址 'trade_type' => 'JSAPI', 'openid' => $openid, ]; $params['sign'] = $this -> getSign($params); $xml = $this -> ArrToXml($params); $res = $this -> curlRequest($unurl,$xml); $arr = $this -> XmlToArr($res); $params2 = [ 'appId' => self::appid, 'timeStamp' => strval(time()), //建議把時間戳轉變成字串 'nonceStr' => uniqid(), 'package' => 'prepay_id='.$arr['prepay_id'], 'signType' => 'MD5' ]; $params2['paySign'] = $this -> getSign($params2); $params2['prepay_id'] = $arr['prepay_id']; $redis = new \Redis(); $redis -> connect('127.0.0.1',6379); $redis -> set($order,$arr['prepay_id']); //儲存prepay_id,呼叫模板訊息的時候需要 return $params2; }
非同步回撥
public function notify(){
$data = file_get_contents('php://input');
$arr = $this -> XmlToArr($data);
$sign = $this -> getSign($arr);
if($sign == $arr['sign']){
//判斷返回狀態
if($arr['return_code'] == 'SUCCESS' || $arr['result_code'] == 'SUCCESS'){
$data = DB::table('mobai_order')->where('rtime',$arr['out_trade_no'])->where('status',1)->first();
//判斷訂單金額
if($data->money == $arr['total_fee']){
//修改訂單狀態
$res = DB::table('mobai_order')->where('rtime',$arr['out_trade_no'])->where('status',1)->update(['status'=>2]);
if($res){
$redis = new \Redis();
$redis -> connect('127.0.0.1',6379);
$prepay_id = $redis -> get($arr['out_trade_no']); //prepay_id要在統一下單的時候做儲存
$money = $arr['total_fee']/100;
$this -> sendTemplateMessage($prepay_id,$arr['out_trade_no'],$money,$arr['openid']); //傳送模板訊息
echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';//給微信正常相應(如果沒有正常相應微信會根據自己的機制多次請求)
}
}
}
}
}
getSign()、XmlToArr()、ArrToXml()方法可以在這個部落格看:https://blog.csdn.net/weixin_42579642/article/details/84861502