VX-微信支付

微信支付地址官方

地址:

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#58

<——点击进入微信公众号官方文档

微信支付【 WeChatPay 】

WeixinJSBridge.invoke、wx.chooseWXPay

业务需求:
现在涉及到微信相关的项目有很多,主要涉及到的功能有【微信自定义分享、微信支付等】。开发微信公众号H5页面时,需要使用微信支付进行金融支付。当微信支付完成【支付成功 点击“完成”】时,需要出发相应的业务逻辑;比如:支付成功时跳转到订单页面;支付失败时跳转到下订单页面;支付取消时保持当前订单页面不变等。
前期开发微信H5页面时,大多考虑的就是【支付成功】之后如何处理,因为是刚接触微信支付,大多都是采用刷新页面获取新数据的方式来更新支付状态。这种方式可以解决当时面临的问题,但是从业务逻辑来看,处理的方式不是很合理。
支付场景越来越多,对微信支付流程有了进一步的了解和认识,现在回过头来对过去项目中使用【微信支付】的业务场景进行梳理和完善,进一步优化支付流程以及对支付后的不同状态做相应的处理和优化,并结合实际情况做相应的业务逻辑分析。

支付方式:

方式一:微信支付【微信公众号】

此支付方式需要在HTML页面中引入JS文件,即【 jweixin-1.6.0.js 】;
此JS文件链接支持http和https两种形式,引用时需要匹配当前项目的请求-响应协议(即http、https);
该JS文件支持使用AMD/CMD标准模块加载方式加载。

let WeChatPay = function() {
    // 2、引入js后、获取公众号校验信息
    let timestamp = '',
        nonceStr = '',
        signature = '';
    let v = {
        // 用于换取微信校验信息的参数:要求不可以包含 “#” 号
        url: location.split('#')[0]
    };

    // 3、通过config接口注入权限验证配置(需要同步进行,在获取到校验信息后方可注入config,否则校验失败!)
    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '', // 必填,签名
        jsApiList: ["checkJsApi", "chooseWXPay", "updateAppMessageShareData", "updateTimelineShareData"] // 必填,需要使用的JS接口列表
    });
    
    axios.post('/wx/pay/orderPay_XXXX', data).then(res => {
        // 支付成功状态
        if (res.code == 200) {
            // 获取支付必备的参数
            let {
                nonceStr,
                package,
                signType,
                paySign
            } = res.data;
            // 4、通过ready接口处理成功验证
            wx.ready(function() {
                /* 微信支付 */
                wx.chooseWXPay({
                    timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
                    nonceStr: nonceStr, // 支付签名随机串,不长于 32 位
                    package: package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
                    signType: signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
                    paySign: paySign, // 支付签名
                    success: function(res) {
                        // 前端判断返回方式,微信团队郑重提示:不保证绝对可靠,切记!
                        if (res.errMsg == 'chooseWXPay:ok') {
                            // 【支付成功】 
                        } else if (res.errMsg == 'chooseWXPay:cancel') {
                            // 【支付取消】:用户取消支付不会进入这个判断,而是进入complate和cancel函数
                        } else {
    
                        }
                    },
                    complete: function(res) {
                        // 接口调用完成时执行的回调函数,无论成功或失败都会执行
                        if (res.errMsg == 'chooseWXPay:ok') {
                            // 【支付成功】:支付成功提示页面,点击完成按钮之后
                            wx.closeWindow(); /* 关闭微信窗口,调用时需要在config中进行校验 */
                        } else if (res.errMsg == 'chooseWXPay:cancel') {
                            // 【支付取消】
                        } else {
    
                        }
                        /**
                         * iOS和Android支付成功点击“完成”后都会进入success和complete函数,都返回'chooseWXPay:ok'
                         * (也有人说Android支付成功不进入success函数,)
                         * 原因是【iOS和Android返回数据不同。支付成功后Android返回 {"errMsg":"getBrandWCPayRequest:ok"},iOS返回{"err_Info":"success","errMsg":"chooseWXPay:ok"},故Android找不到success方法,导致失败】
                         * */
                    },
                    fail: function(err) {
                        // 接口调用失败
                    },
                    cancel: function(err) {
                        // 用户点击取消时的回调函数:用户取消支付后实际上进入cancel 和 complate函数
                    }
                });
            });
        }
    }).catch(err => {
        console.log('支付失败:', err);
    });

}

接口说明:【不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回。】

success:接口调用成功时执行的回调函数。
fail:接口调用失败时执行的回调函数。
complete:接口调用完成时执行的回调函数,无论成功或失败都会执行。
cancel:用户点击取消时的回调函数,仅部分有用户取消操作的api才会用到。
trigger: 监听Menu中的按钮点击时触发的方法,该方法仅支持Menu中的相关接口。

方式二:微信支付【 JSAPI 支付】(常用支付方式)

地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6

function onBridgeReady() {
    WeixinJSBridge.invoke(
        'getBrandWCPayRequest', {
            "appId": "appId", //公众号名称,由商户传入     
            "timeStamp": "timeStamp", //时间戳,自1970年以来的秒数     
            "nonceStr": "nonceStr", //随机串     
            "package": "package",
            "signType": "MD5", //微信签名方式:     
            "paySign": "paySign" //微信签名 
        },
        function(res) {
            // 支付成功
            if (res.err_msg == "get_brand_wcpay_request:ok") {
                // 使用以上方式判断前端返回,微信团队郑重提示:
                //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
            }
            // 支付过程中用户取消
            if (res.err_msg == "get_brand_wcpay_request:cancel") {

​        }
​        // 支付失败
​        if (res.err_msg == "get_brand_wcpay_request:fail") {

​        }
​        /**
     * 其它
     * 1、请检查预支付会话标识prepay_id是否已失效
     * 2、请求的appid与下单接口的appid是否一致
     * */
    if (res.err_msg == "调用支付JSAPI缺少参数:total_fee") {

    }
     });

}
// 检测支付环境中的 WeixinJSBridge

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();
}
JSAPI调起支付注意事项:

在微信浏览器里打开H5网页中执行JS调起支付;
WeixinJSBridge是微信浏览器内置对象,在其他浏览器中无效;
调用支付传递的参数注意区分大小写。

WeixinJSBridge.invoke 、 wx.chooseWXPay 的区别

WeixinJSBridge.invoke()出现的版本更早 无需引用jssdk 无需wx.config方法注入 需要参数appId 使用回调 有详细的说明
而wx.choosewxpay()出现的版本比较晚 需要jssdk注入 不需要参数appId 使用回调 只有SUCCESS 和 FAIL没有具体的说明
WeixinJSBridge.invoke()是微信浏览器的内置方法 其实wx.choosewxpay()在引用的微信jssdk文件中 也调用了WeixinJSBridge.invoke() 是对WeixinJSBridge.invoke()的再次封装
综上所诉 这是微信前后设计的不同方法的支付 还是weixinjsbridge更方便一些 有具体的失败回调

代码演示:

// 支付按钮。

在vue里面

npm install weixin-js-sdk --save

import wx from "weixin-js-sdk";
payBtn() {

​      new Promise((resolve, reject) => {

​        Api_insured.isWaitPay(this.orderNo)

​          .then(res => {

​            // this.payDisabled = true

​            if (this.selectedIndex == 1) {

​              console.log("微信内");

​              if (

​                navigator.userAgent.toLowerCase().indexOf("micromessenger") !==

​                -1

​              ) {

​                var that = this;

​                new Promise((resolve, reject) => {

​                  Api_insured.payEnable()

​                    .then(res => {

​                      if(res.result) {

​                        console.log("微信端");

​                        that.$vux.loading.show();

​                        

​                        new Promise((resolve, reject) => {

​                          Api_insured.wxPay(that.orderNo, that.isSign)

​                            .then(res => {

​                              // that.payDisabled = false

​                              that.appId = res.result.appId;

​                              that.timeStamp = res.result.timeStamp;

​                              that.nonceStr = res.result.nonceStr;

​                              that.package = res.result.package;

​                              that.signType = res.result.signType;

​                              that.paySign = res.result.paySign;

​                              wx.config({

​                                debug: false,

​                                appId: res.result.appId,

​                                timeStamp: res.result.timeStamp,

​                                nonceStr: res.result.nonceStr,

​                                signType: res.result.signType,

​                                paySign: res.result.paySign,

​                                jsApiList: ["chooseWXPay"]

​                              });

​                              that.$vux.loading.hide();

​                              that.onBridgeReady();

​                            })

​                            .catch(error => {

​                              that.$vux.toast.text(error.message);

​                              that.$vux.loading.hide();

​                              // that.payDisabled = false

​                              reject(error);

​                            });

​                        });

​                      } else {

​                        that.h5DialogShow = true

​                        // location.href =

​                        //   location.href.split("#")[0] +

​                        //   "pi-hz/api/wxpay/wapPay?orderNo=" +

​                        //   that.orderNo;

​                        }

​                      })

​                    .catch(error => {

​                      that.$vux.toast.text(error.message);

​                      reject(error);

​                    });

​                });

​                

​              } else {

​                // that.payDisabled = false

​                console.log("H5");

​                var that = this;

​                location.href =

​                  location.href.split("#")[0] +

​                  "pi-hz/api/wxpay/wapPay?orderNo=" +

​                  that.orderNo;

​              }

​            } else {

​              console.log("支付宝");

​              if (

​                navigator.userAgent.toLowerCase().indexOf("micromessenger") !==

​                -1

​              ) {

​                // 弹窗

​                // this.payDisabled = false

​                this.$refs.aliPayDialog.style.display = "";

​              } else {

​                // this.payDisabled = false

​                location.href =

​                  location.href.split("#")[0] +

​                  "pi-hz/api/alipay/wapPay?orderNo=" +

​                  this.orderNo;

​              }

​            }

​          })

​          .catch(error => {

​            this.$vux.toast.text(error.message);

​            reject(error);

​          });

​      });

​    },
 // 公众号支付

​    onBridgeReady() {

​      let that = this;

​      WeixinJSBridge.invoke(

​        "getBrandWCPayRequest",

​        {

​          appId: that.appId, //公众号名称,由商户传入

​          timeStamp: that.timeStamp, //时间戳,自1970年以来的秒数

​          nonceStr: that.nonceStr, //随机串

​          package: that.package,

​          signType: that.signType, //微信签名方式

​          paySign: that.paySign //微信签名

​        },

​        function(res) {

​          if (res.err_msg == "get_brand_wcpay_request:ok") {

​            // 支付成功

​            that.$router.push({

​              path: "/paySuccess",

​              query: {

​                orderNo: that.orderNo

​              }

​            });

​            // that.payDisabled = false

​          } else if (res.err_msg == "get_brand_wcpay_request:cancel") {

​            that.$vux.toast.text("支付取消");

​            // that.payDisabled = false

​          } else {

​            that.$vux.toast.text("支付失败");

​            // that.payDisabled = false

​          }

​        }

​      );

​    },