{"id":2108,"date":"2023-04-01T22:23:11","date_gmt":"2023-04-01T14:23:11","guid":{"rendered":"https:\/\/www.appblog.cn\/?p=2108"},"modified":"2023-04-05T20:46:53","modified_gmt":"2023-04-05T12:46:53","slug":"ios-wechat-payment-access-swift","status":"publish","type":"post","link":"https:\/\/www.appblog.cn\/index.php\/2023\/04\/01\/ios-wechat-payment-access-swift\/","title":{"rendered":"iOS\u5fae\u4fe1\u652f\u4ed8\u63a5\u5165(Swift)"},"content":{"rendered":"<h2>\u9879\u76ee\u914d\u7f6e<\/h2>\n<p>\u5fae\u4fe1\u652f\u4ed8Demo\uff1a<a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/pay.weixin.qq.com\/wiki\/doc\/api\/app\/app.php?chapter=11_1\">https:\/\/pay.weixin.qq.com\/wiki\/doc\/api\/app\/app.php?chapter=11_1<\/a><\/p>\n<p>\u628a\u793a\u4f8b\u9879\u76ee\u4e2d\u7684\u4ee5\u4e0b\u6587\u4ef6\u62d6\u5230\u9879\u76ee\u4e2d<\/p>\n<p><!-- more --><\/p>\n<pre><code class=\"language-c\">Control\u6587\u4ef6\u5939\u4e0b\u7684WXApiManager.h\u548cWXApiManager.m\nlibWeChatSDK.a\nWXApi.h\nWXApiObject.h<\/code><\/pre>\n<p>\u6865\u63a5\u6587\u4ef6\u4e2d\u6dfb\u52a0\u5f15\u7528<\/p>\n<pre><code class=\"language-c\">\/\/\u5fae\u4fe1\u652f\u4ed8\n#import &quot;WXApi.h&quot;\n#import &quot;WXApiObject.h&quot;\n#import &quot;WXApiManager.h&quot;<\/code><\/pre>\n<p>\u9879\u76ee\u914d\u7f6e\u9009\u9879\u5361<code>targets<\/code> -&gt; <code>Info<\/code> -&gt; <code>URL Types<\/code>\u4e2d\u6dfb\u52a0\u4e00\u9879<\/p>\n<pre><code>identifier \u8bbe\u7f6e\u4e3a weixin\nURL Schemes \u8bbe\u7f6e\u4e3a\u4f60app\u5fae\u4fe1\u5f00\u653e\u5e73\u53f0\u4e0a\u7684appid<\/code><\/pre>\n<p>\u5728<code>info.plist<\/code>\u4e2d\u52a0\u5165\u5b89\u5168\u57df\u540d\u767d\u540d\u5355(\u53f3\u952einfo.plist\u7528source code\u6253\u5f00)<\/p>\n<pre><code class=\"language-xml\">&lt;key&gt;LSApplicationQueriesSchemes&lt;\/key&gt;  \n&lt;array&gt;  \n    &lt;string&gt;sinaweibo&lt;\/string&gt;  \n    &lt;string&gt;sinaweibohd&lt;\/string&gt;  \n    &lt;string&gt;weibosdk2.5&lt;\/string&gt;  \n    &lt;string&gt;weibosdk&lt;\/string&gt;  \n    &lt;string&gt;sinaweibosso&lt;\/string&gt;  \n    &lt;string&gt;mqqOpensdkSSoLogin&lt;\/string&gt;  \n    &lt;string&gt;mqzone&lt;\/string&gt;  \n    &lt;string&gt;sinaweibo&lt;\/string&gt;  \n    &lt;string&gt;alipayauth&lt;\/string&gt;  \n    &lt;string&gt;alipay&lt;\/string&gt;  \n    &lt;string&gt;safepay&lt;\/string&gt;  \n    &lt;string&gt;mqq&lt;\/string&gt;  \n    &lt;string&gt;mqqapi&lt;\/string&gt;  \n    &lt;string&gt;mqqopensdkapiV3&lt;\/string&gt;  \n    &lt;string&gt;mqqopensdkapiV2&lt;\/string&gt;  \n    &lt;string&gt;mqqapiwallet&lt;\/string&gt;  \n    &lt;string&gt;mqqwpa&lt;\/string&gt;  \n    &lt;string&gt;mqqbrowser&lt;\/string&gt;  \n    &lt;string&gt;wtloginmqq2&lt;\/string&gt;  \n    &lt;string&gt;weixin&lt;\/string&gt;  \n    &lt;string&gt;wechat&lt;\/string&gt;  \n&lt;\/array&gt;<\/code><\/pre>\n<h2>\u5177\u4f53\u6d41\u7a0b<\/h2>\n<ol>\n<li>\u4e0b\u5355<\/li>\n<\/ol>\n<p>App\u8c03\u7528\u540e\u53f0\u7edf\u4e00\u4e0b\u5355 &#8212;&gt; \u5546\u6237\u540e\u53f0 &#8212;&gt; \u5fae\u4fe1\u540e\u53f0\u8fd4\u56de\u8ba2\u5355 &#8212;&gt; \u5546\u6237\u540e\u53f0\u8fd4\u56de\u8ba2\u5355 &#8212;&gt; \u5546\u6237App<\/p>\n<ol start=\"2\">\n<li>\u652f\u4ed8<\/li>\n<\/ol>\n<p>\u5546\u6237App\u53d1\u9001<code>sendReq<\/code>\u65b9\u6cd5 &#8212;&gt; \u8c03\u8d77\u5fae\u4fe1\u53d1\u8d77\u652f\u4ed8\u8bf7\u6c42 &#8212;&gt; \u5fae\u4fe1\u540e\u53f0\u6388\u6743\u652f\u4ed8 &#8212;&gt; \u5fae\u4fe1\u8fdb\u884c\u652f\u4ed8<\/p>\n<ol start=\"3\">\n<li>\u652f\u4ed8<\/li>\n<\/ol>\n<p>\u5546\u6237App\u56de\u8c03\u5904\u7406 &#8212;&gt; \u82e5\u524d\u7aef\u6210\u529f\u5219\u4e0e\u540e\u53f0\u786e\u8ba4<\/p>\n<ol start=\"4\">\n<li>\u652f\u4ed8\u5b8c\u6210\u4e4b\u540e<\/li>\n<\/ol>\n<p>\u5fae\u4fe1\u540e\u53f0\u5f02\u6b65\u901a\u77e5 &#8212;&gt; \u5546\u6237\u540e\u53f0<br \/>\n\u5fae\u4fe1App\u53d1\u9001\u652f\u4ed8\u72b6\u6001\u4fe1\u606f &#8212;&gt; \u5546\u6237App\u53bb\u540e\u53f0\u67e5\u8be2\u662f\u5426\u771f\u6b63\u652f\u4ed8\u6210\u529f &#8212;&gt; \u5546\u6237\u540e\u53f0\uff08\u5982\u679c\u6b64\u65f6\u540e\u53f0\u672a\u6536\u5230\u5fae\u4fe1\u540e\u53f0\u5f02\u6b65\u901a\u77e5\u5546\u6237\u540e\u53f0\u5219\u4f1a\u8c03\u7528\u67e5\u8be2API &#8212;&gt; \u5fae\u4fe1\u540e\u53f0\u8fd4\u56de\u652f\u4ed8\u7ed3\u679c &#8212;&gt; \u5546\u6237\u540e\u53f0\uff09\u5426\u5219\uff0c\u76f4\u63a5\u6839\u636e\u5fae\u4fe1\u540e\u53f0\u5f02\u6b65\u901a\u77e5\u5546\u6237\u652f\u4ed8\u6210\u529f\u4e0e\u5426 &#8212;&gt; \u5546\u6237App\u786e\u8ba4<\/p>\n<h2>\u4ee3\u7801\u793a\u4f8b<\/h2>\n<h3>\u793a\u4f8b\u4e00<\/h3>\n<p>\u5728<code>AppDelegate<\/code>\u4e2d\u6ce8\u518c<\/p>\n<pre><code class=\"language-swift\">\/\/\u5728appdelegate\u6ce8\u518c\u6ce8\u518cAPPID \u5e76\u9075\u5b88WXApiDelegate\nfunc application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -&gt; Bool {\n    \/\/\u5fae\u4fe1\u652f\u4ed8\n    WXApi.registerApp(&quot;\u4f60\u7684APPID&quot;);\n}\n\nfunc application(application: UIApplication, handleOpenURL url: NSURL) -&gt; Bool {\n    return WXApi.handleOpenURL(url, delegate: WXApiManager.sharedManager());\n    \/\/return UMSocialSnsService.handleOpenURL(url);\n}\n\n\/\/\u8fd9\u91cc\u6f14\u793a\u591a\u4e2a\u5171\u5b58\u7684\u5904\u7406\u65b9\u6cd5\uff0c\u5176\u4e2d\u4e2d\u95f4\u662f\u548c\u5fae\u4fe1\u6709\u5173\u7684\nfunc application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -&gt; Bool {\n    \/\/\u652f\u4ed8\u5b9d\u652f\u4ed8\n    if(sourceApplication!.containsString(&quot;com.alipay.iphoneclient&quot;)){\n        AlipaySDK.defaultService().processOrderWithPaymentResult(url, standbyCallback: nil)\n        return true;\n    }\n    \/\/\u5fae\u4fe1\u652f\u4ed8\n    else if(sourceApplication!.containsString(&quot;com.tencent.xin&quot;)){\n        return WXApi.handleOpenURL(url, delegate: WXApiManager.sharedManager());\n    }\n    \/\/\u53cb\u76df\u5206\u4eab\n    else{\n        return UMSocialSnsService.handleOpenURL(url);\n    }\n}<\/code><\/pre>\n<p>\u9700\u8981\u7684\u4e09\u4e2a\u53c2\u6570<\/p>\n<pre><code>appid (\u5fae\u4fe1\u5f00\u653e\u5e73\u53f0\u4e2d\u83b7\u53d6)\npartnerId (\u5546\u6237ID\uff0c\u5728\u5546\u6237\u5e73\u53f0\u83b7\u53d6)\nAPI_KEY (API\u5bc6\u94a5\uff0c\u5728\u5546\u6237\u5e73\u53f0\u8bbe\u7f6e)<\/code><\/pre>\n<p><strong>\u652f\u4ed8\u6b65\u9aa4<\/strong><\/p>\n<p>\u652f\u4ed8\u603b\u4f53\u4e0a\u5206\u4e3a\u4e24\u6b65<\/p>\n<ul>\n<li>\u83b7\u53d6prepayid(\u9884\u4ed8\u6b3eID)<\/li>\n<li>\u6839\u636eprepayid\u53d1\u8d77\u652f\u4ed8<\/li>\n<\/ul>\n<p>\u7b2c\u4e00\u6b65\u83b7\u53d6prepayid<\/p>\n<p>\u8fd9\u4e00\u6b65\u6bd4\u8f83\u53d8\u6001\uff0c\u5b83\u4e0d\u50cf\u5e73\u5e38\u6211\u4eec\u8bf7\u6c42\u63a5\u53e3\u90a3\u6837\u4f20\u53c3\uff0c\u800c\u662f\u628a\u53c2\u6570\u548c\u503c\u53c8\u62fc\u6210XML\uff0c\u518d\u5199\u5165request\u4e2d\uff0c\u5b9e\u73b0\u8d77\u6765\u8f83\u9ebb\u70e6\uff0c\u5b98\u65b9\u4e5f\u662f\u5728\u540e\u53f0\u53bb\u5b9e\u73b0\u7684\uff0c\u6240\u4ee5\u5efa\u8bae\u7b2c\u4e00\u6b65\u5728\u540e\u53f0\u5b9e\u73b0\uff0cApp\u7aef\u76f4\u63a5\u8c03\u7528\u540e\u53f0\u63d0\u4f9b\u7684\u63a5\u53e3<\/p>\n<p>\u7b2c\u4e8c\u6b65\u53d1\u8d77\u8bf7\u6c42<\/p>\n<p>\u8fd9\u4e00\u6b65\u9664\u4e0b\u7b7e\u540d\u76f8\u5bf9\u9ebb\u70e6\u70b9\u5176\u4ed6\u90fd\u5f88\u7b80\u5355\uff0c\u6ce8\u610f\u6b63\u89c4\u6d41\u7a0b\u5e94\u8be5\u5728\u540e\u53f0\u8fdb\u884c\u52a0\u7b7e<\/p>\n<pre><code class=\"language-swift\">let req = PayReq();\nreq.partnerId = LoadData.WX_PARTNERID;\/\/\u5546\u6237ID\nreq.prepayId = prepayId;\/\/\u9884\u652f\u4ed8ID\nreq.nonceStr = nonceStr;\/\/\u548c\u7b2c\u4e00\u6b65\u4e00\u6837\u7684\u968f\u673a\u6570\nreq.timeStamp = UInt32(NSDate(timeIntervalSinceNow: 0).timeIntervalSince1970);\/\/\u65f6\u95f4\u6233\nreq.package = &quot;Sign=WXPay&quot;;\/\/\u56fa\u5b9a\u503c\n\nvar dic:[String:String] = [:];\ndic[&quot;appid&quot;] = LoadData.WX_APPID;\/\/APPID\ndic[&quot;partnerid&quot;] = LoadData.WX_PARTNERID;\/\/\u5546\u6237ID\ndic[&quot;prepayid&quot;] = prepayId;\ndic[&quot;package&quot;] = &quot;Sign=WXPay&quot;;\ndic[&quot;noncestr&quot;] = req.nonceStr;\ndic[&quot;timestamp&quot;] = &quot;\\(req.timeStamp)&quot;;\n\n\/\/\u4e0b\u9762\u53c2\u6570\u4e2d\u7684key\u662f API\u5bc6\u94a5\nlet sign = WXPayUtils.getSign(dic, key: LoadData.WX_APIKEY);\/\/\u83b7\u53d6\u7b7e\u540d\nreq.sign = sign;\nWXApi.sendReq(req);<\/code><\/pre>\n<p>\u4e0b\u9762\u63d0\u4f9b\u4e00\u4e0b\u6211\u7528\u7684\u5de5\u5177\u7c7b<\/p>\n<pre><code class=\"language-swift\">import Foundation\nimport CryptoSwift\n\nclass WXPayUtils{\n    static var xiadanUrl = &quot;https:\/\/api.mch.weixin.qq.com\/pay\/unifiedorder&quot;;\n    static var appid = &quot;&quot;;\/\/\u516c\u4f17\u8d26\u53f7ID\n    static var mch_id = &quot;&quot;;\/\/\u5546\u6237\u53f7\n    static var nonce_str = &quot;&quot;;\/\/\u968f\u673a\u5b57\u7b26\u4e32\n    static var sign = &quot;&quot;;\/\/\u7b7e\u540d\n    static var body = &quot;&quot;;\/\/\u5546\u54c1\u63cf\u8ff0\n    static var out_trade_no = &quot;&quot;;\/\/\u5546\u6237\u8ba2\u5355\u53f7\n    static var total_fee:Int = 0;\/\/\u603b\u91d1\u989d \u5355\u4f4d\u4e3a\u5206\n    static var spbill_create_ip = &quot;&quot;;\/\/\u7ec8\u7aefIP\n    static var notify_url = &quot;&quot;;\/\/\u901a\u77e5\u5730\u5740\n    static var trade_type = &quot;JSAPI&quot;;\/\/\u4ea4\u6613\u7c7b\u578b\n\n    \/\/\/\u83b7\u53d6\u968f\u673a\u6570 \u5305\u62ecfrom  \u5305\u62ecto\n    static func getRandomNum(from:Int,to:Int) -&gt; Int{\n        let result = Int(from + (Int(arc4random()) % (to - from + 1)));\n        return result;\n    }\n\n    static func getSign(dic:Dictionary&lt;String,String&gt;,key:String) -&gt; String{\n        var sign = &quot;&quot;;\n        let dicNew = dic.sort { (a, b) -&gt; Bool in\n            return a.0 &lt; b.0;\n        }\n\n        sign = getQueryStrByDic(dicNew);\n        sign += &quot;&amp;key=\\(key)&quot;;\n        sign = sign.md5().uppercaseString;\n        return sign;\n    }\n\n    static func getQueryStrByDic(dic:[(String,String)])-&gt;String{\n        var pars = &quot;&quot;;\n        for (index, element) in dic.enumerate() {\n            if(index == 0){\n                pars += &quot;\\(element.0)=\\(element.1)&quot;;\n            }else{\n                pars += &quot;&amp;\\(element.0)=\\(element.1)&quot;;\n            }\n        }\n        return pars;\n    }\n}<\/code><\/pre>\n<p>\u5de5\u5177\u7c7b\u4e2d\u7528\u5230\u7684\u7b2c\u4e09\u65b9\u5e93<\/p>\n<pre><code class=\"language-bash\">pod &#039;CryptoSwift&#039;<\/code><\/pre>\n<h3>\u793a\u4f8b\u4e8c<\/h3>\n<p>1\u3001\u57fa\u672c\u8bbe\u7f6e<\/p>\n<pre><code class=\"language-swift\">\/\/\u5728appdelegate\u6ce8\u518c\u6ce8\u518cAPPID \u5e76\u9075\u5b88WXApiDelegate\nWXApi.registerApp(&quot;wxdc1f628e3a90a9c8&quot;)\n\n\/\/MARK: \u4ee3\u7406\u56de\u8c03\u65b9\u6cd5\nfunc application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -&gt; Bool {\n    let str = &quot;\\(url)&quot;\n    \/\/\u6b64\u79cd\u65b9\u6cd5\u5224\u65ad \u4e0d\u4f1a\u4ea7\u751f \u5206\u4eab\u65e0\u6cd5\u5b9e\u73b0\u56de\u8c03 \u7684\u95ee\u9898\n    if str.contains(&quot;pay&quot;){\n        return WXApi.handleOpen(url, delegate: self)\n    } else {\n        \/\/\u5176\u4ed6\n        return UMSocialManager.default().handleOpen(url)\n    }\n}\n\n\/\/ MARK: \u5fae\u4fe1\u652f\u4ed8\u56de\u8c03\nfunc onResp(_ resp: BaseResp!) {\n    if let payResp = resp as? PayResp {\n        switch payResp.errCode {\n        case WXSuccess.rawValue:\n            NotificationCenter.default.post(Notification(name: NotificationName.didWXPaySucceeded))\n            print(&quot;\u652f\u4ed8\u6210\u529f&quot;)\n        default:\n            NotificationCenter.default.post(Notification(name: NotificationName.didWXPayFailed))\n            print(&quot;\u652f\u4ed8\u5931\u8d25&quot;)\n        }\n    }\n}<\/code><\/pre>\n<p>2\u3001\u5e94\u7528<\/p>\n<pre><code class=\"language-swift\">\/\/\u5728\u652f\u4ed8\u754c\u9762 \nclass func startRewardPayRequest(wish: Wish, money: Float, note: String?, completion: @escaping (Bool, String?, String?) -&gt; Void) {\n    guard let _ = User.current() else {\n        completion(false, nil, nil)\n        return\n    }\n\n    if  !WXApi.isWXAppInstalled(){\n         MBProgressHUD.showForInfo(to: self.view, text: &quot;\u6ca1\u6709\u5b89\u88c5\u5fae\u4fe1&quot;) \n         return\n    }\n\n    Utils.getWxPrepayId(money: money, desc: note ?? &quot;&quot;, orderType: 3, productId: String(wish.id)) { (succeeded, wxPrepayInfo) in\n        guard succeeded &amp;&amp; wxPrepayInfo != nil else {\n            completion(false, nil, nil)\n            return\n        }\n        \/\/\u8c03\u7528\u540e\u53f0\u83b7\u53d6\u76f8\u5e94\u53c2\u6570\u5e76\u751f\u6210\u9884\u8ba2\u5355 \n        let request = PayReq()\n        request.partnerId = wxPrepayInfo!.partnerId\n        request.prepayId = wxPrepayInfo!.prepayId\n        request.package = &quot;Sign=WXPay&quot;\n        request.nonceStr = wxPrepayInfo!.nonceStr\n        request.timeStamp = UInt32(NSDate().timeIntervalSince1970)\n        request.sign = Utils.generateSignForWXPay(paramters: [&quot;appid&quot;: &quot;wxdc1f628e3a90a9c8&quot;,\n                                                              &quot;partnerid&quot;: request.partnerId,\n                                                              &quot;prepayid&quot;: request.prepayId,\n                                                              &quot;package&quot;: request.package,\n                                                              &quot;noncestr&quot;: request.nonceStr,\n                                                              &quot;timestamp&quot;: request.timeStamp])\n\n        let result = WXApi.send(request)\n        completion(result, wxPrepayInfo!.appId, wxPrepayInfo!.outtradeno)\n    }\n}\n*\/\/\u63a5\u6536\u652f\u4ed8\u7ed3\u679c\u7684\u901a\u77e5 \u8c03\u7528\u540e\u53f0\u63a5\u53e3\u5224\u65ad\u662f\u5426\u652f\u4ed8\u6210\u529f \u5728\u7ee7\u7eed\u5904\u7406<\/code><\/pre>\n<p>3\u3001\u7b7e\u540d\u751f\u6210\u65b9\u6cd5<\/p>\n<pre><code class=\"language-swift\">class func generateSignForWXPay(paramters: [String: Any]) -&gt; String {\n    var _paramters = [String: Any]()\n\n    for (key, value) in paramters {\n        if let str = value as? String, str == &quot;&quot; {\n            continue\n        }\n\n        _paramters[key] = value\n    }\n\n    let sortedKeys = _paramters.keys.sorted()\n    var temp = sortedKeys.map({ &quot;\\($0)=\\(_paramters[$0]!)&quot; }).joined(separator: &quot;&amp;&quot;)\n    temp += &quot;&amp;key=64255ed288e44b7298f49a1239103d15&quot;\n\n    return temp.md5().uppercased()\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u9879\u76ee\u914d\u7f6e \u5fae\u4fe1\u652f\u4ed8Demo\uff1ahttps:\/\/pay.weixin.qq.com\/wiki\/doc\/api\/ap [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[171,371],"tags":[],"class_list":["post-2108","post","type-post","status-publish","format-standard","hentry","category-swift","category-wechat-pay"],"_links":{"self":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/2108","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/comments?post=2108"}],"version-history":[{"count":0,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/2108\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/media?parent=2108"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/categories?post=2108"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/tags?post=2108"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}