web-dev-qa-db-ja.com

アプリ購入の自動更新サブスクリプションが有効であるかをチェックする方法

アプリ内購入を使用して新しいAuto Renewableサブスクリプションを実装しようとしていますが、ユーザーが現在サブスクライブしているかどうかを確認する方法とタイミングがわかりません。私の理解では、ユーザーが最初にサブスクライブすると、アプリはサブスクリプションの日付と一緒に購入日を使用して、サブスクリプションの期間を計算できます。この日付が過ぎるとどうなりますか?ユーザーが自動更新またはキャンセルしたかどうかを確認するにはどうすればよいですか?

restoreCompletedTransactionsを使用して、更新ごとにトランザクションと領収書を取得すると、iTunesパスワードの入力を求められます。これは、7日間のサブスクリプションを購入した場合、アプリがサブスクリプションがまだ有効かどうかを確認するときに、7日ごとにパスワードを入力する必要があることを意味しますか?

31
Adam Swinden

Webサーバーから確認する場合は、APIにpingを送信すると、自動更新サブスクリプションのステータスと最後の支払いに関する情報が返されます。

デバイスを使用している場合は、おそらく、restoreCompletedTransactionsを呼び出す必要があります。

他の方法はありません。デバイスから、サーバー側で使用されているのと同じWebサービスにアクセスしてサブスクリプションを確認できると思いますか?その長所と短所がどのようになっているかはわかりません。

9

今日、私はこの問題に苦労しています。

フォロー Apple doc ここで、私はこの方法でサブスクリプションが期限切れかどうかを確認しました。私の考え:user Apple REST API response:(request time + expired time)to check切れかどうか)

+ (BOOL)checkInAppPurchaseStatus
{
    // Load the receipt from the app bundle.
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
    if (receipt) {
        BOOL sandbox = [[receiptURL lastPathComponent] isEqualToString:@"sandboxReceipt"];
        // Create the JSON object that describes the request
        NSError *error;
        NSDictionary *requestContents = @{
                                          @"receipt-data": [receipt base64EncodedStringWithOptions:0],@"password":@"SHARE_SECRET_CODE"
                                          };
        NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                              options:0
                                                                error:&error];

        if (requestData) {
            // Create a POST request with the receipt data.
            NSURL *storeURL = [NSURL URLWithString:@"https://buy.iTunes.Apple.com/verifyReceipt"];
            if (sandbox) {
                storeURL = [NSURL URLWithString:@"https://sandbox.iTunes.Apple.com/verifyReceipt"];
            }
            NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
            [storeRequest setHTTPMethod:@"POST"];
            [storeRequest setHTTPBody:requestData];

            BOOL rs = NO;
            //Can use sendAsynchronousRequest to request to Apple API, here I use sendSynchronousRequest
            NSError *error;
            NSURLResponse *response;
            NSData *resData = [NSURLConnection sendSynchronousRequest:storeRequest returningResponse:&response error:&error];
            if (error) {
                rs = NO;
            }
            else
            {
                NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:resData options:0 error:&error];
                if (!jsonResponse) {
                    rs = NO;
                }
                else
                {
                    NSLog(@"jsonResponse:%@", jsonResponse);

                    NSDictionary *dictLatestReceiptsInfo = jsonResponse[@"latest_receipt_info"];
                    long long int expirationDateMs = [[dictLatestReceiptsInfo valueForKeyPath:@"@max.expires_date_ms"] longLongValue];
                    long long requestDateMs = [jsonResponse[@"receipt"][@"request_date_ms"] longLongValue];
                    NSLog(@"%lld--%lld", expirationDateMs, requestDateMs);
                    rs = [[jsonResponse objectForKey:@"status"] integerValue] == 0 && (expirationDateMs > requestDateMs);
                }
            }
            return rs;
        }
        else
        {
            return NO;
        }
    }
    else
    {
        return NO;
    }
}

この助けを願っています。

16
Clover03ti05

Apple apiを呼び出す前にローカルソリューションを使用することをお勧めします。アプリが実行されるたびに、ローカルの領収書を検証し、ユーザーがアクティブなサブスクリプションでは、まずローカルの領収書から購入を取得し、購入が今日もまだアクティブであることを確認できます。

Swiftで記述された小さなライブラリを実装して、ローカルでのアプリ内受信の操作を簡素化しました。レシート(InAppReceipt)を表すオブジェクトを簡単にフェッチして、アクティブな購入/すべての購入を取得できます。

お気軽にご利用ください。 Githubリンク

問題を解決する例を次に示します。

import TPInAppReceipt

do {
    let receipt = try InAppReceiptManager.shared.receipt()

    //retrive active auto renewable subscription for a specific product and date
    let purchase = receipt.activeAutoRenewableSubscriptionPurchases(ofProductIdentifier: "ProductName", forDate: Date())

    //retrive all auto renewable subscription purchases for a specific product
    let allAutoRenewableSubscriptionPurchases = receipt.purchases(ofProductIdentifier: "productName").filter({ return $0.isRenewableSubscription })
} catch {
    print(error)
}
5
tikhop

この問題についてキャンペーンを始めています。これが私の観察とキャンペーンです。

自動更新時に、App StoreはpaymentQueueを呼び出してトランザクションをポストします。トランザクションは_transaction.transactionState==SKPaymentTransactionStateRestored_で転記されます。

問題は、残念ながらこれが1つのデバイスにのみ投稿されることです。 2番目のデバイスは投稿を取得しません。したがって、自動更新を検出する、または自動更新の欠如を検出して、デバイスの継続的なサブスクリプションを拒否するには、restoreCompletedTransactionまたは "httpに64ビットでエンコードされた最後のJSONを含むJSONをポストする必要があります。トランザクション"。前者の場合、ユーザーはパスワードを入力する必要があります。それは邪魔だ-上で指摘したように。後者の場合、多くの追加のコーディングが必要です。だから、私の質問は...なぜStoreKitにコマンドがないのですか?

(存在しません)- [[SKPaymentQueue defaultQueue] restoreAttachedTransactions:(NSArray *)transactions];

このコマンドはrestoreCompletedTransactionsと同じように流れますが、アタッチされたトランザクションのみを復元します。最も重要なのは、ユーザーによるログインを必要としないことです。これは「最後のトランザクションを含む64ビットでエンコードされたJSONをhttpにポストする」と同じセキュリティ保護を備えており、アプリ内購入プロセス全体をStoreKitで実行できるため、ウェブ投稿コードを必要としません。

これが理にかなっている場合は、これをAppleに提供する方法を提案してください。

3
Peter B. Kramer