现在H5网页前景还是挺好的,毕竟小程序也支持嵌入H5了(使用webview),上篇文章我也讲过小程序中嵌入的H5如何拉起微信支付,有需要的家人们可以翻看上一篇文章~
我们今天还是来讲讲H5微信支付的东西吧
首先上网,收集资料~,我了解到,需要申请服务号,微信支付商户号,开通H5支付,顺便把JSAPI支付也开通一下等(这些事都是我们公司专门有人在开通,所以这些也是我在网上查阅资料得知的)
我们来看看前端需要做什么(我用的是vue的history模式)
首先遇到的第一个难题就是当前页面url未注册,这个问题就是支付授权目录的问题,不是没配置就是配置错误了,这一块其实也是琢磨了挺久,授权目录好像只能支持几个,所以如果一个页面支付页面配置一个那就太奢侈了,最后我新建了/payment/wxpay.vue这个页面来做统一的微信支付页面~
网上也有很多教配置授权目录的,比如
访问url为:http://www.a.com/recharge/index
授权目录应为:http://www.a.com/recharge/
但是我一个做过H5支付这一块的朋友告诉我,他只配置到域名,也就是http://www.a.com/ 就可以了,所以我也是只配置到域名
然后最大的坑就是在支付跳转这一块了~
获取到下单接口返回来的信息,timeStamp、nonceStr、package、signType、paySign这些参数,拿到这些参数之后我把它们存到sessiontStorage中,然后进行页面跳转,这里跳转我跟往常一样用this.$router.push()【坑就在这里了】,然后顺利来到支付页面,参数也可以顺利拿到,调用微信浏览器内置的对象WeixinJSBridge去拉起支付, 一起都很顺利!!! 但是问题来了,安卓可以正常拉起,但是ios老是提示当前页面url未注册,这就让我很奔溃。
但是能怎么办,打工人就是迎难而上,不然就要丢饭碗了~
我开始惯性上网查原因和解决办法,原因是因为支付时,微信在判断合法路径时,ios和安卓是不同,ios 取 Landing Page, Android 取 Current Page
这里引用一下网上别人对Landing Page和Current Page的定义
Current Page:当前页面
Landing Page:当我们从微信别的地方点击链接呼出微信浏览器时所落在的页面、或者点击微信浏览器的刷新按钮时所刷新的页面
而且我的项目ios不能拉起支付,但是你手动刷新一下,又可以拉起支付了。所以我大概知道解决方向了~那不就是刷新吗!一刷新ios的Landing page不就是当前的url了吗,行,开整~
一开始我尝试在跳转到支付页面时使用window.location.href="payment/wxpay“这样的方式去跳转,但是报错了~可以说全都是因为这个错误,才让我把这个坑越挖越深
一看报错,坏了,不能这样搞
然后我就想在支付页面这里下手脚去刷新页面,好家伙,坑越踩越深
我在支付页面,也就是/apyment/wxpay这个页面的created()生命周期中,疯狂刷新,location.reload(); this.$router.go(0); window.location.href="/payment/wxpay",一个一个试,全都不行,我开始怀疑人生,自闭了很久~
最后是一个朋友发了个帖子给我,我......醍醐灌顶
原来vue在微信里的刷新方式是不生效的,看完我快哭了~
然后我就还是回到页面跳转前,使用window.location.href去跳转页面,不就是报WeixinJSBridge is not defined吗,我解决,打工人就是要迎难而上。
我在使用到WeixinJSBridge这个页面里(也就是支付页面),把方法写到mounted里,还是不行,然后我就用this.$nextTick,还是不行,最后我用settimeout,这个管用。至此,H5 在ios和android上都可以拉起微信支付了。
这里贴一下支付页面的代码
<template>
<div></div>
</template>
<script>
import { searchQueryPayStatus } from "@/utils/user.js";
export default {
data() {
return {
params: null,
};
},
created() {
this.params = JSON.parse(sessionStorage.getItem("paymentParams"));
console.log("支付参数", this.params);
},
mounted() {
setTimeout(() => {
this.wxpay();
}, 1000);
},
methods: {
wxpay() {
var vm = this;
//下面是解决WeixinJSBridge is not defined 报错的方法
if (typeof WeixinJSBridge == "undefined") {
//微信浏览器内置对象。参考微信官方文档
if (document.addEventListener) {
document.addEventListener(
"WeixinJSBridgeReady",
vm.onBridgeReady(),
false
);
} else if (document.attachEvent) {
document.attachEvent("WeixinJSBridgeReady", vm.onBridgeReady());
document.attachEvent("onWeixinJSBridgeReady", vm.onBridgeReady());
}
} else {
vm.onBridgeReady();
}
},
onBridgeReady() {
let {
appId,
timeStamp,
nonceStr,
package: packageId,
paySign,
signType,
orderId,
} = this.params;
console.log("appId", appId);
console.log("package", packageId);
WeixinJSBridge.invoke(
"getBrandWCPayRequest",
{
appId: appId, //公众号ID,由商户传入
timeStamp: timeStamp, //时间戳,自1970年以来的秒数
nonceStr: nonceStr, //随机串
package: packageId,
signType: signType, //微信签名方式:
paySign: paySign, //微信签名
},
function (res) {
// 使用以上方式判断前端返回,微信团队郑重提示:
//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
sessionStorage.removeItem("paymentParams"); //无论成功还是失败,都清除下单参数
sessionStorage.removeItem("loaded");
if (res.err_msg == "get_brand_wcpay_request:ok") {
console.log("调起成功11111");
//支付成功后的操作
let phoneList = localStorage.getItem("rechargeRcode");
this.saveRechargeRcord(phoneList, data.phoneinfo);
let count = 3; // 循环调用最多3次
const searchPayState = (id) => {
if (count > 0) {
searchQueryPayStatus({
id,
}).then((res) => {
if (!res.data) {
count--;
let times = setTimeout(() => {
clearTimeout(times);
searchPayState(id);
}, 2000);
} else {
this.$router.push("/pay-success");
}
});
} else if (count === 0) {
// 3次过后表示超时(overtime:超时标识
this.$router.push("/pay-success");
}
};
} else {
history.back();
}
}
);
},
},
},
};
</script>
这里我还是有几个没琢磨明白的地方,记录一下,如果有懂的大佬,可以给我解答一下~
1、为什么用this.$router.push跳转WeixinJSBridge就不会报错,用window.location.href跳转就报WeixinJSBridge is not defined
2、为什么用this.$nextTick不行,用settimeout就可以解决
3、我支付授权目录配置的是到域名,按理说不是所有的路径都是合法路径吗