微信支付-vue 实现微信支付-前端篇

浮生一境 2019年12月18日 1,560次浏览

微信支付系列文章

  1. 微信支付-java后端实现
  2. 微信支付-vue 前端实现

vue demo: 下载地址文章底部


技术栈

  • vue
  • vue-cli
  • weixin-js-sdk (微信jsSdk)

微信支付术语

  • 微信jsSdk需要提前初始化完成
  • 初始化加密参数需要通过后端计算后返回给前端
  • 初始化url为在微信支付配置的前端url. (产品中心 => 开发配置 => JSAPI支付 => 支付授权目录添加)

支付流程

前端需要的核心操作, 总共分为以下几步:

  1. 请求后端接口,获取初始化所需参数(包含加密结果)。
  2. 初始化微信jsSdk(wx.ready()完成初始化)。
  3. 用户确认支付,调用后端下单接口,获取微信统一下单id,以及后端统一下单时加密信息。
  4. 前端调用微信jsSdk.chooseWXPay(),调起微信支付页面。
    1. 支付成功,jsSdk回调success
    2. 支付失败,jsSdk回调fail
    3. 支付取消,jsSdk回调cancel
  5. 触发回调机制,处理回调结果。

注意:微信jsSdk触发的成功结果回调同步不代表真正成功,业务结果还需请求后台拿到最终的支付状态。

代码

获取jsSdk初始化配置并完成初始化操作

created() {
<!--
 微信支付
 初始化微信支付jsApi配置,初始化参数由后端返回
 url 为前端当前域名,需与微信后台配置相同

 chooseWXPay 代表使用微信支付插件,还有很多其他插件,详情移步微信官方文档
 -->
let config = {
    url: 'https://app.*.com/'
};
let promises = Http.post('/wx/getSdkConfig', config);
promises.then((response) => {
    let content = response.content;
    config.nonceStr = content.nonceStr;
    config.signature = content.signature;
    config.timestamp = content.timestamp;
    config.appId = content.appId;
    config.debug = true;
    config.jsApiList = [
        'chooseWXPay'
    ];
    wx.config(config);
    wx.ready(() => {
        this.wx = wx;
    });
    wx.error(function (res) {
        console.info('error 验证失败', res);
    });
});
}

发起支付、调起微信支付页面

<!--
 微信支付
 用户点击确认支付,请求后端发起下单,拿到后端的统一下单id, 调用微信jsApi.chooseWXPay 调起微信支付页面。
 支付成功后会调用success方法
 支付失败后会调用fail方法
 取消支付会调用cancel方法

 此处拿到的成功,不能作为支付成功依据,支付结果需要调用后端接口异步拿到
 -->
pay() {
    let params = {
        payAmount: this.payAmount
    };
    let promises = Http.post('/transaction/do', params);
    let that = this;
    promises.then((response) => {
        if (response.status === 0) {
            let recordOrderGid = response.content.recordOrderGid;
            try {
                this.wx.chooseWXPay({
                    timestamp: response.content.timeStamp, // 支付签名时间戳,注意微信js sdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
                    nonceStr: response.content.nonceStr, // 支付签名随机串,不长于 32 位
                    package: 'prepay_id=' + response.content.prepayId, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
                    signType: response.content.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
                    paySign: response.content.sign, // 支付签名
                    success: function () {
                        that.doWxPayCallback(recordOrderGid);
                    },
                    fail: function () {
                        that.doWxPayCallback(recordOrderGid);
                    },
                    cancel: function () {
                        console.info('取消支付,如需支付请继续。');
                    }
                });
            } catch (e) {
                console.info('订单支付异常, 请稍后重试。');
            }
        } else {
            console.info(response.message);
        }
    });
}

处理微信支付结果

<!--
 微信支付结果处理
 循环调用后端获取支付结果,查询一定次数后跳转到账单或者结果页面,依据个人业务需求即可
 -->
doWxPayCallback: function (recordOrderGid) {
    let taskCount = 0;
    this.intervalid1 = setInterval(() => {
        taskCount++;
        if (taskCount > 5) {
            clearInterval(this.intervalid1);
        }
        let statusPromise = this.queryOrderStatus(recordOrderGid);
        statusPromise.then(sta => {
            if (sta.status === 0) {
                console.info(sta.content);
                let orderStatus = sta.content.status;
                if (orderStatus === 1) {
                    clearInterval(this.intervalid1);
                    this.$router.push({
                        path: 'resultOrder', query: {}
                    });
                } else if (orderStatus === 2) {
                    clearInterval(this.intervalid1);
                    console.info('订单支付失败。');
                } else if (orderStatus === 0) {
                    console.info('订单支付处理中');
                }
            }
        });
    }, 2000);
}

注意点

  • 统一下单的签名和后续前端拉取微信支付的签名需要统一, 也就是都采用MD5加密, 如果2者不同, 会导致前端拉取微信支付fail, 这是一个巨大的坑, 因为这个原因调试了好久, 微信在文档里没有明确标出统一下单的签名校验方式 需要和前端拉取微信支付的签名校验保持一致.
  • 微信jsSdk初始化信息需要后端加密
  • 前端初始化jsSdk配置的url需与微信支付后台配置相同,且以"/"结尾。

vue支付业务流程文档

接口地址描述调用方
src/components/index/Index.vue => created()初始化微信支付jsApi配置,初始化参数由后端返回, url 为前端当前域名,需与微信后台配置相同, chooseWXPay 代表使用微信支付插件,还有很多其他插件,详情移步微信官方文档前端 => 后端 => 微信sdk
src/components/index/Index.vue => methods.pay()用户点击确认支付,请求后端发起下单,拿到后端的统一下单id, 调用微信jsApi.chooseWXPay 调起微信支付页面。支付成功后会调用success方法, 支付失败后会调用fail方法, 取消支付会调用cancel方法, 此处拿到的成功,不能作为支付成功依据,支付结果需要调用后端接口异步拿到前端 => 后端 => 微信sdk
src/components/index/Index.vue => methods.doWxPayCallback()微信支付结果处理, 循环调用后端获取支付结果,查询一定次数后跳转到账单或者结果页面,依据个人业务需求即可微信sdk => 前端 => 后端

博客

请移步: https://www.oopmind.com

Demo

git clone https://github.com/wangjianan1103/pica_pay.git

联系方式

如果 Pica_pay 对你有帮助,可以关注作者支持一下,每天会不定时回复留言(有任何问题都可以留言哦)。

微信公众号

预览图