近期公司項(xiàng)目中的App使用WKWebView封裝作為一個殼,加載web的網(wǎng)頁,其中的支付使用的是H5支付,在APP中需要調(diào)起微信和支付客戶端進(jìn)行支付晦攒,過程中遇到了一些問題,好在通過查找資料找到了以下解決方案得哆,這里來記錄下
一、支付寶
找了下支付寶的開發(fā)文檔哟旗,發(fā)現(xiàn)支付寶自己其實(shí)已經(jīng)做了手機(jī)網(wǎng)站支付轉(zhuǎn)Native支付的接口贩据,使用很方便,直接按照開發(fā)文檔接入即可闸餐,這里是開發(fā)文檔的連接 手機(jī)網(wǎng)站支付轉(zhuǎn)Native支付(下面我大概引用下集成流程)
iOS接入說明(先下載支付的SDK下載Demo)
配置
步驟1:啟動Xcode饱亮,把iOS包中的壓縮文件中以下文件拷貝到項(xiàng)目文件夾下,并導(dǎo)入到項(xiàng)目工程中舍沙。
AlipaySDK.bundle
AlipaySDK.framework
在Build Phases選項(xiàng)卡的Link Binary With Libraries中近上,增加以下依賴:
其中,需要注意的是:
如果是Xcode 7.0之后的版本拂铡,需要添加libc++.tbd壹无、libz.tbd;
如果是Xcode 7.0之前的版本感帅,需要添加libc++.dylib斗锭、libz.dylib(如下圖)。
步驟2:在需要調(diào)用AlipaySDK的文件中失球,增加頭文件引用岖是。
import
步驟3:配置支付寶客戶端返回url處理方法。
(外部存在支付包錢包实苞,支付寶錢包將處理結(jié)果通過url返回豺撑。)
如示例AliSDKDemo\APAppDelegate.m文件中,增加引用代碼:
import
在@implementation AppDelegate中增加如下代碼:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
//如果極簡開發(fā)包不可用黔牵,會跳轉(zhuǎn)支付寶錢包進(jìn)行支付聪轿,需要將支付寶錢包的支付結(jié)果回傳給開發(fā)包
if ([url.host isEqualToString:@"safepay"]) {
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
//【由于在跳轉(zhuǎn)支付寶客戶端支付的過程中,商戶app在后臺很可能被系統(tǒng)kill了荧止,所以pay接口的callback就會失效屹电,請商戶對standbyCallback返回的回調(diào)結(jié)果進(jìn)行處理,就是在這個方法里面處理跟callback一樣的邏輯】
NSLog(@"result = %@",resultDic);
}];
}
if ([url.host isEqualToString:@"platformapi"]){//支付寶錢包快登授權(quán)返回authCode
[[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
//【由于在跳轉(zhuǎn)支付寶客戶端支付的過程中,商戶app在后臺很可能被系統(tǒng)kill了跃巡,所以pay接口的callback就會失效危号,請商戶對standbyCallback返回的回調(diào)結(jié)果進(jìn)行處理,就是在這個方法里面處理跟callback一樣的邏輯】
NSLog(@"result = %@",resultDic);
}];
}
return YES;
}
接口調(diào)用說明
本SDK提供的所有接口均定義在AlipaySDK.h中。
SDK中提供了若干接口素邪,手機(jī)網(wǎng)站轉(zhuǎn)Native支付只用到其中一部分外莲,本文未提到的接口無需關(guān)注。
如何調(diào)用提供的接口?
APP支付最新版本 15.4.0 新增攔截+支付二合一接口(payInterceptorWithUrl...)偷线,該接口將原來的獲取H5支付訂單信息接口和支付接口進(jìn)行了合并磨确。
接口的調(diào)用方式是先調(diào)用defaultService獲取SDK的實(shí)例,然后再調(diào)用單獨(dú)提供的功能接口声邦,以payInterceptorWithUrl為例:
[[AlipaySDK defaultService] payInterceptorWithUrl:url fromScheme:scheme callback:^(NSDictionary result) {
// 處理支付結(jié)果
NSLog(@"%@", result);
}];
如何實(shí)現(xiàn)手機(jī)網(wǎng)站轉(zhuǎn)APP支付乏奥?
步驟一: 實(shí)現(xiàn)UIWebViewDelegate協(xié)議,攔截H5的URL亥曹;
步驟二: 調(diào)用新增攔截+支付二合一接口(payInterceptorWithUrl...)進(jìn)行URL攔截及支付轉(zhuǎn)化邓了;具體參照如下接口說明。
攔截+支付二合一接口
接口原型
/*
- 支付寶H5支付URL攔截器媳瞪,完成攔截及支付方式轉(zhuǎn)化
- @param urlStr 待過濾攔截的 url string
- @param schemeStr 調(diào)用支付的app注冊在info.plist中的scheme
- @param compltionBlock 支付結(jié)果回調(diào)Block
- @return YES:表示URL為支付寶支付URL骗炉,URL已經(jīng)被攔截轉(zhuǎn)化;NO:表示URL非支付寶支付URL蛇受;
*/
- (BOOL)payInterceptorWithUrl:(NSString *)urlStr
fromScheme:(NSString *)schemeStr callback:(CompletionBlock)completionBlock;
接口功能
本接口首先是個攔截器句葵,攔截支付寶H5支付URL;其次是個支付方式轉(zhuǎn)化器兢仰,將手機(jī)網(wǎng)站支付方式轉(zhuǎn)化為APP支付方式乍丈。
參數(shù)說明
參數(shù)名稱類型說明
urlStrNSString *手機(jī)網(wǎng)站支付的請求URL
schemeStrNSString *接入方App注冊的URL scheme,供支付完成后跳回接入方App
completionBlockobjc(^CompletionBlock)(NSDictionary *resultDic)支付結(jié)束之后的回調(diào)其中CompletionBlock定義如下:objctypedef void(^CompletionBlock)(NSDictionary *resultDic);
同步攔截結(jié)果返回值說明
返回值類型說明
BOOL1.如果urlStr是有效的支付寶H5支付URL旨别,則說明攔截轉(zhuǎn)化成功诗赌,返回YES,商戶容器無需再加載該URL秸弛;
2.如果是無效的铭若,則返回NO,商戶容器需要繼續(xù)加載該URL递览。
異步支付結(jié)果返回值說明
支付結(jié)束后SDK將回調(diào)completionBlock叼屠,并將支付結(jié)果resultDic(NSDictionary *類型)作為參數(shù)傳入該Block。resultDic中主要包含兩個字段绞铃,如下所示:
參數(shù)名稱類型說明
resultCodeNSString *返回碼镜雨,標(biāo)識支付狀態(tài),含義如下:
9000——訂單支付成功
8000——正在處理中
4000——訂單支付失敗
5000——重復(fù)請求
6001——用戶中途取消
6002——網(wǎng)絡(luò)連接出錯
returnUrlNSString *支付結(jié)束后應(yīng)當(dāng)跳轉(zhuǎn)的url地址
接口使用方式
調(diào)用本接口對支付寶支付URL進(jìn)行攔截和支付轉(zhuǎn)化儿捧。
當(dāng)接口調(diào)用完成后荚坞,該接口會返回一個BOOL類型的同步攔截結(jié)果,如果同步結(jié)果返回值為YES菲盾,說明傳入的URL為支付寶支付URL颓影,支付寶SDK已經(jīng)成功攔截該URL,并轉(zhuǎn)化為APP支付方式懒鉴,商戶容器無需再加載該URL诡挂;如果返回值為NO碎浇,說明傳入的URL并非支付寶支付URL,商戶容器需要繼續(xù)加載該URL璃俗;
當(dāng)支付結(jié)束后奴璃,會通過回調(diào)的方式返回異步支付結(jié)果,如果返回的支付結(jié)果中的resultCode為9000城豁,則表示支付成功苟穆,接入方可以提示用戶支付成功;如果返回結(jié)果不是9000钮蛛,無需做任何處理鞭缭。當(dāng)返回的returnUrl不為空,建議接入方跳轉(zhuǎn)到該returnUrl魏颓。
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
__weak APWebViewController* wself = self;
BOOL isIntercepted = [[AlipaySDK defaultService] payInterceptorWithUrl:[request.URL absoluteString] fromScheme:@"alisdkdemo" callback:^(NSDictionary *result) {
// 處理支付結(jié)果
NSLog(@"%@", result);
// isProcessUrlPay 代表 支付寶已經(jīng)處理該URL
if ([result[@"isProcessUrlPay"] boolValue]) {
// returnUrl 代表 第三方App需要跳轉(zhuǎn)的成功頁URL
NSString* urlStr = result[@"returnUrl"];
[wself loadWithUrlStr:urlStr];
}
}];
if (isIntercepted) {
return NO;
}
return YES;
}
上面是使用UIWebView的回調(diào)寫法,下面是我使用的WKWebView的代碼:
- (void)webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction decisionHandler:(void(^)(WKNavigationActionPolicy))decisionHandler{
__weakWebViewController* wself = self;
BOOL isIntercepted = [[AlipaySDK defaultService] payInterceptorWithUrl:[navigationAction.request.URL absoluteString] fromScheme:@"PuHuiAlipay" callback:^(NSDictionary *result) {
// 處理支付結(jié)果
NSLog(@"%@", result);
// isProcessUrlPay 代表 支付寶已經(jīng)處理該URL
if ([result[@"isProcessUrlPay"]boolValue]) {
NSString*resultCode = result[@"resultCode"];
// returnUrl 代表 第三方App需要跳轉(zhuǎn)的成功頁URL
NSString* urlStr = result[@"returnUrl"];
if ([resultCodeisEqual:@"6001"]) {//當(dāng)不是取消支付的時候吱晒,重新加載支付前的頁面
urlStr = self.URLString;
[wself toast:@"取消支付了"];
}else {
if (urlStr.length==0) {
urlStr = [NSString stringWithFormat:@"http://huigong.jmzgo.com/weibojie/payResult.aspx?OrderID=%@",_wbjOrderID];
}
}
[wselfloadWithUrlStr:urlStr];
}
}];
if (isIntercepted) {
actionPolicy =WKNavigationActionPolicyCancel;
}
decisionHandler(actionPolicy);
}
二甸饱、微信支付
微信支付目前使用的下面的方法跳轉(zhuǎn)到微信客戶端進(jìn)行支付,做法在WKWebView的回調(diào)中攔截URL仑濒,然后使用openURL的方式叹话,代碼如下:
- (void)webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction decisionHandler:(void(^)(WKNavigationActionPolicy))decisionHandler{
WKNavigationActionPolicy actionPolicy = WKNavigationActionPolicyAllow; NSString*urlString = [[navigationAction.requestURL]absoluteString];
urlString = [urlStringstringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; if ([urlStringcontainsString:@"weixin://wap/pay?"]) {
actionPolicy =WKNavigationActionPolicyCancel;
//解決wkwebview weixin://無法打開微信客戶端的處理
NSURL*url = [NSURLURLWithString:urlString];
if ([[UIApplicationsharedApplication]respondsToSelector:@selector(openURL:options:completionHandler:)]) {
[[UIApplication sharedApplication] openURL:url options:@{UIApplicationOpenURLOptionUniversalLinksOnly: @NO} completionHandler:^(BOOL success) { }];
} else {
[[UIApplicationsharedApplication]openURL:webView.URL];
}
}
}
//這句是必須加上的,不然會異常
decisionHandler(actionPolicy);
}
上面的方法有個問題墩瞳,微信支付完或者取消的時候會跳轉(zhuǎn)是Safari瀏覽器驼壶,沒辦法直接返回到APP端,這個問題一直沒辦法很好的解決喉酌,所以我的做法是在我們的支付結(jié)果頁中加了一個返回APP的按鈕热凹,這樣在Safari中加載支付結(jié)果頁的時候,在頁面中通過Scheme可以打開我們的APP