【问题标题】:How to check In App Purchase Auto Renewable Subscription is valid如何检查应用内购买自动续订订阅是否有效
【发布时间】:2011-07-04 11:01:51
【问题描述】:

我希望使用应用内购买来实施新的自动更新订阅,但我不确定如何或何时检查用户当前是否订阅。我的理解是,当用户最初订阅应用程序时,可以使用购买日期和订阅日期来计算他们的订阅将持续多长时间。此日期过后会发生什么?我们如何检查用户是否自动续订或取消?

如果我使用restoreCompletedTransactions 获取每次续订的交易和收据,系统将提示用户输入他们的 iTunes 密码。这是否意味着如果他们购买了 7 天的订阅,他们必须每 7 天在应用检查订阅是否仍然有效时输入密码?

【问题讨论】:

标签: iphone objective-c ios in-app-purchase subscription


【解决方案1】:

今天,我遇到了这个问题。

在这里关注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;
    }
}

希望对您有所帮助。

【讨论】:

【解决方案2】:

如果您想从网络服务器检查它,您可以 ping 他们的 API,它会返回自动续订订阅的状态和有关上次付款的信息。 link

如果您在设备上,那么您可能必须调用 restoreCompletedTransactions,我猜它会要求输入密码。

我没有看到任何其他方法。我想您可以从设备上通过联系服务器端使用的相同网络服务来验证订阅?我不知道这样做的利弊如何。

【讨论】:

  • 我认为交易是 - 无论如何您都必须使用服务器组件,因为在进行收据有效性检查时,您还必须在调用 Apple 服务器时提供共享密钥作为参数。我认为您不应该将共享密钥放在您的 iOS 应用程序客户端代码中,因为这样该密钥就不再是非常秘密了……
  • 是否需要共享密码才能在沙盒和生产模式下验证自动续订订阅的收据? @乔尼
  • 您好,您说过“您 ping 他们的 API,它会返回自动续订订阅的状态和有关上次付款的信息”什么是用于检查服务器端状态的 API?
  • 您是否阅读了我链接的文档?我认为您需要的所有信息都应该从那里链接到。
  • 链接文档不可用
【解决方案3】:

最好在调用 Apple API 之前在本地验证收据。每次应用程序运行时,验证本地收据是一个很好的做法,如果您需要检查用户是否有任何活动订阅,您可以从本地收据中检索所有购买,看看是否有购买仍然有效。

我已经实现了一个用Swift 编写的小型库,以简化在本地使用应用内收据。您可以轻松获取代表收据的对象 (InAppReceipt) 并检索有效购买/所有购买。

请随意使用。 Github link

以下是解决问题的示例:

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)
}

【讨论】:

  • 这是否仍然要求 iTunes 用户的邮件/通行证?
  • 想知道如何检测免费试用是否有效,并偶然发现了您的图书馆。这很棒!但是从第 18 期看来,从今天开始就不可能在本地查看免费试用了吗?非常感谢您的反馈...
  • 嗨@NiravBhatt,很抱歉延迟回复。由于某些版本,您只需检查收据的subscriptionTrialPeriod 属性即可。
  • 谢谢@tikhop,我猜名字是is_trial_periodApple 有详细的后端示例,我在这里得到它:developer.apple.com/documentation/storekit/in-app_purchase/…
  • @NiravBhatt 您可以采用任何一种方式,具体取决于您使用的验证技术
【解决方案4】:

我正在围绕这个问题发起一场运动。这是我的观察和竞选活动:

在自动续订时,App Store 会调用 paymentQueue 并发布交易。交易通过transaction.transactionState==SKPaymentTransactionStateRestored发布。

问题是不幸的是,这只会发布到一台设备上。第二个设备没有得到发布。因此,要检测自动续订,或者更确切地说是检测缺少自动续订并拒绝设备继续订阅,您必须执行restoreCompletedTransaction 或“http 发布包含最后交易的 64 位编码 JSON”。如果是前者,用户需要提供密码;这是侵入性的-正如您在上面指出的那样。如果是后者,则需要大量额外的编码。所以,我的问题是……为什么StoreKit 没有命令:

(不存在)- [[SKPaymentQueue defaultQueue] restoreAttachedTransactions:(NSArray *)transactions];

这个命令就像restoreCompletedTransactions 一样流动,但它只会恢复附加的事务,最重要的是,它不需要用户登录。它具有与“http 发布包含最后交易的 64 位编码 JSON”相同的安全保护,并且它允许整个应用内购买过程在 StoreKit 中完成,而不需要网络发布代码。

如果这对您有意义,请建议如何将其发送给 Apple....谢谢。

【讨论】:

  • 您所描述的似乎与我在进一步播放时发现的内容相匹配,因此我决定只实现一个服务器组件。虽然因为需要额外编码而很痛苦,但服务器组件非常简单,可能值得用于​​审计跟踪和收据验证。
【解决方案5】:

迟到了,但由于苹果在 WWDC 2020 直接提供了全面的后端解决方案,所以我不得不在这里写。

Apple 发布的entitlement engine 使用 Node JS 后端,也可以基于他们的后端 sample code 推出自己的。

授权引擎的作用:

  • 它将收据base64字符串作为输入(请求参数)
  • 它将它发送到 Apple verifyReceipt 端点。
  • 它解析解码的收据字段(请参阅下面的一些字段解释)
  • 它提供订阅状态。基本上,如果 subscription.entitlementCode > 0.0,客户就有资格接收解锁内容。

要回答有关收据字段的问题:

  • Apple verifyReceipt 端点响应中的 is_trial_period 字段是人们应该检查以了解免费试用是否有效的标志。
  • purchase.expires_date_ms 告诉订阅到期日期。
  • cancellation_date_ms 告诉 Apple 支持何时取消它。
  • This linkverifyReceipt 端点响应中有关于各个字段的最新信息。

最后但并非最不重要的一点是,如果您使用的是授权引擎示例代码,这些字段名称将有所不同。所以要小心,不要把这两件事混为一谈。

【讨论】:

  • 在自动续订的情况下如何验证未来的交易
  • 链接本身的引擎对于每个可能的状态都有不同的返回值。阅读源文件 cmets 中的授权代码。
猜你喜欢
  • 2017-10-29
  • 1970-01-01
  • 2018-06-01
  • 2016-01-25
  • 2016-10-23
  • 2014-02-20
  • 2011-06-29
  • 2013-02-04
  • 2013-11-20
相关资源
最近更新 更多