微信內建H5支付

林恒發表於2024-06-29

🧑‍💻 寫在開頭

點贊 + 收藏 === 學會🤣🤣🤣

場景是使用者透過微信掃app內的收款碼,跳到一個h5頁面。然後完成支付。

程式碼實現的整體流程:

使用微信掃碼,碼是app內生成的,碼的內容是一個h5頁面連結,掃碼完成後跳轉到自定義的h5支付介面。

掃碼進入後,將頁面展示所需要的引數進行快取起來,存到本地。 然後需要微信靜默授權。

  1. 微信靜默授權的流程: 配置appid、redirect_uri等引數,從專案頁面跳轉到微信授權頁面:https://open.weixin.qq.com/connect/oauth2/authorize 詳細參考[ 微信官方文件]open.weixin.qq.com/connect/oau…

引數說明

// 示例
let ua = window.navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == 'micromessenger') {
   // 回撥地址:域名加頁面路徑
   let hdurl = encodeURIComponent('https://.../#/page_wallet');
   let appId = '申請專案的appid';
   window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${hdurl}&response_type=code&scope=snsapi_base#wechat_redirect`;
}

  

  1. 當授權後,會自動跳轉到配置回撥頁面,也就是配置的‘redirect_uri’ 相當攜帶這code,重新開啟了專案
  2. 然後解析url中的code,將code取出,支付的時候將code傳給後端。

點選支付的時候,請求介面,使用微信瀏覽器內建物件WeixinJSBridge調起微信支付,使用方法如下所示,data就是由後端返回的資料。

function onBridgeReady(data) {
  WeixinJSBridge.invoke(
    "getBrandWCPayRequest",
    {
      // 公眾號名稱,由商戶傳入
      appId: data.appId,
      // 時間戳,自1970年以來的秒數
      timeStamp: data.timeStamp,
      // 隨機串
      nonceStr: data.nonceStr,
      package: data.package,
      // 微信簽名方式:
      signType: "MD5",
      // 微信簽名
      paySign: data.paySign,
    },
    function (res) {
      if (res.err_msg == "get_brand_wcpay_request:ok") {
        // 使用以上方式判斷前端返回,微信團隊鄭重提示:
        // res.err_msg將在使用者支付成功後返回ok,但並不保證它絕對可靠。
      }
    }
  )
 }

if (typeof WeixinJSBridge == "undefined") {
  if (document.addEventListener) {
    document.addEventListener("WeixinJSBridgeReady", onBridgeReady, false);
  } else if (document.attachEvent) {
    document.attachEvent("WeixinJSBridgeReady", onBridgeReady);
    document.attachEvent("onWeixinJSBridgeReady", onBridgeReady);
  }
} else {
  onBridgeReady();
}

在使用uniapp開發中使用的程式碼如下:

<template>
   <view v-show="show">
      ...內容省略
       <view @click="confirmPay">付款</view>
   </view>
</template>

<script>
    // 支付介面
 import { payment_code } from '@/api/wallet';
 
 export default {
    data() {
      return {
        show: true, // 控制頁面展示
        user: {}, // 頁面資訊
        form: { price: '', type: 0, code: null, receiver_id: null }, // 提交引數
        paydata: {} //返回的支付資訊
      };
     },
     onLoad(e) {
       // 掃碼後第一次進入該頁面時
       if (e.id) {
          this.user = {
            name: e.name,
            id: e.id,
          };
          this.form.receiver_id = e.id;
          // 將資訊存到本地
          uni.setStorageSync('userpay', this.user);
       }else{
          // 第二次進入(授權成功後,透過回撥進入的頁面)
          let data = uni.getStorageSync('userpay');
          this.user = {
            name: data.name,
            id: data.id,
          };
          this.form.price = data.price;
          this.form.receiver_id = data.id;
          let ua = window.navigator.userAgent.toLowerCase();
          //判斷是不是微信
          if (ua.match(/MicroMessenger/i) == 'micromessenger') {
            // 第二次進來時,路徑上已經攜帶了code,獲取code。
            this.form.code = this.getUrlParam('code');
          }
       }
       // 去授權
       this.goAuthorization()
     },
     methods:{
       // 授權方法
       goAuthorization(){
         let ua = window.navigator.userAgent.toLowerCase();
         // //判斷是不是微信
         if (ua.match(/MicroMessenger/i) == 'micromessenger') {
           // 判斷是否已經獲取了code
           if (this.form.code == null || this.form.code === '') {
               // 如果還沒有code,就跳轉授權頁面
               let hdurl = encodeURIComponent('https://.../#/page_wallet');
               let appId = '申請專案的appid';
               window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${hdurl}&response_type=code&scope=snsapi_base#wechat_redirect`;   
           }else{
             // 有code的話,就將頁面內容顯示出來
             this.show = true;
           }
         }
       }
     },
     
     // 點選支付後,呼叫
     confirm(e) {
       uni.showLoading({});
        uni.$u.http.post('支付介面',this.form).then(res=>{
           uni.hideLoading();
           // 將返回的data賦值
           this.paydata = res.data.data;
           let that = this;
           // 繫結事件
           if (typeof WeixinJSBridge == 'undefined') {
              if (document.addEventListener) {
                document.addEventListener('WeixinJSBridgeReady', that.wxonBridgeReady, false);
              } else if (document.attachEvent) {
                document.attachEvent('WeixinJSBridgeReady', that.wxonBridgeReady);
                document.attachEvent('onWeixinJSBridgeReady', that.wxonBridgeReady);
              }
            } else {
              this.wxonBridgeReady();
            }
        }).catch((err) => {
          // 如果介面呼叫失敗了,將資訊存起來,再走一遍授權。
          this.user.price = this.form.price;
          uni.setStorageSync('userpay', this.user);
          this.form.code = null;
          this.goAuthorization();
        });
     },
     // 微信支付
     wxonBridgeReady(){
       let that = this;
       WeixinJSBridge.invoke(
        'getBrandWCPayRequest',
        {
          appId: that.paydata.appId,
          timeStamp: that.paydata.timeStamp,
          nonceStr: that.paydata.nonceStr,
          package: that.paydata.package,
          signType: that.paydata.signType,
          paySign: that.paydata.paySign
        },
        function (res) {
              // 如果取消了支付,就關閉當前h5頁面,直接返回微信,也可以進行其他操作,透過res.err_msg來判斷即可
          if (res.err_msg == 'get_brand_wcpay_request:cancel') {
            //關閉當前瀏覽器
            WeixinJSBridge.call('closeWindow');
          }
          // 這裡是支付成功
          if (res.err_msg == 'get_brand_wcpay_request:ok') {
            // 使用以上方式判斷前端返回,微信團隊鄭重提示:
            //res.err_msg將在使用者支付成功後返回ok,但並不保證它絕對可靠。
          }
        }
      )
     },
     
     // 獲取路徑上引數的方法,用於獲取code
     getUrlParam(name) {
      const url = window.location.href;
      const queryString = url.split('?')[1];
      if (!queryString) return null;
      const params = queryString.split('&');
      for (const param of params) {
        const [key, value] = param.split('=');
        if (key === name) {
          return decodeURIComponent(value);
        }
      }
      return null;
    },
     
  } 
</script>

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文件,大家一起討論學習,一起進步。

微信內建H5支付


相關文章