前言
以前接入微信和支付寶的支付, 採用的是導入對應的SDK, 調用和返回都是由SDK內部處理, 這一點從操作和集成角度而言, 安全和方便. 但是侷限性也是有的:
- 蘋果限制虛擬類型的商品等必須使用內購, 也就是說 支付寶和微信的三方支付存在很多的侷限性,這個雖然是爲用戶的賬戶資金安全考慮,
但是就目前的國內實際情況而言, 這是一個麻煩(和諧一下) - 在一定程度上增加了包體積的大小
- 增加了審覈的成本
那麼, 問題來了, 有沒有更簡單的方案呢, 答案當然是有的.
網頁支付
微信和支付寶的網頁支付營運而生…
優點:
- 採用網頁支付, 空間上不需要在項目中導入SDK增加體積
- WEB一站式解決支付問題
可以更好地應對審覈(和諧一下)
缺點:(學習使我快樂, 忽略吧)
- H5或者網頁的對接經驗
- 增加了學習的成本
- 需要單獨處理支付寶和微信的鏈接
應用場景:
目前我遇到的大部分是活動網頁.
正文
這邊文章目的是使用網頁支付, 更好的適配審覈, 所以, 有舍有得, 我們不去看缺點, 畢竟, 就過審而言, 這點不算什麼…
進入正題, 網頁支付, 就是使用WKWebView打開網頁, 由網頁調用支付寶or微信的網頁的SDK, 這部分由前端同學(甩鍋中…)完成, 我們這邊通過WK的代理獲取當前請求的網絡連接,判斷是不是需要openURL到微信或者支付寶.
1. 設置URL Scheme
這個相當於你App的銘牌, 別的App想要跳轉到你的App的時候, 就需要知道你App的銘牌,一個App可以設置多個.
2. AppDelegate( 這一步 看大家需求操作吧 )
設置進入前臺(跳轉回來) 處理服務器需要刷新的網頁
3.1 - 微信網頁支付
大致流程:
- 獲取當前請求的鏈接,判斷你是不是微信的
- 保存連接中的參數名爲redirect_url的對應數據爲appWillBecomeActiveWebReloadUrlString,
- 替換redirect_url = “自定App的URLScheme” 用於,
- 替換完後, 重新請求連接,
- 跳轉,
- 支付完成, 返回app(能返回是因爲第3步)
- 在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 - 支付網頁支付
大致流程:
- 獲取當前請求的鏈接,判斷你是不是支付寶的
- 保存連接中的參數名爲redirect_url的對應數據爲appWillBecomeActiveWebReloadUrlString,
- 獲取當前請求的鏈接,判斷是不是支付寶跳轉的協議鏈接, 並且包含fromAppUrlScheme
- WebPayTool.handleWebUrl(urlString) 處理支付寶跳轉的協議鏈接, 這裏是最重要的,內容我放到的對應的方法中, 每個步驟都做了解釋
- 跳轉
- 支付完成, 返回app(能返回是因爲第2步)
- 在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]];
}
上面是有關支付寶和微信的網頁支付的關鍵代碼內容, 具體的需要根據自己的業務邏輯去做代碼適配.
總結:
- 微信的網頁支付主要是替換 redirect_url
- 支付寶的網頁支付主要是替換fromAppUrlScheme
- 包含的回調地址redirect_url 這個是網頁支付中, 你跳轉回來後當前網頁刷新的地址, 前端定義的, 根據實際情況處理.
最後
奉上Demo地址