本文只討論你已經(jīng)成功實(shí)現(xiàn)客戶端->支付寶支付流程,僅僅是支付完成后無法返回自己的APP的問題。
如果你的支付流程是客戶端->Safari->支付寶不在本文討論范圍之類辛馆。
iOS支付寶H5支付不在討論范圍內(nèi)风范。提供下列參考:
本文前大段在講樓主是如何解決這個(gè)問題的,以及中間遇到的麻煩庆锦。趕時(shí)間的同學(xué)可以直接看最后的最終解決方案。
在討論之前轧葛,我們先看看官方文檔上的一句話:
注意:在iOS系統(tǒng)中搂抒,喚起支付寶App支付完成后艇搀,不會(huì)自動(dòng)回到瀏覽器或商戶APP。用戶可手工切回到瀏覽器或商戶APP求晶;支付寶H5收銀臺(tái)會(huì)自動(dòng)跳轉(zhuǎn)回商戶return_url指定的頁面焰雕。
what? 官方直接跟我們說GG了?樓主不甘心芳杏,還是想嘗試一下矩屁。
借鑒之前iOS微信H5支付無法返回APP解決方案的經(jīng)驗(yàn),先在return_url這個(gè)參數(shù)上做個(gè)嘗試吧爵赵。
支付寶和微信不同的是吝秕,支付寶的return_url不需要在支付寶管理后臺(tái)備案(填寫),微信的redirect_url是需要的空幻。
第一次嘗試
webView攔截請求https://mapi.alipay.com/gateway.do烁峭,修改return_url參數(shù)為自己的URLScheme,比如 URLEncode(A.company.com://)秕铛,結(jié)果失敗了约郁,進(jìn)入支付寶報(bào)錯(cuò)的頁面。仔細(xì)看了一下請求的其它參數(shù)但两,居然有個(gè)sign鬓梅!支付寶文檔上也有這個(gè)參數(shù),居然校驗(yàn)了參數(shù)簽名的谨湘,好吧绽快,客戶端篡改參數(shù)的方案宣告失敗悲关!
第二次嘗試
既然不能篡改谎僻,那直接下單的時(shí)候填吧娄柳,請求后臺(tái)的同學(xué)協(xié)助一下寓辱,在下單的時(shí)候把return_url參數(shù)改成 URLEncode(A.company.com://),結(jié)果還是失敗了赤拒。后臺(tái)同學(xué)提示我秫筏,return_url必須是HTTP/HTTPS開頭,支付寶文檔上有說明挎挖。
第三次嘗試
那加上http試試这敬,我又讓后臺(tái)同學(xué)把return_url改成? URLEncode(httpA.company.com://),同時(shí)把APP的URLSchemes改成httpA.company.com蕉朵,再次嘗試崔涂,調(diào)起支付寶返回的時(shí)候打開了Safari,在Safari里面顯示了我們支付中心的錯(cuò)誤頁面始衅,return_url方案徹底失敗了冷蚂!
要不就算了缭保,跟產(chǎn)品說支付寶無法實(shí)現(xiàn)支付完成后跳回APP,反正支付寶官方文檔上都這么寫了蝙茶。
雖然這么想了艺骂,但是我還是繼續(xù)翻看支付寶的文檔,希望能找到點(diǎn)蛛絲馬跡隆夯。
突然看到了這里钳恕,手機(jī)網(wǎng)站支付轉(zhuǎn)Native支付
支付寶文檔
schemeStr,這個(gè)關(guān)鍵字讓我眼前一亮蹄衷。
手機(jī)網(wǎng)站支付轉(zhuǎn)Native支付:支付寶的意思是忧额,我們提供了一個(gè)SDK,你接了之后就可以很方便的實(shí)現(xiàn)H5收銀臺(tái)(即在web上輸入支付寶賬號(hào)密碼支付)到支付寶APP收銀臺(tái)的過渡愧口。
如果你是一個(gè)"正規(guī)"APP開發(fā)者宙址,至此已經(jīng)可以解決你的問題了。按照支付寶文檔接支付寶SDK即可调卑,就能實(shí)現(xiàn)H5支付回調(diào)APP了抡砂。
但,這不是樓主想要的方案恬涧,由于工作需求的原因注益,樓主不想也不敢接支付寶的SDK,怕被蘋果爸爸審核掃包啊溯捆。如果你的APP"應(yīng)該"用蘋果支付丑搔,即使你沒有用到支付寶的功能,但是包含了支付寶的SDK提揍,審核被發(fā)現(xiàn)了啤月,也可能被拒絕的。
繼續(xù)尋找解決辦法劳跃。
下載了支付寶的Demo谎仲,試了下確實(shí)可以跳回APP。
樓主琢磨著刨仑,既然SDK能實(shí)現(xiàn)這個(gè)功能郑诺,說明支付寶還是支持的H5支付完成后返回APP功能的,并不是向文檔上說的杉武,"在iOS系統(tǒng)中辙诞,喚起支付寶App支付完成后,不會(huì)自動(dòng)回到瀏覽器或商戶APP轻抱。用戶可手工切回到瀏覽器或商戶APP"飞涂,只是支付寶不愿意公開而已。
那就以這個(gè)支付寶Demo為切入點(diǎn)吧,雖然SDK中有schemeStr這個(gè)參數(shù)较店,但是SDK是黑盒啊志鹃,你不知道它在里面做了些什么。
/** * 支付接口 * *@paramorderStr 訂單信息 *@paramschemeStr 調(diào)用支付的app注冊在info.plist中的scheme *@paramcompletionBlock 支付結(jié)果回調(diào)Block泽西,用于wap支付結(jié)果回調(diào)(非跳轉(zhuǎn)錢包支付) */- (void)payOrder:(NSString *)orderStr fromScheme:(NSString *)schemeStr callback:(CompletionBlock)completionBlock;
追本溯源曹铃,最終打開支付寶APP都會(huì)走
[UIApplicationsharedApplication] openURL:]
在Demo工程里搜了一下,沒有捧杉。但我肯定SDK里面肯定有陕见!
whatever —— Method Swizzling
#import<UIKit/UIKit.h>
#import<objc/runtime.h>
@implementationUIApplication(TrackTimer)
+ (void)load{
staticdispatch_once_toneToken;dispatch_once(&oneToken, ^{? ? ? ??
SEL mySelector =NSSelectorFromString(@"my_openURL:");? ? ? ??
SEL orginalSelector =NSSelectorFromString(@"openURL:");? ? ? ??
Method myMethod = class_getInstanceMethod([selfclass], mySelector);? ? ? ??
Method orginalMethod = class_getInstanceMethod([selfclass], orginalSelector);
BOOLdidAddMethod = class_addMethod([selfclass], orginalSelector, method_getImplementation(myMethod), method_getTypeEncoding(myMethod));
if(didAddMethod) {? ? ? ? ? ?
class_replaceMethod([selfclass], mySelector, method_getImplementation(orginalMethod), method_getTypeEncoding(orginalMethod));? ? ? ??
}else{? ? ? ? ? ??
method_exchangeImplementations(myMethod, orginalMethod);? ? ? ?
?}? ?
?});}
- (void)my_openURL:(NSURL*)url{
NSLog(@"%@",url);? ??
[selfmy_openURL:url];
}
打印結(jié)果如下
URLDecode
alipaymatrixbwf0cml3://alipayclient/?{
"fromAppUrlScheme" : "alisdkdemo",
"requestType" : "SafePay",
"dataString" : "trade_no="2018041921001001270586523089"&pay_phase_id=""&biz_type="trade"&biz_sub_type="TRADE"&app_name="tb"&extern_token="1fc77c67c70ef70d58e2bf7c513d91a5"&appenv=""&pay_channel_id="alipay_sdk"&bizcontext="{"av":"1","sc":"h5tonative","ty":"ios_lite","appkey":"2014052600006128","sv":"h.a.3.5.3","an":"com.antfin.AliSDKDemo"}""
}
為什么前面會(huì)有一點(diǎn)亂碼,alipaymatrixbwf0cml3味抖,不管它了评甜。fromAppUrlScheme,是不是很驚喜仔涩。
是不是支付寶H5支付都有這個(gè)參數(shù)呢忍坷?樓主趕緊用自己的項(xiàng)目嘗試了一下,webView最終會(huì)有一個(gè)alipay://請求的熔脂,攔截它佩研,看看參數(shù)
URLDecode以后(部分字段我做了屏蔽)
alipay://alipayclient/?{"dataString":"h5_route_token="xxxxxxxxxxxxx"&is_h5_route="true"","requestType":"SafePay","fromAppUrlScheme":"alipays"}
也有fromAppUrlScheme這個(gè)參數(shù),而且默認(rèn)是支付寶APP的URLScheme:alipays霞揉。
對比一下發(fā)現(xiàn)旬薯,SDK中傳入的schemeStr參數(shù)對應(yīng)就是alipay:// 中的 fromAppUrlScheme字段。
由此樓主猜測适秩,在 alipay:// 打開支付寶時(shí)绊序,傳入 fromAppUrlScheme,支付結(jié)束后就會(huì)跳到對應(yīng)的APP秽荞。
最終骤公,樓主在自己的項(xiàng)目中驗(yàn)證了上述猜測。
總結(jié)下吧
最終解決方案
方案一
接支付寶提供的SDK扬跋,schemeStr參數(shù)傳入自己APP的URLScheme即可阶捆。 具體的手機(jī)網(wǎng)站支付轉(zhuǎn)Native支付
方案二
不需要接SDK,不需要添加支付寶白名單胁住,webView攔截alipay://alipayclient請求趁猴,追加或修改參數(shù) fromAppUrlScheme為你自己的URLScheme值(這一步可沒那么簡單刊咳,自己動(dòng)手吧彪见,偷笑),生成新的NSURL娱挨,然后用 [[UIApplication sharedApplication] openURL:] 打開即可余指。
2018.5.24更新(上面看懂了下面這段可以不用看)
總有人私信我問我怎么追加fromAppUrlScheme。可能是我說的"webView攔截"酵镜,讓初學(xué)者不明白吧碉碉,簡單提一下。
在webView"發(fā)起請求的代理方法"里面攔截請求的URL淮韭,即如果請求是alipay://alipayclient開頭的垢粮,說明這個(gè)請求就跳轉(zhuǎn)支付寶的請求。替換里面fromAppUrlScheme的值為你自己的scheme值靠粪。(當(dāng)然如果更嚴(yán)謹(jǐn)?shù)脑捓桑瑧?yīng)該是判斷fromAppUrlScheme這個(gè)key是否存在,存在則替換其值占键,不存在則追加)昔善。用替換好的字符串生成一個(gè)NSURL,用[[UIApplication sharedApplication] openURL:newURL]跳轉(zhuǎn)支付寶畔乙。代理方法返回NO君仆,即終止這次請求。
常見問題
1.支付后沒有返回app而是跳到了Safari
原因:你的Xcode配置里面URLSheme沒寫或者寫錯(cuò)了牲距,和支付寶請求參數(shù)中的fromAppUrlScheme不一致返咱。
解決:Xcode配置中新增或者修改URLSheme,確保和alipay://alipayclient請求參數(shù)中的fromAppUrlScheme一致牍鞠。
2.并沒有看到作者說的alipay: //alipayclient
原因:可能你的app不是在客戶端直接和支付寶通信洛姑,而是中間加了一道跳轉(zhuǎn)到網(wǎng)頁,由你的后臺(tái)(或前端)調(diào)起支付寶皮服。所以你是攔截不到這個(gè)請求的楞艾。我文中所說的方式是基于,“客戶端->支付寶” 這種模式龄广,而你的是“客戶端->Safari->支付寶”模式硫眯,后者無法按照文中說述實(shí)現(xiàn)返回app。
解決:方案1择同,修改你的支付模式為“客戶端->支付寶”两入,這樣改動(dòng)恐怕有點(diǎn)大,工作量主要在你們后臺(tái)敲才。方案2裹纳,在不改模式的情況下,需要后臺(tái)(或前端)的同事去解決這個(gè)問題紧武,原理和本文差不多剃氧,在后臺(tái)和支付寶通訊的參數(shù)中找到一個(gè)類似于fromAppUrlScheme的參數(shù),然后將這個(gè)參數(shù)修改成你的app的URLScheme阻星,至于具體怎處理樓主沒做研究朋鞍,如果你有好的方法,可以分享一下。