当前位置:   article > 正文

手机网站支付转Native支付--Android_手机网站支付转native支付 android

手机网站支付转native支付 android

背景

为了节约开发成本,很多Native-H5混合App采用手机网站支付的方式去实现支付模块。但手机网站支付的网络依赖比较严重,也通常需要经过更多的验证,这种种原因导致手机网站支付的成功率比Native支付低,对商户的利益造成影响。

简介

手机网站支付转Native支付是支付宝标准版SDK内置的一项功能,能够帮助Native-H5混合App以极低的接入成本极大地提升支付成功率。

手机网站支付PK手机网站转Native支付

主要区别是:如果用户手机安装了支付宝App,手机网站转Native支付方式会跳转到支付宝App中进行订单支付,用户体验和支付成功率均优于手机网站支付方式。除此之外,还能使用手机网站支付没有提供的功能,例如:指纹支付、手环、手表支付、免密支付等。

如果用户手机没有安装支付宝App怎么办? 如果用户手机没有安装支付宝App,将在SDK提供的WebView中打开H5页面进行支付。即便如此,由于SDK与服务端的交互携带账号信息,仍比不携带任何账号信息的普通手机网站支付体验更好。

如何实现手机网站转Native支付

要实现上述功能需接入我们提供的SDK。

下载Demo

接入过程十分简单,可以以Demo为参考,该Demo程序只有一个功能:创建一个WebView,在WebView中拦截每个URL,然后调用SDK提供的接口检查该URL是否是有效的支付宝订单支付URL,如果是则将该URL传给SDK提供的支付接口进行支付。

Android接入说明

配置

步骤1:导入开发资源
  1. 将alipaySdk-20170309.jar包放入商户应用工程module的libs目录下,如下图。

    这里写图片描述

  2. 在module的build.gradle中添加依赖

    dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    ......
}
  • 1
  • 2
  • 3
  • 4
步骤2:修改Manifest

在商户应用工程的AndroidManifest.xml文件里面添加Activity声明:

<!-- 支付宝SDK -->
<activity
    android:name="com.alipay.sdk.app.H5PayActivity"
    android:configChanges="orientation|keyboardHidden|navigation"
    android:exported="false"
    android:screenOrientation="behind" >
</activity>

<activity
    android:name="com.alipay.sdk.auth.AuthActivity"
    android:configChanges="orientation|keyboardHidden|navigation"
    android:exported="false"
    android:screenOrientation="behind" >
</activity>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

和权限声明:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  • 1
  • 2
  • 3
  • 4
  • 5
步骤3:添加混淆规则

在商户应用工程的proguard-rules.pro里添加以下相关规则:

# 支付宝SDK
-libraryjars ../appcommon/libs/alipaySdk-20170309.jar

-keep class com.alipay.android.app.IAlixPay{*;}
-keep class com.alipay.android.app.IAlixPay$Stub{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
-keep class com.alipay.sdk.app.PayTask{ public *;}
-keep class com.alipay.sdk.app.AuthTask{ public *;}
-dontwarn android.net.SSLCertificateSocketFactory
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

至此,开发包开发资源导入完成。

接口调用说明

SDK中提供了若干接口,手机网站转Native支付只用到其中一部分,本文未提到的接口无需关注。

如何实现手机网站转Native支付?
步骤一: 在接入方App中拦截H5的URL;
步骤二: 调用SDK提供的“获取订单信息接口(fetchOrderInfoFromH5PayUrl)”对拦截的URL进行处理:
  • 如果返回空字符串则不作任何处理

  • 反之则调用“支付接口(h5Pay)”进行订单支付,并拦截URL

获取订单信息接口

接口原型
/**
 * 获取H5native支付的信息
 * @param h5PayUrl
 * @return
 */
public synchronized String fetchOrderInfoFromH5PayUrl(String h5PayUrl)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
接口功能

从拦截的URL中获取支付请求相关信息,封装成新的订单信息字符串作为返回值。如果该URL不是有效的支付宝支付URL,则返回空字符串。

参数说明
参数名称类型说明
h5PayUrlString手机网站支付的请求URL
返回值说明
返回值类型说明
String1.如果是有效的支付宝支付URL,则返回非空字符串(订单信息字符串)
2.如果是无效的支付宝支付URL,则返回空字符串
接口使用方式

调用本接口对拦截的URL进行处理,如果返回值为空字符串则不拦截该URL;如果返回值为非空字符串,则调用SDK提供的支付接口进行支付,使用示例如下:

@Override
public boolean shouldOverrideUrlLoading(final WebView view, String url) {
    final PayTask task = new PayTask(H5PayDemoActivity.this);
  
    //处理订单信息
    final String ex = task.fetchOrderInfoFromH5PayUrl(url);
        if (!TextUtils.isEmpty(ex)) {
            //调用支付接口进行支付
        } else {
            view.loadUrl(url);
        }
        return true;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

支付接口

接口原型
/**
  * 手机网站支付
  * @param h5PayInfo 订单信息
  * @param isShowPayLoading 是否显示loading图标
  * @return
  */
public synchronized H5PayResultModel h5Pay(String h5PayInfo, boolean isShowPayLoading)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
接口功能

完成订单支付并返回支付结果。

参数说明
参数名称类型说明
h5PayInfoString调用fetchOrderInfoFromH5PayUrl接口返回的订单信息字符串
isShowPayLoadingboolean是否显示loading界面
返回值说明

返回值类型为H5PayResultModel类,包含下述2个成员变量:

参数名称类型说明
resultCodeString返回码,标识支付状态,含义如下:
9000——订单支付成功
8000——正在处理中
4000——订单支付失败
5000——重复请求
6001——用户中途取消
6002——网络连接出错
returnUrlString支付结束后应当跳转的url地址
接口使用方式

调用本接口进行支付。如果返回的resultCode为9000,接入方可以提示用户支付成功;返回结果不是9000的情况,无需做任何处理。如果returnUrl不为空,建议接入方跳转到该returnUrl。

  • 自定义实现帮助WebView处理各种通知、请求时间的WebViewClient
setWebViewClient(new XxWebViewClient());
setWebChromeClient(new XxWebChromeClient());
  • 1
  • 2
   /**
     * 处理页面加载的相关事件
     */
    private class XxWebViewClient extends WebViewClient {

        private AsyncTask<Void, Void, H5PayResultModel> mPayTask = null;

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            if (mRequestHandler != null) {
                String title = view.getTitle();
                if (!TextUtils.isEmpty(title) && !title.contains("http")) {
                    mRequestHandler.onRequestChangeTitle(view.getTitle());
                }
            }
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (URLUtil.isNetworkUrl(url)) {
                // 尝试处理支付宝链接
                if (url.contains("alipay.com")) {
                    return handleAliPayUrl(url);
                }

                return false;
            }

            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            getContext().startActivity(intent);
            return true;
        }

        /**
         * 处理支付宝支付请求,转 native 支付
         */
        private boolean handleAliPayUrl(String url) {
            Context context = getContext();
            if (!(context instanceof Activity)) {
                return false;
            }

            final PayTask task = new PayTask((Activity) context);
            final String ex = task.fetchOrderInfoFromH5PayUrl(url);
            if (TextUtils.isEmpty(ex)) {
                return false;
            }

            // 启动 native 支付
            if (mPayTask == null || mPayTask.getStatus() != AsyncTask.Status.RUNNING) {
                mPayTask = new AsyncTask<Void, Void, H5PayResultModel>() {

                    @Override
                    protected H5PayResultModel doInBackground(Void... params) {
                        return task.h5Pay(ex, true);
                    }

                    @Override
                    protected void onPostExecute(H5PayResultModel result) {
                        super.onPostExecute(result);
                        String returnUrl = result.getReturnUrl();
                        if (TextUtils.isEmpty(returnUrl)) {
                        /*
                         * 返回码,标识支付状态,含义如下:
                         * 9000——订单支付成功
                         * 8000——正在处理中
                         * 4000——订单支付失败
                         * 5000——重复请求
                         * 6001——用户中途取消
                         * 6002——网络连接出错
                         */
                            final String code = result.getResultCode();
                            if ("9000".equals(code)) {
                                if (mRequestHandler != null) {
                                    mRequestHandler.onPaySuccess();
                                }
                            }
                        } else { // 支付结束后应当跳转的url地址

                            // 特殊处理地址中的 notify_id
                            Uri uri = Uri.parse(returnUrl);
                            String notifyId = Uri.encode(uri.getQueryParameter("notify_id"));
                            returnUrl = returnUrl.replace(notifyId, Uri.encode(notifyId));
                            loadUrl(returnUrl);
                        }
                    }
                };
                mPayTask.execute();
            }

            return true;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 客户端处理支付成功后的页面跳转,需要注入JS回调
WebSettings settings = getSettings();
settings.setJavaScriptEnabled(true);
addJavascriptInterface(new JavaScriptInterface(), "android");
  • 1
  • 2
  • 3
    /**
     * 实现一些JS回调的方法
     */
    private class JavaScriptInterface {

        // JS回调的版本,这个值需要根据JavaScriptInterface所支持的方法来调整
        private static final String VERSION_JAVASCRIPT_INTERFACE = "2";

        // 常用的提示文案
        private static final String MSG_REQUEST_HANDLER_IS_NULL = "处理异常,请重新打开页面";

        /**
         * 支付成功后,客户端跳转
         */
        @JavascriptInterface
        public void afterPaySuccess(String jsonParam, String callback, String extra) {
            if (mRequestHandler != null) {
                mRequestHandler.onPaySuccess();
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 处理JS交互请求
/**
 * 处理WebView内js发起的交互请求
 */
public interface OnJsRequestHandler {

    /**
     * 请求处理支付成功后页面跳转
     */
    void onPaySuccess();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 加载WebView的Activity实现OnJsRequestHandler
    @Override
    public void onPaySuccess() {
        //处理业务逻辑及页面重定向
    }
  • 1
  • 2
  • 3
  • 4
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/122843
推荐阅读
相关标签
  

闽ICP备14008679号