IAP实现之一内建模式 — cocos2dx

来源:互联网 发布:杜克大学 知乎 编辑:程序博客网 时间:2024/06/03 22:32


cocos2dx中的IAP实现:一

A.苹果内购IAP两种模式流程:


1.内置模式:
app从app store 获取产品信息
用户选择需要购买的产品
app发送支付请求到app store
app store 处理支付请求,并返回transaction信息
app将购买的内容展示给用户

2.服务器模式的流程:
app从服务器获取产品标识列表
app从app store 获取产品信息
用户选择需要购买的产品
app 发送 支付请求到app store
app store 处理支付请求,返回transaction信息
app 将transaction receipt 发送到服务器
服务器收到收据后发送到app stroe验证收据的有效性
app store 返回收据的验证结果
根据app store 返回的结果决定用户是否购买成功


上述两种模式的不同之处主要在于:交易的收据验证,内建模式没有专门去验证交易收据,而服务器模式会使用独立的服务器去验证交易收据。内建模式简单快捷,但容易被破解。服务器模式流程相对复杂,但相对安全。

B.内置模式代码实现:添加StoreKit.framework

PaymentController.h文件:

/**  PaymentController.h**  Created by chiu on 15-06-16.*  Copyright (c) 2015年 Idlehands. All rights reserved.*/#import <UIKit/UIKit.h>#import <StoreKit/StoreKit.h>@interface PaymentController : NSObject<SKPaymentTransactionObserver,SKProductsRequestDelegate>@property  NSString *productID;- (void)initProductId:(NSString*) productIdStr;- (void)purchaseFunc;@end


PaymentController.mm文件:

/*    author: chiu    project: BYGame    date: 2016/08/22 */#import "PaymentController.h"#import "CCHelp.h"@interface PaymentController ()@end@implementation PaymentControllerstatic bool hasAddObersver = NO;- (id)initWithPayConstructor:(NSString *) productIdStr{    self = [super init];    if (self) {        // Custom initialization        [self initProductId:productIdStr];                if (!hasAddObersver) {            hasAddObersver = YES;            // 监听购买结果            [[SKPaymentQueue defaultQueue] addTransactionObserver:self];        }    }    return self;}- (void)initProductId:(NSString*) productIdStr{    self.productID = productIdStr;}- (void)purchaseFunc{    NSString *product = self.productID;    if([SKPaymentQueue canMakePayments]){        [self requestProductData:product];        NSLog(@"允许程序内付费");    }else{        NSLog(@"不允许程序内付费");    }}//请求商品- (void)requestProductData:(NSString *)type{    NSLog(@"-------------请求对应的产品信息----------------");    NSArray *product = [[NSArray alloc] initWithObjects:type, nil];        NSSet *nsset = [NSSet setWithArray:product];    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];    request.delegate = self;    [request start];    [product release];}//收到产品返回信息- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{        NSLog(@"--------------收到产品反馈消息---------------------");    NSArray *product = response.products;    if([product count] == 0){        NSLog(@"--------------没有商品------------------");        return;    }        NSLog(@"productID:%@", response.invalidProductIdentifiers);    NSLog(@"产品付费数量:%d",[product count]);        SKProduct *payInfoPorduct = 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:self.productID]){            payInfoPorduct = pro;        }    }        if(!payInfoPorduct)    {        return;    }    NSLog(@"发送购买请求");        if (floor(NSFoundationVersionNumber) < NSFoundationVersionNumber_iOS_5_0)    {        NSLog(@"pay_it less 5.0");        SKPayment* payment = [SKPayment paymentWithProductIdentifier:self.productID];        [[SKPaymentQueue defaultQueue] addPayment:payment];    }    else    {        NSLog(@"pay_it 5.0+");                SKMutablePayment* payment = [SKMutablePayment paymentWithProduct:payInfoPorduct];        payment.quantity = [product count];        [[SKPaymentQueue defaultQueue] addPayment:payment];    }    [request autorelease];}- (void)requestProUpgradeProductData{    NSLog(@"------请求升级数据---------");    NSSet *productIdentifiers = [NSSet setWithObject:@"com.productid"];    SKProductsRequest* productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];    productsRequest.delegate = self;    [productsRequest start];    }//请求失败- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{    NSLog(@"------------------错误-----------------:%@", error);    UIAlertView *alerView =  [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Alert",NULL) message:[error localizedDescription]                                                       delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil];    [alerView show];    [alerView release];}- (void)requestDidFinish:(SKRequest *)request{    NSLog(@"------------反馈信息结束-----------------");}-(void) PurchasedTransaction: (SKPaymentTransaction *)transaction{    NSLog(@"-----PurchasedTransaction----");    NSArray *transactions =[[NSArray alloc] initWithObjects:transaction, nil];    [self paymentQueue:[SKPaymentQueue defaultQueue] updatedTransactions:transactions];    [transactions release];}//监听购买结果- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{    for(SKPaymentTransaction *tran in transaction){                switch (tran.transactionState) {            case SKPaymentTransactionStatePurchased:                {                    NSLog(@"交易完成");                    [self completeTransaction:tran];                    CCHelp* cppHelper = GetCCHelp();                    cppHelper->purchaseResult(1,1);                                        [[SKPaymentQueue defaultQueue] finishTransaction:tran];                }                break;            case SKPaymentTransactionStatePurchasing:                {                    NSLog(@"商品添加进列表");                }                break;            case SKPaymentTransactionStateRestored:                {                    NSLog(@"已经购买过商品");                    [self restoreTransaction:tran];                                        [[SKPaymentQueue defaultQueue] finishTransaction:tran];                }                break;            case SKPaymentTransactionStateFailed:                {                    NSLog(@"交易失败");                    [self failedTransaction:tran];                    CCHelp* cppHelper = GetCCHelp();                    cppHelper->purchaseResult(1,-1);                                        [[SKPaymentQueue defaultQueue] finishTransaction:tran];                }                break;            default:                {                    CCHelp* cppHelper = GetCCHelp();                    cppHelper->purchaseResult(1,-1);                                        [[SKPaymentQueue defaultQueue] finishTransaction:tran];                }                break;        }    }}//交易结束- (void)completeTransaction:(SKPaymentTransaction *)transaction{    NSLog(@"交易结束");        // Remove the transaction from the payment queue.    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];}- (void) failedTransaction: (SKPaymentTransaction *)transaction{    if (transaction.error.code != SKErrorPaymentCancelled)    {    }    switch (transaction.error.code) {        case SKErrorUnknown:            NSLog(@"SKErrorUnknown");            break;        case SKErrorClientInvalid:            NSLog(@"SKErrorClientInvalid");            break;        case SKErrorPaymentCancelled:            NSLog(@"SKErrorPaymentCancelled");            break;        case SKErrorPaymentInvalid:            NSLog(@"SKErrorPaymentInvalid");            break;        case SKErrorPaymentNotAllowed:            NSLog(@"SKErrorPaymentNotAllowed");            break;        case SKErrorStoreProductNotAvailable:            NSLog(@"SKErrorStoreProductNotAvailable");            break;        default:            break;    }    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];        }- (void) restoreTransaction: (SKPaymentTransaction *)transaction{    }#pragma mark connection delegate- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{    NSLog(@"%@",  [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]);}- (void)connectionDidFinishLoading:(NSURLConnection *)connection{    }- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{    switch([(NSHTTPURLResponse *)response statusCode]) {        case 200:        case 206:            break;        case 304:            break;        case 400:            break;        case 404:            break;        case 416:            break;        case 403:            break;        case 401:        case 500:            break;        default:            break;    }}- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {    NSLog(@"test");}- (void)dealloc{    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];    [super dealloc];}@end

调用例子:

  /* Ios IAP entrance */        int payPrice = pNotify->GetSubType();        std::string productIdStr;        switch (payPrice)        {            case 1024:                productIdStr = "ttz_yk";                break;            case 1025:                productIdStr = "ttz_6";                break;            default:                break;        }        NSLog(@"----------当前商品ID: %s", productIdStr.c_str());        NSString* ocProductIdStr = [NSString stringWithFormat:@"%s",                                    productIdStr.c_str()];        PaymentController* pPayController = [[PaymentController alloc] initWithPayConstructor:ocProductIdStr];        [pPayController purchaseFunc];


PS:内置模式并没有做订单凭证后台验证,整个流程看起来都非常简单,所以是很不安全的方式,容易被破解内购产品刷单,下篇blog处理服务器模式
原创粉丝点击