從前端的角度來梳理微信支付(小程序、H五、JSAPI)的流程

因業務須要,開發微信支付功能,涉及三種支付方式:php

  • JSAPI 支付:微信內網頁支付,須要開通微信服務號
  • 小程序支付:在小程序中支付,須要開通小程序
  • H5 支付:在手機瀏覽器(出微信內網爺)中網頁支付

使用微信支付的前提必開通微信商戶號,要使用到那種的支付方式要前需在商戶平臺開通(要審覈)。html

支付的錢最終都會到商戶號裏(通常由公司財務開通)。前端

開發微信支付的過程當中大大小小坑仍是踩了很多,終於作完了,整理下開發流程。ios

參考:web

小程序支付

開發流程

  1. 小程序端請求建立訂單接口,後端統一下單獲取 orderId 並返回
  2. 小程序端獲取經過wx.login()獲取code
  3. 小程序端拿這codeorderId請求後端接口,獲取支付所需數據
  4. 獲取支付所需數據以後,小程序端調用wx.requestPayment()接口,直接調用起支付頁面
  5. 判斷是否支付成功後的邏輯

僞代碼

async function wxPay(goodId) {
  // 1. 建立訂單 獲取orderId
  let orderId = await ajax("POST", "/api/OrderProgram/CreateTheOrder", {
    goodId, // 商品id
  });
  // 2. 得到 code
  let code = await wxlogin(); // 基於pr封裝的wx.login()方法
  // 3. 獲取支付的數據
  let payData = await ajax("POST", "/api/OrderProgram/WxXcxPay", {
    orderId,
    code,
  });
  // 4. 發起支付
  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("支付失敗");
  }
}

注意事項

  1. 申請微信小程序帳號
    申請成功可拿到 AppID(小程序 id)和 AppSecret(小程序密鑰)
    申請類型爲企業性質,不然沒法接入微信支付
  2. 微信小程序認證
    經過認證的小程序才能接入微信支付和綁定商戶平臺
  3. 申請商戶平臺帳號
    須要第一步申請的 AppID
    申請成功可拿到 MchID(商戶 id)和 MchKey(商戶密鑰)
  4. 信小程序關聯商戶號
    微信和商戶都認證成功後,在微信後臺微信支付菜單中進行關聯
  5. 接入微信支付
    在微信後臺微信支付菜單中進行接入

參考

H5 支付

開發流程

  1. 前端端請求建立訂單接口,後端統一下單獲取 orderId 並返回
  2. 前端帶着 orderId 請求支付接口,得到 mweb_url
  3. 而後跳轉 mweb_url 會跳轉微信自動調用微信支付
  4. 支付後返回支付頁,判斷是否支付成功(需發送請求後端查詢)
    4.1 刷新頁面,獲取最新的支付(訂單)狀態。
    4.2 設置一個的按鈕"我已支付",讓用戶點擊自動查詢狀態。

僞代碼

async function wxH5Pay(goodId) {
  // 1. 建立訂單 獲取orderId
  let orderId = await ajax("POST", "/api/OrderProgram/CreateTheOrder", {
    goodId, // 商品id
  });
  // 2. 獲取支付跳轉的URL
  let mweb_url = await ajax("POST", "/api/OrderProgram/WxH5Pay", { orderId });
  // 3. 跳轉URL去微信支付
  if (mweb_url) {
    location.href = mweb_url;
  } else {
    console.log("回調地址出錯");
  }
  // 4. 支付後返回支付頁,判斷是否支付成功
  // 4.1 刷新頁面,獲取最新的訂單(商品)狀態。
  // 4.2 設置一個"我已支付"的按鈕,讓用戶點擊以後查詢狀態。
}

注意事項

  • 在商戶平臺設置正確的支付域名
  • 調試須要在線上,若是嫌麻煩可使用內網穿透(Ngrok 或花生殼)
  • 需對redirect_url進行urlencode處理
  • H5 支付不能直接在微信客戶端內調起,請在外部瀏覽器調起。

參考

JSAPI 支付(微信內網頁支付)

開發流程

  • 商品頁
  1. 前端商品頁建立訂單,在後端統一下單後獲取 orderId
  2. 前端帶着 orderId 跳轉到支付頁,
  • 支付頁
  1. 獲取 codeajax

    1. 第一次進入頁面,判斷是否路徑中有 code
    2. 沒有 code,請求數據跳轉受權頁面,code 會經過回調地址一塊兒返回回來
    3. 拿到 code,發送給後端,後端解析到 openid,保存好。
  2. 點擊肯定支付按鈕,觸發 wxPay() 方法npm

    1. 發送 orderId 給後端,獲取 wxData
    2. wxData 中包含 wx.configwx.chooseWXPay 兩個接口的數據。
    3. 先調用 wx.config()而後在調用 wx.chooseWXPay(),若是一切正常,支付頁面就會彈出。
  3. 支付狀態經過後端去查詢

僞代碼

  • 商品頁
// 1. 建立訂單 獲取orderId
let orderId = await ajax("POST", "/api/OrderProgram/CreateTheOrder", {
  goodId, // 商品id
});
// 2. 攜帶id 跳轉到支付頁
this.$router.push({ name: "wx_pay_page", params: { orderId: id } });
  • 入口文件(main.js)
// main.js 引入 js-sdk
import wx from "weixin-js-sdk";
  • 支付頁 HTML
<template>
  <div>
    <button @click="wxPay">點擊支付</button>
  </div>
</template>

支付頁 JSaxios

// Vue
data(){
    return {
        orderId: this.$route.params.orderId, // 訂單id
        url: '',// 獲取code的url
        wxData: null,// js-sdk接口所需的數據
    }
},
mounted(){
    // 判斷是否有code
    this.getCode()
}
methods: {
    getCode() {
        var code = this.getUrlPram("code");
        if (code != null) {
            this.code = code;
            // 拿到 code 發給 後端
            this.sendCode(code);
        } else {
            // 去拿code
            this.getUrl();
        }
    },
    getUrl() {
        // 請求後端拿到url所需數據,而後跳轉頁面在經過回調地址返回,獲取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) {
        // 發送code給後端 後端解析出openid
        this.axios
            .post("/api/OrderProgram/GetOpenidAndAccessTokenFromCode", {
                code: code,
            })
            .then((res) => {
                console.log(res);
            })
            .catch((err) => {
                console.log(err);
            });
    },
    wxPay: async function() {
        // 發送orderid,獲取wx.chooseWXPay和wx.config所需的參數
        this.wxData = await this.axios.post(
            "/api/OrderProgram/WxJSAPIPay",
            { orderId: this.orderId }
        );
        let wxConfigData = this.wxData.wxConfigData // 獲取wx.chooseWXPay()所需數據
        let wxPayData = this.wxData.wxPayData;// 獲取wx.config()所需數據
        this.$wx.config({
            debug: false, // 開啓調試模式,調用的全部api的返回值會在客戶端alert出來,若要查看傳入的參數,能夠在pc端打開,參數信息會經過log打出,僅在pc端時纔會打印。
            appId: wxConfigData.appId, // 必填,公衆號的惟一標識
            timestamp: wxConfigData.timeStamp, // 必填,生成簽名的時間戳
            nonceStr: wxConfigData.nonceStr, // 必填,生成簽名的隨機串
            signature: wxConfigData.paySign, // 必填,簽名
            jsApiList: [
                "chooseWXPay",
            ],
        });
        // 執行支付
        this.$wx.chooseWXPay({
            timestamp: wxPayData.timeStamp, // 支付簽名時間戳,注意微信jssdk中的全部使用timestamp字段均爲小寫。但最新版的支付後臺生成簽名使用的timeStamp字段名需大寫其中的S字符
            nonceStr: wxPayData.nonceStr, // 支付簽名隨機串,不長於 32 位
            package: wxPayData.package, // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=\*\*\*)
            signType: wxPayData.signType, // 簽名方式,默認爲'SHA1',使用新版支付需傳入'MD5'
            paySign: wxPayData.paySign, // 支付簽名
            success: (res) => {
                this.$toast("支付成功");
            },
            fail: (err) => {
                this.$toast("支付失敗");
            },
        });
    },
}

同時支持 H5 支付和 JSAPI 支付

// 在建立訂單以後,就判斷環境使用哪一種方法支付。
if (isWx()) {
  this.WXPay(orderId); // 帶着orderId跳轉到支付頁邏輯
} else {
  this.H5Pay(orderId); // 執行上面H5支付中的建立訂單以後的邏輯
}
// 判斷是不是微信瀏覽器
function isWx() {
  let uAgent = navigator.userAgent.toLowerCase();
  reutrn(/micromessenger/.test(uAgent)) ? true : false;
}

注意事項

  • 開通微信商戶號 - 設置支付目錄(若是是 Vue 這類 SPA 頁面,到根目錄便可,也就是#號以前的地址)
    wxpay1.png
  • 開通微信公衆號(服務號) - 設置安全域名、設置受權域名
    wxpay8.png
  • 收集參數:appId 和 AppSecret
  • 添加 Web 開發工具開發者(須要開發者同時開發者關注開發的微信公衆號和微信公衆帳號安全助手)參考文檔
    [圖片上傳失敗...(image-b07878-1605777597831)]
  • 設置回調域名(例如:www.xx.com/pay,最後獲取的 code 會拼在此回調地址後返回,返回後如www.xx.com/pay?code=xxxx參考 1
    wxpay5.png
  • 獲取 code小程序

    • 參考獲取 code 文檔
    • 在微信客戶端網頁打開受權地址,跳轉以後,在返回的回調地址以後拿到 code
https://open.weixin.qq.com/connect/oauth2/authorize
?appid=你的appid
&redirect_uri=你的回調地址(拿到code後返回)
&response_type=code(返回類型,默認code)
&scope=snsapi_base(受權範圍,靜默受權拿到openid)
&state=STATE(自定義狀態,非必填)
#wechat_redirect(重定向使用必須攜帶)

redirect_uri參數要和你在微信公衆號裏設置的回調域名一致(例如:www.xx.com/pay),須要注意的是這 url 須要urlEncode後端

請求這個地址以後,code 會以你設置的redirect_uri地址裏的參數帶回來,拿到以後傳給後端就好了。

  • 前端引入 js-skd

  • 獲取 wx.config 的參數
    wxpay6.png
  • 獲取 wx.chooseWXPay 所需的參數
    wxpay7.png

參考

總結

整個流程走下來,給個人體驗是:小程序支付最方面(由於配置少),其次是 H5,JSAPI 支付最麻煩(文章一多半都在寫它)

在微信支付功能開發過程當中,其實最麻煩的不是開發流程,而是他的各類配置和受權流程,爲了拿到所需的參數而來回折騰。

開發過程當中的一些參數是常常用到的,如 appid、openid、orderId

支付流程大徑相同,先獲取到用戶的 openid,知道你是誰,而後統一下單拿到 orderId 再去處理不一樣平臺的支付方式

開發時候用到的相關文檔,必定要仔細閱讀二遍以上爲止!!

遇到問題不要死剛,多百度多 Google,說不許你遇到的問題已經有無數的人遇到過而且已經有成熟的解決方案了。

前端和後端要多溝通,有什麼問題(難點)隨時反饋,須要什麼參數好好說,遇到觀點不一致的時候千萬要注意控制住情緒,切莫撕逼(.——.)。

由於本人水平有限,對後端流程懂得很少,只能之前端的角度來梳理整個支付流程。

以上,但願對你有所幫助。

相關文章
相關標籤/搜索