【汇总3种】vue项目中【H5】如何处理后端返回的支付宝form表单,如何实现支付跳转?

背景: 现在的项目,都需要付款,难免涉及支付宝或者微信支付。如果是支付宝支付,很多人都说,都已经2202年了,支付宝返回的还是form表单,然后,唤起支付宝的界面。
    一般来说,支付宝分为前端发起支付,和后台发起支付两种:
①前端发起支付,首先向后台发送订单数据,生成订单。然后,由前端调起手机的支付进行付款;
②如果采用的是,后台发起支付的方式,得到的返回是一个 < form >< /form >的表单html结构,自带< script >里面写的是监听提交按钮事件< /script >标签;
简单来说,由后台发起的支付会返回一个form表单,调用表单中的submit方法唤起支付宝界面。

一、实现思路

    首先,明确业务逻辑,支付跳转之前必然有一个提交订单信息【post】的过程,而我们的整个支付表单form是【post】之后返回发结果。返回的字符串结果如下所示:
在这里插入图片描述

在这里插入图片描述
整理一下,整个的支付流程(此流程,仅针对本公司业务,仅做参考):
①生成token,createToken;
②创建订单createOrder,生成orderCoder(ps:后面获取订单详情需要用到);
H5通过post接口调用,返回form表单(网上大多数案例,就是指的这一步);
④H5和步骤③同时发起,获取订单详情来轮询支付结果,最后,返回支付成功or支付失败的结果(ps:这个流程,后台调用前端无法拿到支付后的回调,目前,采取轮询调取后台支付状态的一个接口)。

二、相关代码

前端相关代码:
2.1 方法一:使用document.forms[0].submit(),提交表单操作
(1)首先,把表单的内容放在一个页面中:

<div class="aliform" v-html="aliform"></div>

(2)通过document.forms[0].submit(),获取当前页面的第一个表单提交:

<script>
export default {
	data() {
	    return {
	      aliform: "",
	    };
  	},
  	methods: {
		async iosAlipay(orderCode) {
      		let data = await requestAlipay(orderCode);
      		if (data.code == 20000) {
        		this.aliform = data.data;  //data.data就是支付宝返回给你的form,获取到的表单内容,具体样子可见上面的图片
        		this.$nextTick(() => {
        			// 获取订单详情来轮询支付结果
          			this.getOrderDetail();  
          			console.log(document.forms);  //跳转之前,可以先打印看看forms,确保后台数据和forms正确,否则,可能会出现一些奇奇怪怪的问题 ╮(╯▽╰)╭
          			document.forms[0].submit();  //重点--这个才是跳转页面的核心,获取第一个表单并提交
        		});
      		}
    	},
    	// 轮询结果
	    getOrderDetail() {
	    //轮询方法,因为支付是跳转到第三方支付宝,我们无法获知用户是否支付成功,或者用户支付成功后是否跳转回来。轮询方法,在一定时间内
	      clearTimeout(this.timer);
	      this.timer = setTimeout(() => {
	        let initTime = +new Date();
	        let loop = () => {
	          getOrderDetail({ orderCode: this.orderCode}).then((res) => {
	            if (res.code == 20000 && res.data && res.data.payStatus == 30) {
	              //支付成功的相关操作
	            } else {
	              let now = +new Date();
	              if (now - initTime < 45000) {
	                loop();
	              } else {
	                // 超时按照失败处理
	                //支付失败的结果
	              }
	            }
	          });
	        };
	        loop();
	      }, 500);
	    },
	}
}
</script>
<style lang="less" scoped >
.aliform {
  width: 1px;
  height: 1px;
  opacity: 0;
}
</style>

(3)题外话–了解一下js提供的document.forms方法:

(1)document.forms //表示获取当前页面的所有表单;
(2)document.forms[0] //表示获取当前页面的第一个表单;
(3)document.forms['exportServlet'] //表示获取当前页面的name="exportServlet"的表单
(4)submit() //表示提交函数

2.2 方法二:使用document.write(),就是重定向,覆盖原始页面

\\ 假设result是后端返回的from字符串
const newWindow = window.open('', '_self');  
newWindow.document.write(result);
newWindow.focus();

或者,直接使用document.write(xxx),来进行支付跳转

await postUserinfo('接口入参').then(res=>{
	document.write(res.data.result)
})

如果是在PC端处理,这种方式是没有问题的,但是需要注意三个问题:
①window.open()在接口回调中触发,可能会被游览器拦截;
②如果本身页面的地址是https的,如果返回的form的action是http的,游览器也会弹出安全提示;
③微信环境window.open()不生效。
2.3 方法三:动态创建div容器,将form渲染进去,js触发form提交
虽然,返回到result的form外面有html包裹,但是,可以动态的创建一个div容器,然后,将包含< html >的result渲染进去,通过js触发form表单的提交。

const div = document.createElement('formdiv');
div.innerHTML = result;
document.body.appendChild(div);
document.forms['cashierSubmit'].setAttribute('target', '_self');
document.forms['cashierSubmit'].submit();
div.remove();

对于H5来说,这种方案兼容性更好。需要注意的是:
一开始,将form的target设置成_blank,导致在ios上的游览器(微信环境,safari,UC)都无法实现form表单的提交。改成_self之后,问题解决。

或者,这样也可:

let divForm = document.getElementsByTagName('divform')
if (divForm.length) {
    document.body.removeChild(divForm[0])
}
const div = document.createElement('divform')
div.innerHTML = res.data // res.data就是支付宝返回给你的form
document.body.appendChild(div)
// document.forms[0].setAttribute('target', '_blank') // 加了_blank可能出问题所以我注释了
document.getElementById('alipay_submit').submit()

又或者,试下这样:

 //将接口返回的Form表单显示到页面
 document.querySelector('body').innerHTML = res.data; // res.data就是支付宝返回给你的form
 //调用submit 方法
 document.forms[0].submit()
参考博客:

UNI-APP解析支付宝返回FORM表单,唤起支付宝界面 https://www.freesion.com/article/6241970398/
Vue完美解决支付宝返回的form表单问题,这可能是最有效的解决办法了 https://blog.zixutech.cn/archives/324
vue项目中后端返回的支付宝form表单,怎么实现支付跳转? https://blog.csdn.net/qq_45934004/article/details/126156546
Vue自动提交form表单后,自动跳转第三方页面 https://www.jianshu.com/p/e2323b4e2cf9
开发笔记之uniapp 支付宝支付返回form表单解决方案 http://blog.haiya360.com/archives/766.html
vue 支付宝返回url 新窗口打开 https://blog.csdn.net/wax9092/article/details/86631151
H5处理支付宝接口返回form https://www.jianshu.com/p/8c5375671495
vue项目中后端返回的支付宝form表单,怎么实现支付跳转? https://blog.csdn.net/qq_45934004/article/details/126156546
Vue完美解决支付宝返回的form表单问题,这可能是最有效的解决办法了 https://blog.zixutech.cn/archives/324

  • 8
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值