從前端的角度來梳理微信支付的流程
作者:張優(yōu)秀
來源:SegmentFault 思否社區(qū)
因業(yè)務(wù)需要,開發(fā)微信支付功能,涉及三種支付方式:
JSAPI 支付:微信內(nèi)網(wǎng)頁支付,需要開通微信服務(wù)號 小程序支付:在小程序中支付,需要開通小程序 H5 支付:在手機(jī)瀏覽器(出微信內(nèi)網(wǎng)爺)中網(wǎng)頁支付
微信支付-接入指引 微信支付-開發(fā)文檔
小程序支付
開發(fā)流程
小程序端請求創(chuàng)建訂單接口,后端統(tǒng)一下單獲取?orderId?并返回 小程序端獲取通過wx.login()獲取code 小程序端拿這code和orderId請求后端接口,獲取支付所需數(shù)據(jù) 獲取支付所需數(shù)據(jù)之后,小程序端調(diào)用wx.requestPayment()接口,直接調(diào)用起支付頁面 判斷是否支付成功后的邏輯
偽代碼
async?function?wxPay(goodId)?{
??//?1.?創(chuàng)建訂單?獲取orderId
??let?orderId?=?await?ajax("POST",?"/api/OrderProgram/CreateTheOrder",?{
????goodId,?//?商品id
??});
??//?2.?獲得?code
??let?code?=?await?wxlogin();?//?基于pr封裝的wx.login()方法
??//?3.?獲取支付的數(shù)據(jù)
??let?payData?=?await?ajax("POST",?"/api/OrderProgram/WxXcxPay",?{
????orderId,
????code,
??});
??//?4.?發(fā)起支付
??let?res?=?await?payment(payData);?//?基于pr封裝的wx.requestPayment()方法
??//?5.?判斷是否支付成功
??let?payResult?=?res.errMsg;
??if?(payResult?==?"requestPayment:ok")?{
????console.log("支付成功");
??}?else?if?(payResult?==?"requestPayment:fail?cancel")?{
????console.log("用戶取消支付");
??}?else?{
????console.log("支付失敗");
??}
}
注意事項(xiàng)
申請微信小程序賬號
申請成功可拿到 AppID(小程序 id)和 AppSecret(小程序密鑰)
申請類型為企業(yè)性質(zhì),否則無法接入微信支付微信小程序認(rèn)證
通過認(rèn)證的小程序才能接入微信支付和綁定商戶平臺(tái)申請商戶平臺(tái)賬號
需要第一步申請的 AppID
申請成功可拿到 MchID(商戶 id)和 MchKey(商戶密鑰)信小程序關(guān)聯(lián)商戶號
微信和商戶都認(rèn)證成功后,在微信后臺(tái)微信支付菜單中進(jìn)行關(guān)聯(lián)接入微信支付
在微信后臺(tái)微信支付菜單中進(jìn)行接入
參考
小程序支付文檔 小程序開發(fā)文檔
H5 支付
開發(fā)流程
前端端請求創(chuàng)建訂單接口,后端統(tǒng)一下單獲取?orderId?并返回 前端帶著?orderId?請求支付接口,獲得?mweb_url, 然后跳轉(zhuǎn)?mweb_url?會(huì)跳轉(zhuǎn)微信自動(dòng)調(diào)用微信支付 支付后返回支付頁,判斷是否支付成功(需發(fā)送請求后端查詢)
4.1 刷新頁面,獲取最新的支付(訂單)狀態(tài)。
4.2 設(shè)置一個(gè)的按鈕"我已支付",讓用戶點(diǎn)擊自動(dòng)查詢狀態(tài)。
偽代碼
async?function?wxH5Pay(goodId)?{
??//?1.?創(chuàng)建訂單?獲取orderId
??let?orderId?=?await?ajax("POST",?"/api/OrderProgram/CreateTheOrder",?{
????goodId,?//?商品id
??});
??//?2.?獲取支付跳轉(zhuǎn)的URL
??let?mweb_url?=?await?ajax("POST",?"/api/OrderProgram/WxH5Pay",?{?orderId?});
??//?3.?跳轉(zhuǎn)URL去微信支付
??if?(mweb_url)?{
????location.href?=?mweb_url;
??}?else?{
????console.log("回調(diào)地址出錯(cuò)");
??}
??//?4.?支付后返回支付頁,判斷是否支付成功
??// 4.1 刷新頁面,獲取最新的訂單(商品)狀態(tài)。
??//?4.2?設(shè)置一個(gè)"我已支付"的按鈕,讓用戶點(diǎn)擊之后查詢狀態(tài)。
}
注意事項(xiàng)
在商戶平臺(tái)設(shè)置正確的支付域名 調(diào)試需要在線上,如果嫌麻煩可以使用內(nèi)網(wǎng)穿透(Ngrok 或花生殼) 需對redirect_url進(jìn)行urlencode處理 H5 支付不能直接在微信客戶端內(nèi)調(diào)起,請?jiān)谕獠繛g覽器調(diào)起。
參考
微信支付-H5 支付-開發(fā)步驟
JSAPI 支付(微信內(nèi)網(wǎng)頁支付)
開發(fā)流程
商品頁
前端商品頁創(chuàng)建訂單,在后端統(tǒng)一下單后獲取?orderId 前端帶著?orderId?跳轉(zhuǎn)到支付頁,
支付頁
獲取?code 第一次進(jìn)入頁面,判斷是否路徑中有?code 沒有?code,請求數(shù)據(jù)跳轉(zhuǎn)授權(quán)頁面,code?會(huì)通過回調(diào)地址一起返回回來 拿到 code,發(fā)送給后端,后端解析到 openid,保存好。 點(diǎn)擊確定支付按鈕,觸發(fā)?wxPay()?方法 發(fā)送?orderId?給后端,獲取?wxData wxData 中包含 wx.config 和 wx.chooseWXPay 兩個(gè)接口的數(shù)據(jù)。 先調(diào)用 wx.config()然后在調(diào)用 wx.chooseWXPay(),如果一切正常,支付頁面就會(huì)彈出。 支付狀態(tài)通過后端去查詢
偽代碼
商品頁
//?1.?創(chuàng)建訂單?獲取orderId
let?orderId?=?await?ajax("POST",?"/api/OrderProgram/CreateTheOrder",?{
??goodId,?//?商品id
});
//?2.?攜帶id?跳轉(zhuǎn)到支付頁
this.$router.push({?name:?"wx_pay_page",?params:?{?orderId:?id?}?});
入口文件(main.js)
//?main.js?引入?js-sdk
import?wx?from?"weixin-js-sdk";
支付頁 HTML
??
????
??
//?Vue
data(){
????return?{
????????orderId:?this.$route.params.orderId,?//?訂單id
????????url:?'',//?獲取code的url
????????wxData:?null,//?js-sdk接口所需的數(shù)據(jù)
????}
},
mounted(){
????//?判斷是否有code
????this.getCode()
}
methods:?{
????getCode()?{
????????var?code?=?this.getUrlPram("code");
????????if?(code?!=?null)?{
????????????this.code?=?code;
????????????//?拿到?code?發(fā)給?后端
????????????this.sendCode(code);
????????}?else?{
????????????//?去拿code
????????????this.getUrl();
????????}
????},
????getUrl()?{
????????//?請求后端拿到url所需數(shù)據(jù),然后跳轉(zhuǎn)頁面在通過回調(diào)地址返回,獲取code.
????????this.axios
????????????.post("/api/OrderProgram/GetOpenidAndAccessToken",?{
????????????????orderId:?this.orderId,
????????????})
????????????.then((data)?=>?{
????????????????this.url?=?`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${data.appId}&redirect_uri=${data.redirect_uri}&response_type=${data.response_type}&scope=${data.scope}&state=${data.state}`;
????????????????window.location.href?=?this.url;
????????????})
????????????.catch((err)?=>?{
????????????????console.log(err);
????????????});
????},
????sendCode(code)?{
????????//?發(fā)送code給后端?后端解析出openid
????????this.axios
????????????.post("/api/OrderProgram/GetOpenidAndAccessTokenFromCode",?{
????????????????code:?code,
????????????})
????????????.then((res)?=>?{
????????????????console.log(res);
????????????})
????????????.catch((err)?=>?{
????????????????console.log(err);
????????????});
????},
????wxPay:?async?function()?{
????????//?發(fā)送orderid,獲取wx.chooseWXPay和wx.config所需的參數(shù)
????????this.wxData?=?await?this.axios.post(
????????????"/api/OrderProgram/WxJSAPIPay",
????????????{?orderId:?this.orderId?}
????????);
????????let?wxConfigData?=?this.wxData.wxConfigData?//?獲取wx.chooseWXPay()所需數(shù)據(jù)
????????let?wxPayData?=?this.wxData.wxPayData;//?獲取wx.config()所需數(shù)據(jù)
????????this.$wx.config({
????????????debug:?false,?//?開啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來,若要查看傳入的參數(shù),可以在pc端打開,參數(shù)信息會(huì)通過log打出,僅在pc端時(shí)才會(huì)打印。
????????????appId:?wxConfigData.appId,?//?必填,公眾號的唯一標(biāo)識
????????????timestamp:?wxConfigData.timeStamp,?//?必填,生成簽名的時(shí)間戳
????????????nonceStr:?wxConfigData.nonceStr,?//?必填,生成簽名的隨機(jī)串
????????????signature:?wxConfigData.paySign,?//?必填,簽名
????????????jsApiList:?[
????????????????"chooseWXPay",
????????????],
????????});
????????//?執(zhí)行支付
????????this.$wx.chooseWXPay({
??????????? timestamp: wxPayData.timeStamp, //?支付簽名時(shí)間戳,注意微信jssdk中的所有使用timestamp字段均為小寫。但最新版的支付后臺(tái)生成簽名使用的timeStamp字段名需大寫其中的S字符
????????????nonceStr:?wxPayData.nonceStr,?//?支付簽名隨機(jī)串,不長于?32?位
??????????? package: wxPayData.package, //?統(tǒng)一支付接口返回的prepay_id參數(shù)值,提交格式如:prepay_id=\*\*\*)
????????????signType:?wxPayData.signType,?//?簽名方式,默認(rèn)為'SHA1',使用新版支付需傳入'MD5'
????????????paySign:?wxPayData.paySign,?//?支付簽名
????????????success:?(res)?=>?{
????????????????this.$toast("支付成功");
????????????},
????????????fail:?(err)?=>?{
????????????????this.$toast("支付失敗");
????????????},
????????});
????},
}
同時(shí)支持 H5 支付和 JSAPI 支付
//?在創(chuàng)建訂單之后,就判斷環(huán)境使用哪種方法支付。
if?(isWx())?{
??this.WXPay(orderId);?//?帶著orderId跳轉(zhuǎn)到支付頁邏輯
}?else?{
??this.H5Pay(orderId);?//?執(zhí)行上面H5支付中的創(chuàng)建訂單之后的邏輯
}
//?判斷是否是微信瀏覽器
function?isWx()?{
??let?uAgent?=?navigator.userAgent.toLowerCase();
??reutrn(/micromessenger/.test(uAgent))???true?:?false;
}
注意事項(xiàng)
開通微信商戶號 - 設(shè)置支付目錄(如果是 Vue 這類 SPA 頁面,到根目錄即可,也就是#號之前的地址) 
開通微信公眾號(服務(wù)號) - 設(shè)置安全域名、設(shè)置授權(quán)域名 
收集參數(shù):appId 和 AppSecret 添加 Web 開發(fā)工具開發(fā)者(需要開發(fā)者同時(shí)開發(fā)者關(guān)注開發(fā)的微信公眾號和微信公眾賬號安全助手)參考文檔
[圖片上傳失敗...(image-b07878-1605777597831)]設(shè)置回調(diào)域名(例如:www.xx.com/pay,最后獲取的 code 會(huì)拼在此回調(diào)地址后返回,返回后如www.xx.com/pay?code=xxxx)參考 1 
獲取 code 參考獲取 code 文檔 在微信客戶端網(wǎng)頁打開授權(quán)地址,跳轉(zhuǎn)之后,在返回的回調(diào)地址之后拿到 code:
https://open.weixin.qq.com/connect/oauth2/authorize
?appid=你的appid
&redirect_uri=你的回調(diào)地址(拿到code后返回)
&response_type=code(返回類型,默認(rèn)code)
&scope=snsapi_base(授權(quán)范圍,靜默授權(quán)拿到openid)
&state=STATE(自定義狀態(tài),非必填)
#wechat_redirect(重定向使用必須攜帶)
前端引入 js-skd 使用script引入js-sdk 下載使用?npm?包weixin-js-sdk 獲取?wx.config?的參數(shù) 
獲取?wx.chooseWXPay?所需的參數(shù) 
總結(jié)

評論
圖片
表情
