1、前言
本文章单纯的直接的肝代码,简洁明了的快速接入支付流程,代码流程仅供参考,可根据需求处理调整
2、流程图
3、代码
3.1 添加支付监听
/// 添加TransactionObserver
- (void)addIAPTransactionObserver {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}
- (void)dealloc { //解除监听
[self removeIAPTransactionObserver];
}
/// 移除TransactionObserver
- (void)removeIAPTransactionObserver {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
3.2 查询商品
//查询商品
- (void)queryProductInfo:(NSArray <NSString *> *)productIdArray {
NSSet *nsset = [NSSet setWithArray:productIdArray]; //productIdArray是商品id数组
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
request.delegate = self;
[request start];
}
/// SKProductsRequestDelegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
for(SKProduct *product in response.products){
if (![self.productArray containsObject:product]) {
[self.productArray addObject:product];
}
}
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
NSLog(@"%s",[error localizedDescription]);
}
3.3 支付
//app是否可支付
- (BOOL)canPay {
return [SKPaymentQueue canMakePayments];
}
/// 发起支付
- (void)launchPay:(NSString *)data orderId:(NSString *)orderId{
[SVProgressHUD show];
if (canPay) {
NSLog(@"start buy");
// populate UI
SKProduct *currentProduct = nil;
for(SKProduct *product in self.productArray){
if ([product.productIdentifier isEqualToString:self.currentID]) {
currentProduct = product;
break;
}
}
if (!currentProduct) {
[SVProgressHUD dismiss];
//支付失败
NSLog(@"No product information, please check the product list");
return;
}
NSLog(@"add payment to queue");
SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:currentProduct];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
else {
[SVProgressHUD dismiss];
//支付失败
NSLog(@"In program purchase is not allowed");
}
}
// SKPaymentTransactionObserver 监听购买结果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
NSLog(@"updatedTransactions");
for (SKPaymentTransaction *transaction in transactions) {
NSString *transationId = transaction.transactionIdentifier;
NSLog(@"transationId:%@", transationId);
NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
BOOL sanbox = [[[receiptUrl absoluteString] lowercaseString] containsString:@"sandbox"];
//可利用是否沙盒做自己的业务逻辑
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased: { //交易完成
NSLog(@"SKPaymentTransactionStatePurchased");
[self iapVerifyTransaction:transaction];
}
break;
case SKPaymentTransactionStateFailed: { //交易失败
//支付失败
NSLog(@"SKPaymentTransactionStateFailed");
[SVProgressHUD dismiss];
IAPErrorType type = transaction.error.code == SKErrorPaymentCancelled ? IAPErrorTypePurchaseCancled : IAPErrorTypePurchaseFailed; //判断失败类型
}
break;
case SKPaymentTransactionStateRestored: {//已经购买过该商品(非消耗性型)
NSLog(@"SKPaymentTransactionStateRestored");
[SVProgressHUD dismiss];
[self finishTransaction:transaction];
}
break;
case SKPaymentTransactionStatePurchasing: { //商品添加进列表
NSLog(@"SKPaymentTransactionStatePurchasing");
}
break;
default:
break;
}
}
}
/// 结束交易
- (void)finishTransaction:(SKPaymentTransaction *)transaction {
NSLog(@"finishTransaction: %@",transaction.transactionIdentifier);
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
3.4 验单
/// 校验交易
- (void)iapVerifyTransaction:(SKPaymentTransaction *)transaction{
//App Store验证:获取票据
NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];
NSString *receiptStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
BOOL sanbox = [[[receiptUrl absoluteString] lowercaseString] containsString:@"sandbox"];
if (receiptStr.length == 0) { //票据为空,刷新票据
[SVProgressHUD dismiss];
SKReceiptRefreshRequest *request = [[SKReceiptRefreshRequest alloc] init];
request.delegate = self;
[request start];
//回调验单失败
return;
}
// 服务器验证.......验单成功结束交易
//本地验单例子
NSURL *url = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];
if (sanbox) {
url = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];
}else{
url = [NSURL URLWithString: @"https://buy.itunes.apple.com/verifyReceipt"];
}
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0f];
NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:payloadData];
[request setHTTPMethod:@"POST"];
NSLog(@"ApplePayverification local:%@", url.absoluteString);
// __weak typeof(self) weakSelf = self;
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
[SVProgressHUD dismiss];
if (error) {
//验单失败,重试3次
NSLog(@"ApplePayverification local, error:%@",error.localizedDescription);
return;
}
[self finishTransaction:transaction];
NSDictionary *responseDic;
if (data) {
responseDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
}
NSString *jsonStr = responseDic.mj_JSONString;
NSLog(@"ApplePayverification request response:%@",jsonStr);
if(responseDic != nil) {
BOOL isSuccess = [[responseDic objectForKey:@"status"] intValue] == 0;
NSLog(@"ApplePayverification local success:%d \ndetail:%@", isSuccess, responseDic);
}
}];
[task resume];
}
3.5 掉单
/// 队列中未完成的交易
- (BOOL)checkPayQueueIncompleteTransaction {
NSArray *transactions = [SKPaymentQueue defaultQueue].transactions;
if (transactions.count > 0) {
SKPaymentTransaction* transaction = [transactions firstObject];
if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
[self iapVerifyTransaction:transaction];
return YES;
}
}
return NO;
}
3.6 恢复购买
/// 查看已购买的产品 (非消耗)
- (void)restoreCompletedTransactions {
[SVProgressHUD show];
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
// Sent when all transactions from the user's purchase history have successfully been added back to the queue.
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
[SVProgressHUD dismiss];
NSMutableArray<SKPaymentTransaction *> *transactionArray = [NSMutableArray new];
NSLog(@"%@",transactionArray);
}
// Sent when all transactions from the user's purchase history have successfully been added back to the queue.
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error{
NSLog(@"%@",[error localizedDescription]);
[SVProgressHUD dismiss];
}
4、总结
本文章就讲到这里,欢迎大家批评指正,共同交流,后续还会讲StoreKit V2。