当开发者已完成 **手机网站支付服务端接入** 后可以通过 Native 支付方式唤起支付宝 App。
为了节约开发成本,商家在自有App内嵌H5页接入手机网站支付,由于手机网站支付的网络依赖比较严重,通常需要经过更多的验证, 这样会降低支付的成功率。为了能够帮助商家使用 Native-H5 混合 App 以极低的接入成本 极大的 提升支付成功率,平台推出了手机网站支付转 Native 支付方式,商家下载使用 [支付宝标准版 SDK](https://ideservice.alipay.com/cms/site/02km9l) 内置的功能完成手机网站支付。
**注意**:若未安装支付宝App参考下图,点击下载支付宝App付款下载之后再进行支付。 ![1.png](https://cdn.nlark.com/yuque/0/2022/png/179989/1667447228519-034881d4-4c94-4cbe-a404-5c3f58641e3f.png#__spacing=both&height=431&id=awOFp&originHeight=956&originWidth=555&originalType=binary&ratio=1&rotation=0&showTitle=false&size=105266&status=done&style=stroke&title=&width=250)下面以淘宝为例对比手机网站支付和手机网站转 Native 支付的流程。 ## 手机网站支付流程 在手机端浏览器中访问淘宝主页 www.taobao.com,在页面挑选商品并进行付款,点击 **立即支付** 进入付款详情页面(H5 页面)。 ### iOS ![](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/210044/1669708516889-1f5ea361-8688-4804-a519-eeca81f29ed2.png#height=341&id=vSiDU&originHeight=2621&originWidth=4610&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=stroke&title=&width=600) ### Android ![](https://intranetproxy.alipay.com/skylark/lark/0/2022/jpeg/210044/1669708527413-c83e4f8d-ee73-45e1-9fe2-c4228a07f1c3.jpeg#height=390&id=MZ3oL&originHeight=2884&originWidth=4438&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=stroke&title=&width=600) ## 手机网站转 Native 支付流程 [下载](https://gw.alipayobjects.com/os/bmw-prod/35af7422-15e4-4605-be0a-e5caf653d50f.zip) 并运行 Demo,将 Demo App 安装到手机上即可体验该流程,并在 Demo 中打开淘宝主页  www.taobao.com,挑选商品并进行付款。
**注意**:请确保手机上安装了支付宝客户端。 ### iOS 点击 **URLPay** >** openUrl**,输入 www.taobao.com 并点击 **Go**,然后在淘宝主页选中商品并付款。 ![ios支付.png](https://cdn.nlark.com/yuque/0/2022/png/179989/1653964887752-d06a0058-2a98-4b58-93ed-1956c6b67884.png#__spacing=both&height=275&id=jvIFn&originHeight=950&originWidth=3114&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1005947&status=done&style=stroke&title=&width=900) ### Android 点击 **网页支付转native** 然后在淘宝主页选中商品并付款。 ![Android支付.png](https://cdn.nlark.com/yuque/0/2022/png/179989/1653964937853-083f3e73-402a-4a9d-9922-d149609f3c44.png#__spacing=both&height=370&id=SJPZT&originHeight=1052&originWidth=2562&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1285106&status=done&style=stroke&title=&width=900) ## 对比总结 手机网站支付与手机网站转 Native 支付的主要区别为: - 如果用户手机安装了支付宝客户端,手机网站转 Native 支付方式将跳转到支付宝客户端中进行订单支付,用户体验和支付成功率均优于手机网站支付方式。除此之外,还能使用手机网站支付没有提供的指纹支付、手环支付、手表支付、免密支付等功能。 - 如果用户手机没有安装支付宝客户端,将在 SDK 提供的 Web-view 中打开 H5 页面进行支付。即便如此,由于 SDK 与服务端的交互携带账号信息,仍比不携带任何账号信息的普通手机网站支付体验更好。 ## 如何实现手机网站转Native支付 要实现上述功能需接入支付宝提供的 SDK。接入过程十分简单,可以以上述 Demo 为参考,该 Demo 程序只有一个功能:创建一个 Web-view,在 Web-view 中拦截每个 URL,然后调用 SDK 提供的接口检查该 URL 是否是有效的支付宝订单支付 URL,如果是则将该 URL 传给 SDK 提供的支付接口进行支付。 # iOS 接入说明 ## 配置 **步骤1:**启动 IDE(如 Xcode),把 iOS 包中的压缩文件中以下文件拷贝到项目文件夹下,并导入到项目工程中。 ```csharp AlipaySDK.bundle AlipaySDK.framework ``` 在 Build Phases 选项卡的 Link Binary With Libraries 中,增加以下依赖: ![ios_依赖.png](https://cdn.nlark.com/yuque/0/2022/png/179989/1653965021904-273b8376-e1f0-4b33-8263-1f6552cf72a0.png#__spacing=both&height=538&id=ra0bH&originHeight=538&originWidth=1112&originalType=binary&ratio=1&rotation=0&showTitle=false&size=131510&status=done&style=none&title=&width=1112)其中,需要注意的是: - 如果是 Xcode 7.0 之后的版本,需要添加 libc++.tbd、libz.tbd。 - 如果是 Xcode 7.0 之前的版本,需要添加 libc++.dylib、libz.dylib(如下图)。 ![额外.png](https://cdn.nlark.com/yuque/0/2022/png/179989/1653965030826-320a9646-03fc-42d2-a41a-85646ee637a4.png#__spacing=both&height=118&id=x67tQ&originHeight=118&originWidth=1500&originalType=binary&ratio=1&rotation=0&showTitle=false&size=32556&status=done&style=none&title=&width=1500)**步骤2:**在需要调用 AlipaySDK 的文件中,增加头文件引用。 ```csharp #import ``` **步骤3:**配置支付宝客户端返回 URL 处理方法。外部存在支付宝客户端,支付宝客户端将处理结果通过 url 返回。如示例 AliSDKDemo\APAppDelegate.m 文件中,增加引用代码: ```csharp #import ``` 在 _@_implementation  AppDelegate 中增加如下代码: ```csharp - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { //如果极简开发包不可用,会跳转支付宝客户端进行支付,需要将支付宝客户端的支付结果回传给开发包 if ([url.host isEqualToString:@"safepay"]) { [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) { //【由于在跳转支付宝客户端支付的过程中,商户App在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理,就是在这个方法里面处理跟callback一样的逻辑】 NSLog(@"result = %@",resultDic); }]; } if ([url.host isEqualToString:@"platformapi"]){//支付宝客户端快登授权返回authCode [[AlipaySDK defaultService] processAuthResult:App在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理,就是在这个方法里面处理跟callback一样的逻辑】 NSLog(@"result = %@",resultDic); }]; } return YES; } ``` ## 接口调用说明 本 SDK 提供的所有接口均定义在 AlipaySDK.h 中。SDK 中提供了若干接口,手机网站转 Native 支付只用到其中一部分,本文未提到的接口无需关注。 ### 调用提供的接口 App 支付最新版本 15.4.0 新增拦截+支付二合一接口(payInterceptorWithUrl... ),该接口将原来的获取 H5 支付订单信息接口和支付接口进行了合并。接口的调用方式是先调用 defaultService 获取 SDK 的实例,然后再调用单独提供的功能接口,以 payInterceptorWithUrl 为例: ```csharp [[AlipaySDK defaultService] payInterceptorWithUrl:url fromScheme:scheme callback:^(NSDictionary *result) { // 处理支付结果 NSLog(@"%@", result); }]; ``` ### 实现手机网站转APP支付 1. 实现 UIWebViewDelegate 协议,拦截 H5 的 URL。 2. 调用新增拦截+支付二合一接口(payInterceptorWithUrl...)进行 URL 拦截及支付转化;具体查看下文 **拦截+支付二合一接口**。 ## 拦截+支付二合一接口 本接口首先是个拦截器,拦截支付宝 H5 支付 URL。其次是个支付方式转化器,将手机网站支付方式转化为 APP 支付方式。 ### 示例代码 ```csharp /** * 支付宝H5支付URL拦截器,完成拦截及支付方式转化 * * @param urlStr 待过滤拦截的 url string * @param schemeStr 调用支付的App注册在info.plist中的scheme * @param compltionBlock 支付结果回调Block * * @return YES:表示URL为支付宝支付URL,URL已经被拦截转化;NO:表示URL非支付宝支付URL; */ - (BOOL)payInterceptorWithUrl:(NSString *)urlStr fromScheme:(NSString *)schemeStr callback:(CompletionBlock)completionBlock; ``` ### 参数说明 | **参数名称** | **类型** | **说明** | | --- | --- | --- | | urlStr | NSString * | 手机网站支付的请求 URL。 | | schemeStr | NSString * | 接入方 App 注册的 URL scheme,供支付完成后跳回接入方 App。 | | completionBlock | objc(^CompletionBlock)(NSDictionary *resultDic) | 支付结束之后的回调,其中 CompletionBlock 定义如下:`objctypedef void(^CompletionBlock)(NSDictionary \\*resultDic);` | ### 同步拦截结果返回值说明 | **返回值类型** | **描述** | | --- | --- | | BOOL |
- 如果 urlStr 是有效的支付宝 H5 支付 URL,则说明拦截转化成功,返回 YES,商户容器无需再加载该 URL。
- 如果是无效的,则返回 NO,商户容器需要继续加载该 URL。
| ### 异步支付结果返回值说明 支付结束后 SDK 将回调 completionBlock,并将支付结果 resultDic(NSDictionary *类型)作为参数传入该 Block。resultDic 中主要包含两个字段,如下所示: | **参数名称** | **类型** | **说明** | | --- | --- | --- | | resultCode | NSString * | 返回码,标识支付状态,含义如下:
9000——订单支付成功
8000——正在处理中
4000——订单支付失败
5000——重复请求
6001——用户中途取消
6002——网络连接出错 | | returnUrl | NSString * | 支付结束后应当跳转的 URL 地址。 | ### 接口使用方式 调用本接口对支付宝支付 URL 进行拦截和支付转化。当接口调用完成后,该接口会返回一个 BOOL 类型的同步拦截结果: - 如果同步结果返回值为 YES,说明传入的 URL 为支付宝支付 URL,支付宝 SDK 已经成功拦截该 URL,并转化为 App 支付方式,商户容器无需再加载该 URL。 - 如果返回值为 NO,说明传入的 URL 并非支付宝支付 URL,商户容器需要继续加载该URL。 当支付结束后,会通过回调的方式返回异步支付结果: - 如果返回的支付结果中的 resultCode 为 9000,则表示支付成功,接入方可以提示用户支付成功。 - 如果返回结果不是 9000,则无需做任何处理。当返回的 returnUrl 不为空,建议接入方跳转到该 returnUrl。 ```csharp - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { __weak APWebViewController* wself = self; BOOL isIntercepted = [[AlipaySDK defaultService] payInterceptorWithUrl:[request.URL absoluteString] fromScheme:@"alisdkdemo" callback:^(NSDictionary *result) { // 处理支付结果 NSLog(@"%@", result); // isProcessUrlPay 代表 支付宝已经处理该URL if ([result[@"isProcessUrlPay"] boolValue]) { // returnUrl 代表 第三方App需要跳转的成功页URL NSString* urlStr = result[@"returnUrl"]; [wself loadWithUrlStr:urlStr]; } }]; if (isIntercepted) { return NO; } return YES; } ``` # Android接入说明 ## 配置 ### 导入开发资源 1. 将 alipaySdk-xxxxxxxx.jar 包放入商户应用工程的 libs 目录下,如下图。
![Android_依赖.png](https://cdn.nlark.com/yuque/0/2022/png/179989/1653965102871-240ece7b-08bf-487a-bdff-992c0b6b78bc.png#__spacing=both&height=78&id=QHGmp&originHeight=78&originWidth=516&originalType=binary&ratio=1&rotation=0&showTitle=false&size=11354&status=done&style=none&title=&width=516) 2. 进入商家应用工程的 Project Structure,在 app module 下选择 File dependency,将 libs 目录下的 alipaySDK-xxxxxxxx.jar 导入,如下图。![导入.png](https://cdn.nlark.com/yuque/0/2022/png/179989/1653965110040-b3275298-86b3-4b0b-b492-18b7cd35b949.png#__spacing=both&height=354&id=DaUCY&originHeight=354&originWidth=1008&originalType=binary&ratio=1&rotation=0&showTitle=false&size=46227&status=done&style=none&title=&width=1008) 或者在 app module 下的 build.gradle 下手动添加依赖,如下代码所示: ```json dependencies { ...... compile files('libs/alipaySdk-20170725.jar') ...... } ``` ### 修改 Manifest 在商家应用工程的 AndroidManifest.xml 文件里面添加声明: ```html ``` 和权限声明: ```html ``` ### 添加混淆规则 在商家应用工程的 proguard-project.txt 里添加以下相关规则: ```csharp -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 *;} -keep class com.alipay.sdk.app.H5PayCallback { ; ; } -keep class com.alipay.android.phone.mrpc.core.** { *; } -keep class com.alipay.apmobilesecuritysdk.** { *; } -keep class com.alipay.mobile.framework.service.annotation.** { *; } -keep class com.alipay.mobilesecuritysdk.face.** { *; } -keep class com.alipay.tscenter.biz.rpc.** { *; } -keep class org.json.alipay.** { *; } -keep class com.alipay.tscenter.** { *; } -keep class com.ta.utdid2.** { *;} -keep class com.ut.device.** { *;} ``` 至此,开发包开发资源导入完成。 ## 接口调用说明 SDK中提供了若干接口,手机网站转 Native 支付只用到其中一部分,本文未提到的接口无需关注。 ### 调用提供的接口 APP 支付最新版本 15.4.0 新增拦截+支付二合一接口(payInterceptorWithUrl...),该接口将原来的获取 H5 支付订单信息接口和支付接口进行了合并。 ### 实现手机网站转Native支付 1. 在接入方 App 中拦截 H5 的 URL。 2. 调用新增拦截+支付二合一接口(payInterceptorWithUrl...)进行 URL 拦截及支付转化;具体可查看下方** 拦截+支付二合一接口**。 ## 拦截+支付二合一接口 本接口首先是个拦截器,拦截支付宝 H5 支付 URL;其次是个支付方式转化器,将手机网站支付方式转化为APP支付方式。 ### 示例代码 ```csharp /** * 支付宝H5支付URL拦截器,完成拦截及支付方式转化 * * @param h5PayUrl 待过滤拦截的 URL * @param isShowPayLoading 是否出现loading * @param callback 异步回调接口 * * @return true:表示URL为支付宝支付URL,URL已经被拦截并支付转化;false:表示URL非支付宝支付URL; * */ public synchronized boolean payInterceptorWithUrl(final String h5PayUrl, final boolean isShowPayLoading, final H5PayCallback callback) ``` ### 参数说明 | **参数名称** | **类型** | **说明** | | --- | --- | --- | | h5PayUrl | String | 手机网站支付的请求 URL。 | | isShowPayLoading | boolean | 是否出现 loading。 | | callback | H5PayCallback | 异步回调接口。 | ### 同步拦截结果返回值说明 | **返回值类型** | **描述** | | --- | --- | | boolean |
- 如果 h5PayUrl 是有效的支付宝 H5 支付 URL,则说明拦截转化成功,返回 true,商户容器无需再加载该 URL。
- 如果是无效的,则返回 false,商户容器需要继续加载该 URL。
| ### 异步支付结果返回值说明 支付结束后 SDK 将回调 H5PayCallback,并将支付结果 H5PayResultModel 作为参数传入该 Callback。H5PayResultModel 中主要包含两个字段,如下所示: | **参数名称** | **类型** | **说明** | | --- | --- | --- | | resultCode | String | 返回码,标识支付状态,含义如下:
9000——订单支付成功
8000——正在处理中
4000——订单支付失败
5000——重复请求
6001——用户中途取消
6002——网络连接出错 | | returnUrl | String | 支付结束后应当跳转的 URL 地址。 | ### 接口使用方式 调用本接口对支付宝支付 URL 进行拦截和支付转化。当接口调用完成后,该接口会返回一个 boolean 类型的同步拦截结果。 - 如果同步结果返回值为 true,说明传入的 URL 为支付宝支付 URL,支付宝 SDK 已经成功拦截该 URL,并转化为 APP 支付方式,商户容器无需再加载该 URL。 - 如果返回值为 false,说明传入的 URL 并非支付宝支付 URL,商户容器需要继续加载该 URL。 当支付结束后,会通过回调的方式返回异步支付结果。 - 如果返回的支付结果中的 resultCode 为 9000,则表示支付成功,接入方可以提示用户支付成功。 - 如果返回结果不是 9000,无需做任何处理。当返回的 returnUrl 不为空,建议接入方跳转到该 returnUrl。 ```csharp @Override public boolean shouldOverrideUrlLoading(final WebView view, String url) { if (!(url.startsWith("http") || url.startsWith("https"))) { return true; } /** * 推荐采用的新的二合一接口(payInterceptorWithUrl),只需调用一次 */ final PayTask task = new PayTask(H5PayDemoActivity.this); boolean isIntercepted = task.payInterceptorWithUrl(url, true, new H5PayCallback() { @Override public void onPayResult(final H5PayResultModel result) { // 支付结果返回 final String url = result.getReturnUrl(); if (!TextUtils.isEmpty(url)) { H5PayDemoActivity.this.runOnUiThread(new Runnable() { @Override public void run() { view.loadUrl(url); } }); } } }); /** * 判断是否成功拦截 * 若成功拦截,则无需继续加载该URL;否则继续加载 */ if (!isIntercepted) { view.loadUrl(url); } return true; } ``` # 沙箱联调指南 沙箱环境是开放平台提供给开发者调试接口的环境,详情可查看[沙箱环境](https://ideservice.alipay.com/cms/site/02kkv7)。请开发者在使用 SDK 时,在支付接口前调用如下方法用于切换沙箱环境与生产环境,如果不使用此方法,默认使用生产环境。 ```csharp EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX); ``` 方法调用位置如下图所示: ![沙箱.png](https://cdn.nlark.com/yuque/0/2022/png/179989/1653965147671-8acc9313-b5ac-4ce6-a271-9a4d1a5a032c.png#__spacing=both&height=256&id=d304f&originHeight=256&originWidth=958&originalType=binary&ratio=1&rotation=0&showTitle=false&size=67340&status=done&style=none&title=&width=958)使用支付宝沙箱版客户端测试:在 **开放平台控制台** > **沙箱** > [沙箱工具](https://openhome.alipay.com/develop/sandbox/tool)。
**注意**:在生产环境,必须将此代码注释。在沙箱调通接口后,必须在生产环境进行测试与验收,所有返回码及业务逻辑以生产环境为准。