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

?

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

?

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

?


?

前言

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

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

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

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

前置準備

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

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

image

操作步驟

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

image

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

2019年4月10日更新
如果像上圖那樣填的是 www.company.com,那 URL Scheme 只能設為其三級域名如 a2.www.company.com 或同樣的 www.company.com

image

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

2. WKWebView加載鏈接

添加協議 WKNavigationDelegateWKUIDelegate

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

- (void)buildWKWebView {
    WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, NAV_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT - NAV_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 使得可以在跳轉微信客戶端后(不管支付成功還是失敗)能順利跳轉回自己的App。其中的 host wxpaycallback/ 可以任意設置,方便在 AppDelegate 里處理跳轉回來后部署業務邏輯。當然如果你不需要在 AppDelegate 里接收動作而是直接跳回支付界面自行后續處理的話就只用設為前一步在 URL Scheme a1.company.com:// 即可。

2019.4.10 更新

經過測試,對于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"] || [url.host isEqualToString:@"safepay"]) {
        // 自行操作業務邏輯,比如使用通知請求查詢訂單狀態,popView回上級頁面等
        UITabBarController *tabBarVC = (UITabBarController *)topRootViewController;
        UINavigationController *navVC = tabBarVC.viewControllers[tabBarVC.selectedIndex];
        [navVC popViewControllerAnimated:YES];
        
        NSString *orderId = [[NSUserDefaults standardUserDefaults] objectForKey:@"PayOrderId"];
            NSString *payFee = [[NSUserDefaults standardUserDefaults] objectForKey:@"PayFee"];
            //以及更多參數
        NSDictionary *resultDict = @{@"order_id":orderId, @"payFee":payFee};
        [[NSNotificationCenter defaultCenter] postNotificationName:@"htmlPaymentNotification" object:self userInfo:resultDict];
    }
}

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

2019年4月10日更新

image

這里額外提一下,截止到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

參考博客鏈接


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,367評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,001評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,213評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,535評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,317評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,868評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,963評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,090評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,599評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,549評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,712評論 1 367
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,233評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,961評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,353評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,607評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,321評論 3 389
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,686評論 2 370

推薦閱讀更多精彩內容