在做一些支付业务的时候,对接第三方的支付平台,在前端页面就会经常使用到 打开新窗口 跳转到第三方的支付页上去的场景。那么就会有以下几种场景需求
- 打开新窗口,给定一个 URL 地址
- 打开新窗口,给定一段 HTML,这个 html 是第三方平台返回的自提交 html(比如支付宝)
- 可能需要监听打开的窗口是否有关闭
打开新窗口,给定 URL 地址
// payUrl 展示开地址的内容
const orderWindow = window.open(payUrl, '_blank', 'width=' + (window.screen.availWidth - 10) + ',height=' + (window.screen.availHeight - 30) + ',top=0,left=0,toolbar=no,menubar=no,scrollbars=no, resizable=no,location=no, status=no')
上面的代码是打开一个新窗口(近乎于全屏的设置),具体的 open 参数含义可以参考 w3c 或则 这个网站
打开新窗口,给定 html 展示
// url 给一个空字符串
const orderWindow = window.open('', '_blank', 'width=' + (window.screen.availWidth - 10) + ',height=' + (window.screen.availHeight - 30) + ',top=0,left=0,toolbar=no,menubar=no,scrollbars=no, resizable=no,location=no, status=no')
// 拿到返回的对象后,将我们自己的 html 写入
orderWindow.document.write(payHtml)
orderWindow.focus() // 让原窗口获取焦点
监听打开的窗口是否关闭
有时候可能会有打开了支付窗口之后,但是用户关闭了,如何处理?
如上图所示,打开新窗口后,原来的页面,你需要间隔的去后台检查这个支付结果,支付完成后,就关闭这个 loading 效果。 正常情况下,新打开的窗口在跳转到支付平台后,支付完成后,会跳转到我们自定义的一个前端页面,这个前端页面,你展示一个结果,然后关闭掉就可以了。
但是这里需要处理 窗口 和 原页面的 loading 交互效果
/**
* 检查支付结果,并且检测打开的新窗口状态,新窗口关闭后,在超时后自动重置 loading 状态
* @param inId 预下单的自定义系统ID,用于像后台获取支付结果,这个结果是支付平台通过异步回调方式通知到后端系统的
* @param orderWindow 新打开的窗口
*/
preOrderSuccessCheckResultAndMonitoringWindow (inId, orderWindow) {
// loading 开关
this.payResultLoading = true
this.windowTimeout = 0 // 发起新的请求时,重置
// 通过每间隔 5 秒检查一次 窗口的 closed 状态,来检查是否已经关闭
const timer = setInterval(() => {
// 如果窗口已关闭
if (orderWindow.closed) {
// 正常支付完成后关闭,最多再等待 10 秒钟
if (this.windowTimeout === 0) {
this.windowTimeout = 10
} else {
// 最多再等待 10 秒,就主动关闭 loading
this.windowTimeout = this.windowTimeout - 5
if (this.windowTimeout <= 0) {
clearTimeout(timer)
this.payResultLoading = false
this.windowTimeout = 0
}
}
}
// 每次去后端检查结果,如果已经成功,就清除定时器和关闭 loading
this.getPayResult(timer, inId)
}, 5000)
this.payResultTimer = timer
},
上面的代码就会实现:
- 如果是正常支付完成,新窗口里面最后会跳转到我们前端的一个自定义结果页,你可以设置 5 秒后自动关闭新窗口,关闭窗口的代码为
**_window_**.close**_()_**
- 如果是人为的直接将新窗口关闭,那么原页面的 loading 效果最多会持续 10 秒种,10 秒后就会关闭