Подтвердить что ты не робот

Как проверить наличие покупки в приложении "Авто возобновляемая подписка"

Я ищу внедрить новые подписки на Auto Renewable, используя In App Purchase, но я не уверен, как и когда нужно проверить, подписан ли пользователь в настоящее время. Я понимаю, что, когда пользователь изначально подписывается, приложение может использовать дату покупки вместе с датой подписки, чтобы рассчитать, как долго будет длиться их подписка. Что произойдет после этой даты? Как проверить, обновлен или отменен пользователь?

Если я использую restoreCompletedTransactions для получения транзакции и квитанции для каждого продления, пользователю будет предложено ввести свой пароль iTunes. Означает ли это, что, если они купили 7-дневную подписку, им придется вводить свой пароль каждые 7 дней, когда приложение проверяет, сохраняет ли подписка?

4b9b3361

Ответ 1

См. это для документов:

http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/VerifyingStoreReceipts/VerifyingStoreReceipts.html#//apple_ref/doc/uid/TP40008267-CH104-SW1

Если вы хотите проверить его с веб-сервера, вы выполните ping их API и он возвращает статус автоматической возобновляемой подписки и информацию о последнем платеже.

Если вы находитесь на устройстве, вам, вероятно, придется вызвать restoreCompletedTransactions, который, как мне кажется, запрашивает пароль.

Я не вижу другого метода. Я полагаю, что с устройства вы можете проверить подписку, связавшись с тем же веб-сервисом, который используется на стороне сервера? Я не знаю, как за и против этого.

Ответ 2

Сегодня у меня проблемы с этой проблемой.

Следуйте Apple doc здесь, я использовал этот способ проверки подписки, истек или нет. Моя идея: пользовательский ответ APPLE REST API: (время запроса + истекшее время) для проверки истек или нет

+ (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;
    }
}

Надеюсь на эту помощь.

Ответ 3

Лучше использовать локальное решение, прежде чем делать какие-либо вызовы Apple api. Каждый раз, когда приложение работает хорошо, проверьте правильность локальной квитанции, и если вам нужно проверить, имеет ли пользователь активную подписку, вы можете сначала получить покупки из местной квитанции и узнать, что покупка по-прежнему активна на сегодня,

Я реализовал небольшую библиотеку, написанную в Swift, чтобы упростить работу с приложением In-App Purchase. Вы можете легко получить объект, который представляет квитанцию ​​(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)
}

Ответ 4

Я начинаю кампанию вокруг этой проблемы. Вот мое наблюдение и кампания:

При автоматическом обновлении App Store вызывает paymentQueue и отправляет транзакцию. Транзакция отправляется с помощью transaction.transactionState==SKPaymentTransactionStateRestored.

Проблема в том, что, к сожалению, это отправляется только на одно устройство. Второе устройство не получает проводку. Таким образом, чтобы обнаружить автоматическое обновление или, скорее, обнаружить отсутствие автообмена и запретить устройству постоянную подписку, вам нужно сделать restoreCompletedTransaction или "http post 64-bit encoded JSON, содержащий последнюю транзакцию". Если первый, пользователь должен указать свой пароль; это навязчивое - как вы указали выше. Если последнее, требуется много дополнительного кодирования. Итак, мой вопрос: почему у StoreKit нет команды:

(не существует) - [[SKPaymentQueue defaultQueue] restoreAttachedTransactions:(NSArray *)transactions];

Эта команда будет течь точно так же, как и restoreCompletedTransactions, но она только восстановит присоединенные транзакции и, самое главное, не потребует входа пользователя. Он обладает той же защитой безопасности, что и "HTTP-пост с 64-битным кодированным JSON, содержащим последнюю транзакцию", и позволяет полностью обрабатывать процесс покупки в приложении StoreKit, а не требовать код веб-публикации.

Если это имеет смысл для вас, пожалуйста, предложите, как получить это в Apple.... спасибо.