【问题标题】:iPhone In App Purchase issueiPhone 应用内购买问题
【发布时间】:2010-11-19 08:48:30
【问题描述】:

我在我的应用程序中使用应用内购买,但在测试时我遇到了问题。我有四种消耗品。有关我在tableview 中显示的产品的信息。有时,当我单击按钮购买某些产品时,我在updatedTransaction 函数中得到一个交易状态SKPaymentTransactionStateFailed,但transaction.error localizedFailureReason 始终是null。 一旦我注意到一笔交易被更新了两次(在updatedTransaction 函数交易中具有相同的transactionIdentifier,交易状态为SKPaymentTransactionStatePurchased) - 那么该产品是否被购买了两次?。

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

我使用该类来管理应用内购买:

@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

在函数 didFinishLaunchingWithOptions 的 AppDelegate 中,我这样做:

[InAppPurchaseManager sharedInstance];

当我点击一个按钮时在购买视图中:

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

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

【问题讨论】:

    标签: iphone in-app-purchase


    【解决方案1】:
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; 
    

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          【解决方案4】:

          确保正确使用 AppID。我遇到了同样的问题“用户已取消”,而且我两次都没有使用正确的 ID 调用交易。我会自动将 com.mycompany.product" 前缀附加到我的代码中,但在某些情况下,com.mycompany.product 已被附加。新手错误...

          【讨论】:

            【解决方案5】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-03-12
              • 1970-01-01
              相关资源
              最近更新 更多