我们客户端经常会提供一个WKWebView用于加载H5页面,今天就总结下WKWebView中支付回调的适配问题
WKWebView适配支付回调,流程是这样的:
- 在WKWebView设置navigationDelegate
- 在TAGETS->Info->URL Types中配置URL Scheme
- 在代理方法
webView:decidePolicyForNavigationAction:preferences:decisionHandler:
中拦截并替换或拼接第2步设置URL Scheme
微信支付宝回调兼容
具体实现如下:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
// com.wynter是URL Scheme中添加
NSString *schemeString = @"com.wynter";
NSString *wxRegisterDomain = @"";
NSURLRequest *request = navigationAction.request;
NSString *scheme = [request.URL scheme];
NSString *absoluteString = [navigationAction.request.URL.absoluteString stringByRemovingPercentEncoding];
static NSString *endPayRedirectURL = nil;
// 支付宝回调处理
if ([absoluteString hasPrefix:@"alipays://"] || [absoluteString hasPrefix:@"alipay://"]) {
NSString *replaceStr = @"\"fromAppUrlScheme\":\"alipays\"";
if([absoluteString rangeOfString:replaceStr].location != NSNotFound){
NSString *replacedUrlStr = [absoluteString stringByReplacingOccurrencesOfString:replaceStr withString:[NSString stringWithFormat:@"\"fromAppUrlScheme\":\"%@\"",schemeString]];
NSCharacterSet *charset = [NSCharacterSet characterSetWithCharactersInString:@"`^{}\"[]|\\<> "].invertedSet;
replacedUrlStr = [replacedUrlStr stringByAddingPercentEncodingWithAllowedCharacters:charset];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:replacedUrlStr]]];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
if ([request.URL.absoluteString containsString:@"redirect_url"]) {
wxRegisterDomain = [NSURL URLWithString:[request.URL parameterForKey:@"redirect_url"]].host;
}
// 需要特殊处理的域名数组,需要和微信支付后台留的域名保持一致,建议设置一级域名
NSArray *arrDealUrl = @[@"xxx1.com",@"xxx2.com"];
// 微信支付回调处理
if (wxRegisterDomain.length > 0 && [arrDealUrl containsObject:wxRegisterDomain]) {
if ([absoluteString hasPrefix:@"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"] && ![absoluteString hasSuffix:[NSString stringWithFormat:@"redirect_url=wynter.%@://",wxRegisterDomain]]) {
decisionHandler(WKNavigationActionPolicyCancel);
NSString *redirectUrl = nil;
if ([absoluteString containsString:@"redirect_url="]) {
endPayRedirectURL = [request.URL parameterForKey:@"redirect_url"];
redirectUrl = [absoluteString stringByReplacingOccurrencesOfString:endPayRedirectURL withString:[NSString stringWithFormat:@"wynter.%@://",wxRegisterDomain]];
} else {
redirectUrl = [absoluteString stringByAppendingString:[NSString stringWithFormat:@"&redirect_url=wynter.%@://",wxRegisterDomain]];
}
NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:redirectUrl] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30];
newRequest.allHTTPHeaderFields = request.allHTTPHeaderFields;
[newRequest setValue:[NSString stringWithFormat:@"wynter.%@://",wxRegisterDomain] forHTTPHeaderField:@"Referer"];
newRequest.URL = [NSURL URLWithString:redirectUrl];
[webView loadRequest:newRequest];
return;
}
}
// 处理跳转到其他应用
if (![scheme isEqualToString:@"https"] && ![scheme isEqualToString:@"http"]) {
decisionHandler(WKNavigationActionPolicyCancel);
// 当重定向地址不为空时,从微信返回时需要重载
if (endPayRedirectURL) {
NSString *decodeURL = [endPayRedirectURL stringByRemovingPercentEncoding];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:decodeURL] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30]];
endPayRedirectURL = nil;
}
[[UIApplication sharedApplication] openURL:request.URL options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:^(BOOL success) {
}];
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
parameterForKey: 方法是一个从URL中通过key快速取值的分类方法,自行查找
支付宝SDK支付
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
NSCharacterSet *charset = [NSCharacterSet characterSetWithCharactersInString:@"`^{}\"[]|\\<> "].invertedSet;
NSString *url = [navigationResponse.response.URL.absoluteString stringByAddingPercentEncodingWithAllowedCharacters:charset];
__weak __typeof(self)weakSelf = self;
BOOL isIntercepted = [[AlipaySDK defaultService] payInterceptorWithUrl:url fromScheme:@"com.wynter" callback:^(NSDictionary *result) {
// isProcessUrlPay 代表 支付宝已经处理该URL
if ([result[@"isProcessUrlPay"] boolValue]) {
// returnUrl 代表 第三方App需要跳转的成功页URL
NSString* urlStr = result[@"returnUrl"];
[weakSelf loadWithUrlStr:urlStr];
}
}];
if (isIntercepted) {
decisionHandler(WKNavigationResponsePolicyCancel);
} else {
decisionHandler(WKNavigationResponsePolicyAllow);
}
}
完~