一般情况下,要实现应用内支付接入 App 支付 SDK 即可满足业务需求,不过考虑到对于一些类似游戏中心的场景,更多是需要支持 H5 支付。相对微信来说,支付宝的对接简单完善很多,所以本篇文章主要说说接入微信 H5 支付的流程和一些问题。
申请流程
按照微信支付官网 H5 支付说明 ,目前是没有直接申请接入 H5 支付的入口,只能在微信商户平台中去另行开通。然鹅~微信商户平台账户也不支持直接注册申请,只能先注册微信开放平台后接入微信 App 支付后才会有商户账号分配。
1. 注册微信开放平台账户
2. 申请开放平台开发者认证
3. 创建一个应用提交申核
需要应用相关资质,主要是为了开通支付功能。
4. 为应用申请微信 App 支付,开通微信支付功能
开通成功后会自动分配微信商户平台账户
5. 登录商户平台申请开通 H5 支付
这里只是简单介绍下申请流程的主要环节,具体操作起来有多麻烦我也不想去体会。
应用内接入
说到这里可能有些人想笑了,既然叫 H5 支付那不是应该跟应用本身没多大关系才对,不就是一个支付链接跳转而已吗。
话是这么说没错,但是具体操作起来还是有些坑需要去踩。由于微信 H5 支付本身就是浏览器网页支付场景下的产物,所以微信官方并不推荐在应用中使用 H5 支付。
跟浏览器不一样,在 WebView 中我们还需要自己处理一些问题。比如为了实现调起微信支付,需要对支付链接进行拦截后才能进行处理,下面就来看看这个流程。
WebViewClient webViewClient = new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// 判断 url 的 scheme 进行相应的处理
if (url.startsWith("weixin://")){
try{
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
return true;
}catch (Exception e) {
//防止crash (如果手机上没有安装处理某个 scheme 开头的 url 的APP, 会导致crash)
AlertDialog.Builder builder;
builder = new AlertDialog.Builder(mActivity);
builder.setTitle("支付中心").setMessage("该手机没有安装微信客户端,请安装微信后重新完成支付,或换用支付宝进行支付").setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
}).create().show();
return true;
}
}else if (url.startsWith("alipays://") || url.startsWith("alipay")){ // ------ 对alipays:相关的scheme处理 -------
try{
mActivity.startActivity(new Intent("android.intent.action.VIEW", Uri.parse(url)));
return true;
}catch (Exception e) {
// 启动支付宝失败,换成网页支付
mPayWebView.loadUrl(url);
return true;
}
}
if (!(url.startsWith("http") || url.startsWith("https"))) {
return true;
}
view.loadUrl(url, map);
return true;
}
}
你以为这样就完了是吧,然鹅并没有,实际开发中很大机率会出现微信提示商家参数格式有误,请联系商家解决的问题,而且更尴尬的是:这个问题并不会 iOS 中出现,也不会 Android 浏览器中出现,偏偏就是在应用的 WebView 中出现了。
查看官方文档出错问题介绍,说是当前调起 H5支付的 referer 为空导致,WTF? 难道 Android WebView 打开一个链接的 referer 不知指向当前页面的域名?都说实践是检验真理的唯一标准,抓包看看好像还真的是,很好,再一次感觉到了 Android 系统咖喱味代码。
没办法,这锅也不能甩给微信,只能按照文档说的解决方法自己来背。然而这文档说的也是不明不白的,只是说域名设置要一致,废话不多说,直接动手更简单,下面给出示例代码(已自行检验过,真实可用的)
直接在原有的代码基础上进行更改
WebViewClient webViewClient = new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
...
if (!(url.startsWith("http") || url.startsWith("https"))) {
return true;
}
// 比如我们申请时填写的是经常用来测试网络连通性的 http://www.baidu.com
HashMap<String, String> map = new HashMap<String, String>();
// 指定申请微信 H5 支付时填写的域名,
map.put("Referer", "http://www.baidu.com");
view.loadUrl(url, map);
return true;
}
}