iOS支付寶H5支付沒法返回APP解決方案

本文只討論你已經成功實現 客戶端->支付寶 支付流程,僅僅是支付完成後沒法返回本身的APP的問題。
若是你的支付流程是 客戶端->Safari->支付寶 不在本文討論範圍之類。
iOS支付寶H5支付不在討論範圍內。提供下列參考:
支付寶H5支付官方文檔
支付寶H5支付官方Demo下載Demo使用文檔前端

我是如何解決這個問題的

本文前大段在講樓主是如何解決這個問題的,以及中間遇到的麻煩。趕時間的同窗能夠直接看最後的 最終解決方案ios

在討論以前,咱們先看看官方文檔上的一句話:web

注意:在iOS系統中,喚起支付寶App支付完成後,不會自動回到瀏覽器或商戶APP。用戶可手工切回到瀏覽器或商戶APP;支付寶H5收銀臺會自動跳轉回商戶return_url指定的頁面。api

what? 官方直接跟咱們說GG了?樓主不甘心,仍是想嘗試一下。
借鑑以前 iOS微信H5支付沒法返回APP解決方案 的經驗,先在 return_url 這個參數上作個嘗試吧。瀏覽器

支付寶和微信不一樣的是,支付寶的return_url不須要在支付寶管理後臺備案(填寫),微信的redirect_url是須要的。bash

第一次嘗試
webView攔截請求https://mapi.alipay.com/gateway.do,修改return_url參數爲本身的URLScheme,好比URLEncode(A.company.com://),結果失敗了,進入支付寶報錯的頁面。仔細看了一下請求的其它參數,竟然有個sign!支付寶文檔上也有這個參數,竟然校驗了參數簽名的,好吧,客戶端篡改參數的方案宣告失敗!微信

第二次嘗試
既然不能篡改,那直接下單的時候填吧,請求後臺的同窗協助一下,在下單的時候把return_url參數改爲 URLEncode(A.company.com://),結果仍是失敗了。後臺同窗提示我,return_url必須是HTTP/HTTPS開頭,支付寶文檔上有說明。app

第三次嘗試
那加上http試試,我又讓後臺同窗把return_url改爲URLEncode(httpA.company.com://),同時把APP的URLSchemes改爲httpA.company.com,再次嘗試,調起支付寶返回的時候打開了Safari,在Safari裏面顯示了咱們支付中心的錯誤頁面,return_url方案完全失敗了!post

要不就算了,跟產品說支付寶沒法實現支付完成後跳回APP,反正支付寶官方文檔上都這麼寫了。
雖然這麼想了,可是我仍是繼續翻看支付寶的文檔,但願能找到點蛛絲馬跡。網站

忽然看到了這裏,手機網站支付轉Native支付

支付寶文檔
schemeStr,這個關鍵字讓我眼前一亮。
手機網站支付轉Native支付:支付寶的意思是,咱們提供了一個SDK,你接了以後就能夠很方便的實現H5收銀臺(即在web上輸入支付寶帳號密碼支付)到支付寶APP收銀臺的過渡。
若是你是一個"正規"APP開發者,至此已經能夠解決你的問題了。按照支付寶文檔接支付寶SDK便可,就能實現H5支付回調APP了。

但,這不是樓主想要的方案,因爲工做需求的緣由,樓主不想也不敢接支付寶的SDK,怕被蘋果爸爸審覈掃包啊。若是你的APP"應該"用蘋果支付,即便你沒有用到支付寶的功能,可是包含了支付寶的SDK,審覈被發現了,也可能被拒絕的。

繼續尋找解決辦法。

下載了支付寶的Demo,試了下確實能夠跳回APP。
樓主琢磨着,既然SDK能實現這個功能,說明支付寶仍是支持的H5支付完成後返回APP功能的,並非向文檔上說的,"在iOS系統中,喚起支付寶App支付完成後,不會自動回到瀏覽器或商戶APP。用戶可手工切回到瀏覽器或商戶APP",只是支付寶不肯意公開而已。

那就以這個支付寶Demo爲切入點吧,雖然SDK中有schemeStr這個參數,可是SDK是黑盒啊,你不知道它在裏面作了些什麼。

/**
 *  支付接口
 *
 *  @param orderStr       訂單信息
 *  @param schemeStr      調用支付的app註冊在info.plist中的scheme
 *  @param completionBlock 支付結果回調Block,用於wap支付結果回調(非跳轉錢包支付)
 */
- (void)payOrder:(NSString *)orderStr
      fromScheme:(NSString *)schemeStr
        callback:(CompletionBlock)completionBlock;
複製代碼

追本溯源,最終打開支付寶APP都會走

[UIApplication sharedApplication] openURL:]
複製代碼

在Demo工程裏搜了一下,沒有。但我確定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];
}
複製代碼

打印結果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"}""
}

爲何前面會有一點亂碼,alipaymatrixbwf0cml3,無論它了。fromAppUrlScheme,是否是很驚喜。

是否是支付寶H5支付都有這個參數呢?樓主趕忙用本身的項目嘗試了一下,webView最終會有一個alipay://請求的,攔截它,看看參數

alipay://alipayclient/?{"dataString":"h5_route_token="xxxxxxxxxxxxx"&is_h5_route="true"","requestType":"SafePay","fromAppUrlScheme":"alipays"}

也有fromAppUrlScheme這個參數,並且默認是支付寶APP的URLScheme: alipays
對比一下發現,SDK中傳入的schemeStr參數對應就是alipay:// 中的 fromAppUrlScheme字段。
由此樓主猜想,在 alipay:// 打開支付寶時,傳入 fromAppUrlScheme,支付結束後就會跳到對應的APP。

最終,樓主在本身的項目中驗證了上述猜想。 總結下吧

最終解決方案

方案一

接支付寶提供的SDK,schemeStr參數傳入本身APP的URLScheme便可。 具體的 手機網站支付轉Native支付

方案二

不須要接SDK,不須要添加支付寶白名單,webView攔截 alipay://alipayclient 請求,追加或修改參數 fromAppUrlScheme爲你本身的URLScheme值,生成新的NSURL,而後用 [[UIApplication sharedApplication] openURL:] 打開便可。

總有人問我怎麼追加fromAppUrlScheme。多是我說的"webView攔截",讓初學者不明白吧,簡單提一下。
在webView"發起請求的代理方法"裏面攔截請求的URL,即若是請求是alipay://alipayclient開頭的,說明這個請求是跳轉支付寶的請求。替換裏面fromAppUrlScheme的值爲你本身的scheme值。(固然若是更嚴謹的話,應該是判斷fromAppUrlScheme這個key是否存在,存在則替換其值,不存在則追加)。用替換好的字符串生成一個NSURL,用[[UIApplication sharedApplication] openURL:newURL]跳轉支付寶。代理方法返回NO,即終止此次請求。

常見問題

1.支付後沒有返回app而是跳到了Safari**

緣由:你的Xcode配置裏面URLSheme沒寫或者寫錯了,和支付寶請求參數中的fromAppUrlScheme不一致。
解決:Xcode配置中新增或者修改URLSheme,確保和alipay://alipayclient請求參數中的fromAppUrlScheme一致。

2.並無看到做者說的alipay: //alipayclient**

緣由:可能你的app不是在客戶端直接和支付寶通訊,而是中間加了一道跳轉到網頁,由你的後臺(或前端)調起支付寶。因此你是攔截不到這個請求的。我文中所說的方式是基於,「客戶端->支付寶」 這種模式,而你的是「客戶端->Safari->支付寶」模式,後者沒法按照文中說述實現返回app。
解決:方案1,修改你的支付模式爲「客戶端->支付寶」,這樣改動恐怕有點大,工做量主要在大家後臺。方案2,在不改模式的狀況下,須要後臺(或前端)的同事去解決這個問題,原理和本文差很少,在後臺和支付寶通信的參數中找到一個相似於fromAppUrlScheme的參數,而後將這個參數修改爲你的app的URLScheme,至於具體怎處理樓主沒作研究,若是你有好的方法,能夠分享一下。

3.支付完成後回來停留在支付寶結果頁面,顯示「繼續支付」和「已完成」,無法回到遊戲**

緣由:web發起支付後,web頁面會嘗試調起支付寶客戶端,不管是否調起客戶端都會將當前頁面重定向到支付寶結果頁面,即「繼續支付,已完成」頁面。因此從支付寶客戶端返回後你會看到這個頁面。
解決:個人作法是,原生另起一個webViewController頁面做爲收銀臺,收銀臺頁面發起支付,發起支付後就關閉收銀臺頁面。這樣原來的遊戲頁面就不會受影響,支付寶客戶端返回時也直接返回到遊戲頁面了。至於支付結果,客戶端沒法直接獲知成功或失敗,若是你須要彈窗提示用戶充值成功,須要遊戲方自行去後臺查詢支付結果。

[[UIApplication sharedApplication] openURL:newRequest.URL];
[self dismissViewControllerAnimated:NO completion:nil];
複製代碼

若是以爲這篇文章對你有幫助,請點個贊吧。若是有疑問能夠關注個人公衆號我留言。
轉載請註明出處,謝謝!

相關文章
相關標籤/搜索