ios - 购买Apple商店产品导致启动时出现 "Purchased"状态

标签 ios objective-c iphone in-app-purchase

现在我正在努力解决下一个问题。我已经制作了简单的 IAPManager 用于在我的应用程序中从 AppStore 购买东西,但问题是 - 当我尝试购买产品时,应用程序调用 updatedTransactions 方法,交易状态为 Purchased 就在显示警报之前,如果我想买那个东西。

只有当我试图在应用程序启动前购买东西时才会发生。在我重新加载应用程序之前,它不会再发生。这是我的 IAPManager 代码:

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

        NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
        _receipt = receiptURL.absoluteString;
        NSLog(@"Receipt = %@", _receipt);
    }

    return self;
}

- (void)purchaseSmallCreditPackWithCompletion:(IAPManagerBlock)completionBlock failure:(IAPManagerBlock)failureBlock
{
    [self makePurchaseWithId:iap_SmallCreditPack completion:completionBlock failure:failureBlock];
}

- (void)purchaseMiddleCreditPackWithCompletion:(IAPManagerBlock)completionBlock failure:(IAPManagerBlock)failureBlock
{
    [self makePurchaseWithId:iap_MiddleCreditPack completion:completionBlock failure:failureBlock];
}

- (void)purchaseLargeCreditPackWithCompletion:(IAPManagerBlock)completionBlock failure:(IAPManagerBlock)failureBlock
{
    [self makePurchaseWithId:iap_LargeCreditPack completion:completionBlock failure:failureBlock];
}

- (void)makePurchaseWithId:(NSString *)idStr completion:(IAPManagerBlock)completionBlock failure:(IAPManagerBlock)failureBlock
{
    if ([SKPaymentQueue canMakePayments]) {

        _completionBlock = completionBlock;
        _failureBlock = failureBlock;

        SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:idStr]];
        productsRequest.delegate = self;
        [productsRequest start];
    }
    else
    {
        NSLog(@"This user can't make any payments");
    }
}

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    if (response.products.count == 0) {
        NSLog(@"There're no any products whatsoever");
        return;
    }

    SKProduct *product = [response.products firstObject];
    [self purchase:product];
}

- (void)purchase:(SKProduct *)product
{
    SKPayment *payment = [SKPayment paymentWithProduct:product];

    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions
{
    SKPaymentTransaction *transaction = [transactions firstObject];

    switch (transaction.transactionState) {
        case SKPaymentTransactionStatePurchasing:

            NSLog(@"Purchasing %@...", transaction.payment.productIdentifier);

            break;
        case SKPaymentTransactionStateFailed:
        {
            NSLog(@"Failed to purchase %@", transaction.payment.productIdentifier);

            if (_failureBlock) {
                _failureBlock();
            }

            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        }
            break;
        case SKPaymentTransactionStateRestored:
        {
            //just in case, we don't need to restore anything so far
            if (_completionBlock) {
                _completionBlock();
            }

            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        }
            break;
        case SKPaymentTransactionStatePurchased:
        {

            NSLog(@"Purchased %@", transaction.description);
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

            NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
            NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
            NSString *strReceipt = [receiptData base64EncodedStringWithOptions:0];
            //NSLog(@"strReceipt = %@", strReceipt);

        }
            break;
        default:
            break;
    }
}

- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray<SKPaymentTransaction *> *)transactions
{
    NSLog(@"Removed Transactions");

    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

最佳答案

我认为你的问题与观察者有关。正如我所见,您每次尝试购买产品时都会添加交易观察者,并在从交易队列中删除交易(任何)时将其删除。

如果您的交易未完成并且您的应用程序已关闭,您将在打开应用程序时收到有关交易完成的通知。所以你不会收到这个通知,你会错过它。

我建议你在 init 方法中添加观察者,不要因为我之前详细说明的原因而将其删除。另外,我建议您在打开应用程序 (didFinishLaunchingWithOptions:) 时创建 IAP 类的实例,以设置交易观察者并接收交易的这些延迟通知。

还有一件事......您应该管理您的交易数组,而不仅仅是第一个。

你应该创建一个 for 循环来像这样处理它们

for (SKPaymentTransaction *transaction in transactions) {
     switch (transaction.transactionState) {
          case SKPaymentTransactionStatePurchased: {
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            break;
          }
          case SKPaymentTransactionStateFailed:
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            break;
          case SKPaymentTransactionStateRestored:
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            break;
          case SKPaymentTransactionStatePurchasing:
            break;
          case SKPaymentTransactionStateDeferred:
            break;
          default:
            break;
    }
};

关于ios - 购买Apple商店产品导致启动时出现 "Purchased"状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40287148/

相关文章:

iphone - 跨多个 View 使用 CoreLocation 的最佳方式

iphone - Facebook SSO 并请求 iOS SDK

iphone - CoreData 相当于 sum...group by

javascript - 谁能帮我分离世博会应用程序

iphone - 当按下 childViewController 中的后退按钮时更改 ParentViewController 中的值

ios - 在 iOS 中使用循环动画​​背景

objective-c - 使用 iPhone SDK 设置预约

iphone - 如何在拍摄照片的那一刻暂停视频?

objective-c - Sin 和 Cos 函数返回不正确的结果

ios - AppDelegate 类声明中的 EXC_BAD_ACCESS