iOS IAP教程

原创 2012年10月31日 09:36:30

1. 创建应用

首先进入iTunes Connect然后按下 Manage Your Applications


接下来按下Add New Application按钮创建应用

2. 在应用中创建IAP


创建应用之后,在Manage Your Applications中点应用的图示,进入应用

就会看到上图画面点击Manage In App Purchases就可以进入IAP的管理画面

在这边要注意左边的Bundle ID,在Xcode项目中,info.plist中的设定需与此Bundle相同

(此Bundle ID会在创建应用时填入)

此为IAP的管理画面,只要按下Create New按钮就可创建IAP

在本图中我已经创建好三个IAP

而其中要注意的是Product ID,只要用Product ID就可以请求IAP的相关讯息及交易

Consumable

消耗品,每次下载都需付费

Non-Consumable

一次性付费,通常用在升级pro版或是移除广告等

Auto-Renewable Subscriptions

自动更新订阅

Free Subscription

免费订阅

Non-Renewing Subscription

自动更新订阅

3. 如何创建沙盒测试用户

进入iTunes Connect,点击Manage Users

在这个画面中点下Test User

按下Add New User就可以了Email Address就是登入沙盒测试的用户名

密码的部份在Add New User时可自行创建

4.代码

/*
 *  CBiOSStoreManager.h
 *  CloudBox Cross-Platform Framework Project
 *
 *  Created by Cloud on 2012/10/30.
 *  Copyright 2011 Cloud Hsu. All rights reserved.
 *
 */

#import <UIKit/UIKit.h> 
#import <StoreKit/StoreKit.h>

@interface CBiOSStoreManager : NSObject<SKProductsRequestDelegate,SKPaymentTransactionObserver>
{
    NSString* _buyProductIDTag;
}

+ (CBiOSStoreManager*) sharedInstance;

- (void) buy:(NSString*)buyProductIDTag;
- (bool) CanMakePay;
- (void) initialStore;
- (void) releaseStore;
- (void) requestProductData:(NSString*)buyProductIDTag;
- (void) provideContent:(NSString *)product;
- (void) recordTransaction:(NSString *)product;

- (void) requestProUpgradeProductData:(NSString*)buyProductIDTag;
- (void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions;
- (void) purchasedTransaction: (SKPaymentTransaction *)transaction;
- (void) completeTransaction: (SKPaymentTransaction *)transaction;
- (void) failedTransaction: (SKPaymentTransaction *)transaction;
- (void) paymentQueueRestoreCompletedTransactionsFinished: (SKPaymentTransaction *)transaction;
- (void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error;
- (void) restoreTransaction: (SKPaymentTransaction *)transaction;

@end

/*
 *  CBiOSStoreManager.mm
 *  CloudBox Cross-Platform Framework Project
 *
 *  Created by Cloud on 2012/10/30.
 *  Copyright 2011 Cloud Hsu. All rights reserved.
 *
 */

#import "CBiOSStoreManager.h"

@implementation CBiOSStoreManager

static CBiOSStoreManager* _sharedInstance = nil;

+(CBiOSStoreManager*)sharedInstance
{
	@synchronized([CBiOSStoreManager class])
	{
		if (!_sharedInstance)
			[[self alloc] init];
        
		return _sharedInstance;
	}
	return nil;
}

+(id)alloc
{
	@synchronized([CBiOSStoreManager class])
	{
		NSAssert(_sharedInstance == nil, @"Attempted to allocate a second instance of a singleton.\n");
		_sharedInstance = [super alloc];
		return _sharedInstance;
	}
	return nil;
}

-(id)init {
	self = [super init];
	if (self != nil) {
		// initialize stuff here
	}
	return self;
}

-(void)initialStore
{
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}
-(void)releaseStore
{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

-(void)buy:(NSString*)buyProductIDTag
{
    [self requestProductData:buyProductIDTag];
}

-(bool)CanMakePay
{
    return [SKPaymentQueue canMakePayments];
}   

-(void)requestProductData:(NSString*)buyProductIDTag
{
    NSLog(@"---------Request product information------------\n");
    _buyProductIDTag = [buyProductIDTag retain];
    NSArray *product = [[NSArray alloc] initWithObjects:buyProductIDTag,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(@"-----------Getting product information--------------\n");
    NSArray *myProduct = response.products;
    NSLog(@"Product ID:%@\n",response.invalidProductIdentifiers);
    NSLog(@"Product count: %d\n", [myProduct count]);
    // populate UI
    for(SKProduct *product in myProduct){
        NSLog(@"Detail product info\n");
        NSLog(@"SKProduct description: %@\n", [product description]);
        NSLog(@"Product localized title: %@\n" , product.localizedTitle);
        NSLog(@"Product localized descitption: %@\n" , product.localizedDescription);
        NSLog(@"Product price: %@\n" , product.price);
        NSLog(@"Product identifier: %@\n" , product.productIdentifier);
    }
    SKPayment *payment = nil;
    payment = [SKPayment paymentWithProduct:[response.products objectAtIndex:0]];
    NSLog(@"---------Request payment------------\n");
    [[SKPaymentQueue defaultQueue] addPayment:payment];
    [request autorelease];    
    
}
- (void)requestProUpgradeProductData:(NSString*)buyProductIDTag
{
    NSLog(@"------Request to upgrade product data---------\n");
    NSSet *productIdentifiers = [NSSet setWithObject:buyProductIDTag];
    SKProductsRequest* productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
    productsRequest.delegate = self;
    [productsRequest start];    
    
}

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
    NSLog(@"-------Show fail message----------\n");
    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(@"----------Request finished--------------\n");
    
}   

-(void) purchasedTransaction: (SKPaymentTransaction *)transaction
{
    NSLog(@"-----Purchased Transaction----\n");
    NSArray *transactions =[[NSArray alloc] initWithObjects:transaction, nil];
    [self paymentQueue:[SKPaymentQueue defaultQueue] updatedTransactions:transactions];
    [transactions release];
}    

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    NSLog(@"-----Payment result--------\n");
    for (SKPaymentTransaction *transaction in transactions)
    {
        switch (transaction.transactionState)
        {
            case SKPaymentTransactionStatePurchased:
                [self completeTransaction:transaction];
                NSLog(@"-----Transaction purchased--------\n");
                UIAlertView *alerView =  [[UIAlertView alloc] initWithTitle:@"Congratulation"
                                                              message:@"Transaction suceed!"
                                                              delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil];   
                
                [alerView show];
                [alerView release];
                break;
            case SKPaymentTransactionStateFailed:
                [self failedTransaction:transaction];
                NSLog(@"-----Transaction Failed--------\n");
                UIAlertView *alerView2 =  [[UIAlertView alloc] initWithTitle:@"Failed"
                                                               message:@"Sorry, your transcation failed, try again."
                                                               delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil];   
                
                [alerView2 show];
                [alerView2 release];
                break;
            case SKPaymentTransactionStateRestored:
                [self restoreTransaction:transaction];
                NSLog(@"----- Already buy this product--------\n");
            case SKPaymentTransactionStatePurchasing:
                NSLog(@"-----Transcation puchasing--------\n");
                break;
            default:
                break;
        }
    }
}

- (void) completeTransaction: (SKPaymentTransaction *)transaction   
{
    NSLog(@"-----completeTransaction--------\n");
    // Your application should implement these two methods.
    NSString *product = transaction.payment.productIdentifier;
    if ([product length] > 0) {   
        
        NSArray *tt = [product componentsSeparatedByString:@"."];
        NSString *bookid = [tt lastObject];
        if ([bookid length] > 0) {
            [self recordTransaction:bookid];
            [self provideContent:bookid];
        }
    }   
    
    // Remove the transaction from the payment queue.   
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];   
    
}   

-(void)recordTransaction:(NSString *)product
{
    NSLog(@"-----Record transcation--------\n");
    // Todo: Maybe you want to save transaction result into plist.
}   

-(void)provideContent:(NSString *)product
{
    NSLog(@"-----Download product content--------\n");
}   

- (void) failedTransaction: (SKPaymentTransaction *)transaction
{
    NSLog(@"Failed\n");
    if (transaction.error.code != SKErrorPaymentCancelled)
    {
    }
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
-(void) paymentQueueRestoreCompletedTransactionsFinished: (SKPaymentTransaction *)transaction
{   
    
}

- (void) restoreTransaction: (SKPaymentTransaction *)transaction
{
    NSLog(@"-----Restore transaction--------\n");
}

-(void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
    NSLog(@"-------Payment Queue----\n");
}

#pragma mark connection delegate
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSLog(@"%@\n",  [[[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\n");
}   

-(void)dealloc
{
    [super dealloc];
}

@end


[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
由于交易是永久有效的,建议addTransactionObserver这个于应用启动后就行监听,而不要在用户想买东西时才监听

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
交易结果会于此处显示

苹果准备沙盒测试环境需一段时间,若是创建IAP后可以取得资讯,却无法交易成功,要稍待一下

另外若是模拟器可以购买,但真机购买却失败的话,做Hard Reset就可以了,一直按住Home键跟电源键就可以做Hard Reset

按住后会出现关机画面,不要理会它,继续等,直到等到白苹果出现后,就可以放开等重开机完毕后再测试

5. IAP运作流程图

6.范例下载

下载连结

苹果IAP开发中的那些坑和掉单问题

相信很多iOS App的开发者,特别是手游开发者,都接触过苹果支付IAP(In-App Purchase)。相信使用了IAP的App,都经历过“掉单”问题。 什么是“掉单”呢?简言之就是用户付款...
  • xtqve
  • xtqve
  • 2016年09月09日 11:06
  • 3856

IAP超级详解,偷懒了,不用自己去翻译了

转载自:http://gaohaijun.blog.163.com/blog/static/176698271201143194018328/ 一、In App Purchase概览 Stor...
  • yang3wei
  • yang3wei
  • 2012年09月30日 21:33
  • 4924

iOS 内购( IAP)处理流程

iOS 内购( IAP)处理流程, 漏单这边介绍的是服务端验证的内购漏单 漏单:正常玩家购买了却没有收到物品、且自己的服务端没有任何记录iOS的订单。iOS的补单是非常麻烦的,用户提供支付的截图中...
  • AD_118
  • AD_118
  • 2016年02月24日 16:05
  • 5086

iOS 内购IAP(In-App Purchases)代码实现(下)

上次介绍了苹果内购的交易流程,接下来讲讲获取票据信息和防止漏单。为什么要获取票据信息?...
  • SeanHuang1661
  • SeanHuang1661
  • 2015年12月11日 10:19
  • 5418

【IOS一气呵成】之IAP集成:内购和内购恢复 DEMO

  • 2014年04月19日 17:27
  • 2KB
  • 下载

iOS 应用内付费(IAP)开发步骤

参考文章链接: (1)http://mobile.51cto.com/iphone-389249.htm (2)http://blog.csdn.net/xiaominghimi/article/...
  • xiaoxiangzhu660810
  • xiaoxiangzhu660810
  • 2013年12月20日 09:05
  • 54143

苹果应用内支付(iOS IAP)的流程与常用攻击方式

苹果应用内支付(iOS IAP)的流程与常用攻击方式 Jan 19, 2017 常见支付流程 iap(in app purchase)指苹果应用内支付, 目前主要有两种方式。 ...
  • u011661836
  • u011661836
  • 2017年02月08日 10:37
  • 1623

iOS内购IAP(In App Purchases)入门

成为ios开发者最大的好处就是,你编写的应用程序会有很多方式可以赚钱。比如,收费版,免费挂广告版,还有就是程序内置购买。 程序内置购买会让你爱不释手,主要有以下原因: 相比程序本身的下载收...
  • u011140147
  • u011140147
  • 2014年05月19日 08:51
  • 1440

[iOS]应用内支付(内购)的个人开发过程及坑!

本文会给大家详细介绍iOS内购,这是本人16年5月底的开发过程,希望对看完此篇文章的人有所帮助。 本文基于XcodeVersion 7.3 (7D175)版本,手机是iPhone 6,9.3系统。 ...
  • darling_shadow
  • darling_shadow
  • 2016年05月30日 15:16
  • 40534

iOS接入IAP教程

https://www.jianshu.com/p/7ae9654b85ee 作者Randall_Steven 前言 什么是IAP,我们什么时候需要使用IAP IAP就是应用内购买的英文缩写,在我们...
  • chenluwolf
  • chenluwolf
  • 2018年01月07日 06:47
  • 81
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:iOS IAP教程
举报原因:
原因补充:

(最多只允许输入30个字)