iOS微信支付接入(Swift)

项目配置

微信支付Demo:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=11_1

把示例项目中的以下文件拖到项目中

Control文件夹下的WXApiManager.h和WXApiManager.m
libWeChatSDK.a
WXApi.h
WXApiObject.h

桥接文件中添加引用

//微信支付
#import "WXApi.h"
#import "WXApiObject.h"
#import "WXApiManager.h"

项目配置选项卡targets -> Info -> URL Types中添加一项

identifier 设置为 weixin
URL Schemes 设置为你app微信开放平台上的appid

info.plist中加入安全域名白名单(右键info.plist用source code打开)

<key>LSApplicationQueriesSchemes</key>  
<array>  
    <string>sinaweibo</string>  
    <string>sinaweibohd</string>  
    <string>weibosdk2.5</string>  
    <string>weibosdk</string>  
    <string>sinaweibosso</string>  
    <string>mqqOpensdkSSoLogin</string>  
    <string>mqzone</string>  
    <string>sinaweibo</string>  
    <string>alipayauth</string>  
    <string>alipay</string>  
    <string>safepay</string>  
    <string>mqq</string>  
    <string>mqqapi</string>  
    <string>mqqopensdkapiV3</string>  
    <string>mqqopensdkapiV2</string>  
    <string>mqqapiwallet</string>  
    <string>mqqwpa</string>  
    <string>mqqbrowser</string>  
    <string>wtloginmqq2</string>  
    <string>weixin</string>  
    <string>wechat</string>  
</array>

具体流程

  1. 下单

App调用后台统一下单 ---> 商户后台 ---> 微信后台返回订单 ---> 商户后台返回订单 ---> 商户App

  1. 支付

商户App发送sendReq方法 ---> 调起微信发起支付请求 ---> 微信后台授权支付 ---> 微信进行支付

  1. 支付

商户App回调处理 ---> 若前端成功则与后台确认

  1. 支付完成之后

微信后台异步通知 ---> 商户后台
微信App发送支付状态信息 ---> 商户App去后台查询是否真正支付成功 ---> 商户后台(如果此时后台未收到微信后台异步通知商户后台则会调用查询API ---> 微信后台返回支付结果 ---> 商户后台)否则,直接根据微信后台异步通知商户支付成功与否 ---> 商户App确认

代码示例

示例一

AppDelegate中注册

//在appdelegate注册注册APPID 并遵守WXApiDelegate
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    //微信支付
    WXApi.registerApp("你的APPID");
}

func application(application: UIApplication, handleOpenURL url: NSURL) -> Bool {
    return WXApi.handleOpenURL(url, delegate: WXApiManager.sharedManager());
    //return UMSocialSnsService.handleOpenURL(url);
}

//这里演示多个共存的处理方法,其中中间是和微信有关的
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
    //支付宝支付
    if(sourceApplication!.containsString("com.alipay.iphoneclient")){
        AlipaySDK.defaultService().processOrderWithPaymentResult(url, standbyCallback: nil)
        return true;
    }
    //微信支付
    else if(sourceApplication!.containsString("com.tencent.xin")){
        return WXApi.handleOpenURL(url, delegate: WXApiManager.sharedManager());
    }
    //友盟分享
    else{
        return UMSocialSnsService.handleOpenURL(url);
    }
}

需要的三个参数

appid (微信开放平台中获取)
partnerId (商户ID,在商户平台获取)
API_KEY (API密钥,在商户平台设置)

支付步骤

支付总体上分为两步

  • 获取prepayid(预付款ID)
  • 根据prepayid发起支付

第一步获取prepayid

这一步比较变态,它不像平常我们请求接口那样传參,而是把参数和值又拼成XML,再写入request中,实现起来较麻烦,官方也是在后台去实现的,所以建议第一步在后台实现,App端直接调用后台提供的接口

第二步发起请求

这一步除下签名相对麻烦点其他都很简单,注意正规流程应该在后台进行加签

let req = PayReq();
req.partnerId = LoadData.WX_PARTNERID;//商户ID
req.prepayId = prepayId;//预支付ID
req.nonceStr = nonceStr;//和第一步一样的随机数
req.timeStamp = UInt32(NSDate(timeIntervalSinceNow: 0).timeIntervalSince1970);//时间戳
req.package = "Sign=WXPay";//固定值

var dic:[String:String] = [:];
dic["appid"] = LoadData.WX_APPID;//APPID
dic["partnerid"] = LoadData.WX_PARTNERID;//商户ID
dic["prepayid"] = prepayId;
dic["package"] = "Sign=WXPay";
dic["noncestr"] = req.nonceStr;
dic["timestamp"] = "\(req.timeStamp)";

//下面参数中的key是 API密钥
let sign = WXPayUtils.getSign(dic, key: LoadData.WX_APIKEY);//获取签名
req.sign = sign;
WXApi.sendReq(req);

下面提供一下我用的工具类

import Foundation
import CryptoSwift

class WXPayUtils{
    static var xiadanUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    static var appid = "";//公众账号ID
    static var mch_id = "";//商户号
    static var nonce_str = "";//随机字符串
    static var sign = "";//签名
    static var body = "";//商品描述
    static var out_trade_no = "";//商户订单号
    static var total_fee:Int = 0;//总金额 单位为分
    static var spbill_create_ip = "";//终端IP
    static var notify_url = "";//通知地址
    static var trade_type = "JSAPI";//交易类型

    ///获取随机数 包括from  包括to
    static func getRandomNum(from:Int,to:Int) -> Int{
        let result = Int(from + (Int(arc4random()) % (to - from + 1)));
        return result;
    }

    static func getSign(dic:Dictionary<String,String>,key:String) -> String{
        var sign = "";
        let dicNew = dic.sort { (a, b) -> Bool in
            return a.0 < b.0;
        }

        sign = getQueryStrByDic(dicNew);
        sign += "&key=\(key)";
        sign = sign.md5().uppercaseString;
        return sign;
    }

    static func getQueryStrByDic(dic:[(String,String)])->String{
        var pars = "";
        for (index, element) in dic.enumerate() {
            if(index == 0){
                pars += "\(element.0)=\(element.1)";
            }else{
                pars += "&\(element.0)=\(element.1)";
            }
        }
        return pars;
    }
}

工具类中用到的第三方库

pod 'CryptoSwift'

示例二

1、基本设置

//在appdelegate注册注册APPID 并遵守WXApiDelegate
WXApi.registerApp("wxdc1f628e3a90a9c8")

//MARK: 代理回调方法
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    let str = "\(url)"
    //此种方法判断 不会产生 分享无法实现回调 的问题
    if str.contains("pay"){
        return WXApi.handleOpen(url, delegate: self)
    } else {
        //其他
        return UMSocialManager.default().handleOpen(url)
    }
}

// MARK: 微信支付回调
func onResp(_ resp: BaseResp!) {
    if let payResp = resp as? PayResp {
        switch payResp.errCode {
        case WXSuccess.rawValue:
            NotificationCenter.default.post(Notification(name: NotificationName.didWXPaySucceeded))
            print("支付成功")
        default:
            NotificationCenter.default.post(Notification(name: NotificationName.didWXPayFailed))
            print("支付失败")
        }
    }
}

2、应用

//在支付界面 
class func startRewardPayRequest(wish: Wish, money: Float, note: String?, completion: @escaping (Bool, String?, String?) -> Void) {
    guard let _ = User.current() else {
        completion(false, nil, nil)
        return
    }

    if  !WXApi.isWXAppInstalled(){
         MBProgressHUD.showForInfo(to: self.view, text: "没有安装微信") 
         return
    }

    Utils.getWxPrepayId(money: money, desc: note ?? "", orderType: 3, productId: String(wish.id)) { (succeeded, wxPrepayInfo) in
        guard succeeded && wxPrepayInfo != nil else {
            completion(false, nil, nil)
            return
        }
        //调用后台获取相应参数并生成预订单 
        let request = PayReq()
        request.partnerId = wxPrepayInfo!.partnerId
        request.prepayId = wxPrepayInfo!.prepayId
        request.package = "Sign=WXPay"
        request.nonceStr = wxPrepayInfo!.nonceStr
        request.timeStamp = UInt32(NSDate().timeIntervalSince1970)
        request.sign = Utils.generateSignForWXPay(paramters: ["appid": "wxdc1f628e3a90a9c8",
                                                              "partnerid": request.partnerId,
                                                              "prepayid": request.prepayId,
                                                              "package": request.package,
                                                              "noncestr": request.nonceStr,
                                                              "timestamp": request.timeStamp])

        let result = WXApi.send(request)
        completion(result, wxPrepayInfo!.appId, wxPrepayInfo!.outtradeno)
    }
}
*//接收支付结果的通知 调用后台接口判断是否支付成功 在继续处理

3、签名生成方法

class func generateSignForWXPay(paramters: [String: Any]) -> String {
    var _paramters = [String: Any]()

    for (key, value) in paramters {
        if let str = value as? String, str == "" {
            continue
        }

        _paramters[key] = value
    }

    let sortedKeys = _paramters.keys.sorted()
    var temp = sortedKeys.map({ "\($0)=\(_paramters[$0]!)" }).joined(separator: "&")
    temp += "&key=64255ed288e44b7298f49a1239103d15"

    return temp.md5().uppercased()
}

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/04/01/ios-wechat-payment-access-swift/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
iOS微信支付接入(Swift)
项目配置 微信支付Demo:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=11_1 把示例项目中的以下文件拖到项目中 Control文件夹下的WXApiManag……
<<上一篇
下一篇>>
文章目录
关闭
目 录