iPhone In App Purchase问题

时间:2010-11-19 08:48:30

标签: iphone in-app-purchase

我在我的应用程序中使用In App Purchase,但是在测试时我遇到了问题。我有四种消费品。有关我在tableview中展示的产品的信息。有时当我点击按钮购买某些产品时,我在SKPaymentTransactionStateFailed函数中获得了一个事务状态updatedTransaction,但transaction.error localizedFailureReason始终为null。 一旦我注意到一次交易被更新了两次(在updatedTransaction函数交易中出现了相同的transactionIdentifier,交易状态为SKPaymentTransactionStatePurchased) - 那么该产品是否被购买了两次?。< / p>

所以我不知道问题出在哪里。请帮帮我。

我使用该课程管理In App Purchase:

@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];
}

5 个答案:

答案 0 :(得分:2)

[[SKPaymentQueue defaultQueue] addTransactionObserver:self]; 

此代码错误,您不能使用多次。您知道,如果您将观察者添加两次,您会发现一个事务已更新两次。

答案 1 :(得分:1)

我有同样的问题,观察者总是有2个交易。即使我删除[[SKPaymentQueue defaultQueue] addPayment:payment],它仍然有1个交易。所以我怀疑“canMakePayments”

我删除[SKPaymentQueue canMakePayments]后,问题似乎解决了......不知道为什么,但可能会解决你的问题

答案 2 :(得分:1)

如果您只是进行测试,请确保从您的个人帐户退出并在iTunesConnect中创建一个新的测试帐户。

奇怪的是,如果我不使用测试用户,它将会失败。 API充满了黑魔法,几乎没有任何解释。

答案 3 :(得分:0)

确保正确使用AppID。我有同样的问题“用户取消”,我没有用正确的ID两次调用交易。我自动将com.mycompany.product“前缀附加到我的代码中,但在某些情况下,com.mycompany.product已经附加了.Rookie bug ...

答案 4 :(得分:0)

我收到此错误是因为我的产品标识错误了。