苹果对于APP的内部虚拟数字产品都要求走其IAP支付,但30%的提成对于很多公司来说都是难以接受的。现在很多公司都在提审时,使用了版本控制,屏蔽掉第三方支付的入口,但是如果使用了微信和支付宝的第三方SDK,在提审代码扫描的时候会被发现,因此最后决定使用H5调取第三方支付。以下主要介绍一下基于WKWebView实现微信支付和支付宝支付方案。
苹果App内打开其他的App需要添加应用白名单,具体在App里的info.list里面,代码如下:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>alipay</string>
<string>weixin</string>
</array>
以上代码里weixin和alipay分别对应微信和支付宝。App中H5要正常调起微信或者支付宝应用进行支付,需要在对应的WKWebview的ViewController内实现其WKNavigationDelegate协议,微信和支付宝的相应处理存在区别,下面将区分微信和支付宝进行说明。
微信支付
对应的WKNavigationDelegate中的代码如下:
//先默认允许加载
WKNavigationActionPolicy actionPolicy = WKNavigationActionPolicyAllow;
NSString*urlString = [[navigationAction.request URL] absoluteString];
urlString = [urlString stringByRemovingPercentEncoding];
//根据跳转URL确定是否需要调起微信App
if([urlString containsString:@"weixin://wap/pay?"] && [[UIApplication sharedApplication] canOpenURL:url] )
{
actionPolicy = WKNavigationActionPolicyCancel;//不再加载网页,微信App里处理
NSURL*url = [NSURL URLWithString:urlString];
//区分版本打开应用并传参
if([[UIApplication sharedApplication] respondsToSelector:@selector(openURL:options:completionHandler:)]) {
[[UIApplication sharedApplication] openURL:url options:@{UIApplicationOpenURLOptionUniversalLinksOnly: @NO} completionHandler:^(BOOL success) {
}];
}
else{
[[UIApplication sharedApplication] openURL:url webView.URL];
}
}
//执行是否加载WKWebview是否加载URL,不加会异常
decisionHandler(actionPolicy);
}
走完以上步骤,App中H5网页是可以打开微信并支付成功了,但之后将会发现存在一个问题,即支付成功后,微信将会打开Safari提示支付成功而不是回到我们App中。
微信支付后跳转App
为了解决这个,查看了对应的微信支付文档,发现主要微信是通过我们在其平台上设置的支付回调地址进行支付结果显示,假设你将结果url设置为xxxxx.com?orderid=1234,其将调起safari加载这个URL显示结果。基于此,问题的关键便是在这个回调的URL上进行处理,Safari是可以打开应用的,只需要输入appscheme://即可,因此,我们可以将回调设置为xxxxx.com://?orderid=1234,在Url Types中添加一个scheme为xxxxx.com,这样即可打开App了,但需要在AppDelegate中对传入的URL进行处理,处理掉://后强制WKWebview加载处理后的URL即xxxxx.com://?orderid=1234。对应AppDelegate中方法如下,方法内代码不加了,读者自己根据逻辑添加:
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
}
以上需要提醒的是回调URL中不要添加http或https,不然将出错,微信会校验地址不通过。微信支付就介绍到这里了。
支付宝支付
比起微信支付,支付宝的支付流程就友好得太多了,必须给其点赞。在设置好应用白名单和用于支付宝回调的Url Types里的scheme后,在对应的WKWebview的ViewController内实现其WKNavigationDelegate协议,并添加加解码方法,对应代码如下:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
// 判断是否为支付宝支付并安装了应用
if ([navigationAction.request.URL.scheme isEqualToString:@"alipay"] && [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:finalStr]]) {
// 1.以?号来切割字符串
NSArray * urlBaseArr = [navigationAction.request.URL.absoluteString componentsSeparatedByString:@"?"];
NSString * urlBaseStr = urlBaseArr.firstObject;
NSString * urlNeedDecode = urlBaseArr.lastObject;
// 2.将截取以后的Str,做一下URLDecode,方便处理
NSMutableString * afterDecodeStr = [NSMutableString stringWithString:[self URLDecodedString:urlNeedDecode]];
// 3.替换里面的默认Scheme为自己的Scheme
NSString * afterHandleStr = [afterDecodeStr stringByReplacingOccurrencesOfString:@"alipays" withString:@"ThirdH5PayAppSheme"];
// 4.然后把处理后的,和最开始切割的做下拼接,就得到了最终的字符串
NSString * finalStr = [NSString stringWithFormat:@"%@?%@",urlBaseStr, [self URLEncodeString:afterHandleStr]];
//打开APP
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//区分版本打开应用并传参
if([[UIApplication sharedApplication] respondsToSelector:@selector(openURL:options:completionHandler:)]) {
[[UIApplication sharedApplication] openURL:finalStr options:@{UIApplicationOpenURLOptionUniversalLinksOnly: @NO} completionHandler:^(BOOL success) {
}];
}
else{
[[UIApplication sharedApplication] openURL:finalStr webView.URL];
}
}
});
//5、WKWebview不再加载此url,交给App处理
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
// OC 做URLEncode的方法
- (NSString *)URLEncodeString:(NSString*)str {
NSString *unencodedString = str;
NSString *encodedString = (NSString *)
CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)unencodedString,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8));
return encodedString;
}
- (NSString*)URLDecodedString:(NSString*)str {
NSString *decodedString=(__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (__bridge CFStringRef)str, CFSTR(""), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
return decodedString;
}
除此之外,我们还需要获取订单支付结果,同样是在AppDelegate中对应方法设置,方法如下
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
}
在方法中判断为支付宝调起后,将url的参数转为JSON,读取result字段即可获知支付结果,弹框或者加载对应页面告知用户即可。
网友评论