iOS H5支付宝 微信支付.

iOS开发中, 如果不想接入支付的SDK 或者 商品只能走内购, 但是又不想要走内购(不想给苹果手续费...), 那么就可以考虑使用支付宝和微信的H5支付.

这里的支付宝支付和微信支付 指的是通过web页, 传给客户端包括订单和其他信息的字符串, 客户端拿到这个特殊的字符串, 进行处理, 然后通过scheme打开支付宝或者微信客户端进行支付.

写在前面:

一般通过WKWebView的

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)

方法来拦截要加载的url, 支付宝支付带有订单信息的URL 前缀为 alipay 或者 alipays. 微信的是 https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb.
我们这样子写是有问题的. 这样子写递交审核, 机审的时候, 会扫描出来alipay tenpay的字眼, 可以判定你没有走内购而拒绝你的递交, 甚至会延迟审核. 所以我们要做的是, 把有关alipay 和 tenpay 这些字符串拆成一个个的字符, 然后用到的时候再进行组装比较, 这样子可以绕过苹果的机审.

进入正题
适配支付宝客户端支付:

支付宝支付比较简单一些, 因为 如果安装了支付宝 可以在支付宝客户端上面进行支付, 如果没有安装, 也可以在网页上面支付.
首先截取到支付宝支付加载的URL

// 某宝相关字符串
        let compareArrayCollect1: [Character] = ["a", "l", "i", "p", "a", "y"]
        let compareArrayCollect2: [Character] = ["a", "l", "i", "p", "a", "y", "s"]
        if loadURLString.hasPrefix(charArray: compareArrayCollect1) || loadURLString.hasPrefix(charArray: compareArrayCollect2) {
            //某宝 stringUrl 为webView所加载的url: navigationAction.request.url?.absoluteString.removingPercentEncoding
            if let url = stringUrl, let changeURL = self.changeURLSchemeStr(urlStr: url) {
                // 跳转
                UIApplication.shared.openURL(changeURL)
            }

        }

changeURLSchemeStr 方法作用是:

  • 对url进行解码.
  • 转换成字典.
  • 替换fromAppUrlScheme的值为当前app对应的scheme.
  • 再进行编码 并返回新的URL.
    其中替换fromAppUrlScheme 的作用是 跳转支付宝 交易结束之后, 支付宝要通过你app的scheme 跳回到你的app
    代码如下:
private func changeURLSchemeStr(urlStr: String) -> URL? {
        if urlStr.contains("fromAppUrlScheme") {
            guard var rmPerEncStr = urlStr.removingPercentEncoding else { return nil }
            guard let temDic = self.dictionaryWithUrlString(urlString: rmPerEncStr) else { return nil }
            guard let temValue = temDic["fromAppUrlScheme"] as? String else { return nil }
            rmPerEncStr = rmPerEncStr.replacingOccurrences(of: temValue, with: "yourAppScheme")
            guard let perEncodingStr = rmPerEncStr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else { return nil }
            return URL(string: perEncodingStr)
        }
        return nil
    }
private func dictionaryWithUrlString(urlString: String) -> [String: Any]? {
        guard urlString.count != 0 else { return nil }
        let array = urlString.components(separatedBy: "?")
        guard array.count == 2 else { return nil }
        guard let paramStr = array.last else { return nil }
        let rmPerEnStr = paramStr.removingPercentEncoding
        return rmPerEnStr?.convertToDictionary()
    }

微信支付

微信的H5支付稍微要麻烦一些. 主要麻烦的点在于设置 微信的回跳地址 redirect_url 和授权域名 Referer.

  • redirect_url 的设置最好设置为本app的urlScheme, Referer为后端或者产品在注册微信支付时所填写的授权域名.
  • redirect_url: 作用为 当app完成支付(不论是否支付成功), 所跳转的页面, 如果不设置, 那么支付完成之后就会直接跳转到Safari, 打开的是一个支付是否成功的验证页面, 设置redirect_url的目的为了支付完成之后 正常跳转到app 并在app中的web页面中打开支付是否成功的验证页面. 所以在这里也要记录一下原始的redirect_url. 用户回跳之后, 要加载显示的验证页面.
  • Referer: 官方文档上面有说明, Referer如果不设置, 跳转到微信, 打不开支付页面, 验证不通过.
if loadURLString.hasPrefix("https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb") && !loadURLString.contains("redirect_url=your_referer_name//paycallback/") {
            // 某信
            // 先判断有没有安装微信
            let someXinCollect: [Character] = ["w", "e", "i", "x", "i", "n", ":", "/", "/"]
            let someXinStr = String.charCollectTransToString(charArray: someXinCollect)
            guard let sonXinURL = URL(string: someXinStr) else { return false }
            if !UIApplication.shared.canOpenURL(sonXinURL) {
                showToast(text: "请安装微信客户端")
                return false
            }

如果当前加载的url的前缀有某信支付的连接并且不包含 “redirect_url=your_referer_name//paycallback/”的字符串, 那么先判断是否安装微信, 如果没有给出toast提示 需要安装微信客户端.

 // 拼接rturl
            var rtUrl: String = ""
            let authHost = "your_refere_name" //你的微信授权域名
            if loadURLString.contains(rtURLStr) {
                guard let redirectRange = loadURLString.range(of: rtURLStr) else { return true }
                let location: Int = loadURLString.distance(from: loadURLString.startIndex, to: redirectRange.lowerBound)
                rtUrl = loadURLString.substring(to: location - 1) + "\(rtURLStr)\(authHost):\(charCallbackCollectStr)"
                originalRtUrlStr = loadURLString.substring(from: location +
                    rtURLStr.count)
            } else {
                rtUrl = loadURLString + "\(rtURLStr)\(authHost):\(charCallbackCollectStr))" // 替换为你自己的授权域名(也就是你的scheme, 微信完成支付时 会按照这个scheme跳转回你的app)
            }
            guard let requestURL = URL(string: rtUrl) else { return true }
            var request = navigationAction.request
            request.url = requestURL
// 在这一步 设置request的header信息. 加入Referer 参数
            if var headerField = request.allHTTPHeaderFields {
                headerField["Referer"] = authHost
            }
            webView.load(request)
            return false

这一步主要做的工作是: 替换掉前端原本传过来redirect_url, 并且记录原始的redirect_url: originalRtUrlStr. 然后拼接好已经替换的loadURL, 设置request, 并且在请求头中加入Referer参数 进行重新加载.
下一步:

if loadURLString.hasPrefix(charArray: "your_referer_name") {
            guard let requestURL = URL(string: originalRtUrlStr) else { return false }
            var request = navigationAction.request
            request.url = requestURL
            webView.load(request)
            return false
        }
if loadURLString.contains("weixin://") {
            UIApplication.shared.openURL(loadURL)
        }
        return true

这一步是如果loadURL, 是以你的授权域名为开头, 那么就加载这个页面. (实际上是微信支付 验证是否成功的页面.), 最后如果加载的url是以weixin://开头, 这个链接就是带有微信支付信息的连接, 就打开微信进行支付操作.

注意: 以上字符串 如果有关alipay 或者 tenPay 这些字眼, 都要将其进行拆分成字符来表示, 判断的时候, 再用字符数组, 进行拼接. 这样子才能不被苹果扫描到有支付宝或者财付通支付.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容