IAP实现之一内建模式 — cocos2dx

11 篇文章 0 订阅
6 篇文章 0 订阅


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 PaymentController

static 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处理服务器模式
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值