学向勤中得,萤窗万卷书。这篇文章主要讲述手机网站支付转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, 则返回空字符串 |
@
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界面 |
参数名称 | 类型 | 说明 |
---|---|---|
resultCode | String | 返回码,
标识支付状态,
含义如下:
9000——订单支付成功 8000——正在处理中 4000——订单支付失败 5000——重复请求 6001——用户中途取消 6002——网络连接出错 |
returnUrl | String | 支付结束后应当跳转的url地址 |
- 自定义实现帮助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() {
//处理业务逻辑及页面重定向
}
推荐阅读
- windows下Qt5.4.2 for android开发环境配置
- App.config的典型应用
- Android开源日志库Logger
- 如何将Pandas DataFrame导出到JSON文件()
- 如何将Pandas DataFrame导出到Excel文件()
- 如何将Pandas DataFrame导出到CSV文件()
- 如何在Python中创建Pandas DataFrame()
- 如何使用Pandas将Excel文件导入Python()
- 如何将具有变量名称的CSV文件导入Python()