iOS WKWebView實現(xiàn)H5跳轉(zhuǎn)微信前联、支付寶支付功戚,并返回原APP

項目開發(fā)遇到web頁調(diào)起支付的功能,參考了網(wǎng)上很多資料蛀恩,在此做個筆記疫铜,便于記憶,同時也希望幫助到遇到相同問題的小伙伴双谆。
參考鏈接:
http://www.reibang.com/p/8ac06ffd090f
http://www.reibang.com/p/28483a16c4d5
http://www.reibang.com/p/66d2c0ff51c6

微信支付

問題:web頁點擊支付跳轉(zhuǎn)微信支付頁后點擊左上角的取消按鈕或完成支付之后壳咕,微信APP跳轉(zhuǎn)的是Safari瀏覽器,而不是跳轉(zhuǎn)回原APP顽馋。
解決方案:
1.設(shè)置自己項目中Schemes

Info->URL Types
格式為:www.xxxx.com谓厘,注意:www.xxxx.com 此域名是H5授權(quán)的域名,如果是二級域名寸谜,可以寫成:aaa.xxxx.com(aaa隨便寫)竟稳。可以直接問申請微信支付的人要熊痴。

Schemes.png

2.修改redirect_url

目的是保證redirect_url這個回調(diào)鏈接能跟設(shè)置的URL Schemes一致他爸。

攔截后我們需要首先關(guān)注在原始地址中是否含有redirect_url=字符串,如果含有該字符串則說明你們后臺人員是利用該字符串在微信支付完成后跳轉(zhuǎn)到支付完成的界面.而我們也需要利用該字段以實現(xiàn)支付完成后跳轉(zhuǎn)回我們的APP.

  • 如果包含redirect_url=字段果善,我們需要先記住后臺重定向的地址诊笤,然后將其替換成我們配置好的URL schemes以實現(xiàn)跳轉(zhuǎn)回我們的APP.然后在跳轉(zhuǎn)回我們APP之后我們會手動再加載一次原先重定向的URL地址。
  • 如果不包含redirect_url=字段巾陕,我們只需要添加該字段到原始URL最后面即可
3.設(shè)置webView請求header中的Referer字段

微信支付結(jié)束后默認(rèn)回調(diào)Referer字段中地址讨跟。
Referer設(shè)置為www.xxxx.com://,這樣的格式鄙煤。

4.添加WKNavigationDelegate代理晾匠,實現(xiàn)重定向代理方法
注意
  • 我們需要判斷微信地址的同時判斷“redirect_url=www.xxxx.com://”,因為我們在第一次檢測到后會重新加載該地址,該地址中也含有 https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb梯刚,會形成循環(huán)沖突凉馆,所以判斷條件如下
  • 如我們項目中有支付完成的重定向地址,我們可以在跳轉(zhuǎn)前即加載該地址亡资,否則我們在回到APP后會有明顯的加載過程句喜,界面不友好
  • 一般跳轉(zhuǎn)到其他APP時,地址不是以http或https開頭沟于,所以我們在最后的判斷中以此為依據(jù),但注意如果服務(wù)器端加載錯誤的地址可能會走入此邏輯咳胃,所以必須對特定的scheme進(jìn)行處理

支付寶支付

問題:web頁點擊支付跳轉(zhuǎn)支付寶支付頁后點擊左上角的取消按鈕或完成支付之后,停留在支付寶旷太,而不是跳轉(zhuǎn)回原APP展懈。
解決方案:
1.添加 URL Scheme
2.實現(xiàn)代理方法攔截鏈接并跳轉(zhuǎn)支付寶

WKNavigationDelegate代碼

#define XDX_URL_TIMEOUT 30
static const NSString *CompanyFirstDomainByWeChatRegister = @"www.xxxx.com";

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    
    NSURLRequest *request        = navigationAction.request;
    NSString     *scheme         = [request.URL scheme];
    // decode for all URL to avoid url contains some special character so that it wasn't load.
    NSString     *absoluteString = [navigationAction.request.URL.absoluteString stringByRemovingPercentEncoding];
    NSLog(@"Current URL is %@",absoluteString);
    
    static NSString *endPayRedirectURL = nil;
    
    // 解決跳轉(zhuǎn)到本地支付寶App不返回的問題
    if ([absoluteString hasPrefix:@"alipays://"] || [absoluteString hasPrefix:@"alipay://"])
    {
        NSURL *openedURL = navigationAction.request.URL;
        
        NSString *prefixString = @"alipay://alipayclient/?";
        //替換里面的默認(rèn)Scheme為自己的Scheme
        NSString *urlString = [[self xh_URLDecodedString:absoluteString] stringByReplacingOccurrencesOfString:@"alipays" withString:[NSString stringWithFormat:@"%@",CompanyFirstDomainByWeChatRegister]];
        
        if ([urlString hasPrefix:prefixString]) {
            NSRange rang = [urlString rangeOfString:prefixString];
            NSString *subString = [urlString substringFromIndex:rang.length];
            NSString *encodedString = [prefixString stringByAppendingString:[self xh_URLEncodedString:subString]];
            openedURL = [NSURL URLWithString:encodedString];
        }
        
        BOOL isSucc = [[UIApplication sharedApplication] openURL:openedURL];
        if (!isSucc) {
            NSLog(@"未安裝某寶客戶端");
        }
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    
    //解決微信支付后為返回當(dāng)前應(yīng)用的問題
    // Wechat Pay, Note : modify redirect_url to resolve we couldn't return our app from wechat client.
    if ([absoluteString hasPrefix:@"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"] && ![absoluteString hasSuffix:[NSString stringWithFormat:@"redirect_url=%@://",CompanyFirstDomainByWeChatRegister]]) {
        decisionHandler(WKNavigationActionPolicyCancel);
        
        // 1. If the url contain "redirect_url" : We need to remember it to use our scheme replace it.
        // 2. If the url not contain "redirect_url" , We should add it so that we will could jump to our app.
        //  Note : 2. if the redirect_url is not last string, you should use correct strategy, because the redirect_url's value may contain some "&" special character so that my cut method may be incorrect.
        NSString *redirectUrl = nil;
        if ([absoluteString containsString:@"redirect_url="]) {
            NSRange redirectRange = [absoluteString rangeOfString:@"redirect_url"];
            endPayRedirectURL =  [absoluteString substringFromIndex:redirectRange.location+redirectRange.length+1];
            redirectUrl = [[absoluteString substringToIndex:redirectRange.location] stringByAppendingString:[NSString stringWithFormat:@"redirect_url=%@://",CompanyFirstDomainByWeChatRegister]];
        }else {
            redirectUrl = [absoluteString stringByAppendingString:[NSString stringWithFormat:@"&redirect_url=%@://",CompanyFirstDomainByWeChatRegister]];
        }
        
        NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:redirectUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:XDX_URL_TIMEOUT];
        newRequest.allHTTPHeaderFields = request.allHTTPHeaderFields;
        [newRequest setValue:[NSString stringWithFormat:@"%@",CompanyFirstDomainByWeChatRegister] forHTTPHeaderField:@"Referer"];
        newRequest.URL = [NSURL URLWithString:redirectUrl];
        [webView loadRequest:newRequest];
        return;
    }
    
    // Judge is whether to jump to other app.
    if (![scheme isEqualToString:@"https"] && ![scheme isEqualToString:@"http"]) {
        decisionHandler(WKNavigationActionPolicyCancel);
        if ([scheme isEqualToString:@"weixin"]) {
            // The var endPayRedirectURL was our saved origin url's redirect address. We need to load it when we return from wechat client.
            if (endPayRedirectURL) {
                [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:endPayRedirectURL] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:XDX_URL_TIMEOUT]];
            }
        }else if ([scheme isEqualToString:[NSString stringWithFormat:@"%@",CompanyFirstDomainByWeChatRegister]]) {

        }

//        BOOL canOpen = [[UIApplication sharedApplication] canOpenURL:request.URL];
//        if (canOpen) {
//            [[UIApplication sharedApplication] openURL:request.URL];
//        }
        if ([navigationAction.request.URL.absoluteString hasPrefix:@"weixin://"]) {
            [[UIApplication sharedApplication] openURL:navigationAction.request.URL];
        }
        return;
    }
  
    decisionHandler(WKNavigationActionPolicyAllow);
    
}

- (NSString *)xh_URLDecodedString:(NSString *)urlString {
    NSString *string = urlString;
    NSString *decodedString=(__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (__bridge CFStringRef)string, CFSTR(""), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
    return decodedString;
}

- (NSString *)xh_URLEncodedString:(NSString *)urlString {
    NSString *string = urlString;
    NSString *encodedString = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                                     (CFStringRef)string,
                                                                                                     NULL,
                                                                                                     (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                                                                                                     kCFStringEncodingUTF8));
    return encodedString;
}

跳轉(zhuǎn)返回通知

跳轉(zhuǎn)回原APP后,在Appdelegate.m文件中會有回調(diào)方法供璧。在方法里存崖,可以寫一些其他的邏輯代碼。

// 僅支持iOS9以上系統(tǒng)睡毒,iOS8及以下系統(tǒng)不會回調(diào)
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
    //6.3的新的API調(diào)用来惧,是為了兼容國外平臺的調(diào)用[如果用6.2的api調(diào)用會沒有回調(diào)],對國內(nèi)平臺沒有影響
    BOOL result = [[UMSocialManager defaultManager]  handleOpenURL:url options:options];
    if (!result) {
        // 其他如支付等SDK的回調(diào)

        // H5微信支付的回調(diào)
        if ([url.scheme isEqualToString:@"www.xxxx.com"]) {
            // 發(fā)送通知加載頁面
            [[NSNotificationCenter defaultCenter] postNotificationName:kWeChatComeBackKey object:nil userInfo:@{@"url" : url.absoluteString}];
        }
    }
    return result;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市演顾,隨后出現(xiàn)的幾起案子供搀,更是在濱河造成了極大的恐慌隅居,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葛虐,死亡現(xiàn)場離奇詭異胎源,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)屿脐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門涕蚤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人的诵,你說我怎么就攤上這事万栅。” “怎么了西疤?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵烦粒,是天一觀的道長。 經(jīng)常有香客問我瘪阁,道長撒遣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任管跺,我火速辦了婚禮义黎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘豁跑。我一直安慰自己廉涕,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布艇拍。 她就那樣靜靜地躺著狐蜕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卸夕。 梳的紋絲不亂的頭發(fā)上层释,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天,我揣著相機(jī)與錄音快集,去河邊找鬼贡羔。 笑死,一個胖子當(dāng)著我的面吹牛个初,可吹牛的內(nèi)容都是我干的乖寒。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼院溺,長吁一口氣:“原來是場噩夢啊……” “哼楣嘁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤逐虚,失蹤者是張志新(化名)和其女友劉穎聋溜,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痊班,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡勤婚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年摹量,在試婚紗的時候發(fā)現(xiàn)自己被綠了涤伐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡缨称,死狀恐怖凝果,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情睦尽,我是刑警寧澤器净,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站当凡,受9級特大地震影響山害,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜沿量,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一浪慌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧朴则,春花似錦权纤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至撤蚊,卻和暖如春古掏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背侦啸。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工槽唾, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人匹中。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓夏漱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親顶捷。 傳聞我的和親對象是個殘疾皇子挂绰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348