iOS支付宝H5支付没法返回APP解决方案

本文只讨论你已经成功实现 客户端->支付宝 支付流程,仅仅是支付完成后没法返回本身的APP的问题。
若是你的支付流程是 客户端->Safari->支付宝 不在本文讨论范围之类。
iOS支付宝H5支付不在讨论范围内。提供下列参考:
支付宝H5支付官方文档
支付宝H5支付官方Demo下载Demo使用文档前端

我是如何解决这个问题的

本文前大段在讲楼主是如何解决这个问题的,以及中间遇到的麻烦。赶时间的同窗能够直接看最后的 最终解决方案ios

在讨论以前,咱们先看看官方文档上的一句话:web

注意:在iOS系统中,唤起支付宝App支付完成后,不会自动回到浏览器或商户APP。用户可手工切回到浏览器或商户APP;支付宝H5收银台会自动跳转回商户return_url指定的页面。api

what? 官方直接跟咱们说GG了?楼主不甘心,仍是想尝试一下。
借鉴以前 iOS微信H5支付没法返回APP解决方案 的经验,先在 return_url 这个参数上作个尝试吧。浏览器

支付宝和微信不一样的是,支付宝的return_url不须要在支付宝管理后台备案(填写),微信的redirect_url是须要的。bash

第一次尝试
webView拦截请求https://mapi.alipay.com/gateway.do,修改return_url参数为本身的URLScheme,好比URLEncode(A.company.com://),结果失败了,进入支付宝报错的页面。仔细看了一下请求的其它参数,竟然有个sign!支付宝文档上也有这个参数,竟然校验了参数签名的,好吧,客户端篡改参数的方案宣告失败!微信

第二次尝试
既然不能篡改,那直接下单的时候填吧,请求后台的同窗协助一下,在下单的时候把return_url参数改为 URLEncode(A.company.com://),结果仍是失败了。后台同窗提示我,return_url必须是HTTP/HTTPS开头,支付宝文档上有说明。app

第三次尝试
那加上http试试,我又让后台同窗把return_url改为URLEncode(httpA.company.com://),同时把APP的URLSchemes改为httpA.company.com,再次尝试,调起支付宝返回的时候打开了Safari,在Safari里面显示了咱们支付中心的错误页面,return_url方案完全失败了!post

要不就算了,跟产品说支付宝没法实现支付完成后跳回APP,反正支付宝官方文档上都这么写了。
虽然这么想了,可是我仍是继续翻看支付宝的文档,但愿能找到点蛛丝马迹。网站

忽然看到了这里,手机网站支付转Native支付

支付宝文档
schemeStr,这个关键字让我眼前一亮。
手机网站支付转Native支付:支付宝的意思是,咱们提供了一个SDK,你接了以后就能够很方便的实现H5收银台(即在web上输入支付宝帐号密码支付)到支付宝APP收银台的过渡。
若是你是一个"正规"APP开发者,至此已经能够解决你的问题了。按照支付宝文档接支付宝SDK便可,就能实现H5支付回调APP了。

但,这不是楼主想要的方案,因为工做需求的缘由,楼主不想也不敢接支付宝的SDK,怕被苹果爸爸审核扫包啊。若是你的APP"应该"用苹果支付,即便你没有用到支付宝的功能,可是包含了支付宝的SDK,审核被发现了,也可能被拒绝的。

继续寻找解决办法。

下载了支付宝的Demo,试了下确实能够跳回APP。
楼主琢磨着,既然SDK能实现这个功能,说明支付宝仍是支持的H5支付完成后返回APP功能的,并非向文档上说的,"在iOS系统中,唤起支付宝App支付完成后,不会自动回到浏览器或商户APP。用户可手工切回到浏览器或商户APP",只是支付宝不肯意公开而已。

那就以这个支付宝Demo为切入点吧,虽然SDK中有schemeStr这个参数,可是SDK是黑盒啊,你不知道它在里面作了些什么。

/**
 *  支付接口
 *
 *  @param orderStr       订单信息
 *  @param schemeStr      调用支付的app注册在info.plist中的scheme
 *  @param completionBlock 支付结果回调Block,用于wap支付结果回调(非跳转钱包支付)
 */
- (void)payOrder:(NSString *)orderStr
      fromScheme:(NSString *)schemeStr
        callback:(CompletionBlock)completionBlock;
复制代码

追本溯源,最终打开支付宝APP都会走

[UIApplication sharedApplication] openURL:]
复制代码

在Demo工程里搜了一下,没有。但我确定SDK里面确定有!

whatever —— Method Swizzling

#import <UIKit/UIKit.h>
#import <objc/runtime.h>

@implementation UIApplication (TrackTimer)

+ (void)load
{
    static dispatch_once_t oneToken;
    dispatch_once(&oneToken, ^{
        SEL mySelector = NSSelectorFromString(@"my_openURL:");
        SEL orginalSelector = NSSelectorFromString(@"openURL:");
        Method myMethod = class_getInstanceMethod([self class], mySelector);
        Method orginalMethod = class_getInstanceMethod([self class], orginalSelector);
        BOOL didAddMethod = class_addMethod([self class], orginalSelector, method_getImplementation(myMethod), method_getTypeEncoding(myMethod));
        if (didAddMethod) {
            class_replaceMethod([self class], mySelector, method_getImplementation(orginalMethod), method_getTypeEncoding(orginalMethod));
        }
        else {
            method_exchangeImplementations(myMethod, orginalMethod);
        }
    });
}

- (void)my_openURL:(NSURL*)url
{
    NSLog(@"%@",url);
    [self my_openURL:url];
}
复制代码

打印结果URLDecode后

alipaymatrixbwf0cml3://alipayclient/?{
"fromAppUrlScheme" : "alisdkdemo",
"requestType" : "SafePay",
"dataString" : "trade_no="2018041921001001270586523089"&pay_phase_id=""&biz_type="trade"&biz_sub_type="TRADE"&app_name="tb"&extern_token="1fc77c67c70ef70d58e2bf7c513d91a5"&appenv=""&pay_channel_id="alipay_sdk"&bizcontext="{"av":"1","sc":"h5tonative","ty":"ios_lite","appkey":"2014052600006128","sv":"h.a.3.5.3","an":"com.antfin.AliSDKDemo"}""
}

为何前面会有一点乱码,alipaymatrixbwf0cml3,无论它了。fromAppUrlScheme,是否是很惊喜。

是否是支付宝H5支付都有这个参数呢?楼主赶忙用本身的项目尝试了一下,webView最终会有一个alipay://请求的,拦截它,看看参数

alipay://alipayclient/?{"dataString":"h5_route_token="xxxxxxxxxxxxx"&is_h5_route="true"","requestType":"SafePay","fromAppUrlScheme":"alipays"}

也有fromAppUrlScheme这个参数,并且默认是支付宝APP的URLScheme: alipays
对比一下发现,SDK中传入的schemeStr参数对应就是alipay:// 中的 fromAppUrlScheme字段。
由此楼主猜想,在 alipay:// 打开支付宝时,传入 fromAppUrlScheme,支付结束后就会跳到对应的APP。

最终,楼主在本身的项目中验证了上述猜想。 总结下吧

最终解决方案

方案一

接支付宝提供的SDK,schemeStr参数传入本身APP的URLScheme便可。 具体的 手机网站支付转Native支付

方案二

不须要接SDK,不须要添加支付宝白名单,webView拦截 alipay://alipayclient 请求,追加或修改参数 fromAppUrlScheme为你本身的URLScheme值,生成新的NSURL,而后用 [[UIApplication sharedApplication] openURL:] 打开便可。

总有人问我怎么追加fromAppUrlScheme。多是我说的"webView拦截",让初学者不明白吧,简单提一下。
在webView"发起请求的代理方法"里面拦截请求的URL,即若是请求是alipay://alipayclient开头的,说明这个请求是跳转支付宝的请求。替换里面fromAppUrlScheme的值为你本身的scheme值。(固然若是更严谨的话,应该是判断fromAppUrlScheme这个key是否存在,存在则替换其值,不存在则追加)。用替换好的字符串生成一个NSURL,用[[UIApplication sharedApplication] openURL:newURL]跳转支付宝。代理方法返回NO,即终止此次请求。

常见问题

1.支付后没有返回app而是跳到了Safari**

缘由:你的Xcode配置里面URLSheme没写或者写错了,和支付宝请求参数中的fromAppUrlScheme不一致。
解决:Xcode配置中新增或者修改URLSheme,确保和alipay://alipayclient请求参数中的fromAppUrlScheme一致。

2.并无看到做者说的alipay: //alipayclient**

缘由:可能你的app不是在客户端直接和支付宝通讯,而是中间加了一道跳转到网页,由你的后台(或前端)调起支付宝。因此你是拦截不到这个请求的。我文中所说的方式是基于,“客户端->支付宝” 这种模式,而你的是“客户端->Safari->支付宝”模式,后者没法按照文中说述实现返回app。
解决:方案1,修改你的支付模式为“客户端->支付宝”,这样改动恐怕有点大,工做量主要在大家后台。方案2,在不改模式的状况下,须要后台(或前端)的同事去解决这个问题,原理和本文差很少,在后台和支付宝通信的参数中找到一个相似于fromAppUrlScheme的参数,而后将这个参数修改为你的app的URLScheme,至于具体怎处理楼主没作研究,若是你有好的方法,能够分享一下。

3.支付完成后回来停留在支付宝结果页面,显示“继续支付”和“已完成”,无法回到游戏**

缘由:web发起支付后,web页面会尝试调起支付宝客户端,不管是否调起客户端都会将当前页面重定向到支付宝结果页面,即“继续支付,已完成”页面。因此从支付宝客户端返回后你会看到这个页面。
解决:个人作法是,原生另起一个webViewController页面做为收银台,收银台页面发起支付,发起支付后就关闭收银台页面。这样原来的游戏页面就不会受影响,支付宝客户端返回时也直接返回到游戏页面了。至于支付结果,客户端没法直接获知成功或失败,若是你须要弹窗提示用户充值成功,须要游戏方自行去后台查询支付结果。

[[UIApplication sharedApplication] openURL:newRequest.URL];
[self dismissViewControllerAnimated:NO completion:nil];
复制代码

若是以为这篇文章对你有帮助,请点个赞吧。若是有疑问能够关注个人公众号我留言。
转载请注明出处,谢谢!

相关文章
相关标签/搜索