廢話不多說,直接說重點
微信官方提醒:H5支付不建議在APP端使用,如需要在APP中使用微信支付,請接APP支付,文件詳見微信支付開發文件
場景:公司業務需要,在移動端App中引入了微信H5支付
邏輯,支付流程Android
沒問題,但是在iOS
端出現了支付成功/失敗之後開啟了Safari
,並沒有直接返回App
的問題。
以下為解決方案:
首先在網頁中H5調起微信時,可以獲取到H5發出的支付連結為https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=************&package=*********&redirect_url=http://pay.*********.com/phonepay/wxsuccess.jsp
此連結會發起支付,然後開啟微信App支付頁面,支付之後返回App,這個流程在Android
中是沒有問題的,但是在iOS
端支付之後確莫名其妙的開啟了Safari
,Safari
顯示的介面為redirect_url
引數對應的http://pay.*********.com/phonepay/wxsuccess.jsp
連結介面。
注意:此處連結中的
redirect_url
是微信支付之後的結果介面,如果在此連結中拼接了redirect_url
,那麼Safari
是一定會被開啟的,如果前端拼接了此地址,那麼可以讓前端來對iOS
端區別操作,不拼接redirect_url
。
如果前端處理起來比較麻煩,或者不願意做處理,那麼只能移動端(iOS)來手動將這部分引數擷取
最終,iOS端發起支付的H5連結為https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=************&package=*********
,僅僅只是這樣還不行,這個時候連結開啟會報錯
此時,還需要一步操作:
在專案中配置Schemes為pay.***.com
注意:此處的
pay.***.com
,為微信H5支付註冊時配置的授權域名
然後在UIWebView的代理-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
中新增以下程式碼:
/*
此處省略了從
https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=************&package=*********&redirect_url=http://pay.*********.com/phonepay/wxsuccess.jsp
連結中刪除redirect_url的程式碼
*/
/*
將刪除了redirect_url的支付連結,頭部新增Referer資訊,以便微信支付之後可以返回app
此處做連結的字首判斷是為了防止在其他連結中加入Referer資訊
*/
NSDictionary *headers = [request allHTTPHeaderFields];
NSString *preStr = @"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb";
if (![[headers objectForKey:@"Referer"] isEqualToString:@"pay.czbanbantong.com://"] && [request.URL.absoluteString hasPrefix:preStr]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSURL *url = [request URL];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[req setHTTPMethod:@"GET"];
[req setValue:@"pay.***.com://" forHTTPHeaderField:@"Referer"];
[self->webView loadRequest:req];
});
});
return YES;
}
複製程式碼
解釋: 如果連結中拼接了
redirect_url
,那麼系統會用Safari
開啟此連結,將此連結相關配置刪除之後,在請求頭部新增Referer
之後,那麼將會開啟Referer
對應的連結。由於我們這裡給Referer
配置的pay.***.com://
協議,之前已經在App中註冊了Schemes
,那麼在Safari
開啟此協議時將會直接開啟App
,並且沒有中間Safari
跳轉的過程(關於此處請自行搜尋iOS 如何使用Safari開啟App
).
到此,支付邏輯可以返回App了,那麼可能還會有疑問,我的redirect_url
對應的支付結果介面如何展示呢。
關於redirect_url
,微信支付開發文件有如下介紹
總的來說:使用redirect_url
返回支付結果介面的時機本就無法精確掌控。所以根據微信此處介紹,可以有兩種方案解決:
- 調起微信支付,五秒之後重新整理
UIWebView
,跳轉支付結果介面redirect_url
- 支付之後,返回App後,彈框進行查單操作(如上圖)。
由於,我們支付成功失敗之後都是同一個介面,所以採用了第一種方案,五秒之後重新整理
最終程式碼如下:
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
/*
此處省略了從
https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=************&package=*********&redirect_url=http://pay.*********.com/phonepay/wxsuccess.jsp
連結中刪除redirect_url的程式碼
*/
/*
將刪除了redirect_url的支付連結,頭部新增Referer資訊,以便微信支付之後可以返回app
此處做連結的字首判斷是為了防止在其他連結中加入Referer資訊
*/
NSDictionary *headers = [request allHTTPHeaderFields];
NSString *preStr = @"https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb";
if (![[headers objectForKey:@"Referer"] isEqualToString:@"pay.czbanbantong.com://"] && [request.URL.absoluteString hasPrefix:preStr]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSURL *url = [request URL];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[req setHTTPMethod:@"GET"];
[req setValue:@"pay.***.com://" forHTTPHeaderField:@"Referer"];
[self->webView loadRequest:req];
});
});
return YES;
}
/*
從開啟微信支付開始,五秒之後重新整理webView介面(redirect_url本就不靠譜,無法精確)
weixin://wap/pay 為最終調起微信支付時的協議開頭
*/
if ([request.URL.absoluteString hasPrefix:@"weixin://wap/pay"]) {
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC));
dispatch_after(delayTime, dispatch_get_main_queue(), ^{
[self->webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://pay.czbanbantong.com/phonepay/wxsuccess.jsp"]]];
});
return YES;
}
}
複製程式碼