前言
- 本文的h5支付具体指的是通过微信和支付宝两个渠道支付的内容。
- 具体介绍了关于支付的流程以及如何使用它们,并在文末会列举一些遇见的问题。
- H5支付是脱离页面所在容器的支付方式,如果 App 不能提供支付方法,那么可采用H5支付,如果 App 可以提供支付方法,那么建议使用 App 原生支付。
- H5支付主要的对接工作在后端,前端所需要处理的是接口返回的支付内容,再进行一系列操作等。
- 微信支付与支付宝支付均以官方文档为主,简洁易懂,还有一些例子提供理解。
- 本文更贴近实际的使用,建议有需要可直接阅读官方文档。
微信h5支付 - 官方文档入口 支付宝h5支付 - 官方文档入口
一、微信支付
上图为微信支付流程图,简单理解就是:
1. 前端请求后端接口下单
2. 后端访问微信后台返回一个可跳转的URL
3. 后端处理之后在接口出参中返回给前端
4. 前端跳转url打开支付跳转页面
5. 支付完成后跳转到目标页面查询支付结果
6. 展示支付结果
在请求创建订单接口,后端接口会返回一个 credential 字段,这个字段会带有微信支付的相关信息。
/**
* 后端订单接口返回的微信跳转
* "tradetype":"MWEB",
* "mchid":"",
* "mweb_url":"",
* "appid":"",
* "sign":"",
* "partnerid":"",
* "prepayid":"",
* "noncestr":"",
* "timestamp":"1607324240"
*/
在这些返回的字段中最重要的是 mweb_url ,我们需要跳转的支付链接。在获取到相关信息之后可以通过下列方法进行处理:
/**
* 微信支付
* @params credential 微信支付相关信息字符串
*/
export function Wxpay(credential) {
console.log('-----------------------------微信支付-------------------------------');
let url = credential.match(/(?<=mweb_url"\:").+(?="\,"appid)/);
let redirect_url = window.location.href; // 用于支付完成跳回原页面
if (url && url.length) {
url = url[0] + '&' + encodeURI(redirect_url);
console.log('微信支付跳转链接: ', url);
OpenWebView(url); // 跳转方法 根据不同项目使用不同方法
} else {
console.log('接口返回支付链接出错')
}
}
在接口返回的字段里如果后端没有处理则需要自己处理返回的字符串,如上图使用正则提取出 mweb_url,在 mweb_url 末端需要加上支付完成后跳转的页面链接(需要使用 encodeURI 处理),在支付完成之后跳回到原来的页面(这里的 OpenWebView 方法需要你们原生开发提供新开一个 webview,或者直接通过 js 创建一个跳转,这个根据不同场景使用)。
跳转的页面会要求你打开微信去支付,如果你是在电脑浏览器打开的,他就关闭当前页面返回首页。所以测试的时候必须在手机浏览器或者壳子中测试。
微信H5支付的实际操作大概就这么多内容,如果想要获取更多更细致的内容还请进入微信支付官网:微信h5支付
二、支付宝
支付宝的交互流程与微信支付大致差不多,不同的是支付宝返回的是一个 html,前端需要操作这个 html 来触发支付。
/**
* 后端返回的支付宝参数
* <form
name="punchout_form"
method="post"
action="https://openapi.alipay.com/gateway.do?charset=UTF-8&method=alipay.trade.wap.pay&sign=...&return_url=...¬ify_url=...&version=1.0&app_id=...&sign_type=RSA2×tamp=2020-12-05+16%3A39%3A29&alipay_sdk=alipay-sdk-java-4.8.73.ALL&format=json">
<input
type="hidden"
name="biz_content"
value="{"out_trade_no":"7777202012051335141732687101954","product_code":"QUICK_WAP_WAY","subject":"价值白马食品饮料","timeout_express":"29m","total_amount":"0.01"}"
>
<input
type="submit"
value="立即支付"
style="display:none"
>
</form>
<script>document.forms[0].submit();</script>
*/
我们可以通过创建 html 的方式使用:
/**
* 支付宝支付
* @params credential form
*/
export function Alipay(credential) {
console.log('-------------------------------支付宝支付-------------------------------');
// 支付宝返回的是一个form表格,如果直接取url会报错,必须使用submit
const div = document.createElement('div');
div.innerHTML = credential;
div.id = 'paySubmit';
document.body.appendChild(div);
document.forms[0].submit();
// 1秒之后清除div,避免新增dom造成的性能问题
setTimeout(() => {
const payDiv = document.getElementById("paySubmit");
payDiv && payDiv.parentNode && payDiv.parentNode.removeChild(payDiv);
}, 1000);
}
此处需要后端在 form 中的 action 加上 return_url 返回跳转链接,这个 return_url 是生成订单的时候入参传给后端的。使用上文中提供的方法跳转会出现支付宝提供的页面。大致过程如下,支付完成后会跳到之前写入的 return_url。
三、关于回调的问题
支付宝和微信支付结束的时候都会把外链的路由加入到历史中,所以我建议在打开生成订单的支付页的时候使用容器新开webview的方法,这样在支付结束直接关闭webview,可以很好的解决点击返回时返回到外链的支付页面。
四、开发过程中遇见的问题
1. 微信支付报错:商家参数格式有误,请联系商家解决
这个错误在官网有提供解决方法,简单来说就是缺失 referer 字段。或者有可能是h5访问的域名和后台申请h5支付的时候填写的h5支付的域名必须一样,否则也会出现这样的错误。
2. 微信:商家存在为配置的参数,请联系商家解决
redirect_url需自己配置在链接末尾,且与申请的域名相同。
3. 微信:打开微信支付之后报错
因为后端的参数没有添加,spbil_create_ip校验严格,必须填正确地址。
4. 支付宝:验签失败
我的项目中报这个错误是因为我开始没有想使用它返回的 form 表单提交,而是直接提取 action 中的链接而忽略了input、type=hidden中的数据,导致访问报错,所以可能时参数没有传入导致的错误,在使用上述列举的方法之后就解决问题了。