Interested in tutoring?

Discussion in 'iOS Programming' started by kevindosi, May 16, 2012.

  1. kevindosi, May 16, 2012
    Last edited by a moderator: May 16, 2012

    kevindosi macrumors regular

    Joined:
    Mar 16, 2006
    #1
    I'm using BuzzTouch (essentially a CMS for iphone/android app development) to create a content-rich app. I really don't know anything about programming and don't need to in order to make a basic app on buzztouch. Unfortunately, I want to utilize in-app purchases for the content on my app and need to know what I'm doing in xcode order to accomplish that. I was just wondering if someone out there might be willing to tutor me for a couple of lessons to walk me through implementing in-app purchases until I can manage to do it on my own. I'd like to use iChat's screen sharing.
     
  2. jnoxx macrumors 65816

    jnoxx

    Joined:
    Dec 29, 2010
    Location:
    Aartselaar // Antwerp // Belgium
    #2
    Hmm, you don't need to pay anyone when you can get free help here..
    The thing is, it's actually not that hard, it's the connecting to iTunes Connect that actually sucks.

    (i'm gonna post the entire code, but this isn't top notch, so i hope someone can refactor it a bit)

    Basically, You want an InAppPurchaseManager
    ->
    InAppPurchaseManager.h (I used SynthesizedSingleton, to make it a Singleton, so you need to download this one from my cloud -> http://cl.ly/420y0p111f1x3H3Z1a0A)
    Code:
    
    //
    //  InAppPurchaseManager.h
    //
    //  Created by Thijs Bastiaens on 06/04/12.
    
    #import <Foundation/Foundation.h>
    #import <StoreKit/StoreKit.h>
    #import "SynthesizeSingleton.h"
    
    #define kInAppPurchaseManagerProductsFetchedNotification @"kInAppPurchaseManagerProductsFetchedNotification"
    #define kInAppPurchaseManagerTransactionFailedNotification @"kInAppPurchaseManagerTransactionFailedNotification"
    #define kInAppPurchaseManagerTransactionSucceededNotification @"kInAppPurchaseManagerTransactionSucceededNotification"
    
    @interface InAppPurchaseManager : NSObject <SKProductsRequestDelegate, SKPaymentTransactionObserver>
    {
        SKProduct *proUpgradeProduct;
        SKProductsRequest *productsRequest;
    }
    
    + (InAppPurchaseManager *) sharedInAppPurchaseManager;
    
    // public methods
    - (void) requestAddonMPack1Data; 
    - (void) requestAddonFPack1Data;
    - (void)loadStore;
    - (BOOL)canMakePurchases;
    
    /* PURCHASE PACKS */
    - (void)purchaseMAddonPack1;
    - (void)purchaseFAddonPack1;
    
    
    @end
    
    InAppPurchaseManager.m

    Code:
    
    //
    //  InAppPurchaseManager.m
    //
    //  Created by Thijs Bastiaens on 06/04/12.
    
    #import "InAppPurchaseManager.h"
    #import "SVProgressHUD.h"
    
    /*
    #define kInAppMPack1ProductId @"com.yourcompany.yourappName.malePack1"
    #define kInAppFPack1ProductId @"com.yourcompany.yourappName.femalePack1"
     */
    #define kInAppMPack1 @"malePack1"
    #define kInAppFPack1 @"femalePack1"
    
    @implementation InAppPurchaseManager
    SYNTHESIZE_SINGLETON_FOR_CLASS(InAppPurchaseManager);
    
    - (id)init
    {
        self = [super init];
        if (self) {
        }
        return self;
    }
    
    - (void)requestAddonMPack1Data
    {
        NSSet *productIdentifiers = [NSSet setWithObjects:kInAppMPack1, nil];
        productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
        productsRequest.delegate = self;
        [productsRequest start];
    }
    
    - (void) requestAddonFPack1Data {
        NSSet *productIdentifiers = [NSSet setWithObjects:kInAppFPack1, nil];
        productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
        productsRequest.delegate = self;
        [productsRequest start];
    }
    
    
    
    #pragma mark -
    #pragma mark SKProductsRequestDelegate methods
     
    - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
    {
        /*
        NSMutableArray *products = [[NSMutableArray alloc] initWithArray:response.products];
        proUpgradeProduct = [products count] == 1 ? [[products objectAtIndex:0] retain] : nil;
        if (proUpgradeProduct)
        {
            NSLog(@"Product title: %@" , proUpgradeProduct.localizedTitle);
            NSLog(@"Product description: %@" , proUpgradeProduct.localizedDescription);
            NSLog(@"Product price: %@" , proUpgradeProduct.price);
            NSLog(@"Product id: %@" , proUpgradeProduct.productIdentifier);
        }
        
        for (NSString *invalidProductId in response.invalidProductIdentifiers)
        {
            NSLog(@"Invalid product id: %@" , invalidProductId);
        }*/
        
        [[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerProductsFetchedNotification object:self userInfo:nil];
    }
    
    #pragma -
    #pragma Public methods
    
    //
    // call this method once on startup (For example, App Delegate)
    //
    - (void)loadStore
    {
        // restarts any purchases if they were interrupted last time the app was open
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
        
        // get the product description (defined in early sections)
        [self requestAddonMPack1Data];
        [self requestAddonFPack1Data];
    }
    
    //
    // call this before making a purchase
    //
    - (BOOL)canMakePurchases
    {
        NSLog(@"%i", [SKPaymentQueue canMakePayments]);
        return [SKPaymentQueue canMakePayments];
    }
    
    //
    // kick off the upgrade transaction
    //
    - (void)purchaseMAddonPack1
    {
        SKPayment *payment = [SKPayment paymentWithProductIdentifier:kInAppMPack1];
        [[SKPaymentQueue defaultQueue] addPayment:payment];
        [SVProgressHUD showWithStatus:@"Requesting Male Package" maskType:SVProgressHUDMaskTypeGradient];
    }
    
    - (void)purchaseFAddonPack1 {
        SKPayment *payment = [SKPayment paymentWithProductIdentifier:kInAppFPack1];
        [[SKPaymentQueue defaultQueue] addPayment:payment];
        [SVProgressHUD showWithStatus:@"Requesting Female Package" maskType:SVProgressHUDMaskTypeGradient];
    }
    
    #pragma -
    #pragma Purchase helpers
    
    //
    // saves a record of the transaction by storing the receipt to disk
    //
    - (void)recordTransaction:(SKPaymentTransaction *)transaction
    {
        if ([transaction.payment.productIdentifier isEqualToString:kInAppMPack1])
        {
            // save the transaction receipt to disk
            [[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:@"addonMPack1TransactionReceipt" ];
            [[NSUserDefaults standardUserDefaults] synchronize];
        } else if ([transaction.payment.productIdentifier isEqualToString:kInAppMPack1]) {
            // save the transaction receipt to disk
            [[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:@"addonFPack1TransactionReceipt" ];
            [[NSUserDefaults standardUserDefaults] synchronize];
        }
    }
    
    //
    // enable pro features
    //
    - (void)provideContent:(NSString *)productId
    {
        if ([productId isEqualToString:kInAppMPack1])
        {
            [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isMAddonPackage1Bought" ];
            [[NSUserDefaults standardUserDefaults] synchronize];
            [[NSNotificationCenter defaultCenter] postNotificationName:@"packageBought" object:nil];
        } else if ([productId isEqualToString:kInAppFPack1])
        {
            [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isFAddonPackage1Bought" ];
            [[NSUserDefaults standardUserDefaults] synchronize];
            [[NSNotificationCenter defaultCenter] postNotificationName:@"packageBought" object:nil];
        }
    }
    
    //
    // removes the transaction from the queue and posts a notification with the transaction result
    //
    - (void)finishTransaction:(SKPaymentTransaction *)transaction wasSuccessful:(BOOL)wasSuccessful
    {
        // remove the transaction from the payment queue.
        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        
        NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:transaction, @"transaction" , nil];
        if (wasSuccessful)
        {
            // send out a notification that we’ve finished the transaction
            [[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerTransactionSucceededNotification object:self userInfo:userInfo];
        }
        else
        {
            // send out a notification for the failed transaction
            [[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerTransactionFailedNotification object:self userInfo:userInfo];
        }
    }
    
    //
    // called when the transaction was successful
    //
    - (void)completeTransaction:(SKPaymentTransaction *)transaction
    {
        [self recordTransaction:transaction];
        [self provideContent:transaction.payment.productIdentifier];
        [self finishTransaction:transaction wasSuccessful:YES];
    }
    
    //
    // called when a transaction has been restored and and successfully completed
    //
    - (void)restoreTransaction:(SKPaymentTransaction *)transaction
    {
        [self recordTransaction:transaction.originalTransaction];
        [self provideContent:transaction.originalTransaction.payment.productIdentifier];
        [self finishTransaction:transaction wasSuccessful:YES];
    }
    
    //
    // called when a transaction has failed
    //
    - (void)failedTransaction:(SKPaymentTransaction *)transaction
    {
        if (transaction.error.code != SKErrorPaymentCancelled)
        {
            // error!
            [self finishTransaction:transaction wasSuccessful:NO];
        }
        else
        {
            // this is fine, the user just cancelled, so don’t notify
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        }
    }
    
    #pragma mark -
    #pragma mark SKPaymentTransactionObserver methods
    
    //
    // called when the transaction status is updated
    //
    - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
    {
        for (SKPaymentTransaction *transaction in transactions)
        {
            switch (transaction.transactionState)
            {
                case SKPaymentTransactionStatePurchased:
                    [self completeTransaction:transaction];
                    break;
                case SKPaymentTransactionStateFailed:
                    [self failedTransaction:transaction];
                    break;
                case SKPaymentTransactionStateRestored:
                    [self restoreTransaction:transaction];
                    break;
                default:
                    break;
            }
        }
        [SVProgressHUD dismiss];
    }
    
    @end
    
    You can also use an SKProduct category called LocalizedPrice (this is taken from a blog the code, so I don't take any credit).

    SKProduct+LocalizedPrice.h

    Code:
    
    //
    //  SKProduct+LocalizedPrice.h
    //
    //  Created by Thijs Bastiaens on 06/04/12.
    
    #import <StoreKit/StoreKit.h>
    
    @interface SKProduct (LocalizedPrice)
    
    @property (nonatomic, readonly) NSString *localizedPrice;
    
    
    @end
    
    .M file
    Code:
    
    //
    //  SKProduct+LocalizedPrice.m
    //
    //  Created by Thijs Bastiaens on 06/04/12.
    
    #import "SKProduct+LocalizedPrice.h"
    
    @implementation SKProduct (LocalizedPrice)
    
    - (NSString *)localizedPrice
    {
        NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
        [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
        [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
        [numberFormatter setLocale:self.priceLocale];
        NSString *formattedString = [numberFormatter stringFromNumber:self.price];
        [numberFormatter release];
        return formattedString;
    }
    
    @end
    
    After that, basically in your code you can do stuff like this ->

    Code:
    - (IBAction)pressedButton:(id)sender {
        UIButton *button = (UIButton*)sender;
        NSInteger taggie = button.tag;
        if (taggie == 0) {
            [self goToMainVCWithArray:[[DataUtil sharedDataUtil] getArrayWithInteger:taggie+1]]; 
        }
        else if ([self packageBought]) {
            [self goToMainVCWithArray:[[DataUtil sharedDataUtil] getArrayWithInteger:taggie+1]]; 
        } else {
            if ([[DataUtil sharedDataUtil] gender] == kTypeMale) {
                [[InAppPurchaseManager sharedInAppPurchaseManager] purchaseMAddonPack1];
            } else if ([[DataUtil sharedDataUtil] gender] == kTypeFemale) {
                [[InAppPurchaseManager sharedInAppPurchaseManager] purchaseFAddonPack1];
            }
        }
    }
    
    - (BOOL) packageBought {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        if ([[DataUtil sharedDataUtil] gender] == kTypeMale) {
            if ([defaults boolForKey:@"isMAddonPackage1Bought"] == YES) {
                return YES;
            } else {
                return NO;
            }
        } else  if ([[DataUtil sharedDataUtil] gender] == kTypeFemale) {
            if ([defaults boolForKey:@"isFAddonPackage1Bought"] == YES) {
                return YES;
            } else {
                return NO;
            }
        }
        return NO;
    }
    I tried to make a clean example, I hope it can helps you :)
    (the itunes connect steps are ignored in my "guide")

    EDIT
    ALso, in your view controller, you can listen to ->
    Code:
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadButtons) name:@"packageBought" object:nil];
    To optionally refresh your UI :)
     
  3. kevindosi thread starter macrumors regular

    Joined:
    Mar 16, 2006
    #3
    Hey, thanks for your post! That looks like a very clear tutorial, and I know there are a lot of helpful people on here who can help out. The problem is that I'm such a beginner, that I don't feel completely comfortable even with a nice tutorial like this. I can try it on my own using a tutorial like yours, I just don't feel completely comfortable because I still don't know what I'm doing, haha. That's why I was looking for someone who can guide me through the process, because I'm a visual person and the feedback is helpful. If I can't find anyone, I'll give this a whirl too.
     
  4. jnoxx macrumors 65816

    jnoxx

    Joined:
    Dec 29, 2010
    Location:
    Aartselaar // Antwerp // Belgium
    #4
    Just PM Me with more specific questions, otherwise this thread will end up in a "Star Wars vs Star Trek thread", with that I mean, in the end, people will end up talking about the SDK of In App Purchase of Apple, next thing you know, you're talking bout how LIght Sabers are the best.. (I want to avoid that, so mail me)
     
  5. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #5
  6. kevindosi thread starter macrumors regular

    Joined:
    Mar 16, 2006
    #6

Share This Page