iOS支付宝,微信,银联支付集成封装调用(下)

Posted 国孩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS支付宝,微信,银联支付集成封装调用(下)相关的知识,希望对你有一定的参考价值。

本人已迁移博客至掘进,以后会在掘进平台更新最新的文章也会有更多的干货,欢迎大家关注!!!https://juejin.im/user/588993965333309

 

一.越来越多的app增加第三方的功能,可能app有不同的页面但调用相同的支付方式,例如界面如下:

 

这两个页面都会使用第三方支付支付:(微信,支付宝,银联)如果在每一个页面都直接调用第三方支付的接口全部代码,显然并不是很合适,更何况,可能一个app并不止两个入口。所以封装还是很有必要的。

1.新建Model:-------后台返回支付方式的列表json

#import <Foundation/Foundation.h>

@interface IOAPayItemModel : NSObject

//name:代表是支付宝,微信,银联或者余额等
@property (nonatomic, copy) NSString *name;
//icon:代表是支付方式的图片
@property (nonatomic, copy) NSString *icon;
//code:代表支付方式的唯一标识
@property (nonatomic, copy) NSString *code;
//payType:代表支付类型(自己确定的)
@property (nonatomic, assign) NSInteger payType;
@end
#import "IOAPayItemModel.h"

@implementation IOAPayItemModel

@end

2.封装第三方支付接口以及回调接口-----直接上源代码----会有解释(相信大家的能力,肯定能看懂)

#import <Foundation/Foundation.h>
//支付宝SDK
#import <AlipaySDK/AlipaySDK.h>
//微信接口
#import <WXApi.h>
//银联接口
#import "UPPaymentControl.h"

/**
 枚举:列出第三方支付方式
 */
typedef NS_ENUM(NSInteger, PayType) {
    kPayTypeWXPay, // 微信支付
    kPayTypeALiPay, // 支付宝支付
    kPayTypeUNPay   // 银联支付
};


/**
 IOAPayRequestModel:第三方支付需要的参数
 */
@interface IOAPayRequestModel: NSObject
@property (nonatomic, assign) PayType payType;

/**
 支付宝和银联-后台返回是字符串类型----支付宝和银联使用此方式
 */
@property (nonatomic, copy) NSString *payString;
@property (nonatomic, copy) NSString *appScheme; // 根据设置的paytype设置

/**
 微信-后台返回是字典类型--- 微信使用此方式
 */
@property (nonatomic, strong) NSDictionary *userInfo;
@end


/**
 第三方支付接口返回的数据---
 */
@interface IOAPayResponseModel: NSObject
@property (nonatomic, assign) PayType payType;

//result和userInfo信息判断支付结果--(支付成功、支付失败、支付取消等)
@property (nonatomic, assign) NSInteger result;
@property (nonatomic, strong) NSDictionary *userInfo;
@end

@interface IOAPayApi : NSObject

//支付返回的回调方法
@property (nonatomic, copy) void (^callback)(IOAPayResponseModel *response);

//支付请求model ----IOAPayRequestModel---第三方支付需要的参数
@property (nonatomic, strong) IOAPayRequestModel *payRequestModel;

//单例方法
+ (instancetype)defaultPayManager;

// 是否安装了客户端
- (BOOL)isPayAppInstalled:(PayType)payType;
// 支付
- (void)pay:(IOAPayRequestModel *)payRequestModel callback:(void (^)(IOAPayResponseModel *response))callback;

// 支付回调
- (void)payCallbackWithUrl:(NSURL *)url;
@end
#import "IOAPayApi.h"

@implementation IOAPayRequestModel

- (void)setPayType:(PayType)payType {
    _payType = payType;
    if (_payType == kPayTypeALiPay) {
        self.appScheme = @"IOAAlipaySDK";
        // 测试
        
        return;
    }
    
    if (_payType == kPayTypeUNPay) {
        self.appScheme = @"UPPay";
        
        // 测试
//        self.payString = @"559018436594292239101";
        
        return;
    }
    
    // 测试
//    self.userInfo = @{
//                                 @"appid":@"",
//                                 @"noncestr":@"J8pJbaEg6AjDQ9kk",
//                                 @"partnerid":@"1497576612",
//                                 @"prepayid":@"wx20180321170621b3fbce61a20187009040",
//                                 @"result_code":@"SUCCESS",
//                                 @"return_code":@"SUCCESS",
//                                 @"return_msg":@"OK",
//                                 @"sign":@"29FFF7B63A71D3FB4C6866BDBC443F72",
//                                 @"timestamp":@"1521623180",
//                                 @"trade_type":@"APP",
//                                 };
}
@end

@implementation IOAPayResponseModel

@end

@interface IOAPayApi() <WXApiDelegate>

@end

@implementation IOAPayApi

//单例方法
static IOAPayApi *manager = nil;
+ (instancetype)defaultPayManager {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [IOAPayApi new];
    });
    return manager;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [super allocWithZone:zone];
    });
    
    return manager;
}

//copy在底层 会调用copyWithZone:
- (instancetype)copyWithZone:(NSZone *)zone {
    return [[self class] defaultPayManager];
}
+ (instancetype)copyWithZone:(struct _NSZone *)zone {
    return [self defaultPayManager];
}
+ (instancetype)mutableCopyWithZone:(struct _NSZone *)zone {
    return [self defaultPayManager];
}
- (instancetype)mutableCopyWithZone:(NSZone *)zone {
    return [[self class] defaultPayManager];
}

#pragma mark - WeiChatPayDelegate
- (void)onResp:(BaseResp *)resp {
    //启动微信支付的response
    if (self.payRequestModel.payType == kPayTypeWXPay) {
        if (self.callback) {
            IOAPayResponseModel *payResponseModel = [IOAPayResponseModel new];
            payResponseModel.result = 0;
            if([resp isKindOfClass:[PayResp class]]){
                //支付返回结果,实际支付结果需要去微信服务器端查询
                switch (resp.errCode) {
                    case 0:
//                        payResoult = @"支付结果:成功!";
                        payResponseModel.result = 1;
                        break;
                    case -1:
                        payResponseModel.result = 0;
                        break;
                    case -2:
                        payResponseModel.result = 0;
                        break;
                    default:
                        break;
                }
            }
            
            self.callback(payResponseModel);
        }
    }
}

#pragma mark - Public

// 是否安装了客户端
- (BOOL)isPayAppInstalled:(PayType)payType {
    switch (payType) {
        case kPayTypeWXPay:
            return [WXApi isWXAppInstalled];
            break;
            
        case kPayTypeALiPay:
            // 未提供接口 返回NO
            return NO;
            break;
        case kPayTypeUNPay:
           return [[UPPaymentControl defaultControl] isPaymentAppInstalled];
            break;
        default:
            break;
    }
    
    return NO;
}

- (void)pay:(IOAPayRequestModel *)payRequestModel callback:(void (^)(IOAPayResponseModel *response))callback {
    if (!payRequestModel) return;
    self.callback = callback;
    self.payRequestModel = payRequestModel;
    
    switch (payRequestModel.payType) {
        case kPayTypeWXPay:
            [self wxPay:payRequestModel];
            break;
            
        case kPayTypeALiPay:
            [self aliPay:payRequestModel];
            break;
        case kPayTypeUNPay:
            [self unPay:payRequestModel];
            break;
        default:
            break;
    }
}

// 支付回调
- (void)payCallbackWithUrl:(NSURL *)url {
    // 其他如支付等SDK的回调
    if ([url.host isEqualToString:@"safepay"]) {
        [self aliPayCallback:url];
    }
    else if ([url.host isEqualToString:@"pay"]) {
        // 处理微信的支付结果
        [self wxPayCallback:url];
    }
    else if ([url.host isEqualToString:@"uppayresult"]) {
        [self unPayCallback:url];
    }
}

#pragma mark - Pay

// 微信支付
- (void)wxPay:(IOAPayRequestModel *)payRequestModel {
    PayReq *req   = [[PayReq alloc] init];
    NSDictionary *dataDic = payRequestModel.userInfo;
    //由用户微信号和AppID组成的唯一标识,用于校验微信用户
    req.openID = dataDic[@"appid"];
    // 商家id,在注册的时候给的
    req.partnerId = dataDic[@"partnerid"];
    // 预支付订单这个是后台跟微信服务器交互后,微信服务器传给你们服务器的,你们服务器再传给你
    req.prepayId  = dataDic[@"prepayid"];
    // 根据财付通文档填写的数据和签名
    req.package  = @"Sign=WXPay";
    // 随机编码,为了防止重复的,在后台生成
    req.nonceStr  = dataDic[@"noncestr"];
    // 这个是时间戳,也是在后台生成的,为了验证支付的
    NSString * stamp = dataDic[@"timestamp"];
    req.timeStamp = stamp.intValue;
    // 这个签名也是后台做的
    req.sign = dataDic[@"sign"];
    //发送请求到微信,等待微信返回onResp
    [WXApi sendReq:req];
}

// 支付宝
- (void)aliPay:(IOAPayRequestModel *)payRequestModel {
    NSString *appScheme = payRequestModel.appScheme;
    NSString *payString = payRequestModel.payString;
    
    __weak __typeof(self)weakSelf = self;
    [[AlipaySDK defaultService] payOrder:payString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
        if (weakSelf.payRequestModel.payType == kPayTypeALiPay) {
            if (weakSelf.callback) {
                IOAPayResponseModel *payResponseModel = [IOAPayResponseModel new];
                payResponseModel.userInfo = resultDic;
                payResponseModel.result = [resultDic[@"result"] integerValue];
                weakSelf.callback(payResponseModel);
            }
        }
    }];
}

// 银联支付
- (void)unPay:(IOAPayRequestModel *)payRequestModel {
    NSString *appScheme = payRequestModel.appScheme;
    NSString *payString = payRequestModel.payString;
    [[UPPaymentControl defaultControl] startPay:payString fromScheme:appScheme mode:@"01" viewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}

//////
- (void)wxPayCallback:(NSURL *)url {
    //跳转支付宝钱包进行支付,处理支付结果
    [WXApi handleOpenURL:url delegate:self];
}

- (void)aliPayCallback:(NSURL *)url {
    __weak typeof(self)weakSelf = self;
    [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
        if (weakSelf.payRequestModel.payType == kPayTypeALiPay) {
            if (weakSelf.callback) {
                IOAPayResponseModel *payResponseModel = [IOAPayResponseModel new];
                payResponseModel.userInfo = resultDic;
                payResponseModel.result = [resultDic[@"result"] integerValue];
                weakSelf.callback(payResponseModel);
            }
        }
    }];
}

- (void)unPayCallback:(NSURL *)url {
    __weak typeof(self)weakSelf = self;
    [[UPPaymentControl defaultControl]handlePaymentResult:url completeBlock:^(NSString *code, NSDictionary *data) {
        if (weakSelf.payRequestModel.payType == kPayTypeUNPay) {
            if (weakSelf.callback) {
                IOAPayResponseModel *payResponseModel = [IOAPayResponseModel new];
                payResponseModel.userInfo = data;
                if ([code isEqualToString:@"success"]) {
                    [[NSNotificationCenter defaultCenter] postNotificationName:@"YINLIANPAYS" object:nil];
                    payResponseModel.result = [code boolValue];
                }
                else if([code isEqualToString:@"fail"]) {
                    //交易失败
                    [[NSNotificationCenter defaultCenter] postNotificationName:@"YINLIANPAYF" object:nil];
                    payResponseModel.result = [code boolValue];
                }
                else if([code isEqualToString:@"cancel"]) {
                    //交易取消
                    [[NSNotificationCenter defaultCenter] postNotificationName:@"YINLIANPAYC" object:nil];
                    payResponseModel.result = 0;
                }
                
                weakSelf.callback(payResponseModel);
            }
        }
    }];
}
@end

3.此时方法就开始封装好了,可以在需要的地方直接使用(弹框已作出)

- (void)alipay{
    [self startProgress];
    self.requestModel.pay_type = @"alipayMobile";
    //自己后台的接口---拿到后台返回的数据作为第三方接口的参数
    [self.viewModel requestCartSettlePay:self.requestModel callback:^(IOAResponse *response) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self stopProgress];
            if (response.success) {
                NSString *appScheme = @"IOAAlipaySDK";
                self.payRequestModel.payString = response.responseObject;
                self.payRequestModel.payType = 1;
                self.payRequestModel.appScheme = appScheme;
                //第三方接口调用(封装)
                [[IOAPayApi defaultPayManager] pay:self.payRequestModel callback:^(IOAPayResponseModel *response) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        NSDictionary *userInfo = response.userInfo;
                        if (![userInfo[@"resultStatus"] isEqualToString:@"9000"]) {
                            //进入待付款界面(支付失败或者支付取消等)
                            [self pushWait];
                        }else{
                            //进入订单列表界面(支付成功)
                            [self pushList];
                        }
                    });
                }];
            }else{
                [self.view makeToast:@"支付失败"];
            }
        });
    }];
}

4.重磅来临(一些人弹框没有作出,可以直接拷贝下面代码)

新建控制器控制弹框.h文件中

#import <UIKit/UIKit.h>

#import "IOAPayApi.h"
#import "IOAPayItemModel.h"

@interface IOAPayViewController : UIViewController
//点击第几行回调声明
@property (nonatomic, copy) void (^clickCallback)(NSInteger atIndex);

+ (instancetype)show;
//block回调方法
+ (instancetype)show:(void (^)(NSInteger atIndex))clickCallback;
+ (void)dismiss;

- (void)setupItemTitles:(NSArray <NSString *>*)titles;
- (void)setupItems:(NSArray <IOAPayItemModel *>*)items;

- (void)setupTitle:(NSString *)title;
@end

实现其方法.m文件中

#import "IOAPayViewController.h"

#define PayCellHeight 50
#define PaySectionHeaderHeight 44

@interface IOAPayViewController () <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) CALayer *maskLayer;

@property (nonatomic, strong) UILabel *titleView;
@property (nonatomic, strong) UIView *payBgView;
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *dataSources;

@property (nonatomic, assign) CGFloat payViewHeight;

- (void)showPayView;
- (void)dismissPayView;
@end

@implementation IOAPayViewController

- (void)dealloc {

}

+ (instancetype)show {
    UIViewController *rootvc = [UIApplication sharedApplication].keyWindow.rootViewController;
    
    IOAPayViewController *vc = [IOAPayViewController new];
    [rootvc addChildViewController:vc];
    [rootvc.view addSubview:vc.view];
    
    [vc setupItemTitles:@[@"微信支付", @"支付宝支付", @"银联支付"]];
    [vc showPayView];
    return vc;
}

+ (instancetype)show:(void (^)(NSInteger atIndex))clickCallback {
    IOAPayViewController *vc = [self show];
    vc.clickCallback = clickCallback;
    
    return vc;
}

+ (void)dismiss {
    UIViewController *rootvc = [UIApplication sharedApplication].keyWindow.rootViewController;
    for (UIViewController *vc in rootvc.childViewControllers) {
        if ([vc isKindOfClass:[IOAPayViewController class]]) {
            IOAPayViewController *tempVC = (IOAPayViewController *)vc;
            [tempVC dismissPayView];
            return;
        }
    }
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor clearColor];
    
    self.maskLayer.frame = self.view.bounds;
    [self.view.layer addSublayer:self.maskLayer];
    
    [self.view addSubview:self.payBgView];
//    [self.view addSubview:self.tableView];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - UITableViewDataSource
- (NSInteger )numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.dataSources.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    id temp = self.dataSources[indexPath.row];
    if ([temp isKindOfClass:[NSString class]]) {
        cell.textLabel.text = temp;
    }
    else {
        IOAPayItemModel *item = temp;
        cell.textLabel.text = item.name;
    }
    cell.textLabel.font = [UIFont systemFontOfSize:18];
    cell.textLabel.textColor = RGB_HEXString(@"#323232");
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
    return cell;
}

#pragma mark - UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return PayCellHeight;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    return self.titleView;
}
- (CGFloat )tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return PaySectionHeaderHeight;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//    IOAPayRequestModel *payRequestModel = [IOAPayRequestModel new];
//    payRequestModel.payType = indexPath.row;
////    WS(weakSelf);
////    __weak typeof (self)weakSelf = self;
//    __block IOAPayViewController *payVC = self;
//    [[IOAPayApi defaultPayManager] pay:payRequestModel callback:^(IOAPayResponseModel *response) {
////        __strong __typeof (weakSelf)strongSelf = weakSelf;
//        response.payType = indexPath.row;
//        if (payVC.clickCallback) {
//            payVC.clickCallback(response);
//            payVC = nil;
//        }
//    }];
    
    if (self.clickCallback) {
        self.clickCallback(indexPath.row);
    }
    
    [self dismissPayView];
}

#pragma mark - Touches
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self dismissPayView];
}

#pragma mark - Public
- (void)setupItemTitles:(NSArray<NSString *> *)titles {
    if (!titles.count) {
        return ;
    }
    
    self.payViewHeight = titles.count * PayCellHeight + PaySectionHeaderHeight;
    CGRect frame = self.view.frame;
    frame.size.height = self.payViewHeight;
    self.tableView.frame = frame;
    
    [self.dataSources removeAllObjects];
    [self.dataSources addObjectsFromArray:titles];
    [self.tableView reloadData];
    
    [self setPayViewFrame];
}

- (void)setupItems:(NSArray <IOAPayItemModel *>*)items {
    if (!items.count) {
        return ;
    }
    
    for (IOAPayItemModel *item in items) {
        if ([item.code isEqualToString:@"appWeixinPay"]) {
            item.payType = 0;
            continue;
        }
        
        if ([item.code isEqualToString:@"alipayMobile"]) {
            item.payType = 1;
            continue;
        }
        
        if ([item.code isEqualToString:@"unionpay"]) {
            item.payType = 2;
            continue;
        }
        if ([item.code isEqualToString:@"ye"]) {
            item.payType = 3;
            continue;
        }
        item.payType = 3;
    }
    
    self.payViewHeight = items.count * PayCellHeight + PaySectionHeaderHeight;
    CGRect frame = self.view.frame;
    frame.size.height = self.payViewHeight;
    self.tableView.frame = frame;
    [self.dataSources removeAllObjects];
    [self.dataSources addObjectsFromArray:items];
    [self.tableView reloadData];
    [self setPayViewFrame];
}

- (void)setupTitle:(NSString *)title {
    self.titleView.text = title;
}

#pragma mark - Private
- (void)showPayView {
    [self.view.layer removeAllAnimations];
    CGFloat payBgViewHeight = self.payViewHeight + BottomHeightOffset;
    CGRect frame = self.view.frame;
    frame.origin.y = self.view.frame.origin.y + self.view.frame.size.height;
    frame.size.height = payBgViewHeight;
    self.payBgView.frame = frame;
    
    frame.origin.y = self.view.frame.size.height - payBgViewHeight;
    [UIView animateWithDuration:0.25 animations:^{
        self.payBgView.frame = frame;
    }];
}

- (void)setPayViewFrame {
    CGFloat payBgViewHeight = self.payViewHeight + BottomHeightOffset;
    CGRect frame = self.view.frame;
    frame.origin.y = self.view.frame.origin.y + self.view.frame.size.height;
    frame.size.height = payBgViewHeight;
    frame.origin.y = self.view.frame.size.height - payBgViewHeight;
    self.payBgView.frame = frame;
}

- (void)dismissPayView {
    CGFloat payBgViewHeight = self.payViewHeight + BottomHeightOffset;

    CGRect frame = self.view.frame;
    frame.origin.y = self.view.frame.origin.y + self.view.frame.size.height;
    frame.size.height = payBgViewHeight;
    
    [UIView animateWithDuration:0.25 animations:^{
        self.payBgView.frame = frame;
    } completion:^(BOOL finished) {
        [self.view removeFromSuperview];
        [self removeFromParentViewController];
    }];
}

#pragma mark - Setter / Getter
- (CALayer *)maskLayer {
    if (_maskLayer == nil) {
        _maskLayer = [CALayer layer];
        _maskLayer.backgroundColor = [UIColor blackColor].CGColor;
        _maskLayer.opacity = 0.2;
    }
    
    return _maskLayer;
}

- (UILabel *)titleView {
    if (!_titleView) {
        _titleView = [UILabel new];
        _titleView.textAlignment = NSTextAlignmentCenter;
        _titleView.text = @"请选择支付方式";
        _titleView.font = [UIFont systemFontOfSize:16];
        _titleView.textColor = [UIColor blackColor];
        _titleView.backgroundColor = RGB_HEXString(@"#f2f2f2");//[UIColor whiteColor];
    }
    
    return _titleView;
}

- (UIView *)payBgView {
    if (!_payBgView) {
        _payBgView = [UIView new];
        _payBgView.backgroundColor = [UIColor whiteColor];
        [_payBgView addSubview:self.tableView];
    }
    return _payBgView;
}

- (UITableView *)tableView{
    if (!_tableView) {
        _tableView = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStylePlain];
        _tableView.delegate = self;
        _tableView.dataSource = self;
        _tableView.showsVerticalScrollIndicator = NO;
        _tableView.showsHorizontalScrollIndicator = NO;
        _tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
        _tableView.separatorColor = RGB_HEXString(@"#f2f2f2");
        if ([_tableView respondsToSelector:@selector(setSeparatorInset:)]) {
            [_tableView setSeparatorInset:UIEdgeInsetsZero];
        }
        if ([_tableView respondsToSelector:@selector(setLayoutMargins:)]) {
            [_tableView setLayoutMargins:UIEdgeInsetsZero];
        }
        
        //
        [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
    }
    return _tableView;
}

- (NSMutableArray *)dataSources {
    if (!_dataSources) {
        _dataSources = [NSMutableArray array];
    }
    return _dataSources;
}

- (void)setPayViewHeight:(CGFloat)payViewHeight {
    _payViewHeight = payViewHeight;
    CGFloat height = self.view.frame.size.height * 0.6;
    self.tableView.scrollEnabled = NO;
    以上是关于iOS支付宝,微信,银联支付集成封装调用(下)的主要内容,如果未能解决你的问题,请参考以下文章

支付sdk —— 该组件为封装了 微信,支付宝,银联支付

iOS开发支付集成之微信支付

iOS开发之支付宝集成

iOS开发之支付宝集成

iOS之支付

iOS支付宝支付详细实现流程