swift基础收集

OC/Swift-支付集成(微信/支付宝)

2019-02-20  本文已影响12人  SK丿希望

一,前期准备,设置URL Types

image.png

微信设置identifier:weixin(可以固定),后面的URL Schemes为注册微信的appkey
支付宝设置identifier:alipay(可以固定),后面的URL Schemes只要唯一就好了
注意:我这里都是固定的,方便后续去info.plist文件里获取数据方便


Swift版

1.创建管理器
import UIKit

private let URLSchemeWechat = "weixin"
private let URLSchemeAlipay = "alipay"
private var successBlock:(()->())?
private var failBlock:((String)->())?
private var appscheme:[String:String] = [:]
enum HWPayType :Int {
    case wx = 0
    case zfb = 1
}

class wxPayModel : BaseModel { // 注意:这里的模型需要对应后台返回的 不一定是这些 可以对应修改
    /// 预支付订单
    var prepayid: String?
    /// 商家向财付通申请的商家id
    var partnerid: String?
    /// 商家根据财付通文档填写的数据和签名
    var package: String?
    /// 随机串,防重发
    var noncestr: String?
    /// 商家根据微信开放平台文档对数据做的签名
    var sign: String?
    /// 时间戳,防重发
    var timestamp: Int = 0
    /// 由用户微信号和AppID组成的唯一标识,发送请求时第三方程序必须填写,用于校验微信用户是否换号登录
    var appid: String?
}
class PaymentManage: NSObject {
    public static var aliSdkManager:PaymentManage!
    /// 获取单例
    public static func shared() -> PaymentManage{
        PaymentManage.aliSdkManager = PaymentManage.init()
        return PaymentManage.aliSdkManager
    }
    /// 注册支付系统
    func registApp(){
        let path = Bundle.main.path(forResource: "Info", ofType: "plist")
        let dict = NSDictionary(contentsOfFile: path!)
        guard let urlTypes:Array<Dictionary<String,Any>> = dict!["CFBundleURLTypes"] as? Array<Dictionary<String,Any>> else {return}
        for  item in urlTypes {
            let urlName = item["CFBundleURLName"] as? String
            if  let urlSchemes : Array<String> = item["CFBundleURLSchemes"] as? Array<String>{
                let urlScheme = urlSchemes.last ?? ""
                if urlName! == URLSchemeWechat {
                    appscheme[URLSchemeWechat] = urlScheme
                    // 注册微信
                    WXApi.registerApp(urlScheme)
                }else if urlName == URLSchemeAlipay{
                    // 保存支付宝的
                    appscheme[URLSchemeAlipay] = urlScheme
                }
            }
        }
    }
    
    // 外部用这个方法调起支付支付
    func pay(_ type: HWPayType,
             request:Any,
             paySuccess: @escaping () -> Void,
             payFail:@escaping (String) -> Void) {
        successBlock = paySuccess
        failBlock = payFail
        if type == .zfb {
            let newrequest = request as! String
            AlipaySDK.defaultService().payOrder(newrequest, fromScheme: appscheme[URLSchemeAlipay]) { (result) in }
        } else {
            if !WXApi.isWXAppInstalled()  {//检查一下是否可以使用微信
                failBlock!("未安装微信")
                HWPrint("未安装微信")
                return
            } else if !WXApi.isWXAppSupport() {
                failBlock!("当前版本微信不支持微信支付")
                HWPrint("当前版本微信不支持微信支付")
                return
            }
            let model = request as! wxPayModel
            let req = PayReq() // 生成支付模型
            req.openID = model.appid
            req.partnerId = model.partnerid
            req.prepayId = model.prepayid
            req.package = model.package
            req.timeStamp = UInt32(model.timestamp)
            req.nonceStr = model.noncestr
            req.sign = model.sign
            WXApi.send(req) //调起微信
        }
    }
    
    func noticeopen(_ url: URL) {
        if url.host == "safepay" { // 支付宝
            AlipaySDK.defaultService().processOrder(withPaymentResult: url as URL?, standbyCallback: { [weak self]
                (resultDic) -> Void in
                //调起支付结果处理
                self?.showResult(result: resultDic! as NSDictionary);
            })
        } else if url.host!.contains("pay"){ // 微信
            WXApi.handleOpen(url, delegate: self)
        }
    }
    
    
    /// 授权回调(这里用的是下一种)
    func showAuth_V2Result(result:NSDictionary){
        //        9000    请求处理成功
        //        4000    系统异常
        //        6001    用户中途取消
        //        6002    网络连接出错
        let returnCode:String = result["resultStatus"] as! String
        var returnMsg:String = ""
        switch  returnCode{
        case "6001":
            returnMsg = "用户中途取消"
            break
        case "6002":
            returnMsg = "网络连接出错"
            break
        case "4000":
            returnMsg = "系统异常"
            break
        case "9000":
            returnMsg = "授权成功"
            break
        default:
            returnMsg = "系统异常"
            break
        }
        HWPrint(returnMsg)
    }
    /// 传入回调参数
    func showResult(result:NSDictionary){
        //        9000    订单支付成功
        //        8000    正在处理中
        //        4000    订单支付失败
        //        6001    用户中途取消
        //        6002    网络连接出错
        let returnCode:String = result["resultStatus"] as! String
        var returnMsg:String = ""
        switch  returnCode{
        case "6001":
            returnMsg = "用户中途取消"
            if failBlock == nil {return}
            failBlock!(returnMsg)
            break
        case "6002":
            returnMsg = "网络连接出错"
            if failBlock == nil {return}
            failBlock!(returnMsg)
            break
        case "8000":
            returnMsg = "正在处理中"
            if failBlock == nil {return}
            failBlock!(returnMsg)
            break
        case "4000":
            returnMsg = "订单支付失败"
            if failBlock == nil {return}
            failBlock!(returnMsg)
            break
        case "9000":
            if successBlock == nil {return}
            successBlock!()
            returnMsg = "支付成功"
            break
        default:
            returnMsg = "订单支付失败"
            if failBlock == nil {return}
            failBlock!(returnMsg)
            break
        }
        HWPrint(returnMsg)
    }
}
extension PaymentManage : WXApiDelegate {
    func onResp(_ resp: BaseResp!) {
        if let payressp:PayResp = resp as? PayResp{
            switch payressp.errCode{
            case 0:
                HWPrint("支付成功")
                if successBlock == nil {return}
                successBlock!()
                break
            case -1:
                HWPrint(resp.errStr)
                if failBlock == nil {return}
                failBlock!(resp.errStr ?? "")
                break
            case -2:
                HWPrint("用户中途取消")
                if failBlock == nil {return}
                failBlock!("用户中途取消")
                break;
            default:
                HWPrint("未知错误")
                if failBlock == nil {return}
                failBlock!("未知错误")
                break;
            }
        }
    }
}
2.使用
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        PaymentManage.shared().registApp() // 注册支付管理者
        return true
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
        let result = UMSocialManager.default().handleOpen(url, sourceApplication: sourceApplication, annotation: annotation)
        if (!result) {
            // 其他如支付等SDK的回调
            PaymentManage.shared().noticeopen(url)
        }
        return result;
    }
例如:当前是微信支付 
if type == .wx {
 // 网络请求对应的支付信息 转成模型 <注意模型要转成wxPayModel类型,因为内部用这个类型处理事件的> 
        PaymentManage.shared().pay(.wx, request: model , paySuccess: {
                    /// 支付成功要做的事
                }, payFail: { (error) in
                    ///error 支付失败的信息
                })
} else {
  支付宝就直接把json数据传入进去就好了
}

OC版

1.创建管理者
#import <Foundation/Foundation.h>

#define DWQWECHATURLNAME @"weixin"
#define DWQALIPAYURLNAME @"alipay"

NS_ASSUME_NONNULL_BEGIN

@interface HWPayWXModel : NSObject

@property (nonatomic, copy) NSString *prepayid;

@property (nonatomic, copy) NSString *partnerid;

@property (nonatomic, copy) NSString *package;

@property (nonatomic, copy) NSString *noncestr;

@property (nonatomic, assign) UInt32 timestamp;

@property (nonatomic, copy) NSString *sign;

@property (nonatomic, copy) NSString *appid;

@end

@interface HWPayManage : NSObject
/** 单例管理 */
+ (instancetype)shareManager;
/** 注册 */
- (void)hw_registerApp;
/** 支付 */
- (void)hw_payWithOrderMessage:(id)orderMessage success:(void(^)(void))success fail:(void(^)(NSString *error))fail;
/** 收到回调后接收通知 */
- (BOOL)hw_handleUrl:(NSURL *)url;
@end

NS_ASSUME_NONNULL_END
#import "HWPayManage.h"
#import <WXApi.h>
#import <AlipaySDK/AlipaySDK.h>

// 回调url地址为空
#define DWQTIP_CALLBACKURL @"url地址不能为空!"
// 订单信息为空字符串或者nil
#define DWQTIP_ORDERMESSAGE @"订单信息不能为空!"
// 没添加 URL Types
#define DWQTIP_URLTYPE @"请先在Info.plist 添加 URL Type"
// 添加了 URL Types 但信息不全
#define DWQTIP_URLTYPE_SCHEME(name) [NSString stringWithFormat:@"请先在Info.plist 的 URL Type 添加 %@ 对应的 URL Scheme",name]

@implementation HWPayWXModel

@end

@interface HWPayManage ()<WXApiDelegate>
// 缓存appScheme
@property (nonatomic,strong)NSMutableDictionary *appSchemeDict;
/** <#注释#> */
@property(nonatomic, copy) void(^successBlock)(void);
/** <#注释#> */
@property(nonatomic, copy) void(^failBlock)(NSString *error);
@end

@implementation HWPayManage

+ (instancetype)shareManager{
    static HWPayManage *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}
- (void)hw_registerApp {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"];
    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
    NSArray *urlTypes = dict[@"CFBundleURLTypes"];
    NSAssert(urlTypes, DWQTIP_URLTYPE);
    for (NSDictionary *urlTypeDict in urlTypes) {
        NSString *urlName = urlTypeDict[@"CFBundleURLName"];
        NSArray *urlSchemes = urlTypeDict[@"CFBundleURLSchemes"];
        NSAssert(urlSchemes.count, DWQTIP_URLTYPE_SCHEME(urlName));
        // 一般对应只有一个
        NSString *urlScheme = urlSchemes.lastObject;
        if ([urlName isEqualToString:DWQWECHATURLNAME]) {
            [self.appSchemeDict setValue:urlScheme forKey:DWQWECHATURLNAME];
            // 注册微信
            [WXApi registerApp:urlScheme];
        } else if ([urlName isEqualToString:DWQALIPAYURLNAME]){
            // 保存支付宝scheme,以便发起支付使用
            [self.appSchemeDict setValue:urlScheme forKey:DWQALIPAYURLNAME];
        }
    }
}

- (void)hw_payWithOrderMessage:(id)orderMessage success:(void(^)(void))success fail:(void(^)(NSString *error))fail {
    self.successBlock = success;
    self.failBlock = fail;
    if (orderMessage[@"info"]) { // 支付宝支付
        [[AlipaySDK defaultService] payOrder:orderMessage[@"info"] fromScheme:self.appSchemeDict[DWQALIPAYURLNAME] callback:^(NSDictionary *resultDic) {}];
    } else { // 微信支付
        if (![WXApi isWXAppInstalled]) { // 没有安装微信
            self.failBlock(@"没有安装微信");
            return;
        }
        if (![WXApi isWXAppSupportApi]) { // 当前版本微信不支持微信支付
            self.failBlock(@"当前版本微信不支持微信支付");
            return;
        }
        HWPayWXModel *model = [HWPayWXModel mj_objectWithKeyValues:orderMessage];
        PayReq *payReq = [[PayReq alloc] init];
        payReq.partnerId = model.partnerid;
        payReq.prepayId = model.prepayid;
        payReq.nonceStr = model.noncestr;
        payReq.timeStamp = model.timestamp;
        payReq.package = model.package;
        payReq.sign = model.sign;
        payReq.openID = model.appid;
        [WXApi sendReq:payReq];
    }
}
- (BOOL)hw_handleUrl:(NSURL *)url {
    NSAssert(url, DWQTIP_CALLBACKURL);
    if ([url.host isEqualToString:@"pay"]) {// 微信
        return [WXApi handleOpenURL:url delegate:self];
    } else if ([url.host isEqualToString:@"safepay"]) {// 支付宝
        __weak typeof(self) weakSelf = self;
        // 支付跳转支付宝钱包进行支付,处理支付结果(在app被杀模式下,通过这个方法获取支付结果)
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            [weakSelf showResult:resultDic];
        }];
        return YES;
    } else{
        return NO;
    }
}
- (void)showResult:(NSDictionary *)resultDic {
    NSString *resultStatus = resultDic[@"resultStatus"];
    if ([resultStatus isEqualToString:@"6001"]) {
        self.failBlock(@"用户中途取消");
    } else if ([resultStatus isEqualToString:@"6002"]) {
        self.failBlock(@"网络连接出错");
    } else if ([resultStatus isEqualToString:@"8000"]) {
        self.failBlock(@"正在处理中");
    } else if ([resultStatus isEqualToString:@"4000"]) {
        self.failBlock(@"订单支付失败");
    } else if ([resultStatus isEqualToString:@"9000"]) {
        self.successBlock();
    } else {
        self.failBlock(@"订单支付失败");
    }
}
#pragma mark - WXApiDelegate
- (void)onResp:(BaseResp *)resp {
    // 判断支付类型
    if([resp isKindOfClass:[PayResp class]]){
        //支付回调
        NSString *errStr = resp.errStr;
        switch (resp.errCode) {
            case 0:
                self.successBlock();
                errStr = @"订单支付成功";
                break;
            case -1:
                errStr = resp.errStr;
                self.failBlock(errStr);
                break;
            case -2:
                errStr = @"用户中途取消";
                self.failBlock(errStr);
                break;
            default:
                errStr = resp.errStr;
                self.failBlock(errStr);
                break;
        }
    }
}
- (NSMutableDictionary *)appSchemeDict{
    if (_appSchemeDict == nil) {
        _appSchemeDict = [NSMutableDictionary dictionary];
    }
    return _appSchemeDict;
}
@end
2.使用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[HWPayManage shareManager] hw_registerApp];
    return YES;
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    BOOL result = [[UMSocialManager defaultManager] handleOpenURL:url];
    if (!result) {
        // 其他如支付等SDK的回调
       return [[HWPayManage shareManager] hw_handleUrl:url];
    }
    return result;
}
[[HWPayManage shareManager] hw_payWithOrderMessage:item.data success:^{
                /// 支付成功处理逻辑
            } fail:^(NSString * _Nonnull error) {
                 /// 支付失败处理逻辑
            }];

总结:如果有分享需要注意,收到回调方法可能会被覆盖这样就收不到支付信息的回调了,需要注意
代码

上一篇下一篇

猜你喜欢

热点阅读