这次遇到的问题主要有两点

1.税收那一块没有填好一些东西,这样会导致 在代码里面调用SDK 没有办法返回 预先创建好的商品类。

2.进行付款时候 将记录进行本地存储。服务端也做这样的处理。 (毕竟这个是涉及到钱,谨慎一点好)


假设 我选择的product_id : com.mytest.xixi

这个id 是在 itunesconnect 设置好


首先要 假如通知,通知是一对的


-(void)dealloc
{
    //解除监听的通知
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    //假如监听的通知
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    //假如这里是选择了product_id = @"com.mytest.xixi";
    selectProductID = @"com.mytest.xixi";
    [self doIAPAction:selectProductID];
}


首先要判断是否能够可以使用IAP, 发起请求向苹果询问是否有哪些商品可售


- (void)doIAPAction:(NSString *)selectArg
{
    if([SKPaymentQueue canMakePayments])
    {
        [self requestProductData:selectArg];
    }
    else
    {
        NSLog(@"不允许程序内付费");
    }
}

//请求商品
- (void)requestProductData:(NSString *)selectArg
{
    NSLog(@"-------------请求对应的产品信息----------------");
    NSArray *product = [[NSArray alloc] initWithObjects:selectArg,
                                                        nil];
    
    NSSet *nsset = [NSSet setWithArray:product];
    self.request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
    self.request.delegate = self;
    [self.request start];
    
}



有网络请求 那么肯定会有成功或者失败,下面这几个都是代理里面可以找到


//收到产品返回信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    
    NSLog(@"--------------收到产品反馈消息---------------------");
    NSArray *product = response.products;
    if([product count] == 0)
    {
        NSLog(@"--------------没有商品------------------");
        return;
    }
    
    NSLog(@"productID:%@", response.invalidProductIdentifiers);
    NSLog(@"产品付费数量:%ld",(long)[product count]);
    
    SKProduct *p = nil;
    for (SKProduct *pro in product)
    {
        NSLog(@"%@", [pro description]);
        NSLog(@"%@", [pro localizedTitle]);
        NSLog(@"%@", [pro localizedDescription]);
        NSLog(@"%@", [pro price]);
        NSLog(@"%@", [pro productIdentifier]);
        
        if([pro.productIdentifier isEqualToString:selectProductID])
        {
            p = pro;
        }
    }
    
    SKPayment *payment = [SKPayment paymentWithProduct:p];
    
    NSLog(@"发送购买请求");
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}



//请求失败
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
    NSLog(@"------------------错误-----------------:%@", error);
}

- (void)requestDidFinish:(SKRequest *)request
{
    NSLog(@"------------反馈信息结束-----------------");
}


//监听购买结果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction
{
    for(SKPaymentTransaction *tran in transaction)
    {
        
        switch (tran.transactionState)
        {
            case SKPaymentTransactionStatePurchased:
                NSLog(@"交易完成");
                [self completeTransaction:tran];
                
                break;
            case SKPaymentTransactionStatePurchasing:
                NSLog(@"商品添加进列表");
                
                break;
            case SKPaymentTransactionStateRestored:
                NSLog(@"已经购买过商品");
                
                break;
            case SKPaymentTransactionStateFailed:
                NSLog(@"交易失败");
                NSLog(@"%@",tran);
                [self failedTransaction:tran];
                
                break;
            default:
                break;
        }
    }
}

//交易结束
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
    NSLog(@"交易结束");
    
    
    // Your application should implement these two methods.
    NSString * productIdentifier = transaction.payment.productIdentifier;
    if ([productIdentifier length] > 0)
    {
        // 向自己的服务器验证购买凭证
        [self verifyPruchase:transaction];
    }
    // Remove the transaction from the payment queue.
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}




- (void)failedTransaction:(SKPaymentTransaction *)transaction
{
    HIDE_PROGRESS(self.view);
    if(transaction.error.code != SKErrorPaymentCancelled)
    {
        NSLog(@"购买失败");
    }
    else
    {
        NSLog(@"用户取消交易");
    }
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

#pragma mark 验证购买凭据
- (void)verifyPruchase:(SKPaymentTransaction *)transaction
{
    // 验证凭据,获取到苹果返回的交易凭据
    // appStoreReceiptURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    // 从沙盒中获取到购买凭据
    NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
    
    NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    
    
    NSString *transId = transaction.transactionIdentifier;
    NSString *productId = transaction.payment.productIdentifier;
    
    if (!encodeStr)
    {
        return;
    }
    
    //下面开始描述处理的逻辑
    /*
     * 1.首先将这些数据(encodeStr,productId,transId,...)进行加密什么的 存储在本地数据库
     * 2.然后将 这些数据 传到服务端 让服务端 跟apple 进行一次验证(也有人放在客户端代码里面进行验证),服务端接收到这些数据最好也是存储一下
     * 3.服务端和apple验证成功之后返回告诉客户端通过之后,客户端这边就把本地数据库存储的相关数据给删掉,服务端也删。(两边都做处理保证一下,毕竟涉及到金钱)
     * 4.这就完成一个正常的流程。(我自己个人认为)
     *
     * 3.1 也会出现这种情况 可能服务端和apple 验证的时候 时间太久了导致超时,那么在客户端要做点处理,可以选择在打开app的时候把数据库的存储的数据找出来重新进行一下验证,或者做一个定时器什么的 多久就扫一下数据库 是否有数据要重新验证。
     */
}