Resolved In-App Purchase, Problems & Solutions

Discussion in 'iOS Programming' started by ArtOfWarfare, Oct 24, 2011.

  1. ArtOfWarfare, Oct 24, 2011
    Last edited: Oct 25, 2011

    ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #1
    Edit #4: Error 0 Solved

    I created a new test user with an email address I knew. I signed out of the store in the Settings app, then opened my app (no new install of it needed) and attempted to purchase with the new account. It said I needed to verify the account, so I did, and I went back and tried again, and it worked!

    So, hopefully this thread can help someone with any of the numerous IAP issues I had.

    (Resolved) Edit #3: Getting error 0?

    This is the article that made me think threading might have anything to do with getting error 0:
    http://blog.mugunthkumar.com/coding...annot-connect-to-itunes-store-skerrorunknown/

    So I decided to replace:
    Code:
    [[SKPaymentQueue defaultQueue] addPayment:[SKPayment paymentWithProductIdentifier:@"quickClipsAdRemoval"]];
    with:
    Code:
    [[SKPaymentQueue defaultQueue] performSelectorOnMainThread:(@selector(addPayment:)) withObject:[SKPayment paymentWithProductIdentifier:@"quickClipsAdRemoval"] waitUntilDone:NO];
    but it appears to have resolved nothing. I still receive an error code of 0.

    I could really use some help...

    (Resolved) Edit #2: Fixed 5002

    I resolved 5002 by deleting the app from my iPhone, then logging out from the store in settings, then installing my app on my iPhone again, and then logging in when it prompted me to in my app. Somehow it wasn't going to the sandbox environment before. And now I'm receiving error 0, which something has told me is possibly because my call to add my product to the queue isn't occurring on the main thread.

    (Resolved) Edit #1: Fixed Crash

    I looked through the crash log and noticed that finishTransaction: was getting called. Seemed odd, given that the Store Kit never gave me a confirmation page. I looked into my code a bit and found that in my effort to reduce how many lines I use, I moved finishTransaction: outside of the switch statement for my transaction observer. I checked the method for finishedTransaction:, and found that evidently invoking finishedTransaction: on a transaction in the middle of purchasing will cause the application to crash. So, yeah, that's the cause of the crash. I fixed that. Now I have an error 5002.

    (Resolved) Original: Getting a Crash...

    Okay, so this whole thing was weird.

    I made an IAP for version 1.0 of my app, but forgot to attach the IAP when I uploaded the app to Apple, so it didn't ever get reviewed.

    Then in 1.1, I remembered to include it for review. The app as a whole was rejected, but my IAP remained "In-Review".

    Before releasing 1.2, I wanted to test my IAP, but I couldn't, because it was stuck "In-Review". When I tested my app, I always ended up with the issue that
    Code:
    - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
    the response was always an empty array while testing, I figured because of the limbo my IAP was stuck in. The empty array caused my app to display an error message, and I decided all I could do was hope that it would work when 1.2 was released, and if it didn't, at least it would have the grace to explain that it failed.

    Well, 1.2 has now been released, and when users are going to get the IAP, the app doesn't throw up an error, instead, it just crashes.

    Here's all the code:

    In my header, I've got these:
    Code:
    #import <StoreKit/StoreKit.h> //The framework is included in my project.
    #import "Reachability.h"
    
    @interface HelpMenu : UIViewController <... UIAlertViewDelegate, SKProductsRequestDelegate, SKPaymentTransactionObserver>
    {
        IBOutlet    UIBarButtonItem         *purchaseButton;
        IBOutlet    UIActivityIndicatorView *purchaseIndicator;
        int                                 responseStatus;
    }
    
    - (IBAction)purchase;
    In main, the related portions are:
    Code:
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            if ([[NSUserDefaults standardUserDefaults] dataForKey:@"receipt"])
            { ... }
            
            else if ([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] == NotReachable)
            {
                NSLog(@"No internet connection.");
            }
            
            else
            {
                if ([SKPaymentQueue canMakePayments])
                {
                    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
                    SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject: @"quickClipsAdRemoval"]];
                    request.delegate = self;
                    responseStatus = 0;
                    [request start];
                }
                else
                {
                    NSLog(@"Not allowed to make purchases.");
                }
            }
            
        }
        return self;
    }
    Code:
    - (IBAction)purchase
    {
        [super viewDidLoad];
        if ([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] == NotReachable)
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"No Internet Connection"
                                                            message:@"You cannot upgrade to premium because you don't have an internet connection on this device."
                                                           delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alert show];
            [alert release];
        }
        
        else
        {
            if ([SKPaymentQueue canMakePayments])
            {
                purchaseButton.enabled = NO;
                switch (responseStatus)
                {
                    case 2: ;
                        NSLog(@"Response had been of failure already.");
                        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Purchase Failed"
                                                                        message:@"The response from the App Store was not as expected. Close and reopen the help menu and try again. If the problem persists, contact the developer."
                                                                       delegate:nil
                                                              cancelButtonTitle:@"OK"
                                                              otherButtonTitles:nil];
    // Generally the error message I got while testing.
                        [alert show];
                        [alert release];
                        purchaseButton.title = @"Failed";
                        break;
                    case 1:
                        NSLog(@"Response had been of success already.");
                        [[SKPaymentQueue defaultQueue] addPayment:[SKPayment paymentWithProductIdentifier:@"quickClipsAdRemoval"]];
                    default:
                        purchaseButton.title = @"   ";
                        [purchaseIndicator startAnimating];
                        break;
                }
            }
            else
            {
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"In-App Purchases are Disabled"
                                                                message:@"You cannot upgrade to premium because In-App Purchases are disabled on this device. To change this, go to your device Settings, choose General, then Restrictions, and enable In-App Purchases."
                                                               delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
                [alert show];
                [alert release];
            }
        }
    }
    Code:
    - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
    {
        NSLog(@"The response count was %i", [response.products count]);
        if ([response.products count] == 1)
        {
            responseStatus = 1;
            if ([purchaseButton.title isEqualToString:@"   "])
            {
                NSLog(@"Purchase had been attempted already.");
                [[SKPaymentQueue defaultQueue] addPayment:[SKPayment paymentWithProductIdentifier:@"quickClipsAdRemoval"]];
            }
        }
        
        else
        {
            responseStatus = 2;
            if ([purchaseButton.title isEqualToString:@"   "])
            {
                NSLog(@"Purchase had been attempted already.");
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Purchase Failed"
                                                                message:@"The response from the App Store was not as expected. Dismiss and reopen the help menu and try again. If the problem persists, contact the developer from the bottom of the help menu."
                                                               delegate:nil
                                                      cancelButtonTitle:@"OK"
                                                      otherButtonTitles:nil];
                [alert show];
                [alert release];
                purchaseButton.title = @"Failed";
                [purchaseIndicator stopAnimating];
            }
        }
        
        [request autorelease];
    }
    Thus far, people have not been getting error popups, but simply crashes when they hit the button.

    Here's what looks like the relevant portion of the crash log:
    Code:
    Exception Type:  EXC_CRASH (SIGABRT)
    Exception Codes: 0x00000000, 0x00000000
    Crashed Thread:  0
    
    Last Exception Backtrace:
    0   CoreFoundation                	0x370f48bf __exceptionPreprocess + 163
    1   libobjc.A.dylib               	0x324641e5 objc_exception_throw + 33
    2   CoreFoundation                	0x370f47b9 +[NSException raise:format:] + 1
    3   CoreFoundation                	0x370f47db +[NSException raise:format:] + 35
    4   StoreKit                      	0x33fd9ac9 -[SKPaymentQueue finishTransaction:] + 81
    5   QuickClip                     	0x00016193 -[HelpMenu paymentQueue:updatedTransactions:] (HelpMenu.m:368)
    6   StoreKit                      	0x33fda7a7 __NotifyObserverAboutChanges + 59
    7   CoreFoundation                	0x37043c8b CFArrayApplyFunction + 39
    8   StoreKit                      	0x33fda763 -[SKPaymentQueue _notifyObserversAboutChanges:] + 119
    9   StoreKit                      	0x33fda453 -[SKPaymentQueue _addLocalTransactionForPayment:] + 251
    10  StoreKit                      	0x33fd994d -[SKPaymentQueue addPayment:] + 445
    11  QuickClip                     	0x00016cf7 -[HelpMenu purchase] (HelpMenu.m:122)
    12  CoreFoundation                	0x3704e435 -[NSObject performSelector:withObject:withObject:] + 53
    13  UIKit                         	0x31ce79eb -[UIApplication sendAction:to:from:forEvent:] + 63
    14  UIKit                         	0x31dad3cf -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 119
    15  CoreFoundation                	0x3704e435 -[NSObject performSelector:withObject:withObject:] + 53
    16  UIKit                         	0x31ce79eb -[UIApplication sendAction:to:from:forEvent:] + 63
    17  UIKit                         	0x31ce79a7 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 31
    18  UIKit                         	0x31ce7985 -[UIControl sendAction:to:forEvent:] + 45
    19  UIKit                         	0x31ce76f5 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 493
    20  UIKit                         	0x31ce802d -[UIControl touchesEnded:withEvent:] + 477
    21  UIKit                         	0x31ce650f -[UIWindow _sendTouchesForEvent:] + 319
    22  UIKit                         	0x31ce5f01 -[UIWindow sendEvent:] + 381
    23  UIKit                         	0x31ccc4ed -[UIApplication sendEvent:] + 357
    24  UIKit                         	0x31ccbd2d _UIApplicationHandleEvent + 5809
    25  GraphicsServices              	0x32d26e13 PurpleEventCallback + 883
    26  CoreFoundation                	0x370c8553 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 39
    27  CoreFoundation                	0x370c84f5 __CFRunLoopDoSource1 + 141
    28  CoreFoundation                	0x370c7343 __CFRunLoopRun + 1371
    29  CoreFoundation                	0x3704a4dd CFRunLoopRunSpecific + 301
    30  CoreFoundation                	0x3704a3a5 CFRunLoopRunInMode + 105
    31  GraphicsServices              	0x32d25fed GSEventRunModal + 157
    32  UIKit                         	0x31cfa743 UIApplicationMain + 1091
    33  QuickClip                     	0x0000246f main (main.m:14)
    34  QuickClip                     	0x00002428 0x1000 + 5160
    
    
    Thread 0 name:  Dispatch queue: com.apple.main-thread
    Thread 0 Crashed:
    0   libsystem_kernel.dylib        	0x30fcf32c __pthread_kill + 8
    1   libsystem_c.dylib             	0x380d5f54 pthread_kill + 48
    2   libsystem_c.dylib             	0x380cefe4 abort + 88
    3   libc++abi.dylib               	0x37159f64 abort_message + 40
    4   libc++abi.dylib               	0x37157346 _ZL17default_terminatev + 18
    5   libobjc.A.dylib               	0x324642dc _objc_terminate + 140
    6   libc++abi.dylib               	0x371573be _ZL19safe_handler_callerPFvvE + 70
    7   libc++abi.dylib               	0x3715744a std::terminate() + 14
    8   libc++abi.dylib               	0x3715881e __cxa_rethrow + 82
    9   libobjc.A.dylib               	0x3246422e objc_exception_rethrow + 6
    10  CoreFoundation                	0x3704a53e CFRunLoopRunSpecific + 398
    11  CoreFoundation                	0x3704a39e CFRunLoopRunInMode + 98
    12  GraphicsServices              	0x32d25fe6 GSEventRunModal + 150
    13  UIKit                         	0x31cfa73c UIApplicationMain + 1084
    14  QuickClip                     	0x00002468 main (main.m:14)
    15  QuickClip                     	0x00002420 0x1000 + 5152
     
  2. thedollarhunter macrumors member

    Joined:
    May 9, 2011
    Location:
    UK
  3. ArtOfWarfare thread starter macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #3
    I was actually looking for help when I posted each thing. It was at the end when I'd finally solved everything myself I decided to retitle the topic. Figured it can help someone (most likely me in the future) from going through the pain of figuring it all out from scratch.
     

Share This Page