App接入微信H5支付常见错误及原因

在App上接入微信H5支付一般都会遇到一些错误。本文讨论了这些错误的解决方案和背后的原因,希望能让读者能少踩些坑。

错误可以分为两类:一是H5支付域名设置错误,二是URL Scheme跳转App错误。

第一类,H5支付域名设置错误

此类错误一般发生在安卓机器上(网上有人说iOS也遇到类似错误),在微信官方文档里有对这类现象的详细描述。

一般情况下,检查下面两点就能排除这类错误:

  1. 登录商户号对应的商户平台—“产品中心”—“开发配置”,查看设置的H5支付域名是否包含商家发起支付的网页所在的域名。

  2. 在商家发起支付的网页,在发起支付的时候,浏览器会重定向到一个微信的页面(页面地址类似于: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”。

image

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);
    }
}

如果你使用UIApplicationopenURL方法打开URL Scheme,你就不需要在Info.plist中把对应的URL Scheme列为白名单。

因为,UIApplicationcanOpenURL会查询Info.plist中LSApplicationQueriesSchemes中的Scheme,如果没有对应的Scheme就返回NO。而当你使用UIApplicationopenURL方法打开一个URL Scheme的时候,并不会调用canOpenURL

2、支付完成后无法从微信App跳转回到我们的App

在调用微信支付的时候,微信允许你设置一个回调URL。在iOS上,支付完成后,微信会调起手机上的Safari浏览器加载这个回调URL。

这个回调URL的逻辑我们无法改变,但是我们可以在回调URL指向的HTML页面里,判断是否是iOS Safari浏览器。如果是Safari,就可以调用我们App自己的URL Scheme。

我们可以在Info.plist里增加一个URL Types:

image

然后在回调页面里合适的时机调用window.location = "testappdemo",注意"testappdemo"是你在Info.plist里设置的URL Scheme。

这样Safari就会调起你的App。但是在调起你的App之前,会询问用户“是否在xxx里打开”

image

总结

不论iOS还是安卓,在浏览器中完成微信H5支付一般是没有问题的,这也是微信H5支付设计的应用场景。

不论在iOS还是安卓App上,接入微信H5支付都可能遇到各种各样的问题,所以微信官方文档提醒:

H5支付不建议在APP端使用,如需要在APP中使用微信支付,请接APP支付

你可能感兴趣的:(App接入微信H5支付常见错误及原因)