本文只討論已成功調(diào)起支付寶支付后荆残,無(wú)法返回自己的APP的問(wèn)題稀火,iOS支付寶H5支付不在討論范圍內(nèi)。提供下列參考:
支付寶H5支付官方文檔
支付寶H5支付官方Demo下載 (Demo使用文檔)
本文前大段在講樓主是如何解決這個(gè)問(wèn)題的,以及中間遇到的麻煩倚喂。趕時(shí)間的同學(xué)可以直接看最后的 最終解決方案。
在討論之前瓣戚,我們先看看官方文檔上的一句話:
注意:在iOS系統(tǒng)中端圈,喚起支付寶App支付完成后,不會(huì)自動(dòng)回到瀏覽器或商戶APP子库。用戶可手工切回到瀏覽器或商戶APP舱权;支付寶H5收銀臺(tái)會(huì)自動(dòng)跳轉(zhuǎn)回商戶return_url指定的頁(yè)面。
what? 官方直接跟我們說(shuō)GG了仑嗅?樓主不甘心宴倍,還是想嘗試一下。
借鑒之前 iOS微信H5支付無(wú)法返回APP解決方案 的經(jīng)驗(yàn)仓技,先在 return_url 這個(gè)參數(shù)上做個(gè)嘗試吧鸵贬。
支付寶和微信不同的是,支付寶的return_url不需要在支付寶管理后臺(tái)備案(填寫(xiě))浑彰,微信的redirect_url是需要的恭理。
第一次嘗試
webView攔截請(qǐng)求https://mapi.alipay.com/gateway.do,修改return_url參數(shù)為自己的URLScheme郭变,比如 URLEncode(A.company.com://)颜价,結(jié)果失敗了,進(jìn)入支付寶報(bào)錯(cuò)的頁(yè)面诉濒。仔細(xì)看了一下請(qǐng)求的其它參數(shù)周伦,居然有個(gè)sign!支付寶文檔上也有這個(gè)參數(shù)未荒,居然校驗(yàn)了參數(shù)簽名的专挪,好吧,客戶端篡改參數(shù)的方案宣告失斊拧寨腔!
第二次嘗試
既然不能篡改,那直接下單的時(shí)候填吧率寡,請(qǐng)求后臺(tái)的同學(xué)協(xié)助一下迫卢,在下單的時(shí)候把return_url參數(shù)改成 URLEncode(A.company.com://),結(jié)果還是失敗了冶共。后臺(tái)同學(xué)提示我乾蛤,return_url必須是HTTP/HTTPS開(kāi)頭每界,支付寶文檔上有說(shuō)明。
第三次嘗試
那加上http試試家卖,我又讓后臺(tái)同學(xué)把return_url改成 URLEncode(httpA.company.com://)眨层,同時(shí)把APP的URLSchemes改成 httpA.company.com,再次嘗試上荡,調(diào)起支付寶返回的時(shí)候打開(kāi)了Safari趴樱,在Safari里面顯示了我們支付中心的錯(cuò)誤頁(yè)面,return_url方案徹底失敗了榛臼!
要不就算了伊佃,跟產(chǎn)品說(shuō)支付寶無(wú)法實(shí)現(xiàn)支付完成后跳回APP,反正支付寶官方文檔上都這么寫(xiě)了沛善。
雖然這么想了航揉,但是我還是繼續(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)的過(guò)渡产捞。
如果你是一個(gè)"正規(guī)"APP開(kāi)發(fā)者醇锚,至此已經(jīng)可以解決你的問(wèn)題了。按照支付寶文檔接支付寶SDK即可坯临,就能實(shí)現(xiàn)H5支付回調(diào)APP了焊唬。
但,這不是樓主想要的方案看靠,由于工作需求的原因赶促,樓主不想也不敢接支付寶的SDK,怕被蘋(píng)果爸爸審核掃包啊挟炬。如果你的APP"應(yīng)該"用蘋(píng)果支付鸥滨,即使你沒(méi)有用到支付寶的功能,但是包含了支付寶的SDK谤祖,審核被發(fā)現(xiàn)了婿滓,也可能被拒絕的。
繼續(xù)尋找解決辦法粥喜。
下載了支付寶的Demo空幻,試了下確實(shí)可以跳回APP。
樓主琢磨著容客,既然SDK能實(shí)現(xiàn)這個(gè)功能秕铛,說(shuō)明支付寶還是支持的H5支付完成后返回APP功能的,并不是向文檔上說(shuō)的缩挑,"在iOS系統(tǒng)中但两,喚起支付寶App支付完成后,不會(huì)自動(dòng)回到瀏覽器或商戶APP供置。用戶可手工切回到瀏覽器或商戶APP"谨湘,只是支付寶不愿意公開(kāi)而已。
那就以這個(gè)支付寶Demo為切入點(diǎn)吧芥丧,雖然SDK中有schemeStr這個(gè)參數(shù)紧阔,但是SDK是黑盒啊,你不知道它在里面做了些什么续担。
/**
* 支付接口
*
* @param orderStr 訂單信息
* @param schemeStr 調(diào)用支付的app注冊(cè)在info.plist中的scheme
* @param completionBlock 支付結(jié)果回調(diào)Block擅耽,用于wap支付結(jié)果回調(diào)(非跳轉(zhuǎn)錢包支付)
*/
- (void)payOrder:(NSString *)orderStr
fromScheme:(NSString *)schemeStr
callback:(CompletionBlock)completionBlock;
追本溯源,最終打開(kāi)支付寶APP都會(huì)走
[UIApplication sharedApplication] openURL:]
在Demo工程里搜了一下物遇,沒(méi)有乖仇。但我肯定SDK里面肯定有!
whatever —— Method Swizzling
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
@implementation UIApplication (TrackTimer)
+ (void)load
{
static dispatch_once_t oneToken;
dispatch_once(&oneToken, ^{
SEL mySelector = NSSelectorFromString(@"my_openURL:");
SEL orginalSelector = NSSelectorFromString(@"openURL:");
Method myMethod = class_getInstanceMethod([self class], mySelector);
Method orginalMethod = class_getInstanceMethod([self class], orginalSelector);
BOOL didAddMethod = class_addMethod([self class], orginalSelector, method_getImplementation(myMethod), method_getTypeEncoding(myMethod));
if (didAddMethod) {
class_replaceMethod([self class], mySelector, method_getImplementation(orginalMethod), method_getTypeEncoding(orginalMethod));
}
else {
method_exchangeImplementations(myMethod, orginalMethod);
}
});
}
- (void)my_openURL:(NSURL*)url
{
NSLog(@"%@",url);
[self my_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://請(qǐng)求的蜀铲,攔截它,看看參數(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蝙茶。
對(duì)比一下發(fā)現(xiàn),SDK中傳入的schemeStr參數(shù)對(duì)應(yīng)就是alipay:// 中的 fromAppUrlScheme字段诸老。
由此樓主猜測(cè)隆夯,在 alipay:// 打開(kāi)支付寶時(shí),傳入 fromAppUrlScheme别伏,支付結(jié)束后就會(huì)跳到對(duì)應(yīng)的APP蹄衷。
最終,樓主在自己的項(xiàng)目中驗(yàn)證了上述猜測(cè)厘肮。
總結(jié)下吧
最終解決方案
方案一
接支付寶提供的SDK愧口,schemeStr參數(shù)傳入自己APP的URLScheme即可。 具體的 手機(jī)網(wǎng)站支付轉(zhuǎn)Native支付
方案二
不需要接SDK类茂,不需要添加支付寶白名單耍属,webView攔截 alipay://alipayclient 請(qǐng)求托嚣,追加或修改參數(shù) fromAppUrlScheme為你自己的URLScheme值(這一步可沒(méi)那么簡(jiǎn)單,自己動(dòng)手吧厚骗,偷笑)示启,生成新的NSURL,然后用 [[UIApplication sharedApplication] openURL:] 打開(kāi)即可领舰。
2018.5.24更新(上面看懂了下面這段可以不用看)
總有人私信我問(wèn)我怎么追加fromAppUrlScheme夫嗓。可能是我說(shuō)的"webView攔截"冲秽,讓初學(xué)者不明白吧舍咖,簡(jiǎn)單提一下。
在webView"發(fā)起請(qǐng)求的代理方法"里面攔截請(qǐng)求的URL锉桑,即如果請(qǐng)求是alipay://alipayclient開(kāi)頭的排霉,說(shuō)明這個(gè)請(qǐng)求就跳轉(zhuǎn)支付寶的請(qǐng)求。替換里面fromAppUrlScheme的值為你自己的scheme值刨仑。(當(dāng)然如果更嚴(yán)謹(jǐn)?shù)脑捴E担瑧?yīng)該是判斷fromAppUrlScheme這個(gè)key是否存在,存在則替換其值杉武,不存在則追加)辙诞。用替換好的字符串生成一個(gè)NSURL,用[[UIApplication sharedApplication] openURL:newURL]跳轉(zhuǎn)支付寶轻抱。代理方法返回NO飞涂,即終止這次請(qǐng)求。
作者:CocoaKier
鏈接:http://www.reibang.com/p/0d8dd04fe94e
來(lái)源:簡(jiǎn)書(shū)
簡(jiǎn)書(shū)著作權(quán)歸作者所有祈搜,任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處较店。