iOS-StoreKit V1(Original API for In-App Purchase)代码接入

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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值