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 CBiOSStoreManagerstatic 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.範例下載
下載連結