由于不能在iOS客戶端內(nèi)集成支付寶和微信的App支付SDK(為了防蘋果審核檢測SDK)舆驶,因此使用H5支付往史,雖然微信和支付寶的H5支付文檔都說不要在App內(nèi)使用H5支付而是使用App支付嫉沽,但辦法總是有的糕再。
這篇講的是微信H5支付如何從App跳轉(zhuǎn)微信以及如何從微信跳轉(zhuǎn)回App锨能,支付寶支付的見這篇:
實(shí)現(xiàn)的效果是:App→微信→支付(成功失敗或取消)→App
前置準(zhǔn)備
準(zhǔn)備時(shí)大家需要看下官方文檔: 微信H5支付開發(fā)文檔
本項(xiàng)目使用WKWebView
丑罪,前置動(dòng)作是后端小伙伴已經(jīng)處理好支付寶H5
支付下單流程,客戶端接收到下單鏈接后的操作鬓长。
下單鏈接即為微信支付文檔-統(tǒng)一下單API中返回的 mweb_url
谒拴,格式為 https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx2016121516420242444321ca0631331346&package=1405458241
。
操作步驟
1. 添加 URL Scheme 并把微信加入白名單
添加 URL Scheme
涉波。在 xcodeproj
文件Info
選項(xiàng)卡最下面的 URL Types
內(nèi)設(shè)置英上。 注意此URL的一級(jí)域名需要與微信商戶后臺(tái)(微信商戶平臺(tái)-產(chǎn)品中心-開發(fā)配置-H5支付)設(shè)置的的一級(jí)域名一致炭序,比如微信商戶里設(shè)置的是company.com
,那 URL Schemes
可以設(shè)為 a1.company.com
苍日,此特性使得一套H5
支付可以方便得集成到多個(gè)App
惭聂。只有一個(gè)App
需要H5
支付的話也可以直接填與微信后臺(tái)的一致的 company.com
。
如果像上圖那樣填的是 www.company.com
相恃,那URL Scheme
只能設(shè)為其三級(jí)域名如 a2.www.company.com
或同樣的 www.company.com
把微信的URL Scheme
weixin
和 wechat
填入項(xiàng)目的白名單辜纲。在 xcodeproj
文件 Info
選項(xiàng)卡內(nèi)的 Custom iOS Target Properties
的LSApplicationQueriesSchemes
里添加上述兩個(gè)字符串,若沒有 LSApplicationQueriesSchemes
就手動(dòng)輸入添加拦耐,類型為數(shù)組 Array
耕腾。
2. WKWebView加載鏈接
添加協(xié)議 WKNavigationDelegate
和 WKUIDelegate
。
創(chuàng)建一個(gè)WKWebView杀糯,并加載統(tǒng)一下單鏈接扫俺。
- (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
就是后臺(tái)傳來的微信H5支付統(tǒng)一下單鏈接,格式為 https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx2016121516420242444321ca0631331346&package=1405458041
固翰。
我們需要做的處理是根據(jù)文檔給這個(gè)請求添加請求頭Referer
狼纬,關(guān)鍵在于這個(gè) a1.company.com://wxpaycallback/
既滿足了微信檢測到有商戶后臺(tái)設(shè)置好的一級(jí)域名,同時(shí)把這個(gè)鏈接做成了 URL Scheme
使得可以在跳轉(zhuǎn)微信客戶端后(不管支付成功還是失斅罴省)能順利跳轉(zhuǎn)回自己的App
疗琉。其中的 host
wxpaycallback/
可以任意設(shè)置,方便在 AppDelegate
里處理跳轉(zhuǎn)回來后部署業(yè)務(wù)邏輯歉铝。當(dāng)然如果你不需要在 AppDelegate
里接收動(dòng)作而是直接跳回支付界面自行后續(xù)處理的話就只用設(shè)為前一步在 URL Scheme
a1.company.com://
即可盈简。
經(jīng)過測試,對于App
內(nèi)的H5
支付而言太示,實(shí)際上是下面步驟里
@"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"
后接的參數(shù) redirect_url
對支付后跳回App起作用送火,Referer
只起到給微信校驗(yàn)的作用。
所以Referer
只需要設(shè)置成微信H5
支付登記的域名的子域名即可先匪,如
[request setValue:@"a1.company.com" forHTTPHeaderField:@"Referer"];
3. 實(shí)現(xiàn)代理方法攔截鏈接并跳轉(zhuǎn)微信
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURLRequest *request = navigationAction.request;
NSString *absoluteString = [navigationAction.request.URL.absoluteString stringByRemovingPercentEncoding];
// 攔截WKWebView加載的微信支付統(tǒng)一下單鏈接, 將redirect_url參數(shù)修改為喚起自己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;
}
//攔截重定向的跳轉(zhuǎn)微信的 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 中接收跳轉(zhuǎn)動(dòng)作
當(dāng)然你也不一定需要在AppDelegate里接收返回動(dòng)作种吸,也可以直接返回支付界面,自行操作后續(xù)邏輯呀非。
以下是AppDelegate接收返回動(dòng)作的示例坚俗。
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
//safepay是支付寶H5支付的回調(diào)host
if ([url.host isEqualToString:@"wxpaycallback"] ) {
// 自行操作業(yè)務(wù)邏輯
}
}
5. 關(guān)于微信H5支付域名設(shè)置
這里額外提一下,截止到2019年4月岸裙,微信支付設(shè)置頁面明確說了
添加域名后猖败,其所屬的子域名將都有權(quán)限
也就是說只需要填一個(gè)一級(jí)域名比如 company.com
,就可以有無限多個(gè)二級(jí)域名可供不同App
使用降允,繞過微信H5
支付只能添加5個(gè)域名的限制恩闻。如果填的是二級(jí)域名比如 www.company.com
,那么只能往下使用三級(jí)域名比如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