背景

为了节约开发成本,很多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'])......
}

步骤2:修改Manifest

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

<!-- 支付宝SDK -->
<activityandroid:name="com.alipay.sdk.app.H5PayActivity"android:configChanges="orientation|keyboardHidden|navigation"android:exported="false"android:screenOrientation="behind" >
</activity><activityandroid: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;@Overridepublic 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());}}}@Overridepublic 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>() {@Overrideprotected H5PayResultModel doInBackground(Void... params) {return task.h5Pay(ex, true);}@Overrideprotected 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_idUri 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 = "处理异常,请重新打开页面";/*** 支付成功后,客户端跳转*/@JavascriptInterfacepublic void afterPaySuccess(String jsonParam, String callback, String extra) {if (mRequestHandler != null) {mRequestHandler.onPaySuccess();}}}
  • 处理JS交互请求
/*** 处理WebView内js发起的交互请求*/
public interface OnJsRequestHandler {/*** 请求处理支付成功后页面跳转*/void onPaySuccess();
}
  • 加载WebView的Activity实现OnJsRequestHandler
    @Overridepublic void onPaySuccess() {//处理业务逻辑及页面重定向}

手机网站支付转Native支付--Android相关推荐

  1. 手机网站调起支付宝支付

    手机网站调起支付宝支付 由于前几天公司要求我来做支付模块,于是我在总结了各路大佬的代码之后加上了自己的需求,现在把代码和步骤给大家分享出来,希望可以帮到大家. 1.进入支付宝开放平台>开发者中心 ...

  2. phpcms实现PC网站接入微信Native支付

    微信支付-PC网站接入支付 微信支付支持完成域名ICP备案的网站接入支付功能.PC网站接入支付后,可以通过JSAPI支付或Native支付,自行开发生成二维码,用户使用微信"扫一扫" ...

  3. 微信支付,JSAPI支付,APP支付,H5支付,Native支付,小程序支付功能详情以及回调处理

    一.支付相关文档地址 支付wiki:https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml 支付api: https://pay.weixin.qq. ...

  4. 实现微信支付(Native支付),使用WebSocket进行推送——1.简单介绍

    实现微信支付(Native支付),使用WebSocket进行推送--1.简单介绍 一.实现逻辑 1.由于本人的项目是web版本的,因此选用native实现微信支付,在网站生成支付二维码,然后用户在手机 ...

  5. 微信支付之Native支付H5支付JSAPI支付退款

    参考文档: https://mp.weixin.qq.com/mp/homepage?__biz=MzI3OTIwNDU0MA==&hid=2&sn=efa76e36c5b580e41 ...

  6. 实现微信支付(Native支付),使用WebSocket进行推送——3.创建支付订单,接收付款结果

    实现微信支付(Native支付),使用WebSocket进行推送--3.创建支付订单,接收付款结果 注:本实验使用springboot框架 一.创建订单 1.流程 2.创建支付订单所需参数 2. AP ...

  7. 实现微信支付(Native支付),使用WebSocket进行推送 ——4.配置SpringBoot支持WebSocket,推送结果

    实现微信支付(Native支付),使用WebSocket进行推送 --4.配置SpringBoot支持WebSocket,推送结果 依赖 <dependency><groupId&g ...

  8. PC网站微信扫码支付之Native支付(模式二)

    简介 Native支付是指商户系统按微信支付协议生成支付二维码,用户再用微信"扫一扫"完成支付的模式.该模式适用于PC网站.实体店单品或订单.媒体广告支付等场景. Native支付 ...

  9. 记录支付宝手机网站(WAP)支付踩过的坑

    由于苹果审核机制变化,除了JSPatch等热修复的应用受到影响外,另个影响较大的就是非法集成第三方支付SDK(尤其支付宝)而审核被拒.但是由于你懂的的原因,不想走IAP(In App Pay),所以当 ...

最新文章

  1. 第6章:可维护性软件构建方法 6.2可维护性设计模式
  2. Python模块之间的相互引用问题
  3. 剔除异常值栅格计算器_R语言系列 数据清洗3 异常值处理
  4. 解决swiper-slide在ion-slide-box不滑动的问题(暂且这么描述)
  5. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol52]49.描述在IPsec和TLS后的基本想法
  6. Java Web笔记之Struts2.1 +Hibernate3.3 +Spring3.0
  7. css 3d魔方源代码,CSS3 3D环境实现立体 魔方效果代码(示例代码)
  8. 百度再回应“泼水门”:强烈谴责 肇事者已被公安机关带走
  9. 1.12 梯度的数值逼近
  10. 解决:IE中不能自动选择UTF-8编码的解决方法
  11. Postman怎么用?
  12. 解析xlsx与xls--使用2012poi.jar
  13. XML 文档四种解析放式
  14. matlab如何将二进制文件写入txt文档中
  15. 微信小程序 实时音视频通话
  16. 计算机没有休眠,没有休眠选项,电脑没有休眠选项
  17. 如何做html链接,怎么做超链接,制作超链接的详细操作步骤
  18. Python 练习题1
  19. 《我的眼睛--图灵识别》第十一章:实战演练:图像类识别
  20. 关于get请求中文乱码的原因分析

热门文章

  1. 梦里什么都有(状压DP)
  2. HBuilder IOS 打包异常:com.apple.developer.associated-domains权利 ,解决!
  3. Python pip自动管理脚本
  4. Arch Linux 安装Google Earth
  5. Android Dialog 弹窗的生命周期
  6. 元芳, 我在 Win10 上用 Docker 肝了个 LNMP , 康康?
  7. Intellij-出现Module ** must not contain source root **. The root already belongs to module **
  8. “华为起诉美国”事件进展:美国联邦法院给美国政府发传票
  9. npm本地仓库搭建教程
  10. 用区块链解决电子证据司法存证