Cordova H5打包APP调用微信支付返回APP

2020-07-14  本文已影响0人  小二郎_Ejun

APP的调用通过scheme,流程如下:

1、info.plist配置scheme

需要将微信H5支付的安全域名配置成scheme,微信支付完成会通过这个scheme跳转回APP。

根据微信后台的微信H5支付配置APP的schemes,传过去的redirect_url微信会做安全校验。所以用schemes作为redirect_url可以通过微信的安全校验。并且微信支付完毕,会通过redirect_url回调。所以用schemes替换redirect_url,这样微信支付后就能跳回APP,否则打开的就是Safari浏览器加载这个redirect_url。

根据微信H5支付的安全域名配置APP的schemes,比如安全域名是aa.baidu.com。APP的schemes就是aa.baidu,com.redirect_url为aa.baidi.com://.

<key>CFBundleURLTypes</key>
 <array>
     <dict>
         <key>CFBundleTypeRole</key>
         <string>Editor</string>
         <key>CFBundleURLName</key>
         <string>wxPay</string>
         <key>CFBundleURLSchemes</key>
         <array>
<string>微信scheme(安全域名)</string> </array> 
     </dict>
 </array>

<key>LSApplicationQueriesSchemes</key>
 <array>
     <string>wechat</string>
     <string>weixin</string>

</array>

2、拦截微信中间页,截取redirect_url,并修改redirect_url,重新加载

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{

    NSString *wxScheme = @"pay.xslp.cn";
    NSString *referer = [NSString stringWithFormat:@"%@://",wxScheme];

    NSString *urlString = [request.URL absoluteString];

    //与js交互
    if ([webView.request.URL.absoluteString isEqualToString:@"http://t-tcp.xs815.com/sbc.html#/class"]) {

        NSString *func = @"window.isApp()";

        NSString *str = [webView stringByEvaluatingJavaScriptFromString:func]; 
        NSLog(@"%@", str);
    }


    NSLog(@"%@", urlString);
    BOOL shouldLoad = YES;

    if ([urlString containsString:@"alipay://alipayclient/"]) {
        //调起支付宝支付
        [[UIApplication sharedApplication] openURL:request.URL options:@{} completionHandler:nil];
        return NO;
    }

    //由微信支付返回到APP回调
    if ([urlString hasPrefix:wxScheme]) {

        NSRange range = [urlString rangeOfString:wxScheme];
        if (range.location != NSNotFound) {
            
            NSString *lastUrlString = [urlString substringFromIndex:range.location+range.length];

            urlString = [@"https" stringByAppendingString:lastUrlString];

            NSURL * url = [NSURL URLWithString:urlString];
            NSURLRequest *tmpRequest = [[NSURLRequest alloc] initWithURL:url];
            [webView loadRequest:tmpRequest];
            return NO;
        }
            
        
    }

//   此处为最初方案,拦截生成订单接口添加平台参数,然后重新加载
//    if ([urlString isEqualToString:@"https://pay.xslp.cn/index.php/User/Payment/pay"]) {
//
//        NSData *data = request.HTTPBody;
//
//
//        NSString *params = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//        NSLog(@"%@", params);
//
//        if ([params containsString:@"platform=ios"]) {
//            return YES;
//        }
//        NSURL *url = [NSURL URLWithString:urlString];
//        NSMutableURLRequest *requestM = [NSMutableURLRequest requestWithURL:url];
//        // 如果有webMethod并且是POST,则POST方式组合提交
//        [requestM setHTTPMethod:@"POST"];
//        NSString *body = nil;
//        body = [NSString stringWithFormat:@"%@&platform=ios",params];
//        [requestM setHTTPBody: [body dataUsingEncoding: NSUTF8StringEncoding]];
//
//        NSLog(@"%@",body);
//       urlString = [urlString stringByAppendingFormat:@"%@&platform=ios",params];
//
//        [webView loadRequest:requestM];
//        return NO;
//
//    }


    if ([[request.URL absoluteString] containsString:@"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"]) {
        //https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx141510111101428929331aef1977552000&package=1029873265&redirect_url=https%3A%2F%2Fpay.xslp.cn%2Findex.php%2FUser%2FPayment%2Fjump
        //weixin://wap/pay?prepayid%3Dwx2317173862758252dcad00251141517400&package=1136975133&noncestr=1592903981&sign=4d26d96740bc8240197aa215c4137180
        
        
        NSRange range = [urlString rangeOfString:@"redirect_url="];
        if (range.location != NSNotFound) {
            NSString *url = [urlString substringToIndex:range.location+range.length];

            NSString *subString = [urlString substringFromIndex:range.location+range.length];

            //判断URL是否修改,使返回App
            if (redirectUrl && [subString isEqualToString:redirectUrl]) {
                redirectUrl = nil;
                return YES;
            }
            
            
            subString = [subString substringFromIndex:5];

            subString = [wxScheme stringByAppendingString:subString];

            redirectUrl = subString;
            
            urlString = [url stringByAppendingString:subString];

            NSMutableURLRequest *tmpRequest =  [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
            //设置授权域名
            [tmpRequest setValue:referer forHTTPHeaderField:@"Referer"];

            [webView loadRequest:tmpRequest];
            return NO;
        }

    }


    if ([_delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
        shouldLoad = [_delegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
    }

    VerboseLog(@"webView shouldLoad=%d (before) state=%d loadCount=%d URL=%@", shouldLoad, _state, _loadCount, request.URL);

    if (shouldLoad) {
        // When devtools refresh occurs, it blindly uses the same request object. If a history.replaceState() has occured, then
        // mainDocumentURL != URL even though it's a top-level navigation.
        BOOL isDevToolsRefresh = (request == webView.request);
        BOOL isTopLevelNavigation = isDevToolsRefresh || [request.URL isEqual:[request mainDocumentURL]];
        if (isTopLevelNavigation) {
            // Ignore hash changes that don't navigate to a different page.
            // webView.request does actually update when history.replaceState() gets called.
            if ([self request:request isEqualToRequestAfterStrippingFragments:webView.request]) {
                NSString* prevURL = [self evalForCurrentURL:webView];
                if ([prevURL isEqualToString:[request.URL absoluteString]]) {
                    VerboseLog(@"Page reload detected.");
                } else {
                    VerboseLog(@"Detected hash change shouldLoad");
                    return shouldLoad;
                }
            }

            switch (_state) {
                case STATE_WAITING_FOR_LOAD_FINISH:
                    // Redirect case.
                    // We expect loadCount == 1.
                    if (_loadCount != 1) {
                        NSLog(@"CDVWebViewDelegate: Detected redirect when loadCount=%ld", (long)_loadCount);
                    }
                    break;

                case STATE_IDLE:
                case STATE_IOS5_POLLING_FOR_LOAD_START:
                case STATE_CANCELLED:
                    // Page navigation start.
                    _loadCount = 0;
                    _state = STATE_WAITING_FOR_LOAD_START;
                    break;

                default:
                    {
                        NSString* description = [NSString stringWithFormat:@"CDVWebViewDelegate: Navigation started when state=%ld", (long)_state];
                        NSLog(@"%@", description);
                        _loadCount = 0;
                        _state = STATE_WAITING_FOR_LOAD_START;

                        NSDictionary* errorDictionary = @{NSLocalizedDescriptionKey : description};
                        NSError* error = [[NSError alloc] initWithDomain:@"CDVUIWebViewDelegate" code:1 userInfo:errorDictionary];
                        [self webView:webView didFailLoadWithError:error];
                    }
            }
        } else {
            // Deny invalid URLs so that we don't get the case where we go straight from
            // webViewShouldLoad -> webViewDidFailLoad (messes up _loadCount).
            shouldLoad = shouldLoad && [self shouldLoadRequest:request];
        }
        VerboseLog(@"webView shouldLoad=%d (after) isTopLevelNavigation=%d state=%d loadCount=%d", shouldLoad, isTopLevelNavigation, _state, _loadCount);
    }
    return shouldLoad;
}

[参考链接 https://www.jianshu.com/p/65979e8bf251]

上一篇 下一篇

猜你喜欢

热点阅读