知識(shí)
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們?cè)谧非笃湟曈X(jué)表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營(yíng)銷(xiāo)的便利,運(yùn)營(yíng)的高效,讓網(wǎng)站成為營(yíng)銷(xiāo)工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!
您當(dāng)前位置>首頁(yè) » 新聞資訊 » 小程序相關(guān) >
從前端的角度來(lái)梳理微信支付(小程序、H5、JSAPI)的流程
發(fā)表時(shí)間:2021-1-5
發(fā)布人:葵宇科技
瀏覽次數(shù):152
因業(yè)務(wù)需要,開(kāi)發(fā)微信支付功能,涉及三種支付方式:
- JSAPI 支付:微信內(nèi)網(wǎng)頁(yè)支付,需要開(kāi)通微信服務(wù)號(hào)
- 小程序支付:在小程序中支付,需要開(kāi)通小程序
- H5 支付:在手機(jī)瀏覽器(出微信內(nèi)網(wǎng)爺)中網(wǎng)頁(yè)支付
使用微信支付的前提必開(kāi)通微信商戶號(hào),要使用到那種的支付方式要前需在商戶平臺(tái)開(kāi)通(要審核)。
支付的錢(qián)最終都會(huì)到商戶號(hào)里(一般由公司財(cái)務(wù)開(kāi)通)。
開(kāi)發(fā)微信支付的過(guò)程中大大小小坑還是踩了不少,終于做完了,整理下開(kāi)發(fā)流程。
參考:
- 微信支付-接入指引
- 微信支付-開(kāi)發(fā)文檔
小程序支付
開(kāi)發(fā)流程
- 小程序端請(qǐng)求創(chuàng)建訂單接口,后端統(tǒng)一下單獲取
orderId
并返回 - 小程序端獲取通過(guò)wx.login()獲取
code
- 小程序端拿這
code
和orderId
請(qǐng)求后端接口,獲取支付所需數(shù)據(jù) - 獲取支付所需數(shù)據(jù)之后,小程序端調(diào)用wx.requestPayment()接口,直接調(diào)用起支付頁(yè)面
- 判斷是否支付成功后的邏輯
偽代碼
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 = http://www.wxapp-union.com/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)
- 申請(qǐng)微信小程序賬號(hào)
申請(qǐng)成功可拿到 AppID(小程序 id)和 AppSecret(小程序密鑰)
申請(qǐng)類(lèi)型為企業(yè)性質(zhì),否則無(wú)法接入微信支付 - 微信小程序認(rèn)證
通過(guò)認(rèn)證的小程序才能接入微信支付和綁定商戶平臺(tái) - 申請(qǐng)商戶平臺(tái)賬號(hào)
需要第一步申請(qǐng)的 AppID
申請(qǐng)成功可拿到 MchID(商戶 id)和 MchKey(商戶密鑰) - 信小程序關(guān)聯(lián)商戶號(hào)
微信和商戶都認(rèn)證成功后,在微信后臺(tái)微信支付菜單中進(jìn)行關(guān)聯(lián) - 接入微信支付
在微信后臺(tái)微信支付菜單中進(jìn)行接入
參考
- 小程序支付文檔
- 小程序開(kāi)發(fā)文檔
H5 支付
開(kāi)發(fā)流程
- 前端端請(qǐng)求創(chuàng)建訂單接口,后端統(tǒng)一下單獲取
orderId
并返回 - 前端帶著
orderId
請(qǐng)求支付接口,獲得mweb_url
, - 然后跳轉(zhuǎn)
mweb_url
會(huì)跳轉(zhuǎn)微信自動(dòng)調(diào)用微信支付 - 支付后返回支付頁(yè),判斷是否支付成功(需發(fā)送請(qǐng)求后端查詢)
4.1 刷新頁(yè)面,獲取最新的支付(訂單)狀態(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 = http://www.wxapp-union.com/mweb_url;
} else {
console.log("回調(diào)地址出錯(cuò)");
}
// 4. 支付后返回支付頁(yè),判斷是否支付成功
// 4.1 刷新頁(yè)面,獲取最新的訂單(商品)狀態(tài)。
// 4.2 設(shè)置一個(gè)"我已支付"的按鈕,讓用戶點(diǎn)擊之后查詢狀態(tài)。
}
注意事項(xiàng)
- 在商戶平臺(tái)設(shè)置正確的支付域名
- 調(diào)試需要在線上,如果嫌麻煩可以使用內(nèi)網(wǎng)穿透(Ngrok 或花生殼)
- 需對(duì)
redirect_url
進(jìn)行urlencode
處理 - H5 支付不能直接在微信客戶端內(nèi)調(diào)起,請(qǐng)?jiān)谕獠繛g覽器調(diào)起。
參考
- 微信支付-H5 支付-開(kāi)發(fā)步驟
JSAPI 支付(微信內(nèi)網(wǎng)頁(yè)支付)
開(kāi)發(fā)流程
- 商品頁(yè)
- 前端商品頁(yè)創(chuàng)建訂單,在后端統(tǒng)一下單后獲取
orderId
- 前端帶著
orderId
跳轉(zhuǎn)到支付頁(yè),
- 支付頁(yè)
獲取
code
- 第一次進(jìn)入頁(yè)面,判斷是否路徑中有
code
- 沒(méi)有
code
,請(qǐng)求數(shù)據(jù)跳轉(zhuǎn)授權(quán)頁(yè)面,code
會(huì)通過(guò)回調(diào)地址一起返回回來(lái) - 拿到
code
,發(fā)送給后端,后端解析到openid
,保存好。
- 第一次進(jìn)入頁(yè)面,判斷是否路徑中有
點(diǎn)擊確定支付按鈕,觸發(fā)
wxPay()
方法- 發(fā)送
orderId
給后端,獲取wxData
wxData
中包含wx.config
和wx.chooseWXPay
兩個(gè)接口的數(shù)據(jù)。- 先調(diào)用
wx.config()
然后在調(diào)用wx.chooseWXPay()
,如果一切正常,支付頁(yè)面就會(huì)彈出。
- 發(fā)送
- 支付狀態(tài)通過(guò)后端去查詢
偽代碼
- 商品頁(yè)
// 1. 創(chuàng)建訂單 獲取orderId
let orderId = await ajax("POST", "/api/OrderProgram/CreateTheOrder", {
goodId, // 商品id
});
// 2. 攜帶id 跳轉(zhuǎn)到支付頁(yè)
this.$router.push({ name: "wx_pay_page", params: { orderId: id } });
- 入口文件(
main.js
)
// main.js 引入 js-sdk
import wx from "weixin-js-sdk";
- 支付頁(yè) HTML
<template>
<div>
<button @click="wxPay">點(diǎn)擊支付button>
div>
template>
支付頁(yè) JS
// 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() {
// 請(qǐng)求后端拿到url所需數(shù)據(jù),然后跳轉(zhuǎn)頁(yè)面在通過(guò)回調(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 = http://www.wxapp-union.com/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 = http://www.wxapp-union.com/await this.axios.post(
"/api/OrderProgram/WxJSAPIPay",
{ orderId: this.orderId }
);
let wxConfigData = http://www.wxapp-union.com/this.wxData.wxConfigData // 獲取wx.chooseWXPay()所需數(shù)據(jù)
let wxPayData = http://www.wxapp-union.com/this.wxData.wxPayData;// 獲取wx.config()所需數(shù)據(jù)
this.$wx.config({
debug: false, // 開(kāi)啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來(lái),若要查看傳入的參數(shù),可以在pc端打開(kāi),參數(shù)信息會(huì)通過(guò)log打出,僅在pc端時(shí)才會(huì)打印。
appId: wxConfigData.appId, // 必填,公眾號(hào)的唯一標(biāo)識(shí)
timestamp: wxConfigData.timeStamp, // 必填,生成簽名的時(shí)間戳
nonceStr: wxConfigData.nonceStr, // 必填,生成簽名的隨機(jī)串
signature: wxConfigData.paySign, // 必填,簽名
jsApiList: [
"chooseWXPay",
],
});
// 執(zhí)行支付
this.$wx.chooseWXPay({
timestamp: wxPayData.timeStamp, // 支付簽名時(shí)間戳,注意微信jssdk中的所有使用timestamp字段均為小寫(xiě)。但最新版的支付后臺(tái)生成簽名使用的timeStamp字段名需大寫(xiě)其中的S字符
nonceStr: wxPayData.nonceStr, // 支付簽名隨機(jī)串,不長(zhǎng)于 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)到支付頁(yè)邏輯
} else {
this.H5Pay(orderId); // 執(zhí)行上面H5支付中的創(chuàng)建訂單之后的邏輯
}
// 判斷是否是微信瀏覽器
function isWx() {
let uAgent = navigator.userAgent.toLowerCase();
reutrn(/micromessenger/.test(uAgent)) ? true : false;
}
注意事項(xiàng)
- 開(kāi)通微信商戶號(hào) - 設(shè)置支付目錄(如果是 Vue 這類(lèi) SPA 頁(yè)面,到根目錄即可,也就是#號(hào)之前的地址)
- 開(kāi)通微信公眾號(hào)(服務(wù)號(hào)) - 設(shè)置安全域名、設(shè)置授權(quán)域名
- 收集參數(shù):appId 和 AppSecret
- 添加 Web 開(kāi)發(fā)工具開(kāi)發(fā)者(需要開(kāi)發(fā)者同時(shí)開(kāi)發(fā)者關(guān)注開(kāi)發(fā)的微信公眾號(hào)和微信公眾賬號(hào)安全助手)
[圖片上傳失敗...(image-b07878-1605777597831)] - 設(shè)置回調(diào)域名(例如:
www.xx.com/pay
,最后獲取的 code 會(huì)拼在此回調(diào)地址后返回,返回后如www.xx.com/pay?code=xxxx
) 獲取 code
- 參考獲取 code 文檔
- 在微信客戶端網(wǎng)頁(yè)打開(kāi)授權(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(返回類(lèi)型,默認(rèn)code)
&scope=snsapi_base(授權(quán)范圍,靜默授權(quán)拿到openid)
&state=STATE(自定義狀態(tài),非必填)
#wechat_redirect(重定向使用必須攜帶)
redirect_uri
參數(shù)要和你在微信公眾號(hào)里設(shè)置的回調(diào)域名一致(例如:www.xx.com/pay
),需要注意的是這 url 需要urlEncode
。
請(qǐng)求這個(gè)地址之后,code
會(huì)以你設(shè)置的redirect_uri
地址里的參數(shù)帶回來(lái),拿到之后傳給后端就行了。
前端引入 js-skd
- 使用
script
引入js-sdk - 下載使用
npm
包weixin-js-sdk
- 使用
參考
- 微信支付-JSAPI
- 微信公眾號(hào)-網(wǎng)頁(yè)授權(quán)
- JS-SDK 開(kāi)發(fā)文檔
總結(jié)
整個(gè)流程走下來(lái),給我的體驗(yàn)是:小程序支付最方面(因?yàn)榕渲蒙伲浯问?H5,JSAPI 支付最麻煩(文章一多半都在寫(xiě)它)
在微信支付功能開(kāi)發(fā)過(guò)程中,其實(shí)最麻煩的不是開(kāi)發(fā)流程,而是他的各種配置和授權(quán)流程,為了拿到所需的參數(shù)而來(lái)回折騰。
開(kāi)發(fā)過(guò)程中的一些參數(shù)是經(jīng)常用到的,如 appid、openid、orderId
支付流程大徑相同,先獲取到用戶的 openid,知道你是誰(shuí),然后統(tǒng)一下單拿到 orderId 再去處理不同平臺(tái)的支付方式
開(kāi)發(fā)時(shí)候用到的相關(guān)文檔,一定要仔細(xì)閱讀二遍以上為止?。?/p>
相關(guān)案例查看更多
相關(guān)閱讀
- 云南網(wǎng)站建設(shè)制作
- 小程序公司
- 定制小程序開(kāi)發(fā)
- 小程序開(kāi)發(fā)
- 云南etc微信小程序
- flex
- vue開(kāi)發(fā)小程序
- 云南網(wǎng)絡(luò)推廣
- 云南網(wǎng)站建設(shè)首選
- 云南網(wǎng)站建設(shè)公司
- 網(wǎng)站排名
- 報(bào)廢車(chē)回收管理系統(tǒng)
- 軟件定制
- php網(wǎng)站
- python開(kāi)發(fā)小程序
- 云南小程序開(kāi)發(fā)課程
- 云南小程序開(kāi)發(fā)
- 微分銷(xiāo)
- 公眾號(hào)模板消息
- 云南小程序開(kāi)發(fā)公司
- 網(wǎng)站建設(shè)價(jià)格
- web前端
- 云南小程序開(kāi)發(fā)推薦
- 網(wǎng)絡(luò)營(yíng)銷(xiāo)
- 云南網(wǎng)站建設(shè)方法
- 云南網(wǎng)站開(kāi)發(fā)哪家好
- 百度小程序開(kāi)發(fā)
- 小程序模板開(kāi)發(fā)公司
- 退款
- 網(wǎng)站建設(shè)靠譜公司