iOS開發--微信和支付寶網頁支付(過審, 支付寶支付成功可回跳)

前言

以前接入微信和支付寶的支付, 採用的是導入對應的SDK, 調用和返回都是由SDK內部處理, 這一點從操作和集成角度而言, 安全和方便. 但是侷限性也是有的:

  1. 蘋果限制虛擬類型的商品等必須使用內購, 也就是說 支付寶和微信的三方支付存在很多的侷限性,這個雖然是爲用戶的賬戶資金安全考慮, 但是就目前的國內實際情況而言, 這是一個麻煩(和諧一下)
  2. 在一定程度上增加了包體積的大小
  3. 增加了審覈的成本

那麼, 問題來了, 有沒有更簡單的方案呢, 答案當然是有的.

網頁支付

微信和支付寶的網頁支付營運而生…
優點:

  1. 採用網頁支付, 空間上不需要在項目中導入SDK增加體積
  2. WEB一站式解決支付問題
  3. 可以更好地應對審覈(和諧一下)

缺點:(學習使我快樂, 忽略吧)

  1. H5或者網頁的對接經驗
  2. 增加了學習的成本
  3. 需要單獨處理支付寶和微信的鏈接

應用場景:

目前我遇到的大部分是活動網頁.

正文

這邊文章目的是使用網頁支付, 更好的適配審覈, 所以, 有舍有得, 我們不去看缺點, 畢竟, 就過審而言, 這點不算什麼…

進入正題, 網頁支付, 就是使用WKWebView打開網頁, 由網頁調用支付寶or微信的網頁的SDK, 這部分由前端同學(甩鍋中…)完成, 我們這邊通過WK的代理獲取當前請求的網絡連接,判斷是不是需要openURL到微信或者支付寶.

1. 設置URL Scheme

這個相當於你App的銘牌, 別的App想要跳轉到你的App的時候, 就需要知道你App的銘牌,一個App可以設置多個.

2. AppDelegate( 這一步 看大家需求操作吧 )

設置進入前臺(跳轉回來) 處理服務器需要刷新的網頁

3.1 - 微信網頁支付

大致流程:

  1. 獲取當前請求的鏈接,判斷你是不是微信的
  2. 保存連接中的參數名爲redirect_url的對應數據爲appWillBecomeActiveWebReloadUrlString,
  3. 替換redirect_url = “自定App的URLScheme” 用於,
  4. 替換完後, 重新請求連接,
  5. 跳轉,
  6. 支付完成, 返回app(能返回是因爲第3步)
  7. 在AppDelegate的程序進入前臺的代理方法中處理當前網頁刷新之前保存的appWillBecomeActiveWebReloadUrlString(至於這個保存的appWillBecomeActiveWebReloadUrlString的鏈接地址內容是啥,就看你們前端如何處理了).
// 判斷非返回或者刷新
if (!(navigationAction.navigationType == WKNavigationType.backForward || navigationAction.navigationType == WKNavigationType.reload)) {
// 微信判斷
    let pre_string = "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"
    if request.url?.absoluteString.hasPrefix(pre_string) ?? false {
        
        let par = WebPayTool.params(of: navigationAction.request.url)
        let params: NSMutableDictionary = NSMutableDictionary(dictionary:par);
        
        if var allKeys = params.allKeys as? [String] {
        	// openWebResult.webpaye.com這個是你自定義的你的App的名牌
        	//  ://app_paycallback/ 是你回調後判斷的類型 這個部分自定義, 邏輯自定義        
            let app_name = "openWebResult.webpaye.com://app_paycallback/"
            
            let return_new_value = WebPayTool.urlDecodedString(app_name);
            let returnKey = "redirect_url"
			// 判斷連接中是不是有redirect_url 參數, 添加或者更換爲上面自定義的 app_name
            if (allKeys.contains { (item: String) -> Bool in
                return item == returnKey
            }) {
                // 有對應的回調地址
                let return_old_value = params[returnKey] as? String
                let isOpenOther = return_old_value == return_new_value
                if !isOpenOther {
                    // 保存回調地址 這個是自己服務器的參數,也就是支付或者回來後, 網頁需要刷新的頁面
                    self.appWillBecomeActiveWebReloadUrlString = WebPayTool.urlDecodedString(return_old_value ?? "")
                    params[returnKey] = return_new_value;
                    allKeys.append(returnKey);
                    var newURLStr = NSString(format: "%@", pre_string)
                    for key in allKeys {
                        if let value = params[key] {
                            newURLStr = NSString(format: "%@", newURLStr).urlAddCompnent(forValue: value as! String, key: key) as NSString
                        }
                    }
                    // 重新組織好新的連接, 重新請求
                    if let newUrl = URL(string: newURLStr as String) {
                        decisionHandler(.cancel)
                        var newRequest = URLRequest.init(url: newUrl)
                        newRequest.allHTTPHeaderFields = request.allHTTPHeaderFields;
                        webView.load(newRequest)
                        
                        return;
                    }
                }
            }
        }
    }
}

3.2 - 支付網頁支付

大致流程:

  1. 獲取當前請求的鏈接,判斷你是不是支付寶的
  2. 保存連接中的參數名爲redirect_url的對應數據爲appWillBecomeActiveWebReloadUrlString,
  3. 獲取當前請求的鏈接,判斷是不是支付寶跳轉的協議鏈接, 並且包含fromAppUrlScheme
  4. WebPayTool.handleWebUrl(urlString) 處理支付寶跳轉的協議鏈接, 這裏是最重要的,內容我放到的對應的方法中, 每個步驟都做了解釋
  5. 跳轉
  6. 支付完成, 返回app(能返回是因爲第2步)
  7. 在AppDelegate的程序進入前臺的代理方法中處理當前網頁刷新之前保存的appWillBecomeActiveWebReloadUrlString(至於這個保存的appWillBecomeActiveWebReloadUrlString的鏈接地址內容是啥,就看你們前端如何處理了).
// 支付寶判斷
if let url = request.url {
    let urlString = url.absoluteString
    
    if urlString.hasPrefix("https://openapi.alipay.com/gateway.do") {
        if let aliUrl = URL(string: urlString) {
            let returnReloadKey = "return_url"
            let par = WebPayTool.params(of: aliUrl)
            let params: NSMutableDictionary = NSMutableDictionary(dictionary:par);
            let return_old_value = params[returnReloadKey] as? String
            let redirct = WebPayTool.urlDecodedString(return_old_value ?? "")
            self.appWillBecomeActiveWebReloadUrlString = redirct
        }
    }
}

if let urlString = navigationAction.request.url?.absoluteString {
    if urlString.contains("alipay://") || urlString.contains("alipays://"){
        if urlString.contains("fromAppUrlScheme") {
            decisionHandler(.cancel)
            // 下面是重點, 這裏面處理了支付寶支付的鏈接參數問題
            // 主要 是 你跳去了支付寶App 還可以調回來
            WebPayTool.handleWebUrl(urlString)
            return
        }
    }
}

支付寶的WebPayTool.handleWebUrl(urlString)

重點

修改fromAppUrlScheme的參數爲自定義的App的URL Scheme

if ([url containsString:@"fromAppUrlScheme"]) {
	NSString *encodeUrl = [url stringByRemovingPercentEncoding];
	NSArray *urlParArry = [encodeUrl componentsSeparatedByString:@"?"];
	NSMutableDictionary *beSetParDic = [self dictionaryWithJsonString:urlParArry.lastObject];
	// 下面是重點 fromAppUrlScheme的設置, 是支付寶客戶端回跳到你的App的參數,設置URL Scheme
	[beSetParDic setObject:@"你的App的自定義的URL Scheme" forKey:@"fromAppUrlScheme"];
	NSString *overJsonStr = [self dictionaryToJson:beSetParDic];
	NSString *overUrlStr = [NSString stringWithFormat:@"%@?%@",urlParArry.firstObject,overJsonStr];
	NSString *canUseEncodeUrl = [overUrlStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
	[[UIApplication sharedApplication] openURL:[NSURL URLWithString:canUseEncodeUrl]];
}

上面是有關支付寶和微信的網頁支付的關鍵代碼內容, 具體的需要根據自己的業務邏輯去做代碼適配.

總結:

  1. 微信的網頁支付主要是替換 redirect_url
  2. 支付寶的網頁支付主要是替換fromAppUrlScheme
  3. 包含的回調地址redirect_url 這個是網頁支付中, 你跳轉回來後當前網頁刷新的地址, 前端定義的, 根據實際情況處理.

最後
奉上Demo地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章