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
  • 2790

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

转载自:http://gaohaijun.blog.163.com/blog/static/176698271201143194018328/ 一、In App Purchase概览 Stor...

ios IAP - [[SKPaymentQueue defaultQueue] addTransactionObserver:resumeIAP];

注意 这个方法 对一个 IAP 只要 Add 一次,Add 多次将导致 - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactio...

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

参考文章链接: (1)http://mobile.51cto.com/iphone-389249.htm (2)http://blog.csdn.net/xiaominghimi/article/...

IAP入门笔记

附:本文来自IOS6-Tutorias的翻译,本做笔记之用,故语言简练。 一,可用的IAP类型: Non-Consumable:用户只需购买一次,不需要再次购买,即可在多台设备上拥有之(rest...
  • chowpan
  • chowpan
  • 2014年03月25日 13:20
  • 10684

stm32 IAP + APP ==>双剑合一

(扩展-IAP主要用于产品出厂后应用程序的更新作用,上一篇博文详细的对IAP 升级程序做了详细的分析http://blog.csdn.net/yx_l128125/article/details/12...

内支付-SKProductsRequest

一、In App Purchase概览 Store Kit代表App和App Store之间进行通信。程序将从App Store接收那些你想要提供的产品的信息,并将它们显示出来供用户购买。 当用户...
  • ch_soft
  • ch_soft
  • 2012年06月29日 12:08
  • 10304

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

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

基于蓝牙4.0(Bluetooth Low Power)探鱼器BLE-Sonar介绍

拿着一根鱼杆在池塘边白费几个小时后开始产生很多想法,想拿着一个智能手机能显示鱼儿躲藏在哪里.Friday Lab设计开发了世界首个专为业余垂钓者和专业捕鱼公司的智能无线声纳探鱼器BLE-Sonar,....

iOS MFi App端开发步骤

字数1157 阅读1807 评论5 喜欢7 本文为官方文档:About External Accessories及相关文档、个人开发调试过程的汇总。 与附件设备通讯的App需设备支持的...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:iOS IAP教程
举报原因:
原因补充:

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