通过查看网页源代码,发现“立即购买”是一个按钮,其连接点击协议是这样的:
href="weixin://wap/pay?appid%3Dwx2421b1c4370ec43b%26noncestr%3D3e84679af4efab5f32ee9ea01b2ec290%26package%3DWAP%26prepayid%3Dwx20160504154919fdacd7bc0d0127918780%26timestamp%3D1462348159%26sign%3DC40DC4BB970049D6830BA567189B463B"
瞬间觉得非常熟悉,以前集成app支付的关键代码是这样的:
IWXAPI api;
PayReq request = new PayReq();
request.appId = "wxd930ea5d5a258f4f";
request.partnerId = "1900000109";
request.prepayId= "1101000000140415649af9fc314aa427",;
request.packageValue = "Sign=WXPay";
request.nonceStr= "1101000000140429eb40476f8896f4c9";
request.timeStamp= "1398746574";
request.sign= "7FFECB600D7157C5AA49810D2D8F28BC2811827B";
api.sendReq(req);
上 述a链接里的协议就是app支付里面的各种参数,因此可以得到结论,weixin://wap/pay是微信定义的一种支付协议,用于网页端支付,微信 app必定设置了名为weixin://的scheme,因此可以在网页上唤起微信app,在通过约定的参数名称,获取各种参数,从而可以完成支付,具体 机制跟app支付是相同的。至于上面一系列参数,是第三方网页端跟微信那边获取的,均由第三方服务端处理,客户端不必关心。
知道了以上原理,就该讨论解决方案了,下面有几种可行的方案。
解决方案1
上面可知,微信的H5支付协议可以在浏览器中调起微信,这也是最简单的方案。如果我们的app打开第三方网页用的是手机浏览器的话,就不用做什么,直接可以调起微信支付了。按微信文档所说,应该大部分浏览器都支持,我只是简单测试了两款。
解决方案2
第一种方案固然简单,但事实上我们往往使用WebView来打开第三方网页,而不是手机浏览器,因此如何让WebView也支持调起微信支付才是核心问题。经过测试发现,原生WebView是可以唤起微信支付的,核心代码如下:
webView = new WebView(this);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("http://wxpay.weixin.qq.com/pub_v2/pay/wap.v2.php");
对,就这样简单就OK了。
然而往往我们的app中使用自定义的WebView,经测试发现如果为WebView设置了WebViewClient,如下:
webView.setWebViewClient(new WebViewClient() {
// some logic
}
那么就不能唤起微信支付了,errorCode返回-10,提示“不支持该协议”。联系到可以在浏览器中唤起微信支付,因此我的解决方案如下,经测试是可以的。
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// 如下方案可在非微信内部WebView的H5页面中调出微信支付
if (url.startsWith("weixin://wap/pay?")) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
startActivity(intent);
return true;
}
return super.shouldOverrideUrlLoading(view, url);
}
@Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
}
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
// TODO Auto-generated method stub
super.onReceivedError(view, errorCode, description, failingUrl);
}
});
第二种解决方案的效果图如下,注意使用了WebView打开的网页: