All in WKWebView binding protocol, handled in navigation Request protocol

  • (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;

Alipay Payment

Note:

  • Alipays needs to be replaced with its own Schemes so that return will open its own app.
  • It is easy to fail to decide whether Alipay can be opened, so directly open Alipay to pay.

Code description:

  • Config.PayDomain configures its own access to wechat PayDomain names and also calls to xxx.com project name callbacks.
  • UrlDecoded and urlEncoded for domain name substitutions.

The codec code is as follows and placed in String Extension:

    // Decode: Converts any arguments to a string suitable for placing in the URL.
     func urlEncoded(a) -> String {
         let encodeUrlString = self.addingPercentEncoding(withAllowedCharacters:
             .urlQueryAllowed)
         return encodeUrlString ?? ""
     }
  
     // Convert the encoded URL back to the original URL
     func urlDecoded(a) -> String {
         return self.removingPercentEncoding ?? ""
     }
Copy the code

The payment code is as follows:

         guard let url = navigationAction.request.url else {
            decisionHandler(.allow)
            return
        }
        let reqUrl = url.absoluteString
        // Call aliPays to add URLtype in info to facilitate alipay to cancel payment return
        if ((reqUrl.hasPrefix("alipays://")) = = true) || ((reqUrl.hasPrefix("alipay://")) = = true) {
          // Fix URL Schemes taget -> info -> URL Types for AliPays
            let aliURLString = reqUrl.urlDecoded().replacingOccurrences(of: "alipays", with: Config.jiaYiDoctorScheme)
            let openedURL = URL.init(string: aliURLString.urlEncoded())!
          // Alipay can easily lead to failure if it is opened or not
            if #available(iOS 10.0.*) {
                UIApplication.shared.open(openedURL) { (bSucc) in
                    if bSucc = = false {
                      ProgressHUD.showMessage("You have not installed alipay App, please install and try again")}}UIApplication.shared.open(openedURL,  completionHandler: nil)}else {
                let bSucc = UIApplication.shared.openURL(openedURL)
                if bSucc = = false {
                  ProgressHUD.showMessage("You have not installed alipay App, please install and try again")}}}Copy the code

WeChat

Note: 1. Just like Alipay, we need to configure our app’s access schemes, but wechat must configure its top-level domain name to access schemes, otherwise app will also report wrong format of merchant parameters. 2. It is necessary to reload wechat Pay and configure the Referer, whose value is the first-level domain name applied by the company in wechat; otherwise, the format of merchant parameters will be reported wrong. 3. Wechat returns the loading page written for H5, and then returns a blank with the title weixin. If you need to process the blank page, you need to receive wechat callback notification in the Appdelegate and reload the Web page for processing.

The Appdelegate protocol handles: – (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {// [self wxPayHandlerPostNoti:url]; return YES; }

The specific code is as follows, and the code description is the same as Alipay:

               var redirectUrl:String?
        // wechat must also set redirect_URL as payment domain name otherwise merchant error will be reported
        if ((reqUrl.hasPrefix("https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb")) = = true && (reqUrl.hasSuffix("redirect_url=\(Config.PayDomain): / /")) = = false) {
          decisionHandler(.cancel)
          // Add your own app scheme for easy callback if not updated will jump back to the browser
            if ((reqUrl.contains("redirect_url=")) = = true) {
                let array = reqUrl.components(separatedBy: "redirect_url=")
                if array.count = = 2 {
                endPayRedirectURL = array[1]
                redirectUrl = array[0] + "redirect_url=\(Config.PayDomain): / /"}}else {
            redirectUrl = reqUrl +  "redirect_url=\(Config.PayDomain): / /"
          }
          // Set the request information to avoid skipping. The browser says the format of the merchant information is wrong. Wechat also needs to be redirected to load once
          let newRequest:NSMutableURLRequest = NSMutableURLRequest.init(url: URL.init(string: redirectUrl!)!)
          newRequest.allHTTPHeaderFields = navigationAction.request.allHTTPHeaderFields
          newRequest.setValue(Config.PayDomain, forHTTPHeaderField: "Referer")
          newRequest.url = URL.init(string: redirectUrl!)
          webView.load(newRequest as URLRequest)
          return
        }
    
        let scheme:String = navigationAction.request.url?.scheme ?? ""
        if scheme ! = "https" && scheme ! = "http" {
          decisionHandler(.cancel)
          // To load the wechat page, you need to load your own result page first, but the result page will return a blank page
          // If you do not display blank pages, you can send a notice to refresh the page after the wechat payment result callback, so that there will not be blank pages
          if scheme = = "weixin" {
            if endPayRedirectURL ! = nil {
              // Must decode again otherwise return a blank page but only AppDelega adds the result refresh to return a blank page with still weixin title
               webView.load(URLRequest.init(url: URL.init(string: endPayRedirectURL!.urlDecoded())!))}}// Open wechat Pay
            if reqUrl.hasPrefix("weixin://") {
                if UIApplication.shared.canOpenURL(url) = = false {
                ProgressHUD.showMessage("You have not installed wechat App, please install it and try again")}else {
                if #available(iOS 10.0.*) {
                    UIApplication.shared.open(url)
                } else {
                    UIApplication.shared.openURL(url)
                }
            }
          }
          return
        }


Copy the code

Complete code:

  func webView(_ webView: WKWebView.decidePolicyFor navigationAction: WKNavigationAction.decisionHandler: @escaping (WKNavigationActionPolicy) - >Void) {
        guard let url = navigationAction.request.url else {
            decisionHandler(.allow)
            return
        }
        let reqUrl = url.absoluteString
        // Call aliPays to add URLtype in info to facilitate alipay to cancel payment return
        if ((reqUrl.hasPrefix("alipays://")) = = true) || ((reqUrl.hasPrefix("alipay://")) = = true) {
            // Fix URL Schemes taget -> info -> URL Types for AliPays
            let aliURLString = reqUrl.urlDecoded().replacingOccurrences(of: "alipays", with: Config.jiaYiDoctorScheme)
            let openedURL = URL.init(string: aliURLString.urlEncoded())!
            // Alipay can easily lead to failure if it is opened or not
            if #available(iOS 10.0.*) {
                UIApplication.shared.open(openedURL) { (bSucc) in
                    if bSucc = = false {
                        ProgressHUD.showMessage("You have not installed alipay App, please install and try again")}}UIApplication.shared.open(openedURL,  completionHandler: nil)}else {
                let bSucc = UIApplication.shared.openURL(openedURL)
                if bSucc = = false {
                    ProgressHUD.showMessage("You have not installed alipay App, please install and try again")}}}var redirectUrl:String?
        // wechat must also set redirect_URL as payment domain name otherwise merchant error will be reported
        if ((reqUrl.hasPrefix("https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb")) = = true && (reqUrl.hasSuffix("redirect_url=\(Config.PayDomain): / /")) = = false) {
            decisionHandler(.cancel)
            // Add your own app scheme for easy callback if not updated will jump back to the browser
            if ((reqUrl.contains("redirect_url=")) = = true) {
                let array = reqUrl.components(separatedBy: "redirect_url=")
                if array.count = = 2 {
                    endPayRedirectURL = array[1]
                    redirectUrl = array[0] + "redirect_url=\(Config.PayDomain): / /"}}else {
                redirectUrl = reqUrl +  "redirect_url=\(Config.PayDomain): / /"
            }
            // Set the request information to avoid skipping. The browser says the format of the merchant information is wrong. Wechat also needs to be redirected to load once
            let newRequest:NSMutableURLRequest = NSMutableURLRequest.init(url: URL.init(string: redirectUrl!)!)
            newRequest.allHTTPHeaderFields = navigationAction.request.allHTTPHeaderFields
            newRequest.setValue(Config.PayDomain, forHTTPHeaderField: "Referer")
            newRequest.url = URL.init(string: redirectUrl!)
            webView.load(newRequest as URLRequest)
            return
        }
        
        let scheme:String = navigationAction.request.url?.scheme ?? ""
        if scheme ! = "https" && scheme ! = "http" {
            decisionHandler(.cancel)
            // To load the wechat page, you need to load your own result page first, but the result page will return a blank page
            // If you do not display blank pages, you can send a notice to refresh the page after the wechat payment result callback, so that there will not be blank pages
            if scheme = = "weixin" {
                if endPayRedirectURL ! = nil {
                    // Must decode again otherwise return a blank page but only AppDelega adds the result refresh to return a blank page with still weixin title
                    webView.load(URLRequest.init(url: URL.init(string: endPayRedirectURL!.urlDecoded())!))}}// Open wechat Pay
            if reqUrl.hasPrefix("weixin://") {
                if UIApplication.shared.canOpenURL(url) = = false {
                    ProgressHUD.showMessage("You have not installed wechat App, please install it and try again")}else {
                    if #available(iOS 10.0.*) {
                        UIApplication.shared.open(url)
                    } else {
                        UIApplication.shared.openURL(url)
                    }
                }
            }
            return
        }
        decisionHandler(.allow)
    }
    
Copy the code