兼容移动端浏览器用户未付费挽留页提示
// visibilityChange事件兼容性写法 var hidden, visibilityChange; if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support hidden = "hidden"; visibilityChange = "visibilitychange"; } else if (typeof document.msHidden !== "undefined") { hidden = "msHidden"; visibilityChange = "msvisibilitychange"; } else if (typeof document.webkitHidden !== "undefined") { hidden = "webkitHidden"; visibilityChange = "webkitvisibilitychange"; } // 监听用户返回页面的事件 if (sessionStorage.getItem('qyyz_paying') == 'true') { this.signStack.push('reload') this.httpQueryOrderPay('reload'); } window.addEventListener('pageshow', this.pageShow, false); document.addEventListener(visibilityChange, this.visibilityChange, false); // 参数说明: httpCount: 请求是否支付的接口次数, httpQueryOrderPay根据自己的接口逻辑来替换, methods: { pageShow() { if (sessionStorage.getItem('sign_paying') == 'true') { // 是否支付中 // 轮询是否支付了 this.signStack.push('pageShow'); setTimeout(() => { this.httpQueryOrderPay('pageShow'); }, 0) } }, visibilityChange() { if (!document[hidden]) { if (sessionStorage.getItem('sign_paying') == 'true') { // 是否支付中 // 轮询是否支付了 this.signStack.push('visibilityChange'); setTimeout(() => { this.httpQueryOrderPay('visibilityChange'); }, 0) } } }, httpQueryOrderPay(type) { if (type !== this.signStack[0]) { // 谁最先执行就走哪个 return; } this.httpCount++; ajax({ url: '查询订单支付结果的接口', type: 'get', data: { orderId: 订单id }, success: res => { if (res.result) { this.httpCount = 0; sessionStorage.setItem('sign_paying', false); } else { if (this.httpCount < 3) { // 轮询不超过3次 setTimeout(() => { this.httpQueryOrderPay(type); }, 500) } else if (this.httpCount == 3) { // 轮询到第3次没有找到,则提示用户 this.httpCount = 0; sessionStorage.setItem('sign_paying', false); // 挽留提示 } } }, //异常处理 error: e => { this.httpCount = 0; sessionStorage.setItem('sign_paying', false); } }) }, }
这边就只展示解决兼容移动端浏览器去请求后端是否支付订单的步骤;
解释一下为啥使用两种监听事件,还有为啥要用sessionStorage去存储sign_paying这个是否支付中状态
在一些移动端浏览器中,各个浏览器五花八门,一些浏览器的行为也千姿百态,
在ios的safari浏览器中,前进后退是走缓存的,安卓浏览器中一些走缓存一些不走缓存,如果不用localStorage存储状态每次前进后退会导致sign_paying一直都被重置为false,导致不去请求支付结果接口,从而导致不执行支付成功或失败的逻辑
pageshow事件是不管页面走不走缓存都会触发的window事件,页面刷新也会执行,也就是说只要来到这个页面就执行,但是后台挂起在打开不执行
visibilitychange事件将后台挂起在打开会执行,
正如上面所说的各个浏览器心怀鬼胎,我们都猜不到他们的行为是如何的,在拉起支付宝(针对原生支付)的行为上也不太清楚,就我测试的ios是直接跳到新的页面在提示拉起(产生前进/后退),在安卓上有的也是跳到新的页面在提示拉起(产生前进/后退),有的直接在当前页就直接提示拉起(不产生前进/后退);
因此同时监听上2个事件,并在监听事件里加上httpCount:0时才能执行httpQueryOrderPay, signStack是用来限制只走一遍查询,因为2个监听可能同时都会执行httpQueryOrderPay
还有一点就是可能有人会觉得奇怪为什么把httpQueryOrderPay用setTimeout变为异步, 因为在部分手机(在我测试来看 三星默认浏览器存在这个问题)会导致ajax请求xhr.status返回0,导致直接走到error;具体原因我也不太清楚T_T,但是只要异步一下就OK了。
这些也只是为了知道啥时候才去请求支付结果接口,不然也大可以直接在页面一展示就去请求轮询,但是对服务器压力太大~