我在我的应用程序中使用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];
}
答案 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)
我收到此错误是因为我的产品标识错误了。