美文网首页
iOS内购类 封装

iOS内购类 封装

作者: master_huang | 来源:发表于2017-07-30 00:35 被阅读0次

    之前做过游戏SDK,所以当时写了一个内购的类,觉得还可以吧。直接看代码

    #import#import#import "FishApiDelegate.h"@interface CApiAppleStore : NSObject/*! 单例 */+(CApiAppleStore *) sharedInstance;/*! @method  @abstract 设置支付代理 */-(void) setDelegate:(id) delegate;

    /*!

    @method

    @abstract SDK启动的时候,将未完成的订单通知服务器

    */

    -(void)restoreUnfinishPayment;

    /*!

    @method

    @abstract 成功登入之后 初始化商品列表

    */

    -(void)initProducts;

    /*!

    @method

    @abstract 返回SDK服务器保存的商品ID列表

    @return 字符串数组

    */

    -(NSArray *)getProductIds;

    /*!

    @method

    @abstract 获取有效的商品

    @return SKProduct数组

    */

    -(NSArray *)getProducts;

    /*!

    @method

    @abstract 获取有效商品数量

    @return 数量

    */

    -(NSInteger)getProductNum;

    /*!

    @method

    @abstract 购买

    @param getProducts列表中的index

    */

    -(void)buy:(NSInteger)productIndex info:(NSString *)info;

    -(void)didRequestCompleted:(NSDictionary *)data;

    @end

    #import "CApiAppleStore.h"#import "FishApi.h"#import "CApiRequest.h"#import "CApiRequestData.h"#import "CEncrypt.h"#import "AppsFlyerTracker.h"#import "CApiResponse.h"@interface CApiAppleStore(){@private    iddelegate;@private    NSArray * productIds;    NSArray * products;    NSDictionary * productDic;    NSString * extraInfo;    NSMutableArray * cacheReceipts; //缓存收据  直接跟文件数据对应的}@end@implementation CApiAppleStore//初始化单例+ (CApiAppleStore *)sharedInstance {    static dispatch_once_t pred;    static CApiAppleStore *instance = nil;    dispatch_once(&pred, ^{instance = [[self alloc] init];});    return instance;}//请求初始化-(id)init{    if (self = [super init]) {                [self initParams];        [self setDelegate:self];    }    return self;}//初始化参数-(void)initParams{    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];}/*! @method  @abstract 设置支付代理 */-(void) setDelegate:(id) de

    {

    delegate = de;

    }

    /*!

    @method

    @abstract SDK启动的时候,将未完成的订单通知服务器

    */

    -(void)restoreUnfinishPayment

    {

    [self loadCacheReceipts];

    if (cacheReceipts == nil || cacheReceipts.count == 0) {

    return;

    }

    //NSLog(@"%@ restoreUnfinishPayment ready", [NSThread currentThread]);

    NSArray * receipts = [cacheReceipts copy];

    [NSThread detachNewThreadSelector:@selector(restoreUnfinishPaymentThreadFun:) toTarget:self withObject:receipts];

    }

    /*!

    @method

    @abstract 线程操作

    */

    -(void)restoreUnfinishPaymentThreadFun:(id)param

    {

    [NSThread sleepForTimeInterval:1]; //延迟1秒执行

    NSLog(@"%@ restoreUnfinishPaymentThread started", [NSThread currentThread]);

    NSArray * receipts = (NSArray *)param;

    if (receipts && receipts.count > 0){

    for (NSDictionary * data in receipts) {

    [self repaid:data];

    }

    }

    }

    /*!

    @method

    @abstract 成功登入之后 初始化商品列表

    */

    -(void)initProducts

    {

    CApiRequestData *data = [[CApiRequestData alloc]init];

    NSDictionary *params = [data withParams:nil];

    [CApiRequest post:params to:@"index" attach:@"appleproducts"];

    //    [self restoreUnfinishPayment];

    }

    /*!

    @method

    @abstract 返回SDK服务器保存的商品ID列表

    @return 字符串数组

    */

    -(NSArray *)getProductIds

    {

    return productIds;

    }

    /*!

    @method

    @abstract 获取有效的商品

    @return SKProduct数组

    */

    -(NSArray *)getProducts

    {

    if (products.count == 0) {

    NSSet * set = [NSSet setWithArray:productIds];

    SKProductsRequest * request = [[SKProductsRequest alloc]initWithProductIdentifiers:set];

    request.delegate = self;

    [request start];

    }

    return products;

    }

    /*!

    @method

    @abstract 获取有效商品数量

    @return 数量

    */

    -(NSInteger)getProductNum

    {

    if (products == nil){

    return 0;

    }

    return products.count;

    }

    /*!

    @method

    @abstract 购买

    @param getProducts列表中的index

    @param info附加信息

    */

    -(void)buy:(NSInteger)productIndex info:(NSString *)info

    {

    if(products == nil){

    return;

    }

    if(productIndex >= products.count){

    return;

    }

    [delegate transactionStart];

    extraInfo = [info copy];//这里一定要copy一份,因为内购需要的时间比较长,传进来的可能已经被释放

    NSLog(@"extraInfo is :%@",extraInfo);

    SKProduct * p = products[productIndex];

    SKPayment * payment = [SKPayment paymentWithProduct:p];

    [[SKPaymentQueue defaultQueue] addPayment:payment];

    }

    #pragma mark SKProductsRequestDelegate代理方法

    -(void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response

    {

    NSLog(@"valid products count %lu", (unsigned long)response.products.count);

    NSLog(@"无效商品:%@",response.invalidProductIdentifiers);

    NSMutableDictionary * dic = [[NSMutableDictionary alloc] init];

    for (SKProduct * p in response.products) {

    [dic setObject:p forKey:p.productIdentifier];

    }

    NSMutableArray * plist = [[NSMutableArray alloc]init];

    id obj;

    for (NSString * pid in productIds){

    obj = [dic objectForKey:pid];

    if (obj != nil){

    [plist addObject:obj];

    }

    }

    productDic = dic;

    products = plist;

    }

    #pragma mark SKPaymentTransactionObserver代理方法

    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions

    {

    for (SKPaymentTransaction * transaction in transactions) {

    switch (transaction.transactionState) {

    case SKPaymentTransactionStatePurchased:

    [self transactionSuccess:transaction];

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

    break;

    case SKPaymentTransactionStateFailed:

    NSLog(@"failed %@ %@ %@", transaction.transactionIdentifier, transaction.error.description, transaction.error.debugDescription);

    [self transactionFailed:transaction];

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

    break;

    case SKPaymentTransactionStateRestored:

    NSLog(@"restored %@", transaction.transactionIdentifier);

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

    break;

    case SKPaymentTransactionStatePurchasing:

    //NSLog(@"purchasing %@", transaction.transactionIdentifier);

    break;

    default:

    break;

    }

    }

    }

    -(void)transactionSuccess:(SKPaymentTransaction *)transaction

    {

    //这里拿到收据,可以自己验证也可以传给后台验证

    }

    -(void)transactionFailed:(SKPaymentTransaction *)transaction

    {

    NSLog(@"transactionFailed %@ %@", transaction.transactionIdentifier, transaction.error.description);

    [delegate transactionFinish:NO msg:transaction.error.localizedDescription];

    }

    -(void)didRequestCompleted:(NSDictionary *)data

    {

    NSInteger code = [[data objectForKey:@"code"]intValue];

    NSLog(@"code:%ld",(long)code);

    NSDictionary * paydata;

    NSString * receiptId;

    switch (code) {

    case FishReqProductsOK:

    productIds = [[data objectForKey:@"data"] copy];

    NSSet * set = [NSSet setWithArray:productIds];

    SKProductsRequest * request = [[SKProductsRequest alloc]initWithProductIdentifiers:set];

    request.delegate = self;

    [request start];

    break;

    case FishError_ReqProducts:

    NSLog(@"code:%ld",(long)code);

    break;

    case FishPayOK:

    case FishError_Pay:

    paydata = [data objectForKey:@"data"];

    if (paydata){

    receiptId = [paydata objectForKey:@"id"];

    if (receiptId){

    [self delCacheReceipt:receiptId];

    }

    }

    [delegate paymentFinish:(code == FishPayOK)?YES:NO];

    break;

    default:

    break;

    }

    }

    /*!

    @method repaid

    @abstract 重新通知服务器

    */

    -(void)repaid:(NSDictionary *)params

    {

    CApiRequestData *data = [[CApiRequestData alloc]init];

    params = [data withParams:params];

    [CApiRequest post:params to:@"index" attach:@"applepay"];

    }

    /*!

    @method

    @abstract 开始购买

    */

    -(void) transactionStart

    {

    }

    /*!

    @method

    @abstract 结束购买

    */

    -(void) transactionFinish:(Boolean)result msg:(NSString*)msg;

    {

    }

    /*!

    @method

    @abstract SDK通知服务器结束

    @param result 成功或者失败

    */

    -(void) paymentFinish:(Boolean)result

    {

    }

    /*!

    @method

    @abstract 获取订单保存路径

    */

    -(NSString *) getCachePath

    {

    NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString *doucumentsDirectory=[paths objectAtIndex:0];

    return [doucumentsDirectory stringByAppendingPathComponent:@"iap7725.plist"];

    }

    /*!

    @method

    @abstract 删除cache中的订单

    */

    -(BOOL)delCacheReceipt:(NSString *)key

    {

    if(cacheReceipts == nil){

    return NO;

    }

    BOOL redBool = NO;

    NSString *file = [self getCachePath];

    for (NSDictionary *objc in cacheReceipts) {

    NSString *name = [objc objectForKey:@"id"];

    if ([name isEqualToString:key]) {

    [cacheReceipts removeObject:name];

    [cacheReceipts writeToFile:file atomically:YES];

    redBool = YES;

    break;

    }

    }

    return redBool;

    }

    /*!

    @method

    @abstract 从文件中加载所有

    */

    -(void)loadCacheReceipts

    {

    NSString *file = [self getCachePath];

    if ([[NSFileManager defaultManager] fileExistsAtPath:file]) {

    cacheReceipts =[[NSMutableArray alloc]initWithContentsOfFile:file];

    }else{

    cacheReceipts = [[NSMutableArray alloc]init];

    }

    }

    /*!

    @method

    @abstract 保存数据到文件

    */

    -(void) addCacheReceipt:(NSDictionary *)data

    {

    NSString * key = [data objectForKey:@"id"];

    for (NSDictionary * objc in cacheReceipts){

    NSString * name = [objc objectForKey:@"id"];

    if ([name isEqualToString:key]){

    return;

    }

    }

    NSString *file = [self getCachePath];

    [cacheReceipts addObject:data];

    [cacheReceipts writeToFile:file atomically:YES];

    }

    - (void)dealloc

    {

    [super dealloc];

    NSLog(@"购买队列被释放");

    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

    }

    相关文章

      网友评论

          本文标题:iOS内购类 封装

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