一句话集成微信支付,支付宝支付以及内购
可以在github上下载的工具类
如何使用
1.将工具类拖入工程
2.AppDelegate代码如下:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { return [[XNPayManager sharedPayManager] handleOpenURL:url]; }// NOTE: 9.0以后使用新API接口- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options { return [[XNPayManager sharedPayManager] handleOpenURL:url]; }
3.在使用的地方调起微信或者支付宝
支付宝
TIPS:拼装参数应在商户服务端完成,商户服务端直接将组装和签名后的请求串orderString传给客户端,客户端直接传给SDK发起请求。文档和Demo是为了示例效果在客户端实现。所以我们项目中应该按照次操作
// params应该是由后台返回的 [[XNPayManager sharedPayManager] ALIPayWithPayParams: params success:^(PayCode code) { // 成功业务逻辑 DLog(@"成功"); } failure:^(PayCode code) { // 失败业务逻辑 DLog(@"失败"); }]
微信支付
// dict应该是由后台返回的 [[XNPayManager sharedPayManager] WXPayWithPayDict: dict success:^(PayCode code) { // 成功业务逻辑 DLog(@"成功"); } failure:^(PayCode code) { // 失败业务逻辑 DLog(@"成功"); }];
内购
//productId 产品唯一标示 [[XNPayManager sharedPayManager] requestProductData: productId success:^(PayCode code) { // 成功业务逻辑 } failure:^(PayCode code) { // 失败业务逻辑 }];
详细代码
在封装的代码中没有使用通知,因为通知是全局的,然后在项目中出现了一下问题,比如:待支付订单->订单详情 这两个页面都有支付的操作.如果使用通知:这两个控制器支付成功\失败的业务逻辑就会冲突
1.声明支付单例
+ (instancetype)sharedPayManager { static dispatch_once_t onceToken; static XNPayManager *instance; dispatch_once(&onceToken, ^{ instance = [[XNPayManager alloc] init]; }); return instance; }
2.自定义支付状态码,其实也可以不用定义
/** 支付状态码 */typedef NS_ENUM(NSInteger, PayCode) { WXSUCESS = 1001, /**成功*/ WXERROR = 1002, /**失败*/ WXSCANCEL = 1003, /**取消*/ ALIPAYSUCESS = 1101, /**支付宝支付成功*/ ALIPAYERROR = 1102, /**支付宝支付错误*/ ALIPAYCANCEL = 1103, /**支付宝支付取消*/ APPSTOREPAYSUCESS = 1201, /**内购支付成功*/ APPSTOREPAYERROR = 1201, /**内购支付成功*/ APPSTOREPAYCANCEL = 1201, /**内购支付成功*/};
3.微信支付
/** 微信支付 @param dict 微信订单字典(全部由后台拼接好给iOS端) @param successBlock 成功的回调 @param failBolck 失败的回调 */- (void)WXPayWithPayDict:(NSDictionary *)dict success:(void(^)(PayCode code)) successBlock failure:(void(^)(PayCode code)) failBolck { self.successBlock = successBlock; self.failBolck = failBolck; NSString *strMsg = nil; //1. 判断是否安装微信 if (![WXApi isWXAppInstalled]) { NSLog(@"您尚未安装\"微信App\",请先安装后再返回支付"); strMsg = @"您尚未安装\"微信App\",请先安装后再返回支付"; [self tipMessageAlert:nil message:strMsg]; return; } //2.判断微信的版本是否支持最新Api if (![WXApi isWXAppInstalled]) { NSLog(@"您微信当前版本不支持此功能,请先升级微信应用"); strMsg = @"您微信当前版本不支持此功能,请先升级微信应用"; [self tipMessageAlert:nil message:strMsg]; return; } if (!kDictIsEmpty(dict)) { //调起微信支付 PayReq *req = [[PayReq alloc]init]; req.openID = dict[@"appid"]; req.partnerId = dict[@"partnerid"]; req.prepayId = dict[@"prepayid"]; req.nonceStr = dict[@"noncestr"]; req.timeStamp = [dict[@"timestamp"] intValue]; req.package = @"Sign=WXPay"; req.sign = dict[@"sign"]; [WXApi sendReq:req]; } }#pragma mark - WXApiDelegate//支付结果回调/// - see [支付结果回调](https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5)- (void)onResp:(BaseResp *)resp { NSString *strMsg = [NSString stringWithFormat:@"errcode:%d",resp.errCode]; //回调中errCode值列表: // 0 成功 展示成功页面 //-1 错误 可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等 //-2 用户取消 无需处理。发生场景:用户不支付了,点击取消,返回APP if ([resp isKindOfClass:[PayResp class]]) { // 支付返回结果,实际支付结果需要去微信服务器端查询 switch (resp.errCode) { case WXSuccess:{ strMsg = @"支付结果:成功!"; self.successBlock(WXSUCESS); DLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode); break; } case WXErrCodeUserCancel:{ strMsg = @"支付结果:取消"; self.failBolck(WXSCANCEL); DLog(@"支付取消-PayCancel,retcode = %d", resp.errCode); } default:{ strMsg = @"支付结果:失败"; self.failBolck(WXERROR); DLog(@"错误,retcode = %d, retstr = %@", resp.errCode,resp.errStr); break; } } [self tipMessageAlert:@"支付结果" message:strMsg]; } }
4.支付宝
/** 支付宝支付 @param params 支付宝支付参数(全部由后台拼接好给iOS端) @param successBlock 成功的回调 @param failBolck 失败的回调 */- (void)ALIPayWithPayParams:(NSString *)params success:(void(^)(PayCode code)) successBlock failure:(void(^)(PayCode code)) failBolck { self.successBlock = successBlock; self.failBolck = failBolck; NSString *appScheme = @"appScheme"; [[AlipaySDK defaultService] payOrder:params fromScheme:appScheme callback:^(NSDictionary *resultDic) { DLog(@"我这里是payVC%@",resultDic); DLog(@"%@",resultDic[@"memo"]); [self aliPayResult:resultDic]; }]; }#pragma mark - 支付宝支付结果处理- (void)aliPayResult:(NSDictionary *)resultDic { // 返回结果需要通过 resultStatus 以及 result 字段的值来综合判断并确定支付结果。 在 resultStatus=9000,并且 success="true"以及 sign="xxx"校验通过的情况下,证明支付成功。其它情况归为失败。较低安全级别的场合,也可以只通过检查 resultStatus 以及 success="true"来判定支付结果 NSInteger resultStatus = [resultDic[@"resultStatus"] integerValue]; if (resultDic && [resultDic objectForKey:@"resultStatus"]) { switch (resultStatus) { case 9000: [self tipMessageAlert:@"支付结果" message:@"订单支付成功"]; self.successBlock(ALIPAYSUCESS); break; case 8000: [self tipMessageAlert:@"支付结果" message:@"正在处理中"]; self.failBolck(ALIPAYERROR); break; case 4000: [self tipMessageAlert:@"支付结果" message:@"订单支付失败,请稍后再试"]; self.failBolck(ALIPAYERROR); break; case 6001: [self tipMessageAlert:@"支付结果" message:@"已取消支付"]; self.failBolck(ALIPAYCANCEL); break; case 6002: [self tipMessageAlert:@"支付结果" message:@"网络连接错误,请稍后再试"]; self.failBolck(ALIPAYERROR); break; default: break; } } }
5.内购
/** 内购 @param productId productId @param successBlock 成功的回调 @param failBolck 失败的回调 */- (void)requestProductData:(NSString *)productId success:(void(^)(PayCode code)) successBlock failure:(void(^)(PayCode code)) failBolck { if ([SKPaymentQueue canMakePayments]) { self.successBlock = successBlock; self.failBolck = failBolck; // 最好设置上 MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:kKeyWindow animated:YES]; hud.labelText = @"正在购买,请勿离开..."; hud.dimBackground = YES; self.productId = productId; NSArray *productArr = [[NSArray alloc]initWithObjects:productId, nil]; NSSet *productSet = [NSSet setWithArray:productArr]; SKProductsRequest *request = [[SKProductsRequest alloc]initWithProductIdentifiers:productSet]; request.delegate = self; [request start]; }else{ DLog(@"不允许程序内付费"); } }#pragma mark - SKProductsRequestDelegate// 收到产品返回信息- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { NSArray *productArr = response.products; if ([productArr count] == 0) { DLog(@"没有该商品"); [MBProgressHUD hideAllHUDsForView:kKeyWindow animated:YES]; return; } DLog(@"productId = %@",response.invalidProductIdentifiers); DLog(@"产品付费数量 = %zd",productArr.count); SKProduct *p = nil; for (SKProduct *pro in productArr) { DLog(@"description:%@",[pro description]); DLog(@"localizedTitle:%@",[pro localizedTitle]); DLog(@"localizedDescription:%@",[pro localizedDescription]); DLog(@"price:%@",[pro price]); DLog(@"productIdentifier:%@",[pro productIdentifier]); if ([pro.productIdentifier isEqualToString:self.productId]) { p = pro; } } SKPayment *payment = [SKPayment paymentWithProduct:p]; //发送内购请求 [[SKPaymentQueue defaultQueue] addPayment:payment]; }#pragma mark - SKRequestDelegate- (void)requestDidFinish:(SKRequest *)request { DLog(@"获取产品成功");// [MBProgressHUD hideHUDForView:kKeyWindow animated:YES]; } - (void)request:(SKRequest *)request didFailWithError:(NSError *)error { [MBProgressHUD hideHUDForView:kKeyWindow animated:YES]; MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:kKeyWindow animated:YES]; hud.labelText = @"购买失败"; hud.mode = MBProgressHUDModeText; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [MBProgressHUD hideHUDForView:kKeyWindow animated:YES]; }); }// 监听购买结果//SKPaymentTransactionObserver- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions { for (SKPaymentTransaction *tran in transactions) { switch (tran.transactionState) { case SKPaymentTransactionStatePurchased: //交易完成 [self completeTransaction:tran]; // Remove the transaction from the payment queue. [[SKPaymentQueue defaultQueue] finishTransaction: tran]; break; case SKPaymentTransactionStatePurchasing: //商品添加进列表 break; case SKPaymentTransactionStateRestored: //购买过 [self restoreTransaction:tran]; break; case SKPaymentTransactionStateFailed: //交易失败 [self failedTransaction:tran]; // Remove the transaction from the payment queue. [[SKPaymentQueue defaultQueue] finishTransaction: tran]; break; default: break; } } } - (void)completeTransaction:(SKPaymentTransaction *)transaction { NSString * productIdentifier = transaction.payment.productIdentifier; DLog(@"productIdentifier Product id:%@", productIdentifier); NSString *transactionReceiptString= nil; //系统IOS7.0以上获取支付验证凭证的方式应该改变,切验证返回的数据结构也不一样了。 // 验证凭据,获取到苹果返回的交易凭据 // appStoreReceiptURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址 NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL]; NSData * receiptData = [NSData dataWithContentsOfURL:receiptUrl]; transactionReceiptString = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; DLog(@"transactionReceiptString == %@",transactionReceiptString); if ([productIdentifier length] > 0) { self.hud.labelText = @"正在验证,请勿离开..."; // 请求自己的服务器去验证用户购买结果 // 往后台验证,只有服务器有反应就hide [MBProgressHUD hideAllHUDsForView:kKeyWindow animated:YES]; } } - (void)failedTransaction:(SKPaymentTransaction *)transaction { if(transaction.error.code != SKErrorPaymentCancelled) { DLog(@"购买失败"); self.failBolck(APPSTOREPAYCANCEL); } else { DLog(@"用户取消交易"); self.failBolck(APPSTOREPAYCANCEL); } [MBProgressHUD hideHUDForView:kKeyWindow animated:YES]; [SMGlobalMethod showViewCenter:kKeyWindow.center longMessage:@"购买失败"]; } - (void)restoreTransaction:(SKPaymentTransaction *)transaction { // 对于已购商品,处理恢复购买的逻辑 [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; }
6.单例回调
#pragma mark - 单例类回调- (BOOL)handleOpenURL:(NSURL *)url { if ([url.host isEqualToString:@"safepay"]) { //跳转支付宝钱包进行支付,处理支付结果 [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) { DLog(@"result = %@",resultDic); DLog(@"openURL : 支付宝回调 : result = %@",resultDic); [self aliPayResult:resultDic]; }]; // 授权跳转支付宝钱包进行支付,处理支付结果 [[AlipaySDK defaultService] processAuth_V2Result:url standbyCallback:^(NSDictionary *resultDic) { NSLog(@"result = %@",resultDic); // 解析 auth code NSString *result = resultDic[@"result"]; NSString *authCode = nil; if (result.length>0) { NSArray *resultArr = [result componentsSeparatedByString:@"&"]; for (NSString *subResult in resultArr) { if (subResult.length > 10 && [subResult hasPrefix:@"auth_code="]) { authCode = [subResult substringFromIndex:10]; break; } } } DLog(@"授权结果 authCode = %@", authCode?:@""); }]; return [url.host isEqualToString:@"safepay"]; } else { return [WXApi handleOpenURL:url delegate:self]; } }
作者:看我的大白眼
链接:https://www.jianshu.com/p/4e03b45e687a
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦