微信内置H5支付

🧑‍💻 写在开头

点赞 + 收藏 === 学会🤣🤣🤣

场景是用户通过微信扫app内的收款码,跳到一个h5页面。然后完成支付。

代码实现的整体流程:

使用微信扫码,码是app内生成的,码的内容是一个h5页面链接,扫码完成后跳转到自定义的h5支付界面。

扫码进入后,将页面展示所需要的参数进行缓存起来,存到本地。 然后需要微信静默授权。

  1. 微信静默授权的流程: 配置appid、redirect_uri等参数,从项目页面跳转到微信授权页面:https://open.weixin.qq.com/connect/oauth2/authorize 详细参考[ 微信官方文档]open.weixin.qq.com/connect/oau…

参数说明

1
2
3
4
5
6
7
8
// 示例
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就是由后端返回的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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开发中使用的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<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>

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 


 

 

 

posted @   林恒  阅读(127)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)
历史上的今天:
2023-06-29 记录--写一个高德地图巡航功能的小DEMO
2022-06-29 记录--Vue常问问题整合
欢迎阅读『微信内置H5支付』
点击右上角即可分享
微信分享提示