手机网站支付转Native支付--Android
Posted Zhang Jun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手机网站支付转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:导入开发资源
-
将alipaySdk-20170309.jar包放入商户应用工程module的libs目录下,如下图。
-
在module的build.gradle中添加依赖
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
......
}
步骤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>
和权限声明:
<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" />
步骤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
至此,开发包开发资源导入完成。
接口调用说明
SDK中提供了若干接口,手机网站转Native支付只用到其中一部分,本文未提到的接口无需关注。
如何实现手机网站转Native支付?
步骤一: 在接入方App中拦截H5的URL;
步骤二: 调用SDK提供的“获取订单信息接口(fetchOrderInfoFromH5PayUrl)”对拦截的URL进行处理:
-
如果返回空字符串则不作任何处理
-
反之则调用“支付接口(h5Pay)”进行订单支付,并拦截URL
获取订单信息接口
接口原型
/**
* 获取H5native支付的信息
* @param h5PayUrl
* @return
*/
public synchronized String fetchOrderInfoFromH5PayUrl(String h5PayUrl)
接口功能
从拦截的URL中获取支付请求相关信息,封装成新的订单信息字符串作为返回值。如果该URL不是有效的支付宝支付URL,则返回空字符串。
参数说明
参数名称 | 类型 | 说明 |
---|---|---|
h5PayUrl | String | 手机网站支付的请求URL |
返回值说明
返回值类型 | 说明 |
---|---|
String | 1.如果是有效的支付宝支付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;
}
}
支付接口
接口原型
/**
* 手机网站支付
* @param h5PayInfo 订单信息
* @param isShowPayLoading 是否显示loading图标
* @return
*/
public synchronized H5PayResultModel h5Pay(String h5PayInfo, boolean isShowPayLoading)
接口功能
完成订单支付并返回支付结果。
参数说明
参数名称 | 类型 | 说明 |
---|---|---|
h5PayInfo | String | 调用fetchOrderInfoFromH5PayUrl接口返回的订单信息字符串 |
isShowPayLoading | boolean | 是否显示loading界面 |
返回值说明
返回值类型为H5PayResultModel类,包含下述2个成员变量:
参数名称 | 类型 | 说明 |
---|---|---|
resultCode | String | 返回码,标识支付状态,含义如下: 9000——订单支付成功 8000——正在处理中 4000——订单支付失败 5000——重复请求 6001——用户中途取消 6002——网络连接出错 |
returnUrl | String | 支付结束后应当跳转的url地址 |
接口使用方式
调用本接口进行支付。如果返回的resultCode为9000,接入方可以提示用户支付成功;返回结果不是9000的情况,无需做任何处理。如果returnUrl不为空,建议接入方跳转到该returnUrl。
- 自定义实现帮助WebView处理各种通知、请求时间的WebViewClient
setWebViewClient(new XxWebViewClient());
setWebChromeClient(new XxWebChromeClient());
/**
* 处理页面加载的相关事件
*/
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;
}
}
- 客户端处理支付成功后的页面跳转,需要注入JS回调
WebSettings settings = getSettings();
settings.setjavascriptEnabled(true);
addJavascriptInterface(new JavaScriptInterface(), "android");
/**
* 实现一些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();
}
}
}
- 处理JS交互请求
/**
* 处理WebView内js发起的交互请求
*/
public interface OnJsRequestHandler {
/**
* 请求处理支付成功后页面跳转
*/
void onPaySuccess();
}
- 加载WebView的Activity实现OnJsRequestHandler
@Override
public void onPaySuccess() {
//处理业务逻辑及页面重定向
}
以上是关于手机网站支付转Native支付--Android的主要内容,如果未能解决你的问题,请参考以下文章
手机网络安全问题,浏览器里面的网页跳转到微信支付,或者支付宝,在支付的过程中会有木马病毒吗?
PC软件/web网站/小程序/手机APP产品如何增加个人收款接口