SKPaymentTransactionStatePurchased 多次调用错误

Posted

技术标签:

【中文标题】SKPaymentTransactionStatePurchased 多次调用错误【英文标题】:SKPaymentTransactionStatePurchased called multiple times by error 【发布时间】:2013-11-21 13:13:25 【问题描述】:

我正在进行应用内购买,但我有一个错误,我找不到它的来源...

首先,我有一个按钮,当您单击它时,我的应用程序会请求产品,捕获响应,您付款并获得产品(一切正常)。 但是我的问题来了。如果我点击按钮再次购买任何东西,我会收到两次提醒我买了两次东西。即使我第三次点击,我也会收到 3 次提醒我买了东西 3 次,根据我点击的次数分别是 4 次和 5 次。

所以似乎有些变量一直在存储请求。这是我的代码:

这会验证产品 ID

- (void) validateProductIdentifiers
 
NSString *monedas = @" ID FROM PRODUCT ";
NSSet *product = [NSSet setWithObject:monedas];

productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:product];

productsRequest.delegate = self;
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[productsRequest start];
NSLog(@"STARTED REQUEST");

这会处理来自 Apple 的响应

- (void)productsRequest:(SKProductsRequest *)request
 didReceiveResponse:(SKProductsResponse *)response



productsRequest=nil;

int found=0;

SKProduct *paraPagar;
skProducts = response.products;

for (SKProduct * skProduct in skProducts) 
             NSLog(@"Found product: %@ %@ %0.2f",
          skProduct.productIdentifier,
          skProduct.localizedTitle,
          skProduct.price.floatValue);
    found=1;

    paraPagar = skProduct;

if (found==1) 
    payment = [SKMutablePayment paymentWithProduct:paraPagar];
    payment.quantity = 1;

    [[SKPaymentQueue defaultQueue]addPayment:payment];

else 

 //error (not relevant code)



接受付款并完成交易

- (void)paymentQueue:(SKPaymentQueue *)queue
updatedTransactions:(NSArray *)transactions




for (SKPaymentTransaction *transaction in transactions) 
    switch (transaction.transactionState) 

        case SKPaymentTransactionStatePurchased:
            NSLog(@"BOUGHT");

            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            [self completeTransaction:transaction];


            break;
        case SKPaymentTransactionStateFailed:
            NSLog(@"FAILED");
           [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

            [self failedTransaction];
            break;
        case SKPaymentTransactionStateRestored:
            NSLog(@"RESTORED");
            //[self restoreTransaction:transaction];
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        case SKPaymentTransactionStatePurchasing:
            NSLog(@"PURCHASING");
        default:
            break;
    




非常感谢您的宝贵时间!

【问题讨论】:

【参考方案1】:

我的问题是每次单击按钮或更改视图时都会复制观察者。

解决方案是添加一个标志,看看是否已经添加了观察者。

static bool hasAddObserver=NO;

PAYMENT METHOD
if (!hasAddObserver) 
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    hasAddObserver=YES;

.....

【讨论】:

根据 Apple 的文档,“您的应用程序应在应用程序初始化期间将观察者添加到支付队列。” 所以您的解决方案有效,但更好的是开始观察交易一次只要您的应用启动。【参考方案2】:

我遇到了同样的问题,我会在 IAP 上点击购买,然后会收到来自 Apple 的多次回复和购买。

每次我离开时都会调用addTransactionObserver(),然后通过viewDidLoad()返回视图。

我需要在viewWillDisappear() 中取消观察它:

override func viewWillDisappear() 
  SKPaymentQueue.defaultQueue().removeTransactionObserver(self)

我无法使用标志来阻止像 mursang 回答中的多个观察者,因为我在其他视图中侦听了事务。

【讨论】:

好吧,我的观察者是 UIViewController 的后代,因为我需要它在 updatedTransactions: 方法中执行一些 UI 操作。在调用 viewDidLoad 方法并创建该 UIViewController 的实例之前,这是不可能完成的。【参考方案3】:

你还记得打电话吗

[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

什么时候购买完成?

【讨论】:

它是在“case SKPaymentTransactionStatePurchased:”中添加的,我需要在其他地方添加它吗?【参考方案4】:

Swift 3:根据@sponrad 的回答

override func viewWillDisappear(_ animated: Bool)  
    SKPaymentQueue.default().remove(self)

【讨论】:

有谁知道为什么需要这个?!你会认为我们不需要这个,它会包含在代码的事务完成部分中。【参考方案5】:

[addTransactionObserver] 应该只运行一次。

所以你可以使用单例模式来解决这个问题。

+ (InAppPurchase *)sharedInstance

    static dispatch_once_t once;
    static InAppPurchase * sharedInstance;
    dispatch_once(&once, ^
        sharedInstance = [[self alloc] initWithProductIdentifiers:nil];
    );
    return sharedInstance;


- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers 

    if ((self = [super init])) 
        // Add self as transaction observer
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    
    return self;

【讨论】:

但是不能解决这个问题。您最好在 didFinishLaunchingWithOptions 中调用它,例如 [InAppPurchase sharedInstance];当你想买东西时,你可以像 [[InAppPurchase sharedInstance] buyProduct:(SKProduct) myProduct];

以上是关于SKPaymentTransactionStatePurchased 多次调用错误的主要内容,如果未能解决你的问题,请参考以下文章