• 微信支付前端对接流程


    以vue spa项目为例,测试微信支付对接。

    1. 在index.html中添加sdk
     <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
    

    在main.js中注册wx全局变量

    Vue.prototype.$wx = window.wx
    

    特别说明: 如果使用了weixin-js-sdk的npm包,在测试环境会导致wx的值是undefined,在本地环境没问题,具体原因未知,因此还是建议在index.htlm中引入sdk。

    1. 在支付后台配置支付域名,建议是一级域名,如payment.domain.com,也就是前端的访问域名,主要用于回调跳转。

    调试过程中如果遇到微信提示“回调地址未注册”,说明地址配置错了。地址不支持配置192.168类型的地址,因此调试支付的时候,建议放到测试环境或者使用类似ngrok的代理工具。

    1. 流程说明:获取微信授权code,用code请求后端接口获取openid,openid用于唯一标识当前用户,因此openid是不变的,但是code每次授权都是不一样的并且有时效性,所以应该建议每次打开页面都获取最新的code。
    <template>
      <div>
        <button @click="handlePay">支付</button>
      </div>
    </template>
    
    <script>
    import axios from "axios";
    export default {
      data() {
        return {
          browser: "",
          code: "",
          openid: "",
          orderNo: "xxxxxxxxxxx",
          appId: "wxxxxxxxxxx",
        };
      },
      mounted() {
        if (navigator.userAgent.indexOf("MicroMessenger") > -1) {
          this.browser = "wechat";
        } else if (navigator.userAgent.indexOf("AlipayClient") > -1) {
          this.browser = "alipay";
        } else {
          this.browser = "other";
        }
    
        if (this.browser === "wechat") {
          this.getCode();
        }
      },
      methods: {
        handlePay() {
          const url = "http://dev.domain.com/order-center/pay/wxPayment";
          axios
            .post(url, {
              orderNo: this.orderNo,
              payAmount: "0.01",
              payType: "2", // 1-支付宝;2-微信;3线下支付
              openId: this.openid,
            })
            .then(({ data }) => {
              if (this.browser === "wechat") {
                const wxConfig = data.data;
                // signature
                this.$wx.config({
                  debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                  appId: wxConfig.appId, // 必填,公众号的唯一标识
                  timestamp: wxConfig.timeStamp, // 必填,生成签名的时间戳
                  nonceStr: wxConfig.nonceStr, // 必填,生成签名的随机串
                  signType: wxConfig.signType,
                  paySign: wxConfig.paySign, // 必填,签名
                  jsApiList: ["chooseWXPay"],
                });
                this.$wx.chooseWXPay({
                  appId: wxConfig.appId,
                  timestamp: wxConfig.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。(但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符,因此后端返回的是驼峰)
                  nonceStr: wxConfig.nonceStr, // 支付签名随机串,不长于 32 位
                  package: wxConfig.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
                  signType: wxConfig.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
                  paySign: wxConfig.paySign, // 支付签名
                  success: (res) => {
                    this.$toast("支付成功");
                  },
                  fail: (err) => {
                    this.$toast("支付失败");
                  },
                });
              }
            });
        },
        getCode() {
          const code = this.getUrlPram("code");
          if (code != null) {
            this.code = code;
            // 拿到 code 发给 后端
            this.sendCode(code);
          } else {
            // 去拿code
            this.getUrl();
          }
        },
        sendCode(code) {
          // 发送code给后端 后端解析出openid
          axios
            .get("http://dev.domain.com/notify/authCodeToOpenid/" + code)
            .then((res) => {
              this.openid = res.data.openid;
            })
            .catch((err) => {
              console.log(err);
            });
        },
        getUrlPram(name, url) {
          if (!url) url = location.href;
          name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
          var regexS = "[\\?&]" + name + "=([^&#]*)";
          var regex = new RegExp(regexS);
          var results = regex.exec(url);
          return results == null ? null : results[1];
        },
        getUrl() {
          // 获取微信code,获取到后code会挂到re_url上
          // state用于追加需要回调的数据,你希望授权后把原来路由上的数据能带回来,比如说orderId、orderState,拼接方式:state=xxxxxx,xxxxxx
          const re_url = encodeURIComponent(
            "http://payment.test.domain.com/index.html#/new-pay"
          );
          this.url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${this.appId}&redirect_uri=${re_url}&response_type=code&scope=snsapi_base&state=${this.orderNo}`;
          window.location.href = this.url;
        },
      },
    };
    </script>
    
    <style lang="less" scoped>
    </style>
    
    

    当我点击支付按钮,用当前用户的openid发起支付请求,后端返回我们拉起支付需要的参数(前端不参与加密的任何过程),特别要注意的是timestamp的s是小写,如果支付返回“签名验证失败”可能是这个问题导致的,我被这个问题坑了一下。。。

    常用网站: SegmentFault | GitHub | 掘金社区
  • 相关阅读:
    c++参考书籍
    安装驱动踩坑
    杂项讨论
    《机器学习篇》目录
    《计算机技术》目录
    数学:统计:参数估计
    神经网络
    数学:统计:数据的概括性度量
    数学:概率:一维随机变量
    多维随机变量:相互独立的随机变量
  • 原文地址:https://www.cnblogs.com/yesyes/p/15739896.html
Copyright © 2020-2023  润新知