天天看點

【詳解iOS應用程式内使用IAP/StoreKit付費、沙盒(SandBox)測試、建立測試賬号流程!】【二】

 第二步:申請測試賬号,利用沙盒測試模拟AppStore購買道具流程!

  回到itunesconnect首頁中,選擇“Manage Users”然後選擇“Test User”,然後出現的界面如下圖: 

<a target="_blank" href="http://blog.51cto.com/attachment/201111/011238706.png"></a>

 這裡Himi已經建立了兩個測試賬号了,點選界面中的 “Add New User”進行建立即可;記住賬号和密碼哈,記不住就删掉重建立 娃哈哈~(切記:不能用于真正的AppStore中使用此賬号,不僅不能用,而且一旦AppStore發現後果你懂得~) 

   第三步:在項目中申請購買産品代碼以及監聽;

         這裡關于購買的代碼部分呢,我都有備注的,Himi這裡就不詳細講解了,Himi隻是在代碼後介紹幾點值得注意的地方:

 這裡Himi是建立的一個Cocos2d的項目,然後給出HelloWorldLayer.h以及HelloWorldLayer.m的全部代碼,所有購買代碼也全在裡面也對應有Himi的注釋!

          HelloWorldLayer.h

//   

//  HelloWorldLayer.h   

//  buytest   

//  Created by 華明 李 on 11-10-29.   

//  Copyright Himi 2011年. All rights reserved.   

// When you import this file, you import all the cocos2d classes   

#import "cocos2d.h"   

#import &lt;UIKit/UIKit.h&gt;   

#import &lt;StoreKit/StoreKit.h&gt;   

enum{   

     IAP0p99=10,   

     IAP1p99,   

     IAP4p99,   

     IAP9p99,    

     IAP24p99,   

}buyCoinsTag;    

@interface HelloWorldLayer : CCLayer&lt;SKProductsRequestDelegate,SKPaymentTransactionObserver&gt;   

{   

    int buyType;   

}   

+(CCScene *) scene;     

- (void) requestProUpgradeProductData;   

-(void)RequestProductData;   

-(bool)CanMakePay;                                

-(void)buy:(int)type;    

- (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;   

-(void)provideContent:(NSString *)product;   

-(void)recordTransaction:(NSString *)product;   

@end   

 HelloWorldLayer.m

//  IapLayer.m   

//  Created by Himi on 11-5-25.   

//  Copyright 2011年 李華明 . All rights reserved.   

#import "HelloWorldLayer.h"    

#define ProductID_IAP0p99 @"com.buytest.one"//$0.99     

#define ProductID_IAP1p99 @"com.buytest.two" //$1.99    

#define ProductID_IAP4p99 @"com.buytest.three" //$4.99     

#define ProductID_IAP9p99 @"com.buytest.four" //$19.99     

#define ProductID_IAP24p99 @"com.buytest.five" //$24.99     

@implementation HelloWorldLayer   

+(CCScene *) scene   

    CCScene *scene = [CCScene node];   

    HelloWorldLayer *layer = [HelloWorldLayer node];   

    [scene addChild: layer];   

    return scene;   

-(id)init   

    if ((self = [super init])) {   

        CGSize size = [[CCDirector sharedDirector] winSize];   

        CCSprite *iap_bg  = [CCSprite spriteWithFile:@"Icon.png"];     

        [iap_bg setPosition:ccp(size.width/2,size.height/2)];   

        [self addChild:iap_bg z:0];   

        //---------------------   

        //----監聽購買結果   

        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];   

        //申請購買   

        /*  

         enum{  

         IAP0p99=10,  

         IAP1p99,  

         IAP4p99,  

         IAP9p99,  

         IAP24p99,  

         }buyCoinsTag;  

         */   

        [self buy:IAP24p99];   

    }   

    return self;   

-(void)buy:(int)type   

{    

    buyType = type;     

    if ([SKPaymentQueue canMakePayments]) {   

        //[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];   

        [self RequestProductData];     

        CCLOG(@"允許程式内付費購買");   

    else   

    {   

        CCLOG(@"不允許程式内付費購買");    

        UIAlertView *alerView =  [[UIAlertView alloc] initWithTitle:@"Alert"    

                                                            message:@"You can‘t purchase in app store(Himi說你沒允許應用程式内購買)"                                                           

                                                           delegate:nil cancelButtonTitle:NSLocalizedString(@"Close(關閉)",nil) otherButtonTitles:nil];   

        [alerView show];   

        [alerView release];   

    }    

-(bool)CanMakePay   

    return [SKPaymentQueue canMakePayments];   

-(void)RequestProductData   

    CCLOG(@"---------請求對應的産品資訊------------");   

    NSArray *product = nil;   

    switch (buyType) {   

        case IAP0p99:   

            product=[[NSArray alloc] initWithObjects:ProductID_IAP0p99,nil];   

            break;   

        case IAP1p99:   

            product=[[NSArray alloc] initWithObjects:ProductID_IAP1p99,nil];   

        case IAP4p99:   

            product=[[NSArray alloc] initWithObjects:ProductID_IAP4p99,nil];   

        case IAP9p99:   

            product=[[NSArray alloc] initWithObjects:ProductID_IAP9p99,nil];   

        case IAP24p99:   

            product=[[NSArray alloc] initWithObjects:ProductID_IAP24p99,nil];   

        default:   

    NSSet *nsset = [NSSet setWithArray:product];   

    SKProductsRequest *request=[[SKProductsRequest alloc] initWithProductIdentifiers: nsset];   

    request.delegate=self;   

    [request start];   

    [product release];   

//&lt;SKProductsRequestDelegate&gt; 請求協定   

//收到的産品資訊   

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{   

    NSLog(@"-----------收到産品回報資訊--------------");   

    NSArray *myProduct = response.products;   

    NSLog(@"産品Product ID:%@",response.invalidProductIdentifiers);   

    NSLog(@"産品付費數量: %d", [myProduct count]);   

    // populate UI    

    for(SKProduct *product in myProduct){   

        NSLog(@"product info");   

        NSLog(@"SKProduct 描述資訊%@", [product description]);      

        NSLog(@"産品标題 %@" , product.localizedTitle);   

        NSLog(@"産品描述資訊: %@" , product.localizedDescription);   

        NSLog(@"價格: %@" , product.price);   

        NSLog(@"Product id: %@" , product.productIdentifier);    

    SKPayment *payment = nil;    

            payment  = [SKPayment paymentWithProductIdentifier:ProductID_IAP0p99];    //支付$0.99   

            payment  = [SKPayment paymentWithProductIdentifier:ProductID_IAP1p99];    //支付$1.99   

            payment  = [SKPayment paymentWithProductIdentifier:ProductID_IAP4p99];    //支付$9.99   

            payment  = [SKPayment paymentWithProductIdentifier:ProductID_IAP9p99];    //支付$19.99   

            payment  = [SKPayment paymentWithProductIdentifier:ProductID_IAP24p99];    //支付$29.99   

    CCLOG(@"---------發送購買請求------------");   

    [[SKPaymentQueue defaultQueue] addPayment:payment];     

    [request autorelease];    

- (void)requestProUpgradeProductData   

    CCLOG(@"------請求更新資料---------");   

    NSSet *productIdentifiers = [NSSet setWithObject:@"com.productid"];   

    SKProductsRequest* productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];   

    productsRequest.delegate = self;   

    [productsRequest start];    

//彈出錯誤資訊   

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{   

    CCLOG(@"-------彈出錯誤資訊----------");   

    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{   

    CCLOG(@"-----PurchasedTransaction----");   

    NSArray *transactions =[[NSArray alloc] initWithObjects:transaction, nil];   

    [self paymentQueue:[SKPaymentQueue defaultQueue] updatedTransactions:transactions];   

    [transactions release];   

}    

//&lt;SKPaymentTransactionObserver&gt; 千萬不要忘記綁定,代碼如下:   

//----監聽購買結果   

//[[SKPaymentQueue defaultQueue] addTransactionObserver:self];   

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions//交易結果   

    CCLOG(@"-----paymentQueue--------");   

    for (SKPaymentTransaction *transaction in transactions)   

        switch (transaction.transactionState)   

        {    

            case SKPaymentTransactionStatePurchased://交易完成    

                [self completeTransaction:transaction];   

                CCLOG(@"-----交易完成 --------");   

                CCLOG(@"不允許程式内付費購買");    

                UIAlertView *alerView =  [[UIAlertView alloc] initWithTitle:@"Alert"    

                                                                    message:@"Himi說你購買成功啦~娃哈哈"                                                         

                                                                   delegate:nil cancelButtonTitle:NSLocalizedString(@"Close(關閉)",nil) otherButtonTitles:nil];   

                [alerView show];   

                [alerView release];    

                break;    

            case SKPaymentTransactionStateFailed://交易失敗    

                [self failedTransaction:transaction];   

                 CCLOG(@"-----交易失敗 --------");   

                UIAlertView *alerView2 =  [[UIAlertView alloc] initWithTitle:@"Alert"    

                                                                    message:@"Himi說你購買失敗,請重新嘗試購買~"                                                         

                [alerView2 show];   

                [alerView2 release];   

            case SKPaymentTransactionStateRestored://已經購買過該商品    

                [self restoreTransaction:transaction];   

                 CCLOG(@"-----已經購買過該商品 --------");   

            case SKPaymentTransactionStatePurchasing:      //商品添加進清單   

                 CCLOG(@"-----商品添加進清單 --------");   

                break;   

            default:   

        }   

- (void) completeTransaction: (SKPaymentTransaction *)transaction   

    CCLOG(@"-----completeTransaction--------");   

    // Your application should implement these two methods.   

    NSString *product = transaction.payment.productIdentifier;   

    if ([product length] &gt; 0) {   

        NSArray *tt = [product componentsSeparatedByString:@"."];   

        NSString *bookid = [tt lastObject];   

        if ([bookid length] &gt; 0) {   

            [self recordTransaction:bookid];   

            [self provideContent:bookid];   

    // Remove the transaction from the payment queue.   

    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];   

//記錄交易   

-(void)recordTransaction:(NSString *)product{   

    CCLOG(@"-----記錄交易--------");   

//處理下載下傳内容   

-(void)provideContent:(NSString *)product{   

    CCLOG(@"-----下載下傳--------");    

- (void) failedTransaction: (SKPaymentTransaction *)transaction{   

    NSLog(@"失敗");   

    if (transaction.error.code != SKErrorPaymentCancelled)   

-(void) paymentQueueRestoreCompletedTransactionsFinished: (SKPaymentTransaction *)transaction{   

- (void) restoreTransaction: (SKPaymentTransaction *)transaction   

    NSLog(@" 交易恢複處理");   

-(void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error{   

    CCLOG(@"-------paymentQueue----");   

#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:   

        case 304:    

        case 400:    

            break;     

        case 404:   

        case 416:   

        case 403:   

        case 401:   

        case 500:   

    }           

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {   

    NSLog(@"test");   

-(void)dealloc   

    [super dealloc];   

代碼注釋的相當清楚了,沒有什麼可解釋的,這裡說幾點值得注意的地方:

2. 越獄機器無法沙盒測試!模拟器的話,Himi用4.3模拟器不可以,因為提示沒有開啟程式内付費- -(我都沒看到模拟器有store的選項,so~);但是使用iOS5的模拟器可以測試沙盒,但是執行的順序會有些問題,但是還沒真機的童鞋可以使用,建議一切以真機實測為準

3. 千萬不要忘記在iTunesConnect中建立App Bundle ID一定要跟你的項目中的info.plist中的Bundle ID保證一緻!!!!

4. 以上代碼中你需要修改的就是我在HelloWorldLayer.m類中的宏定義的Product ID(産品ID),例如Himi剛才建立了一個産品ID是“com.himi.wahaha"

然後我運作項目截圖如下以及運作控制台列印的資訊如下:

<a target="_blank" href="http://blog.51cto.com/attachment/201111/011342989.png"></a>

點選Buy之後運作截圖以及列印資訊:

<a target="_blank" href="http://blog.51cto.com/attachment/201111/011401918.png"></a>

輸入測試賬号密碼後以及列印資訊:

<a target="_blank" href="http://blog.51cto.com/attachment/201111/011415617.png"></a>

      這裡Himi最後一張截圖是沒有購買成功,這裡Himi是故意截圖出來的,原因就是想告訴童鞋們:

 如果你的産品資訊能夠正常得到,但是始終無法成功的話,不要着急,因為你的産品要進入iTunes Connect,并且Apple準備好沙箱環境需要一些時間。Himi之前遇到過,然後在一天後我沒有修改任何一行代碼,但産品ID變為有效并能成功購買。=。 =郁悶ing~~  起始要使産品釋出到Apple的網絡系統是需要一段時間的!

    好了,寫了這麼多了,咳咳、Himi繼續忙了,做iOS的童鞋們我想此篇将成為你必須收藏的一篇哦~嘿嘿!

本文轉自 xiaominghimi 51CTO部落格,原文連結:http://blog.51cto.com/xiaominghimi/706419,如需轉載請自行聯系原作者

繼續閱讀