Android通过webview调用H5调起微信app支付

通过Android把H5页面封装成APP,在封装过程中遇到H5中存在调用微信支付的功能。 通过测试我们可以发现:iOS内置浏览器中只要输入相关协议都可以调起相关app的,比如: 

  1. 输入weixin://可以调起微信 

  2. 输入alipay://可以调起支付宝

但android在浏览器中输入上述协议,没有任何响应。因此本文主要探讨是基于android平台的。

我们拿微信官网的支付案例来测试。 https://wxpay.wxutil.com/mch/pay/h5.v2.php
这个是微信商户平台官网的H5支付体验链接。 我们拿这个来封装成Android的APP来调起微信支付。

activity_main.xml页面如下

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <WebView
        android:id="@+id/wv_pay"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</RelativeLayout>  

最主要的是MainActivity.java

public class MainActivity extends Activity {

    private WebView wv_pay;
    private WebSettings mWebSettings;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);

        wv_pay = (WebView) findViewById(R.id.wv_pay);
        wv_pay.setScrollContainer(false);
        wv_pay.setWebChromeClient(new MyWebChromeClient());

        // 设置一些属性
        mWebSettings = wv_pay.getSettings();
        mWebSettings.setJavaScriptEnabled(true); // 可执行js
        mWebSettings.setDefaultZoom(WebSettings.ZoomDensity.MEDIUM); // 设置页面默认缩放密度
        mWebSettings.setDefaultTextEncodingName("UTF-8"); // 设置默认的文本编码名称,以便在解码html页面时使用
        mWebSettings.setAllowContentAccess(true); // 启动或禁用WebView内的内容URL访问
        mWebSettings.setAppCacheEnabled(false); // 设置是否应该启用应用程序缓存api
        mWebSettings.setBuiltInZoomControls(false); // 设置WebView是否应该使用其内置的缩放机制
        mWebSettings.setUseWideViewPort(true); // 设置WebView是否应该支持viewport
        mWebSettings.setLoadWithOverviewMode(true); // 不管WebView是否在概述模式中载入页面,将内容放大适合屏幕宽度
        mWebSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); // 重写缓存的使用方式
        mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true); // 告知js自动打开窗口
        mWebSettings.setLoadsImagesAutomatically(true); // 设置WebView是否应该载入图像资源
        mWebSettings.setAllowFileAccess(true); // 启用或禁用WebView内的文件访问
        mWebSettings.setDomStorageEnabled(true); // 设置是否启用了DOM存储API,默认为false

        String payUrl = "https://wxpay.wxutil.com/mch/pay/h5.v2.php";
        wv_pay.loadUrl(payUrl);

        wv_pay.setWebViewClient(new WebViewClient() {

            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed(); // 让webView接受证书,可以访问https
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                // H5调起微信app支付
                if (url.contains("wx.tenpay")) {
                    Map<String, String> extraHeaders = new HashMap<String, String>();
                    extraHeaders.put("Referer", "https://wxpay.wxutil.com");
                    view.loadUrl(url, extraHeaders);
                    return true;
                }
                if (url.startsWith("weixin://wap/pay?")) {
                    Intent intent = new Intent();
                    intent.setAction(Intent.ACTION_VIEW);
                    intent.setData(Uri.parse(url));
                    startActivity(intent);
                    return true;
                }
                // 以下是调用支付宝支付功能,我没有测试,不确定可用不。
                if (url.startsWith("alipays:") || url.startsWith("alipay")) {
                    try {
                        startActivity(new Intent("android.intent.action.VIEW", Uri.parse(url)));
                    } catch (Exception e) {
                        new AlertDialog.Builder(MainActivity.this).setMessage("未检测到支付宝客户端,请安装后重试。")
                                .setPositiveButton("立即安装", new DialogInterface.OnClickListener() {

                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        Uri alipayUrl = Uri.parse("https://d.alipay.com");
                                        startActivity(new Intent("android.intent.action.VIEW", alipayUrl));
                                    }
                                }).setNegativeButton("取消", null).show();
                    }
                    return true;
                }
                if (!(url.startsWith("http") || url.startsWith("https"))) {
                    return true;
                }
                view.loadUrl(url);
                return true;
            }
        });

        // android 5.0以上默认不支持Mixed Content
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            wv_pay.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
        }
    }

    // 点击返回上一页面而不是退出浏览器
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && wv_pay.canGoBack()) {
            wv_pay.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}

下面说最重要的两点

1.这里是重写onReceivedSslError方法,一定要handler.proceed();这样WebView才可以接受所有证书,访问https!

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {  
        handler.proceed(); // 让webView接受证书,可以访问https
}

这个方法不重写,就会出现白屏!

2.APP里调起H5支付,需要在webview中手动设置referer,这里的这个域名是商户申请H5时提交的授权域名

extraHeaders.put("Referer","https://wxpay.wxutil.com");  

这个不设置很容易出现错误!

以上就是主要的代码啦! 最后记住在AndroidManifest.xml添加上网络权限哦!

Allen

是非本无绝对,答案何须完美?

你在哪儿,我就在哪儿 https://blog.csdn.net/Sias_666