iOS集成H5微信支付實現跳轉與回調的解決方案

由于不能在iOS客戶端內集成支付寶和微信的App支付SDK(為了防蘋果審核檢測SDK),因此使用H5支付,雖然微信和支付寶的H5支付文檔都說不要在App內使用H5支付而是使用App支付,但辦法總是有的。

這篇講的是微信H5支付如何從App跳轉微信以及如何從微信跳轉回App,支付寶支付的見這篇:

iOS集成支付寶H5支付實現跳轉與回調的解決方案

實現的效果是:App→微信→支付(成功失敗或取消)→App

前置準備

準備時大家需要看下官方文檔: 微信H5支付開發文檔

本項目使用WKWebView,前置動作是后端小伙伴已經處理好支付寶H5支付下單流程,客戶端接收到下單鏈接后的操作。

下單鏈接即為微信支付文檔-統一下單API中返回的 mweb_url,格式為 https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx2016121516420242444321ca0631331346&package=1405458241

下單鏈接

操作步驟

1. 添加 URL Scheme 并把微信加入白名單

添加 URL Scheme

添加 URL Scheme。在 xcodeproj文件Info 選項卡最下面的 URL Types內設置。 注意此URL的一級域名需要與微信商戶后臺(微信商戶平臺-產品中心-開發配置-H5支付)設置的的一級域名一致,比如微信商戶里設置的是company.com,那 URL Schemes 可以設為 a1.company.com,此特性使得一套H5支付可以方便得集成到多個App。只有一個App需要H5支付的話也可以直接填與微信后臺的一致的 company.com 。

如果像上圖那樣填的是 www.company.com,那URL Scheme 只能設為其三級域名如 a2.www.company.com 或同樣的 www.company.com

白名單

把微信的URL Scheme weixinwechat填入項目的白名單。在 xcodeproj 文件 Info 選項卡內的 Custom iOS Target PropertiesLSApplicationQueriesSchemes 里添加上述兩個字符串,若沒有 LSApplicationQueriesSchemes 就手動輸入添加,類型為數組 Array。

2. WKWebView加載鏈接

添加協議 WKNavigationDelegateWKUIDelegate。

創建一個WKWebView,并加載統一下單鏈接。

- (void)buildWKWebView {
    WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
    [self.view addSubview:webView];
    webView.navigationDelegate = self;
    webView.UIDelegate = self;
    NSURL *payURL = [NSURL URLWithString:self.payString];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:payURL];
    [request setValue:@"a1.company.com://wxpaycallback/" forHTTPHeaderField:@"Referer"];
    [webView loadRequest:request];
}

此處self.payString就是后臺傳來的微信H5支付統一下單鏈接,格式為 https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx2016121516420242444321ca0631331346&package=1405458041。

我們需要做的處理是根據文檔給這個請求添加請求頭Referer,關鍵在于這個 a1.company.com://wxpaycallback/既滿足了微信檢測到有商戶后臺設置好的一級域名,同時把這個鏈接做成了 URL Scheme 使得可以在跳轉微信客戶端后(不管支付成功還是失?。┠茼樌D回自己的App。其中的 host wxpaycallback/可以任意設置,方便在 AppDelegate 里處理跳轉回來后部署業務邏輯。當然如果你不需要在 AppDelegate里接收動作而是直接跳回支付界面自行后續處理的話就只用設為前一步在 URL Scheme a1.company.com://即可。

經過測試,對于App 內的H5 支付而言,實際上是下面步驟里
@"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"
后接的參數 redirect_url 對支付后跳回App起作用,Referer 只起到給微信校驗的作用。

所以Referer 只需要設置成微信H5 支付登記的域名的子域名即可,如
[request setValue:@"a1.company.com" forHTTPHeaderField:@"Referer"];

3. 實現代理方法攔截鏈接并跳轉微信

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    
    NSURLRequest *request = navigationAction.request;
    NSString *absoluteString = [navigationAction.request.URL.absoluteString stringByRemovingPercentEncoding];
    
    // 攔截WKWebView加載的微信支付統一下單鏈接, 將redirect_url參數修改為喚起自己App的URLScheme
    if ([absoluteString hasPrefix:@"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"] && ![absoluteString hasSuffix:[NSString stringWithFormat:@"redirect_url=a1.company.com://wxpaycallback/"]]) {
        decisionHandler(WKNavigationActionPolicyCancel);
        NSString *redirectUrl = nil;
        if ([absoluteString containsString:@"redirect_url="]) {
            NSRange redirectRange = [absoluteString rangeOfString:@"redirect_url"];
            redirectUrl = [[absoluteString substringToIndex:redirectRange.location] stringByAppendingString:[NSString stringWithFormat:@"redirect_url=a1.company.com://wxpaycallback/"]];
        } else {
            redirectUrl = [absoluteString stringByAppendingString:[NSString stringWithFormat:@"redirect_url=a1.company.com://wxpaycallback/"]];
        }
        NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:redirectUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30];
        newRequest.allHTTPHeaderFields = request.allHTTPHeaderFields;
        newRequest.URL = [NSURL URLWithString:redirectUrl];
        [webView loadRequest:newRequest];
        return;
    }
    
    //攔截重定向的跳轉微信的 URL Scheme, 打開微信
    if ([absoluteString hasPrefix:@"weixin://"]) {
        decisionHandler(WKNavigationActionPolicyAllow);
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            if ([[UIApplication sharedApplication] canOpenURL:navigationAction.request.URL]) {
                [[UIApplication sharedApplication] openURL:navigationAction.request.URL];
            } else {
                //未安裝微信, 自行處理
            }
        });
        return;
    }
    
    decisionHandler(WKNavigationActionPolicyAllow);
    return;
}

4. AppDelegate 中接收跳轉動作

當然你也不一定需要在AppDelegate里接收返回動作,也可以直接返回支付界面,自行操作后續邏輯。

以下是AppDelegate接收返回動作的示例。

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
    //safepay是支付寶H5支付的回調host
    if ([url.host isEqualToString:@"wxpaycallback"] ) {
        // 自行操作業務邏輯
       
    }
}

5. 關于微信H5支付域名設置

這里額外提一下,截止到2019年4月,微信支付設置頁面明確說了


域名設置

添加域名后,其所屬的子域名將都有權限

也就是說只需要填一個一級域名比如 company.com ,就可以有無限多個二級域名可供不同App使用,繞過微信H5支付只能添加5個域名的限制。如果填的是二級域名比如 www.company.com,那么只能往下使用三級域名比如a1.www.company.com

以微信H5支付域名填了 company.com為例,那可以這樣操作

App Alpha Beta-A1 Beta-A2 Gamma
添加的Referer alpha.company.com a1.beta.company.com a2.beta.company.com gamma.company.com
要替換的redirect_url alpha.company.com://optional a1.beta.company.com:// a2.beta.company.com://optional gamma.company.com://
URL Scheme alpha.company.com a1.beta.company.com a2.beta.company.com gamma.company.com

參考:
https://paaatrick.com/2019-03-22-ios-wxpay-h5-solution/
https://www.cnblogs.com/Life-Record/p/8472319.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。