2010-11-19 94 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