xcode 应用内购买 SKPaymentQueue 完成交易不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11008636/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 00:35:31  来源:igfitidea点击:

InApp Purchase SKPaymentQueue finish Transaction doesn't work

iphoneiosxcodeios5

提问by Dinesh

i am working inapp purchase project in iOS sdk.i have prepared inapp purchase class for purchasing app from appstore with enable inner contents of the project.but, my problem is SKPaymentQueue doesn't finish working on my class.here's code of my inapp purchase class:

我正在使用 iOS sdk 中的应用内购买项目。我已经准备了应用内购买类,用于从应用商店购买应用并启用项目的内部内容。但是,我的问题是 SKPaymentQueue 没有完成我的类的工作。这是我的应用内购买的代码班级:

- (void)purchase {
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
    SKPayment *payment = [SKPayment paymentWithProductIdentifier:@"com.test"];
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    [[SKPaymentQueue defaultQueue] addPayment:payment];

}

- (void)provideContent:(NSString *)productIdentifier {

    NSLog(@"Toggling flag for: %@", productIdentifier);
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:productIdentifier];
    [[NSUserDefaults standardUserDefaults] synchronize];
    //[_purchasedProducts addObject:productIdentifier];

    [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchasedNotification object:productIdentifier];

}

- (void)completeTransaction:(SKPaymentTransaction *)transaction {

    NSLog(@"completeTransaction...");

    //[self recordTransaction: transaction];
    [self provideContent: transaction.payment.productIdentifier];
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}

- (void)restoreTransaction:(SKPaymentTransaction *)transaction {

    NSLog(@"restoreTransaction...");

    //[self recordTransaction: transaction];
    [self provideContent: transaction.originalTransaction.payment.productIdentifier];
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}

- (void)failedTransaction:(SKPaymentTransaction *)transaction {

    if (transaction.error.code != SKErrorPaymentCancelled)
    {
        NSLog(@"Transaction error: %@", transaction.error.localizedDescription);
    }


    [[NSNotificationCenter defaultCenter] removeObserver:self name:kProductPurchaseFailedNotification object:transaction];


    [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchaseFailedNotification object:transaction];


    //[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationName" object:transaction];

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

}



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

    for (SKPaymentTransaction *transaction in transactions) {

        switch (transaction.transactionState) {

            case SKPaymentTransactionStatePurchasing:

                break;

            case SKPaymentTransactionStatePurchased:
                [self completeTransaction:transaction];
                //[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

                break;

            case SKPaymentTransactionStateRestored:
                //[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                [self restoreTransaction:transaction];

                break;

            case SKPaymentTransactionStateFailed:
                if (transaction.error.code != SKErrorPaymentCancelled) {
                    NSLog(@"An error encounterd");
                }
                else {
                    NSLog(@"Cancelled!");
                }
                //[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

                [self failedTransaction:transaction];

                break;

        }

    }

}

- (void)dealloc
{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

    [request release];
    [super dealloc];

}

that's line doesn't work on my class [[SKPaymentQueue defaultQueue] finishTransaction:transaction];transaction doesn't finish. and my another problem is nsnotificationcenter calls multiple times like if i click first time it's call only one time no problem,another time it's nsnotificationcenter calls 3 times.

那条线路对我的班级 [[SKPaymentQueue defaultQueue] finishTransaction:transaction];交易没有完成不起作用。我的另一个问题是 nsnotificationcenter 多次调用,就像我第一次点击它只调用一次没问题,另一次是 nsnotificationcenter 调用 3 次。

回答by Dinesh

i got solution your problem is addTransaction server duplicate to your issue,

我得到了解决方案,您的问题是 addTransaction 服务器与您的问题重复,

try below code it's must working:

尝试下面的代码它必须工作:

static bool hasAddObserver=NO;

- (void)purchase {
    if (!hasAddObserver) {//flag to fix this bug
        /*=====================================*/
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
        hasAddObserver=YES;
    }
    SKPayment *payment = [SKPayment paymentWithProductIdentifier:@"com.test"];
    //[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    [[SKPaymentQueue defaultQueue] addPayment:payment];

}


- (void)provideContent:(NSString *)productIdentifier {

    NSLog(@"Toggling flag for: %@", productIdentifier);
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:productIdentifier];
    [[NSUserDefaults standardUserDefaults] synchronize];
    //[_purchasedProducts addObject:productIdentifier];

    [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchasedNotification object:productIdentifier];

}

- (void)completeTransaction:(SKPaymentTransaction *)transaction {

    NSLog(@"completeTransaction...");

    //[self recordTransaction: transaction];
    [self provideContent: transaction.payment.productIdentifier];
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}

- (void)restoreTransaction:(SKPaymentTransaction *)transaction {

    NSLog(@"restoreTransaction...");

    //[self recordTransaction: transaction];
    [self provideContent: transaction.originalTransaction.payment.productIdentifier];
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}

- (void)failedTransaction:(SKPaymentTransaction *)transaction {

    if (transaction.error.code != SKErrorPaymentCancelled)
    {
        NSLog(@"Transaction error: %@", transaction.error.localizedDescription);
    }




    [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchaseFailedNotification object:transaction];


    //[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationName" object:transaction];

    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

}



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

    for (SKPaymentTransaction *transaction in transactions) {

        switch (transaction.transactionState) {

            case SKPaymentTransactionStatePurchasing:

                break;

            case SKPaymentTransactionStatePurchased:
                //[self completeTransaction:transaction];
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

                break;

            case SKPaymentTransactionStateRestored:
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                //[self restoreTransaction:transaction];

                break;

            case SKPaymentTransactionStateFailed:
                if (transaction.error.code != SKErrorPaymentCancelled) {
                    NSLog(@"An error encounterd");
                }
                else {
                    NSLog(@"Cancelled!");
                }
                //[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

                [self failedTransaction:transaction];

                break;

        }

    }

}

- (void)dealloc
{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

    [request release];
    [super dealloc];

}

Welcome!

欢迎!

回答by Kristoffer Stensaa

To fix this problem just add [[SKPaymentQueue defaultQueue]removeTransactionObserver:self];right after [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

要解决此问题,只需在[[SKPaymentQueue defaultQueue]removeTransactionObserver:self];之后添加[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

回答by Lova

You can do like this:

你可以这样做:

 - (void)buyProduct:(SKProduct *)product {

NSLog(@"Buying %@...", product.productIdentifier);
SKPayment * payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];

 }


- (void)validateReceiptForTransaction:(SKPaymentTransaction *)transaction {
VerificationController * verifier = [VerificationController sharedInstance];
[verifier verifyPurchase:transaction completionHandler:^(BOOL success) {
    if (success) {
        NSLog(@"Successfully verified receipt!");
        [self provideContentForProductIdentifier:transaction.payment.productIdentifier];
    } else {
        NSLog(@"Failed to validate receipt.");
        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];

    }
}];
}


#pragma mark SKPaymentTransactionOBserver

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions) {
    switch (transaction.transactionState) {
        case SKPaymentTransactionStatePurchasing:
            NSLog(@"Prossing.............");

            break;

        case SKPaymentTransactionStatePurchased:
        {

            [self completeTransaction:transaction];
            NSError* error;
            NSDictionary* jsonDict = [NSJSONSerialization
                                  JSONObjectWithData:transaction.transactionReceipt

                                  options:kNilOptions 
                                  error:&error];
            NSLog(@"JSON Receipt: %@",jsonDict);

            [[NSUserDefaults standardUserDefaults] setObject:jsonDict forKey:@"A"];
            NSLog(@"Purchase was a Success.....");
        }
            break;
        case SKPaymentTransactionStateFailed:

            [self failedTransaction:transaction];

            NSLog(@"Purchase cancelled");


            break;

        case SKPaymentTransactionStateRestored:

            [self restoreTransaction:transaction];

            default:

            break;
    }         
}
}



- (void)completeTransaction:(SKPaymentTransaction *)transaction {
NSLog(@"completeTransaction...");

[self validateReceiptForTransaction:transaction];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}


- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
NSLog(@"restoreTransaction...");

[self validateReceiptForTransaction:transaction];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}


 - (void)failedTransaction:(SKPaymentTransaction *)transaction {

NSLog(@"failedTransaction...");

[[SKPaymentQueue defaultQueue] finishTransaction: transaction];


if (transaction.error.code != SKErrorPaymentCancelled)
{
    NSLog(@"Transaction error: %@", transaction.error.localizedDescription);
    MedPulseAppDelegate *appdelegate =( MedPulseAppDelegate *)[[UIApplication sharedApplication]delegate];
    [appdelegate hideLoading];
}

[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}



 - (void)provideContentForProductIdentifier:(NSString *)productIdentifier {

if ([productIdentifier isEqualToString:kMDPulseSubscriptionProductIdentifier]) {
    [self purchaseSubscriptionWithMonths:1];
 }

[[NSNotificationCenter defaultCenter] postNotificationName:IAPHelperProductPurchasedNotification object:productIdentifier userInfo:nil];

  }



  - (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
NSLog(@"%s","User Cancel.");



  }



 - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
 {
NSLog(@"Restore completed transactions finished.");
NSLog(@" Number of transactions in queue: %d", [[queue transactions] count]);
for (SKPaymentTransaction *trans in [queue transactions])
  {
    NSLog(@" transaction id %@ for product %@.", [trans transactionIdentifier], [[trans payment] productIdentifier]);
    NSLog(@" original transaction id: %@ for product %@.", [[trans originalTransaction] transactionIdentifier],
          [[[trans originalTransaction] payment]productIdentifier]);


    if ([[[trans payment] productIdentifier] isEqual: kMDPulseSubscriptionProductIdentifier]) {

        NSLog(@"Purchase Restored");

        // Do your stuff to unlock
    }
  }
 }


 - (void)restoreCompletedTransactions
 {
    NSLog(@"Restore Tapped in transaction process");
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
  }

Welcome!
If you have any doubt comment it down

欢迎!
如果您有任何疑问,请发表评论