这两天,在做的项目上遇到一个问题:接入微信支付。它有五种支付模式,如下所示:

支付模式

  由于项目采用h5的呈现方式,所以采用的是第三个支付模式,即JSAPI支付,相比第五种支付模式支持的范围更大一些。

  微信支付的限制还是挺多的,其中一点是一个微信支付账户只能设置五个支付目录,如果是有多个地方或者多个版本需要支付,这个配置还是会让人很头疼的。
  特别的一点,由于是采用vue的框架,页面的链接还因为是hash模式的,导致其地址也会不同于一般的url,单纯靠精准配置对应的url是不可行的。对于网上所说的将链接进行替换,这边采用后无法保证100%成功,故不建议此种方式。

常见错误
  针对我们的问题,对应到错误里就是一直报第三个,当前页面url未注册
  所以针对以上的问题,采取的折中方式(该方式是处于时间紧的情况下所采取的)解决如下:


1. 编写统一的支付页面

 /**此页面无需其他过多样式,只是作为一个中介来调起支付,
 故此处只写入采用JSAPI调起微信支付以及一些处理页面的跳转逻辑 
 其中执行完支付后返回原页面带的参数,是因为暂时没有较好的方法
  只能借由原页面携带参数一起过来支付页面后,再返回回去,因为某些
 页面需要这些参数进行后续的判断和处理。**/
 <script>
    export default {
        data() {
            return {    //此处是一些重要参数的配置,包括页面跳转以及需要带的参数
                tOrderID:0,
                payInfo:{},
                backUrl:"",
                linkerNo:"",
                type:0
            }
        },
        mounted() {
            this.tOrderID = parseInt(this.$route.query.tOrderID)            
            this.getPaymentParam()
            this.backUrl = decodeURI(this.$route.query.backUrl)
            this.linkerNo = this.$route.query.linkerNo
            this.type = this.$route.query.type
        },
        methods: {
            getPaymentParam(){
               //此处为调用后台接口获取微信支付所需要的参数
               //payInfo在此处进行赋值
            },
            onBridgeReady(){
                let that = this
                WeixinJSBridge.invoke(
                    'getBrandWCPayRequest', {
                         "appId":this.payInfo.appId,     //公众号名称,由商户传入     
                         "timeStamp":this.payInfo.timeStamp,         //时间戳,自1970年以来的秒数     
                         "nonceStr":this.payInfo.nonceStr, //随机串     
                         "package":this.payInfo.packageStr,     
                         "signType":this.payInfo.signType,         //微信签名方式:     
                         "paySign":this.payInfo.paySign //微信签名 
                    },
                function(res){
                    if(res.err_msg == "get_brand_wcpay_request:ok" ){
                    // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
                        console.log("点击成功");
                        uni.showToast({
                            title: '支付成功',
                            duration: 2000,
                            icon:'none',
                            mask: true
                        });
                        setTimeout(()=>{
                            uni.navigateTo({
                                url:that.backUrl+"?payCode=" + 0 + '&linkerNo=' + that.linkerNo + '&type=' + that.type
                                })
                            },2100)
                    } else if(res.err_msg == "get_brand_wcpay_request:cancel"){
                        console.log("点击取消");
                        uni.showToast({
                            title: '点击取消',
                            duration: 2000,
                            icon:'none',
                            mask: true
                        });
                        setTimeout(()=>{
                            uni.navigateTo({
                                url:that.backUrl+"?payCode=" + 1 + '&linkerNo=' + that.linkerNo + '&type=' + that.type
                            })
                        },2100)
                    }else{
                        console.log("支付失败");
                        uni.showToast({
                            title: '支付失败',
                            duration: 2000,
                            icon:'none',
                            mask: true
                        });
                        setTimeout(()=>{
                            uni.navigateTo({
                                url:that.backUrl+"?payCode=" + 2 + '&linkerNo=' + that.linkerNo + '&type=' + that.type
                            })
                        },2100)
                    }
                }); 
            },
        }
    }
</script>

2. 微信账户配置支付页面

  上面的页面建议写在根目录下,将页面链接记下,然后在微信账户上配置仅需配置根目录即可,防止出现其他奇怪的问题。


3. 在需要的地方设置页面跳转逻辑

  进行完上面两步后,即可在之前页面唤起微信支付处设置页面跳转,借由空白页面进行微信支付后,再跳回原来页面处理后续逻辑。具体如下:

/**此处仅举例一个页面,且只截取调起微信支付的部分,大概逻辑如下
采用此种做法,对于取消支付的情况,如果后台有存储跳页面前的数据则没问题
如果没有的话,页面返回来的数据则都会清空,所以需要保存数据的
请调接口保存到后台数据库中,否则,请采用其他方法,不建议存入缓存。**/

success: (res, code, data, error) => {
                wx.hideLoading();
                if (code == 0) {
                    var url = encodeURI("/pages/earning/recharge")
                    /**只有个别需要判断的参数,可向下面页面如此,带过去支付页面后
再返回回来onShow里进行处理。**/
                    uni.navigateTo({
                        url:'/pages/pay?tOrderID=' + data+ "&backUrl="+url + "&linkerNo="+this.linkerNo
                        })
                    // WeixinJSBridge.invoke(
                    //     'getBrandWCPayRequest',
                    //     {
                    //         appId: res.appId, //公众号名称,由商户传入
                    //         timeStamp: res.timeStamp, //时间戳,自1970年以来的秒数
                    //         nonceStr: res.nonceStr, //随机串
                    //         package: res.packageStr,
                    //         signType: res.signType, //微信签名方式:
                    //         paySign: res.paySign //微信签名
                    //     },
                    //     res => {
                    //         if (res.err_msg == 'get_brand_wcpay_request:ok') {
                    //             // 使用以上方式判断前端返回,微信团队郑重提示:
                    //             //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
                    //             console.log('点击成功');
                    //             wx.showToast({
                    //                 title: '支付成功'
                    //             });
                    //             this.getMemAccount();
                    //         } else if (res.err_msg == 'get_brand_wcpay_request:cancel') {
                    //             console.log('点击取消');
                    //             uni.showToast({
                    //                 title: '你已取消支付',
                    //                 duration: 5000,
                    //                 icon: 'none',
                    //                 mask: true
                    //             });
                    //         } else {
                    //             console.log('支付失败');
                    //             uni.showToast({
                    //                 title: '支付失败',
                    //                 duration: 5000,
                    //                 icon: 'none',
                    //                 mask: true
                    //             });
                    //         }
                    //     }
                    // );
                } else {
                    uni.showToast({
                        title: error,
                        icon: 'none',
                        duration: 2000
                    });
                }
        },

  上方是将之前唤起微信支付的地方,替换为跳转到统一的支付页面。而下方是关于一些完成支付后或者取消支付亦或是支付失败f的后续处理逻辑

/**onShow的生命周期,每次调该页面时都会执行,适用于
在支付完成、失败以及取消支付的后续逻辑处理,此处仅为一个简单例子**/
    onShow() {
        if(this.$route.query.payCode){
            this.payCode = this.$route.query.payCode
            this.linkerNo = this.$route.query.linkerNo;
            if( this.payCode == 0 ){  //0 成功  1 取消  2 失败
                console.log('点击成功');
                wx.showToast({
                    title: '支付成功'
                });
                this.getMemAccount();
            }else if(this.payCode == 1){
                console.log('点击取消');
                uni.showToast({
                    title: '你已取消支付',
                    duration: 5000,
                    icon: 'none',
                    mask: true
                });
            }else if(this.payCode == 2){
                console.log('支付失败');
                uni.showToast({
                    title: '支付失败',
                    duration: 5000,
                    icon: 'none',
                    mask: true
                });
            }
        }
    },

  以上只是在短时间里想到的比较折衷的方法,在跳转前后的数据保存方面,如处理不好会带来更大麻烦。
  能力有限,此处仅为一个总结,关于支付,较好的方法无疑是跳转统一的支付页面如有更好的方法,欢迎小伙伴们评论区留言,谢谢大家的阅读,如本篇文章对你有帮助,欢迎转发给更多需要的人儿们。