2010-11-19 92 views
2

我在我的應用程序中使用In App Purchase,但是我在測試時遇到問題。我有四種消耗品。有關我在tableview中展示的產品的信息。有時當我點擊一個按鈕來購買一些產品時,我在updatedTransaction函數中獲得SKPaymentTransactionStateFailed的交易狀態,但transaction.error localizedFailureReason始終爲null。 一旦我注意到有一筆交易更新了兩次(在updatedTransaction函數交易中與transactionIdentifier相同,交易狀態爲SKPaymentTransactionStatePurchased) - 那麼這個產品是兩次購買的?iPhone In App購買問題

所以我不知道問題在哪裏。請幫幫我。

我使用這個類來管理應用程序內購買:

@implementation InAppPurchaseManager 

@synthesize upgradeProducts; 
@synthesize productsRequest; 
@synthesize delegate; 

- (id) init 
{ 
    self = [super init]; 
    if (!self) return nil; 

    if ([SKPaymentQueue canMakePayments]) { 
     [self loadStore]; 
     [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; 
    } 

    upgradeProducts = [[NSMutableArray alloc] init]; 
    delegate = nil; 

    return self; 
} 

+ (InAppPurchaseManager *) sharedInstance 
{ 
    static InAppPurchaseManager *myInstance = nil; 

    if (nil == myInstance) { 
     myInstance = [[[self class] alloc] init]; 
    } 

    return myInstance; 
} 

- (void) loadStore 
{ 
    NSSet *productsIdentifiers = [[NSSet alloc] initWithObjects:PRODUCT_1_ID, PRODUCT_2_ID, PRODUCT_3_ID, PRODUCT_4_ID, nil]; 
    [self requestUpgradeProductsData:productsIdentifiers]; 
     [productsIdentifiers release]; 
} 

- (void) requestUpgradeProductsData:(NSSet *) productIdentifiers 
{ 
    productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers]; 
    productsRequest.delegate = self; 
    [productsRequest start]; 
} 

- (void) productsRequest:(SKProductsRequest *) request didReceiveResponse:(SKProductsResponse *) response 
{ 
    [upgradeProducts removeAllObjects]; 

    for (int i = 0; i < [response.products count]; i++) { 
     SKProduct *product = [response.products objectAtIndex:i]; 

     UpgradeProduct *upgradeProduct = [[UpgradeProduct alloc] initWithProductID:product.productIdentifier]; 
     upgradeProduct.title = product.localizedTitle; 
     upgradeProduct.description = product.localizedDescription; 

     NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; 
     [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4]; 
     [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; 
     [numberFormatter setLocale:product.priceLocale]; 
     NSString *price = [numberFormatter stringFromNumber:product.price]; 
     [numberFormatter release]; 

     upgradeProduct.price = price; 

     [self.upgradeProducts addObject:upgradeProduct]; 

     [upgradeProduct release]; 
    } 

     [productsRequest release]; 

    if ([self.delegate respondsToSelector:@selector(didLoadStore:)]) 
     [self.delegate didLoadStore:self.upgradeProducts]; 
} 

+ (BOOL) canMakePurchases 
{ 
    if ([SKPaymentQueue canMakePayments]) 
     return YES; 
    else { 
     [Global showAlertViewWithTitle:NSLocalizedString(@"Payment Error", @"Payment Error Alert Title") 
              message:NSLocalizedString(@"You are not authorized to purchase from AppStore", @"Payment Error Alert Text when user cannot make payments from store")]; 
     return NO; 
    } 
} 

- (void) purchaseUpgrade:(NSString *) productIdentifier 
{ 
    if ([InAppPurchaseManager canMakePurchases]) { 
     SKPayment *payment = [SKPayment paymentWithProductIdentifier:productIdentifier]; 
     [[SKPaymentQueue defaultQueue] addPayment:payment]; 
    } 
} 

- (void) recordTransaction:(SKPaymentTransaction *) transaction 
{ 
    [[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:@"upgradeTransactionReceipt" ]; 
    [[NSUserDefaults standardUserDefaults] synchronize]; 
} 

- (void) finishTransaction:(SKPaymentTransaction *) transaction 
{ 
    [self paymentSucceeded:transaction]; 
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; 
} 

- (void) paymentSucceeded:(SKPaymentTransaction *) transaction 
{ 
    // provide content here 

    if ([self.delegate respondsToSelector:@selector(didFinishPaymentTransaction)]) 
     [self.delegate didFinishPaymentTransaction]; 
} 

- (void) completeTransaction:(SKPaymentTransaction *) transaction 
{ 
    [self recordTransaction:transaction]; 
    [self finishTransaction:transaction]; 
} 

- (void) restoreTransaction:(SKPaymentTransaction *) transaction 
{ 
    [self recordTransaction:transaction.originalTransaction]; 
    [self finishTransaction:transaction]; 
} 

- (void) failedTransaction:(SKPaymentTransaction *) transaction 
{ 
    if (transaction.error.code != SKErrorPaymentCancelled) { 
     NSMutableString *messageToBeShown = [[NSMutableString alloc] init]; 

     if ([transaction.error localizedFailureReason] != nil) { 
      [messageToBeShown setString:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"Reason:", @"Reason Text in alert when payment transaction failed"), [transaction.error localizedFailureReason]]]; 

      if ([transaction.error localizedRecoverySuggestion] != nil) 
       [messageToBeShown appendFormat:@", %@ %@", NSLocalizedString(@"You can try:", @"Text for sugesstion in alert when payment transaction failed"), [transaction.error localizedRecoverySuggestion]]; 
     } 

     [Global showAlertViewWithTitle:NSLocalizedString(@"Unable to complete your purchase", @"Payment transaction failed alert title") 
              message:messageToBeShown]; 

     [messageToBeShown release]; 

     if ([self.delegate respondsToSelector:@selector(didFailedPaymentTransaction)]) 
      [self.delegate didFailedPaymentTransaction]; 
    } else { 
     if ([self.delegate respondsToSelector:@selector(didCancelPaymentTransaction)]) 
      [self.delegate didCancelPaymentTransaction]; 
    } 

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; 
} 

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

- (void) request:(SKRequest *) request didFailWithError:(NSError *) error 
{ 
    [Global showAlertViewWithTitle:NSLocalizedString(@"Payment Error", @"Payment Error Alert Title") 
     message:[NSString stringWithFormat:@"%@, %@", NSLocalizedString(@"Could not contact App Store properly", @"Alert text when request did fail"), 
       [error localizedDescription]]]; 
} 

- (void) dealloc 
{ 
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self]; 

    [upgradeProducts release]; 

    if (productsRequest) 
     productsRequest = nil; 

    [super dealloc]; 
} 

@end 

在AppDelegate中的功能didFinishLaunchingWithOptions我作出這樣的:

[InAppPurchaseManager sharedInstance]; 

在採購視圖,當我點擊一個按鈕,我做:

UpgradeProduct *selectedProduct = [self.faxProducts objectAtIndex:[purchaseButton.identifier intValue]]; 

if (selectedProduct) { 
    [[InAppPurchaseManager sharedInstance] purchaseUpgrade:selectedProduct.productID]; 
} 

回答

0

請確保您正確使用AppID。我有同樣的問題「用戶取消」,並且我沒有使用正確的ID雙向調用交易。我自動附加com.mycompany.product「前綴到我的代碼,但在某些情況下,com.mycompany.product已被追加。菜鳥bug ...

0

我得到這個錯誤,因爲我有錯誤的產品標識符。

1

我有同樣的問題,觀察者總是有2交易。即使我刪除[[SKPaymentQueue defaultQueue] addPayment:payment],它仍然有1個交易。所以我懷疑「canMakePayments」

之後我刪除[SKPaymentQueue canMakePayments],這個問題似乎解決。 。不知道爲什麼,但可能會解決你的問題

2
[[SKPaymentQueue defaultQueue] addTransactionObserver:self]; 

此代碼錯誤,您不能多次使用。您知道,如果您將觀察者添加兩次,您會發現一次事務更新了兩次。

+0

您節省了我的Time..Thanks很多... – girish 2013-11-17 09:11:43

1

如果您只是測試,只需確保您從個人帳戶註銷並在iTunesConnect中創建一個新的測試帳戶。

奇怪的是,如果我不使用測試用戶,它會失敗。該API充滿了黑魔法,沒有多少解釋。

+0

偉大的答案 - 解決了我的問題 – Curnelious 2013-11-12 11:27:30