微信小程式支付流程
阿新 • • 發佈:2020-09-20
首先,先把官網的流程圖放上來,然後按照圖一步步的來。
第一步:使用者請求開發者後臺,發起下單請求
- 發起請求前在小程式端呼叫
wx.checkSession()
檢視session_key
是否過期- 如果過期了 重新呼叫
wx.login()
返回session_key
和openid
- 如果沒過期 繼續下一步操作,請求開發者後臺
- 如果過期了 重新呼叫
第二步:開發者查詢一下資料庫或者快取裡是否有openid
和session_key
- 如果有生成訂單編號
out_trade_no
- 如果沒有返回錯誤訊息,缺少
openid
、session_key
第三步:開發者伺服器請求統一下單API
,帶上要求的引數:
appid
mch_id
nonce_str
sign
body
out_trade_no
total_fee
spbill_create_ip
nonce_str
獲取隨機字串:
js
/* * 功能: 返回32位隨機字串 * create by tiankai on 2018-06-25 15:39 */ getNonceStr(){ let char = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; let len = 32; let result = ''; for(let i = 0; i < len; i++){ let randomNum = Math.floor(Math.random()*char.length); result += char[randomNum]; } return result; }
sign
引數簽名, 第二個tab(js)是呼叫函式的方法,key
為商戶平臺設定的金鑰key
- js
- js
/* * 功能:sign 引數簽名 * create by tiankai on 2018-06-26 12:00 */ async makeSign(params, key){ // 生成簽名 sign let strOrderArr = Object.keys(params).sort(); let stringA= ""; strOrderArr.map(val =>{ //如果引數值為空,或者驗證返回的 sign 不參與簽名 if( think.isNullOrUndefined(params[val]) || val === 'sign' || params[val].length === 0 ) return; stringA += val + "=" + params[val] + "&"; }); let stringSignTemp = stringA + "key=" + key; let sign = think.md5(stringSignTemp).toUpperCase(); return sign; }
得到這幾個引數就開始發起請求統一下單 API 了,這裡需要注意的是,請求引數應該以xml
的形式傳送過去,這裡藉助一個工具xml2js
把物件轉換為 xml,也可以把 xml 轉換為 物件、json。
安裝xml2js
npm i xml2js
使用xml2js
js
const xml2js = require('xml2js'); //xml->json //xml2js預設會把子子節點的值變為一個數組, explicitArray設定為false var xmlParser = new xml2js.Parser({explicitArray : false, ignoreAttrs : true}) //json->xml var jsonBuilder = new xml2js.Builder();
請求引數轉換為 xml
test.jsjs
/* * 功能:獲取統一下單 API 請求XML引數 * create by tiankai on 2018-06-25 15:23 */ async getUnifiedOrderParams(){ let signString = { appid: config.appid, mch_id: config.mchid, nonce_str: await this.getNonceStr(), body: '簡訊平臺-簡訊套餐購買', out_trade_no: '20180926125346',//訂單號 total_fee: 88,//訂單金額 //APP和網頁支付提交使用者端ip,Native支付填呼叫微信支付API的機器IP //需要自行獲取,這裡只是為了測試直接寫上了 spbill_create_ip: '123.12.12.123', notify_url: config.notify_url, trade_type: 'JSAPI', openid: await think.cache('openId') } let sign = await this.makeSign(signString,config.key); signString.sign = sign; /* console.log("--------------------------"); * console.log(sign); * console.log("--------------------------"); */ let xml = await jsonBuilder.buildObject(signString); /* console.log(xml); */ return xml; }
然後就可以發起統一下單API請求了
test.jsjs
/* * 功能:呼叫統一下單API介面 * create by tiankai on 2018-06-26 11:01 */ async unifiedOrder(){ let xmlParams = await this.getUnifiedOrderParams(); let unifiedOrderUrl = config.unifiedOrderUrl; let opt = { method: "POST", mode: 'cors', headers: { 'content-type': 'text/xml' }, body: xmlParams } let res = await this.fetch(unifiedOrderUrl, opt); //這裡微信返回的也是 xml let result = await res.text(); let data = null; // 微信返回的 XML 轉換為 JSON xmlParser.parseString(result,function(err, jsonData){ if(!err){ /* console.log(jsonData); */ data = jsonData; } }); return data; }
第四步:當請求成功時 判斷一下return_code
和result_code
- 如果它們都等於
SUCCESS
的時候,微信會把我們需要的預支付訂單資訊prepay_id
返回來, - 否則返回
return_msg
給前端 展示具體錯誤
第五步:拿上prepay_id
,進行再次簽名,然後返回給前端
js
/* * 功能:統一下單介面返回 prepay_id 再次簽名 返回給前端 * create by tiankai on 2018-06-26 15:45 */ async payParams(){ let signString = { appid: config.appid, timeStamp: +new Date(), nonce_str: await this.getNonceStr(), package: null, signType: 'MD5' } //呼叫 統一下單 API let jsonData = await this.unifiedOrder(); if(think.isNullOrUndefined(jsonData) && jsonData.xml.return_code === 'SUCCESS' && jsonData.xml.result_code === 'SUCCESS' ){ signString.package = 'perpay_id='+jsonData.xml.perpay_id }else{ return jsonData.xml.return_msg; } //進行再次簽名 let paySign = await this.makeSign(signString,config.key); signString.paySign = paySign; let { appid, signType, ...result } = signString; // result 中不包括 appid 和 signType 返回給前端 return result; }
第六步:使用者確認支付後,小程式端呼叫支付介面,根據返回結果提示使用者
test.jsjs
wx.requestPayment({ 'timeStamp': '', 'nonceStr': '',//後端返回的隨機字串 'package': '',//後端返回的 'signType': 'MD5', 'paySign': '',//後端返回的 'success':function(res){ }, 'fail':function(res){ } });
第七步:支付成功後,微信伺服器會把支付結果返回給配置的notify_url
,開發者根據支付結果,更新伺服器的訂單狀態。