在App上接入微信H5支付一般都会遇到一些错误。本文讨论了这些错误的解决方案和背后的原因,希望能让读者能少踩些坑。
错误可以分为两类:一是H5支付域名设置错误,二是URL Scheme跳转App错误。
第一类,H5支付域名设置错误
此类错误一般发生在安卓机器上(网上有人说iOS也遇到类似错误),在微信官方文档里有对这类现象的详细描述。
一般情况下,检查下面两点就能排除这类错误:
登录商户号对应的商户平台—“产品中心”—“开发配置”,查看设置的H5支付域名是否包含商家发起支付的网页所在的域名。
-
在商家发起支付的网页,在发起支付的时候,浏览器会重定向到一个微信的页面(页面地址类似于:
https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096
),这个页面会校验权限和安全性,我们暂且把它叫做微信校验页面。为了校验发起支付的域名是否合法,在请求微信校验页面的HTTP请求里,头部(HTTP Header)需要有“Referer”这个字段。了解HTTP的同学可能知道,Referer字段会告诉服务器请求的原始资源的URI。也就是说,Referer会告诉腾讯的服务器,是谁在请求微信校验页面。所以Referer的值应该是商家发起支付的页面的域名。
通常情况下,浏览器或者WebView会为我们自动加上Referer,但是在安卓的自定义WebView中,无法自动加上Referer。需要在WebView中手动设置Referer,如:
Map extraHeaders = new HashMap(); extraHeaders.put("Referer", "商户申请H5时提交的授权域名"
第二类,URL Scheme跳转错误
1、无法跳转到微信App
在完成了上述校验后,浏览器或者WebView会被重定向到一个URL Scheme(类似于:weixin://wap/pay?prepayid%3Dwx261541599457545c6f11d41a1106566432&package=1888940394&noncestr=1564126923&sign=1ba23428a32b17d5d03cf032b283379f
)。
对于安卓或者iOS的浏览器来说,这种URL Scheme一般可以成功跳转。但是对于安卓自定义WebView和iOS的WKWebView来说,无法使用URL Scheme跳转。
1)安卓自定义WebView
往往我们的app中使用自定义的WebView,会设置很多参数,经测试发现如果为WebView设置了WebViewClient,如下:
webView.setWebViewClient(new WebViewClient() {
// some logic
}
那么就不能唤起微信支付了,errorCode返回-10,提示“不支持该协议”。我们需要手动调起微信:
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// 如下方案可在非微信内部WebView的H5页面中调出微信支付
if (url.startsWith("weixin://")) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
startActivity(intent);
return true;
}
return super.shouldOverrideUrlLoading(view, url);
}
2) iOS UIWebView
如果iOS端使用的是UIWebView,是可以支持URL Scheme的。但是自iOS 9之后,URL Scheme必须在Info.plist中列为白名单才有效。
打开Info.plist,增加“LSApplicationQueriesSchemes”一行,类型设置为Array,并在这个数组中加入一个条目:“weixin”。
3)iOS WKWebView
WKWebView不支持URL Scheme,或者叫默认不支持URL Scheme,需要我们手动调起微信。参考解决方法:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURL *url = navigationAction.request.URL;
NSString *urlString = (url) ? url.absoluteString : @"";
if ([urlString containsString:@"weixin://"]) {
[[UIApplication sharedApplication] openURL:url];
decisionHandler(WKNavigationActionPolicyCancel);
}
}
如果你使用UIApplication
的openURL
方法打开URL Scheme,你就不需要在Info.plist中把对应的URL Scheme列为白名单。
因为,UIApplication
的canOpenURL
会查询Info.plist中LSApplicationQueriesSchemes中的Scheme,如果没有对应的Scheme就返回NO。而当你使用UIApplication
的openURL
方法打开一个URL Scheme的时候,并不会调用canOpenURL
。
2、支付完成后无法从微信App跳转回到我们的App
在调用微信支付的时候,微信允许你设置一个回调URL。在iOS上,支付完成后,微信会调起手机上的Safari浏览器加载这个回调URL。
这个回调URL的逻辑我们无法改变,但是我们可以在回调URL指向的HTML页面里,判断是否是iOS Safari浏览器。如果是Safari,就可以调用我们App自己的URL Scheme。
我们可以在Info.plist里增加一个URL Types
:
然后在回调页面里合适的时机调用window.location = "testappdemo"
,注意"testappdemo"是你在Info.plist里设置的URL Scheme。
这样Safari就会调起你的App。但是在调起你的App之前,会询问用户“是否在xxx里打开”
总结
不论iOS还是安卓,在浏览器中完成微信H5支付一般是没有问题的,这也是微信H5支付设计的应用场景。
不论在iOS还是安卓App上,接入微信H5支付都可能遇到各种各样的问题,所以微信官方文档提醒:
H5支付不建议在APP端使用,如需要在APP中使用微信支付,请接APP支付