在我以前的应用程序中,只有一个IAP,所以我没有意识到我的代码存在问题。今天我有一个带有多个IAP产品的应用程序,我发现了这个问题。
我跟着Troy's IAP tutorial,几乎复制了他的代码。这适用于我以前的应用程序,因为每个应用程序中只有一个IAP产品。本教程也使用一个IAP产品作为示例。我试图在他的博客上发帖询问我的问题,但我的帖子太长,没有格式化,而且我认为这里的专家可以帮助我理解更多,并检查我是否误解了某些内容或遗漏了什么。
现在我必须处理两件事(除非我错过了,教程没有提到多个IAP产品的情况)。
1,我不知道我是否误解了,在教程中,有一个对loadStore方法的评论,就像这样
//
// call this method once on startup
//
- (void)loadStore {
// restarts any purchases if they were interrupted last time the app was open
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
// get the product description (defined in early sections)
[self requestProUpgradeProductData];
}
所以我在ViewController.m文件中的应用程序开头调用此方法。我的理解是这个方法需要检查是否有任何先前的事务挂在那里,并且需要在应用程序重新启动时处理它。这是此loadStore方法的第一个语句。该方法继续调用requestProUpgradeProductData,如下所示:
- (void)requestProUpgradeProductData {
NSSet *productIdentifiers = [NSSet setWithObject:@"com.runmonster.runmonsterfree.upgradetopro" ];
productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate = self;
[productsRequest start];
// we will release the request object in the delegate callback
}
请注意,此方法中的第一个语句是获取IAP产品ID。这对于单IAP产品应用程序来说都很好,因为产品ID是固定的,并且可以在运行应用程序之初调用loadStore。实际上,loadStore可能必须在运行应用程序的开始时运行,因为,这是第二个问题。
2,如果loadStore在用户想要购买IAP的时刻运行,而不是在应用程序的开头,那么当[productRequest start]运行时,将运行以下方法:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray *products = response.products;
proUpgradeProduct = [products count] == 1 ? [[products firstObject] retain] : nil;
if (proUpgradeProduct)
{
NSLog(@"Product title: %@" , proUpgradeProduct.localizedTitle);
NSLog(@"Product description: %@" , proUpgradeProduct.localizedDescription);
NSLog(@"Product price: %@" , proUpgradeProduct.price);
NSLog(@"Product id: %@" , proUpgradeProduct.productIdentifier);
}
for (NSString *invalidProductId in response.invalidProductIdentifiers)
{
NSLog(@"Invalid product id: %@" , invalidProductId);
}
// finally release the reqest we alloc/init’ed in requestProUpgradeProductData
[productsRequest release]; //I didn't do this because of ARC
[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseManagerProductsFetchedNotification object:self userInfo:nil];
}
这将运行并返回产品响应。然后我需要开始付款,但我不确定如何调用以下方法。这是启动IAP付款的方法。正如我所提到的,一旦loadStore在应用程序的开头运行,就会有足够的时间用于productRequest ....响应方法(右上图)完成并发送回通知,因为用户点击此处和那里一秒钟。正如我所说,对于one-IAP产品应用程序,没关系,我可以在开头指定产品ID。现在,对于具有多IAP产品的应用,我需要向用户呈现多个产品,并且用户选择其中一个。在此之后,我需要按顺序执行两项操作:A,通过loadStore指定哪个IAP产品 - > productRequest方法(右上图)和B,调用以下方法来启动付款。
- (void)purchaseProUpgrade
{
SKPayment *payment = [SKPayment paymentWithProductIdentifier:kInAppPurchaseProUpgradeProductId];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
但是,在我调用付款启动方法的那一刻,productRequest .....响应方法可能还没有返回。我无法付款。我想在一两秒左右之间设置延迟功能,但我认为这种方法根本就是错误的。但是,如何解决这个问题呢?
有人可以帮忙吗?
答案 0 :(得分:1)
关键是,在您从productsRequest
收到回复之前,您不能允许用户购买任何内容。首先,initWithProductIdentifiers:
采用一组标识符。因此,在应用启动时或在向用户提供购买选项之前的任何其他时间,您可以使用标识符/ skus为您可以允许用户购买的所有产品调用它。在启动时调用它似乎对我来说是浪费,但它也应该工作,可能是某些应用程序的唯一选择。
只有在获得包含产品对象的productsRequest:didReceiveResponse:
回调后,才允许用户点击/触摸或以其他方式调用该产品的购买操作。在允许用户尝试购买之前,您必须检查响应以确保产品存在。我有一个购买屏幕,当用户输入时,我调用productsRequest
所有与应用程序当前状态相关的产品(例如,省略已经购买的商品或按级别限制产品)。我也创建了购买屏幕,但我没有用任何产品填充它。在响应委托中,我实际上用可购买的对象填充屏幕。这样,用户就不能尝试购买无效产品。
当用户点击/点击时,您可以使用响应中的产品对象创建付款对象:
[SKPayment paymentWithProduct:product]
请注意,这是对使用paymentWithProductIdentifier:
的当前设置的更改 - 不推荐使用的方法。