36

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

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

4

5 回答 5

19

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

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

希望这有帮助。

于 2016-09-16T10:11:39.463 回答
10

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

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

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

于 2011-03-19T19:05:21.603 回答
10

最好在调用 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)
}
于 2017-01-24T04:19:37.477 回答
3

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

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

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

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

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

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

于 2011-04-09T19:30:24.020 回答
2

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

Apple 发布的授权引擎与 Node JS 后端一起使用,也可以根据他们的后端示例代码推出自己的授权引擎。

授权引擎的作用:

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

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

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

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

于 2020-07-14T15:51:59.060 回答