IOS客户端内购(IAP)简单总结

近期需要用到所以稍微研究,整理了一下,囧

需要注意的几点: 

1.导入StoreKit框架 
2.确保 product ID惟一且与IITUNNES CONNECT中的一致
3. 请确保plist文件中的Bundle identifier与ITunes Connet中的 Bundle ID一致
4.虚拟机好像跑不起来
5.iTunes Connect 中 product ID 的分配上限为10W个
6.内购不分区域,可以在任何地方购买,即使应用在不分区域没上架
7.越狱设备可能无法使用(我的机子就没通过,囧)
8.沙盒测试的话,请使用 iTunes Connect Test User的账号




下面是个流程图(闲话:这张图从别而网站扒下来的,不过不记得是从哪个网站扒下来的了)
IOS客户端内购(IAP)简单总结_第1张图片


以下涉及到的分别有
(1)框架
       
(2)1个类和3个Delegate
         Class: SKProductsRequest
      Delegate:< SKPaymentTransactionObserver , SKProductsRequestDelegate , SKRequestDelegate ]]]]>

下面上几段核心代码

.h中
#import 
@interface IAPUnity : NSObject

@property(retain,nonatomic)NSArray* products;       //产品列表
@property(retain,nonatomic)NSSet* productIdf;       //产品标记符
@property(retain,nonatomic)SKProductsRequest* request;  //用于请求相关信息

///获取商店信息
-(void)requestStart;

///初始化
- (id)initProductIdf:(NSSet*)productIdf;

///购买
-(void)buyProduct;

///恢复交易
-(void)restorer;

@end



.m
#import "IAPUnity.h"

@interface IAPUnity ()

@property(retain,nonatomic)SKProduct* product;

@end


@implementation IAPUnity

- (id)initProductIdf:(NSSet*)productIdf
{
    self = [super init];
    if (self) {
        self.productIdf=productIdf;
        [self getProducts];
    }
    return self;
}
-(void)getProducts
{
    _request=[[SKProductsRequest alloc]initWithProductIdentifiers:_productIdf];
}
-(void)requestStart
{
    [_request setDelegate:self];
    ///请求数据
    [_request start];
}

#pragma SKProductsRequestDelegate 
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    ///判断用户是否禁用内购功能
    if ([SKPaymentQueue canMakePayments]) {
        NSLog(@"%@",response.products);
        //得到产品列表
        self.products=response.products;
    
    }
    
    ///获取成功列表成功,并且取到第0个的相关信息
    if ([response.products count]>0) {
        self.product=[response.products objectAtIndex:0];
        NSLog(@"产品本地标题:%@",[self.product localizedTitle]);
        NSLog(@"产品描述:%@",self.product.localizedDescription);
        NSLog(@"产品价格:%@",self.product.price);
        NSLog(@"产品标识:%@",self.product.productIdentifier);
    }
    
    
    ///发生错误的时候输出错误信息
    for (NSString *invalidProductId in response.invalidProductIdentifiers)
    {
        NSLog(@"Invalid product id: %@" , invalidProductId);
    }
}
-(void)buyProduct
{
    if (self.product) {
        
        if ([SKPaymentQueue canMakePayments]) {
            SKPayment* payment=[SKPayment paymentWithProduct:self.product];
            ///为支付队列增加一个观察者
            [[SKPaymentQueue defaultQueue]addTransactionObserver:self];
            ///增加了一个观察者到付款队列中
            [[SKPaymentQueue defaultQueue]addPayment:payment];
        }
    }
}

-(void)restorer
{
    
    [[SKPaymentQueue defaultQueue]restoreCompletedTransactions];
}


// Sent when the transaction array has changed (additions or state changes).  Client should check state of transactions and finish as appropriate.
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    for (SKPaymentTransaction* transaction in transactions) {
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchasing:
            {
                NSLog(@"购买中");
            }
                break;
            case SKPaymentTransactionStatePurchased:
            {
                NSLog(@"SKPaymentTransactionStatePurchased");
                NSLog(@"%@",[[NSString alloc]initWithData:transaction.transactionReceipt encoding:NSUTF8StringEncoding]);
                NSString* temp=[[NSString alloc]initWithData:transaction.transactionReceipt encoding:NSUTF8StringEncoding];
                UIAlertView* alertView=[[UIAlertView alloc]initWithTitle:@"提示" message:@"内购成功" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
                [alertView show];
                NSLog(@"BASE64:%@",[self encode:temp.UTF8String length:temp.length]);
                [[SKPaymentQueue defaultQueue]finishTransaction:transaction];
            }
                break;
            case SKPaymentTransactionStateFailed:
            {
                if (transaction.error.code!=SKErrorPaymentCancelled) {
                    NSLog(@"Failed....%d",transaction.error.code);
                    NSLog(@"%@",transaction.error.localizedDescription);
                }
                [[SKPaymentQueue defaultQueue]finishTransaction:transaction];
            
            }
                break;
            case SKPaymentTransactionStateRestored:
            {
                [[SKPaymentQueue defaultQueue]finishTransaction:transaction];
            }
                break;
            default:
                break;
        }
    }

}


@end

之前的BASE64函数有点问题,所以删掉了,换了一个
下面是 transaction.transactionState的几种状态
     SKPaymentTransactionStatePurchasing,    // 这一个是应用商店是正在处理交易的状态
     SKPaymentTransactionStatePurchased,     // 这一个是应用商店成功处理付款的状态
     SKPaymentTransactionStateFailed,        // 这儿是应用商店处理失败的状态
     SKPaymentTransactionStateRestored       // 这个是应用商店恢复之前的状态





中间遇到的问题

(1)问题:使用 SKPayment paymentWithProductIdentifier无法连接上APP STORE导致无法进行购买(网络不好也可能出现连接不上的情况)
     解决方法:改用 SKPayment的 paymentWithProduct方法

(2)问题:购买时,登陆成功后提示  [environment:sandbox] ,导致无法成功购买
     解决方案:我在这, 就是回到ITUNESCONNETION中重新Add了1个账号(美国地区的,中国的试了几个都不行),回到设备上注销掉之前的账号和关掉APP STORE,重新登陆即可

(3)问题: -( void )productsRequest:( SKProductsRequest  *)request didReceiveResponse:( SKProductsResponse  *)response 中  response. invalidProductIdentifiers count>0的情况。
     解决方案:我换了一台非越狱设备,就正常了


苹果IAP文档:https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/13_ManagingIn-AppPurchases/ManagingIn-AppPurchases.html#//apple_ref/doc/uid/TP40011225-CH4-SW1

苹果视频(Using Store Kit for In-App Purchases):https://developer.apple.com/wwdc/videos/?id=305



著作权声明:本文由 http://blog.csdn.net/dalehui/ 原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!

你可能感兴趣的:(IOS)