As the app purchases virtual goods, native access to Alipay and wechat Payment will be subject to apple review risk, so H5 access payment is adopted.
Existing problems: Wechat payment can not return app, but open Safari Alipay payment success or stay in Alipay
1. Wechat Pay
- The authorized domain name is configured on the wechat background, for example, HTTP: //aaa.bbb.com
- – Added URL Schemes: aaa.bbb.com to App project configuration
The value must be consistent with the domain name
) - Intercept the WKWebView proxy method
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { NSURL *url = navigationAction.request.URL; if ([url.absoluteString hasPrefix:@"weixin://"]) { if ([[UIApplication sharedApplication] canOpenURL:url]) { [[UIApplication sharedApplication] openURL:url]; } } NSString *kWXPay_url = @"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"; NSString *referer = @"aaa.bbb.com://"; If ([url.absoluteString containsString:kWXPay_url]) {NSDictionary *headers = [navigationAction.request allHTTPHeaderFields]; BOOL hasReferer = [referer isEqualToString:[headers objectForKey:@"Referer"]]; If (hasReferer) {/ / has set up a decisionHandler (WKNavigationActionPolicyAllow); } else { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_main_queue(), ^{ NSURL *url = [navigationAction.request URL]; NSDictionary *dic = [url bf_queryDictionary]; if ([dic.allKeys containsObject:@"redirect_url"]) { self.redirect_url = dic[@"redirect_url"]; // save redirect_URL to refresh payment results} NSString *urlStr = [NSString stringWithFormat:@"%@?prepay_id=%@&package=%@",kWXPay_url,dic[@"prepay_id"],dic[@"package"]]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlStr] CachePolicy: NSURLRequestUseProtocolCachePolicy timeoutInterval: 20.0]; [request setHTTPMethod:@"GET"]; [request setValue:referer forHTTPHeaderField: @"Referer"]; [self.webView loadRequest:request]; }); }); decisionHandler(WKNavigationActionPolicyCancel); } return; } decisionHandler(WKNavigationActionPolicyAllow); } / / monitor app back to the front desk event [[NSNotificationCenter defaultCenter] addObserver: self selector: @ the selector (handleWillEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil]; - (void)handleWillEnterForeground { if (self.redirect_url) { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.redirect_url] cachePolicy:NSURLRequestUseProtocolCachePolicy TimeoutInterval: 20.0]; [self.webView loadRequest:request]; self.redirect_url = nil; }} // Remember to remove listener - (void)dealloc {[[NSNotificationCenter defaultCenter] removeObserver:self]; }Copy the code
Description:
- Intercept jump wechat URL, with
[[UIApplication sharedApplication] openURL:url]
Open, will jump to the wechat client - Intercept wechat order address kWXPay_url, set the request header
Referer
The format is scheme:// - Remove the callback address from the URL argument
redirect_url
Otherwise, Safari will still be opened. At the same time, save the redirect_URL address. When the payment is successful, listen to the event that the APP returns to the foreground and refresh the webView to update the payment status.
2. Pay treasure
Compared with wechat, Alipay is much simpler. It only needs to intercept the URL redirecting to Alipay and replace fromAppUrlScheme with its own scheme (such as AAA). [[UIApplication sharedApplication] openURL:url] (Both the backend and H5 say they can’t change the value of fromAppUrlScheme, so the client intercepts it instead)
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { NSURL *url = navigationAction.request.URL; If ([url. AbsoluteString hasPrefix: @ "alipay: / /") | | [url. AbsoluteString hasPrefix: @ "alipays: / /"]) {/ / replace scheme for aaa NSString *newUrl = [url.absoluteString stringByReplacingOccurrencesOfString:@"fromAppUrlScheme%22%3A%22alipays" withString:@"fromAppUrlScheme%22%3A%22aaa"]; if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:newUrl]]) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:newUrl]]; } } decisionHandler(WKNavigationActionPolicyAllow); }Copy the code
supplement
A method to get the parameter dictionary from the URL
@implementation NSURL (URLQuery) - (NSDictionary *)bf_queryDictionary { return self.query.bf_URLQueryDictionary; } @end @implementation NSString (URLQuery) - (NSDictionary *)bf_URLQueryDictionary { NSMutableDictionary *mute = @{}.mutableCopy; for (NSString *query in [self componentsSeparatedByString:@"&"]) { NSArray *components = [query componentsSeparatedByString:@"="]; if (components.count == 0) { continue; } NSString *key = [components[0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; id value = nil; if (components.count == 1) { // key with no value value = [NSNull null]; } if (components.count == 2) { value = [components[1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; // cover case where there is a separator, but no actual value value = [value length] ? value : [NSNull null]; } if (components.count > 2) { NSString *prefixStr = [NSString stringWithFormat:@"%@=",components[0]]; value = [[query substringFromIndex:prefixStr.length] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; } if (value == nil || value == [NSNull null]) { continue; } else { mute[key] = value; } } return mute.count ? mute.copy : nil; } @endCopy the code