iOS-OC-内购In-App Purchases

公司项目要做会员功能,支付方式我采用的是内购In-App Purchases。说实话,我真的不想用苹果的内购功能,不说苹果要收百分之三十的手续费,就说它那么多的坑,我是真的不想往里面跳啊,但公司担心用支付宝、微信支付等方式苹果不让上架,做个开关的话又怕突然下架、甚至封掉开发者帐号。所以,这个坑我就只有跳了, 俗话说:我不入地狱,谁入地狱???!!!


话不多说,开始!
itunes connect里面的就不说了,我只说程序里面的代码部分。


  1. 首先要导入StoreKit.framework。引用 #import
{
        BOOL      startBuyAppleProduct;
}
  1. 添加监听,这个最好写在- (void)viewDidLoad { }中。
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
  1. 当点某一个按钮的时候先去检测用户是否打开手机内购功能,如果打开了就执行requestProductData:方法请求商品数据,否则提示用户。ProductID是在itunes connect中设置的产品ID。
  - (void)performPayFunctionOnIos
{
    if([SKPaymentQueue canMakePayments]){
        [self requestProductData:ProductID]; 
    }else{
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"您的手机没有打开内购功能" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
        [alert addAction:cancel];
        [self presentViewController:alert animated:YES completion:nil];
       }
}
  1. 添加产品ID,设置代理并发起请求。请求是从的苹果的服务器请求产品的数据.

    - (void)requestProductData:(NSString*)productString{
      startBuyAppleProduct = YES; //这里把它设为YES,表明是你发起的请求。
      NSArray*product = [[NSArray alloc] initWithObjects:productString,nil];
      NSSet*nsset = [NSSet setWithArray:product];
      SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
      request.delegate=self;
      [request start];
    }
    
  2. 添加代理方法
  - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
      NSArray*product = response.products;
      if([product count] ==0){
        NSLog(@"没有商品");
        return;
      }
      SKProduct *p = nil;
      for (SKProduct *pro in product) {
        if ([pro.productIdentifier isEqualToString:ProductID]) {
            p = pro;
        }
    }
      SKPayment *payment = [SKPayment paymentWithProduct:p];
      [[SKPaymentQueue defaultQueue] addPayment:payment];
}

  - (void)request:(SKRequest*)request didFailWithError:(NSError*)error {
        NSLog(@"商品信息请求错误:%@", error);  
  }  

    - (void)requestDidFinish:(SKRequest*)request {
        NSLog(@"请求结束"); 
    }
  1. 添加监听方法

    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction {
                  for(SKPaymentTransaction *tran in transaction){  
    
        switch(tran.transactionState) {
    
        case SKPaymentTransactionStatePurchased:
            // 这里要用最开始就定义的BOOL值startBuyAppleProduct来判断下是否是你本次发起的内购,
               不是就跳过验证。
            不知道为什么每次进这个控制器,它就会走这个监听方法,不在其它的case里判断是因为其它的并没有做什么逻辑处理。
            if (startBuyAppleProduct) {
                [self verifyFinishedTransaction:tran]; 
            }
            [self restoreTransaction:tran];
            NSLog(@"交易完成");
            break;
    
        case SKPaymentTransactionStatePurchasing:
            NSLog(@"商品添加进列表");
            break;
    
        case SKPaymentTransactionStateRestored:
            NSLog(@"已经购买过商品");
            [self restoreTransaction:tran];
            break;
    
        case SKPaymentTransactionStateFailed:
            NSLog(@"交易失败");
            [self restoreTransaction:tran];
            break;
    
        default:
            NSLog(@"other");
            [self restoreTransaction:tran];
            break;      
        }
      }
        }
    

  - (void)restoreTransaction:(SKPaymentTransaction *)transaction {
    //  取消订单,或者说是恢复订单
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    // 每次都要把startBuyAppleProduct设置为NO,不然购买成功就不会验证
     startBuyAppleProduct = NO;  
  }
// 验证
        - (void)verifyFinishedTransaction:(SKPaymentTransaction *)transaction {
             if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
                NSString * productIdentifier = transaction.payment.productIdentifier;
                NSLog(@"%@",transaction.transactionIdentifier);
                NSString *receipt = [[NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL] ] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
             if ([productIdentifier length] > 0) {
                // 向自己的服务器验证购买凭证,用post的方式把receipt传给服务器就可以了。

              }
            }
        }

因为苹果审核的时候是用的测试服务器, 但我们又不知道它的审核什么时间通过,所以最好先验证苹果的测试服务器,如果返回的是21007,再向正式的服务器发起验证。
测试服务器验证链接
https://sandbox.itunes.apple.com/verifyReceipt
正式服务器验证链接
https://buy.itunes.apple.com/verifyReceipt
验证返回的数据其中status为0,也就是”status”:0时就是验证成功了。这个要记住!记住!记住!并不是非零即真!这里零才是真!!!
7. 最后就是移除监听。

    -(void)dealloc{
       [[SKPaymentQueue defaultQueue]  removeTransactionObserver:self];
    }

看嘛,这就弄完了, 应该没有什么问题,我们就假如没有问题。������
希望能给各位一点帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值