15

まれに、非消耗品を購入できないユーザーがいるようです。購入しようとしても「プレミアム」がアクティブ化されず、現在のインストールまたは新規インストールから復元するときにpaymentQueue: updatedTransactions:呼び出されません。

復元が予期されたフローに従っていない理由を特定するために、特に多くのログを追加しました。復元が失敗した場合、「RESTORE」カテゴリのイベントは発生しません。

参考まで[self success];に、コンテンツ ビューを[self fail:]表示するだけで、代わりにユーザーにエラー メッセージを表示します。

また[[SKPaymentQueue defaultQueue] addTransactionObserver:self];、呼び出され、ボタンを押すと呼び出されますviewDidLoad[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];

- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
    // COMPLETION POINT - RESTORE COMPLETE***
    [MBProgressHUD hideHUDForView:self.view animated:TRUE];

    if ([SKPaymentQueue defaultQueue].transactions.count == 0) {
        [self.tracker send:[[GAIDictionaryBuilder createEventWithCategory:@"RESTORE"
                                                                   action:@"failure_hard"
                                                                    label:@"no_purchases"
                                                                    value:nil] build]];
        [self fail:@"There are no items available to restore at this time."];
    } else {
        [self success];
    }
}

- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
    // COMPLETION POINT - RESTORE FAILED
    [MBProgressHUD hideHUDForView:self.view animated:TRUE];

    [self.tracker send:[[GAIDictionaryBuilder createEventWithCategory:@"RESTORE"
                                                               action:@"failure_hard"
                                                                label:error.localizedDescription
                                                                value:nil] build]];
    [self fail:error.localizedDescription];
}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
    // Make sure completion states call [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    // in order to prevent sign in popup
    // http://stackoverflow.com/a/10853107/740474
    [MBProgressHUD hideHUDForView:self.view animated:TRUE];
    for (SKPaymentTransaction *transaction in transactions) {
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchasing:
                break;
            case SKPaymentTransactionStateDeferred:
                break;
            case SKPaymentTransactionStateFailed:
                // COMPLETION POINT - PURCHASE FAILED
                [self.tracker send:[[GAIDictionaryBuilder createEventWithCategory:@"PURCHASE"
                                                                           action:@"failure_hard"
                                                                            label:transaction.error.localizedDescription
                                                                            value:nil] build]];
                if (transaction.error.code != SKErrorPaymentCancelled) {
                    // only show error if not a cancel
                    [self fail:transaction.error.localizedDescription];
                }
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
            case SKPaymentTransactionStatePurchased:
                // COMPLETION POINT - PURCHASE SUCCESS
                if ([transaction.payment.productIdentifier isEqualToString:(NSString*)productID]) {
                    // premium purchase successful
                    [self.tracker send:[[GAIDictionaryBuilder createEventWithCategory:@"PURCHASE"
                                                                               action:@"success"
                                                                                label:nil
                                                                                value:nil] build]];
                    [Utils setPremium:YES];
                    [self success];
                } else {
                    [self.tracker send:[[GAIDictionaryBuilder createEventWithCategory:@"PURCHASE"
                                                                               action:@"failure_hard"
                                                                                label:@"no_id"
                                                                                value:nil] build]];
                    [self fail:@"The item you purchased was not returned from Apple servers. Please contact us."];
                }
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
            case SKPaymentTransactionStateRestored:
                if ([transaction.payment.productIdentifier isEqualToString:(NSString*)productID]) {
                    // premium purchase restored
                    [self.tracker send:[[GAIDictionaryBuilder createEventWithCategory:@"RESTORE"
                                                                               action:@"restore_success"
                                                                                label:nil
                                                                                value:nil] build]];
                    [Utils setPremium:YES];
                } else {
                    [self.tracker send:[[GAIDictionaryBuilder createEventWithCategory:@"RESTORE"
                                                                               action:@"failure_hard"
                                                                                label:@"no_id"
                                                                                value:nil] build]];
                }
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
            default:
                // For debugging
                   [self.tracker send:[[GAIDictionaryBuilder createEventWithCategory:@"STORE"
                                                                           action:@"transaction_weird"
                                                                               label:[NSString stringWithFormat:@"Unexpected transaction state %@", @(transaction.transactionState)]
                                                                            value:nil] build]];
                break;
        }
    }
}

任意の提案をいただければ幸いです

4

6 に答える 6

1

これがあなたの問題と関係があるかどうかはわかりませんが、それが原因である可能性があります。(または、少なくともアップルが推奨することです)。

アップルのドキュメント

Apple は、SKPaymentQueue を特定のクラスではなく、AppDelegate のオブザーバーとして登録することをお勧めます (AppDelegate 自体でこのクラスを呼び出さない限り)。

これは、次のことを意味します。

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

実際には、AppDelegate 内のapplicationDidFinishLaunchingWithOptionsメソッド内に移動する必要があります。

何でこれが大切ですか?あなたは次のように述べました:

復元が失敗した場合、「RESTORE」カテゴリのイベントは発生しません。

これは、リスナーが適切に登録されていない、または時間どおりに登録されていないと私に信じさせます. (または非常にまれなケースですが、ユーザーが適切にログインするためにアプリの外部にリダイレクトされたり、メモリの問題によってアプリが強制終了されたりする場合があります。どちらの方法でも、ユーザーがアプリに戻るとすぐに、常にApple から送信された通知を処理する準備ができているオブザーバー)


アプリの領収書を使用して購入を復元する

ドキュメンテーションはこちら

または、アプリの領収書を更新し、ユーザーが購入したものに基づいてコンテンツを配信することで、購入の復元ロジックを実装する方がはるかに簡単です。

request = [[SKReceiptRefreshRequest alloc] init];
request.delegate = self;
[request start];

これにより、デリゲート メソッドが呼び出されます。

func requestDidFinish(SKRequest)

また

func request(SKRequest, didFailWithError: Error)

リクエストが正常に終了したら、領収書を解析して、以前に購入したすべてのアイテムをユーザーに付与できます。領収書の解析ガイドについては、こちらで説明しています。

于 2017-07-18T02:12:24.503 に答える