美文网首页
苹果内购

苹果内购

作者: 云天涯丶 | 来源:发表于2018-05-16 18:03 被阅读20次

    先附上一篇介绍怎么填写协议、税务和银行业务的文章

    本文主要介绍内购代码部分

    首先导入StoreKit/StoreKit.h,再遵循两个代理SKPaymentTransactionObserver,SKProductsRequestDelegate

    .h文件

    @interface ApplePayManager : NSObject
    
    + (instancetype)sharedApplePayManager;
    
    // 创建订单号
    - (void)createPayOrderWithOrderModel:(OrderPayModel *)orderModel;
    
    @end
    

    .m文件

    @interface ApplePayManager ()<SKPaymentTransactionObserver,SKProductsRequestDelegate>
    
    @property (nonatomic,strong) OrderPayModel *orderModel;
    @property (nonatomic,copy) NSString *productId;
    @property (nonatomic,strong) PayModel *payModel;// 充值信息
    
    @end
    
    @implementation ApplePayManager
    
    + (instancetype)sharedApplePayManager{
        static ApplePayManager *manager = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            manager = [[self alloc] init];
            //添加一个交易队列观察者
            [[SKPaymentQueue defaultQueue] addTransactionObserver:manager];
        });
        return manager;
    }
    
    - (void)createPayOrderWithOrderModel:(OrderPayModel *)orderModel{
        // 该方法里是请求支付的一些信息
        // ...
        [self gotoApplePayWithProductId:@"对应的内购项目id"];
    }
    
    
    // 去购买
    - (void)gotoApplePayWithProductId:(NSString *)productId{
        
        if([SKPaymentQueue canMakePayments]){
            self.productId = productId;
            [self requestProductData:self.productId];
        }else{
            [APP_WIN makeToast:@"您的设备不支持苹果支付" duration:2 position:CSToastPositionCenter];
        }
    }
    
    //去苹果服务器请求商品
    - (void)requestProductData:(NSString *)productId{
        // 加载
        [GMBProgressHUD showHUDAddedTo:APP_WIN animated:YES];
        
        NSArray *product = [[NSArray alloc] initWithObjects:productId,nil];
        NSSet *nsset = [NSSet setWithArray:product];
        SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
        request.delegate = self;
        [request start];
        
    }
    
    #pragma mark -- SKProductsRequestDelegate
    
    - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
        NSArray *productArr = response.products;
        if (productArr.count == 0) {
            [GMBProgressHUD hideHUDForView:APP_WIN animated:YES];
            [APP_WIN makeToast:@"该商品已下架" duration:2 position:CSToastPositionCenter];
            return;
        }
        
        SKProduct *skPro = nil;
        for (SKProduct *pro in productArr) {
            if ([pro.productIdentifier isEqualToString:self.productId]) {
                skPro = pro;
            }
        }
        if (!skPro) {
            [APP_WIN makeToast:@"没有该商品" duration:2 position:CSToastPositionCenter];
            return;
        }
        SKPayment *payment = [SKPayment paymentWithProduct:skPro];
        //发送内购请求
        [[SKPaymentQueue defaultQueue] addPayment:payment];
        
        
    }
    
    #pragma mark -- SKRequestDelegate
    
    - (void)requestDidFinish:(SKRequest *)request {
        [GMBProgressHUD hideHUDForView:APP_WIN animated:YES];
    }
    
    - (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
        [APP_WIN makeToast:@"支付失败" duration:2 position:CSToastPositionCenter];
    }
    
    #pragma mark -- SKPaymentTransactionObserver
    
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {
        
        for (SKPaymentTransaction *tran in transactions) {
            switch (tran.transactionState) {
                case SKPaymentTransactionStatePurchased: //交易完成
                    // 发送到苹果服务器验证凭证
                    GLog(@"交易完成");
                    [self verifyPurchaseWithPaymentTrasactionWithSandBox:NO];
                    [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                    break;
                case SKPaymentTransactionStatePurchasing: //商品添加进列表
                    GLog(@"商品添加进列表");
                    break;
                case SKPaymentTransactionStateRestored: //购买过
                    GLog(@"购买过");
                    [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                    break;
                case SKPaymentTransactionStateFailed: //交易失败
                    GLog(@"交易失败");
                    [[SKPaymentQueue defaultQueue] finishTransaction:tran];
                    [APP_WIN makeToast:@"购买失败" duration:2 position:CSToastPositionCenter];
                    break;
                default:
                    break;
            }
        }
    }
    
    /*
     * 发送到苹果服务器验证凭证
     */
    
    // 二次验证(沙盒还是正式环境)
    - (void)verifyPurchaseWithPaymentTrasactionWithSandBox:(BOOL)sandBox{
        
        // 验证凭据,获取到苹果返回的交易凭据
        // appStoreReceiptURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址
        NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
        // 从沙盒中获取到购买凭据
        NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
        if (!receiptData) {
            GLog(@"没有数据");
        }
        // 发送网络POST请求,对购买凭据进行验证
        //测试验证地址:https://sandbox.itunes.apple.com/verifyReceipt
        //正式验证地址:https://buy.itunes.apple.com/verifyReceipt
        
        NSString *url;
        if (sandBox == YES) {
            url = @"https://sandbox.itunes.apple.com/verifyReceipt";
        } else {
            url = @"https://buy.itunes.apple.com/verifyReceipt";
        }
        
        // 根据苹果官方文档来操作 https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html
    
        NSDictionary *requestContents = @{@"receipt-data":[receiptData base64EncodedStringWithOptions:0]};
        NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents options:0 error:nil];
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
        request.HTTPMethod = @"POST";
        request.HTTPBody = requestData;
        NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            
            dispatch_async(dispatch_get_main_queue(), ^{
                if (error) {
                    [APP_WIN makeToast:error.domain duration:2 position:CSToastPositionCenter];
                } else {
                    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
                    GLog(@"%@",dict);
                    if ([dict[@"status"] isEqual:@0]) {// 正确
                        // 发数据给自己公司后台
                        [self checkPayment];
    
                    } else if([dict[@"status"] isEqual:@21007]){// 此收据来自测试环境,但已发送至生产环境进行验证。切换环境
                        [self verifyPurchaseWithPaymentTrasactionWithSandBox:YES];
                    }
                }
            });
    
        }];
        
        [dataTask resume];
        
    }
    
    
    @end
    
    

    错误集:
    1、刚开始没用单利,在dealloc里[[SKPaymentQueue defaultQueue] removeTransactionObserver:self],导致代理不走
    2、发送到苹果服务器验证凭证出现21002,后来按照官方文档操作成功

    相关文章

      网友评论

          本文标题:苹果内购

          本文链接:https://www.haomeiwen.com/subject/fskmdftx.html