2011-02-25 72 views
18

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

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

+0

此链接https://stackoverflow.com/questions/22680059/auto-renewable-subscription-in-ios7/45220204#45220204 可能有帮助您。 –

回答

7

的文档显示方式:

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

如果你想检查它从一个Web服务器,您ping他们的API,并返回该自动再生订阅的状态和信息关于最后付款。

如果你在设备上,那么你可能不得不打电话给restoreCompletedTransactions,我猜想要求输入密码。

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

+1

我认为这笔交易是 - 您必须使用服务器组件,因为在进行收据有效性检查时,您还必须提供共享密钥作为Apple服务器调用中的参数。我认为你不应该把共享秘密放在你的iOS应用客户端代码中,因为那时秘密不会再是秘密了...... – Jonny

+0

验证沙箱和产品上的收据是否需要共享秘密密码自动续订订阅模式? @Jonny –

+0

嗨,你已经说过“你可以ping他们的API,它返回自动更新订阅的状态和有关最后付款的信息”什么是API来检查服务器端的状态? – Yohan

3

我开始围绕此问题开展一项活动。这是我的观察和活动:

自动更新后,App Store调用paymentQueue并发布事务。交易过帐为transaction.transactionState==SKPaymentTransactionStateRestored

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

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

此命令将流就像一个restoreCompletedTransactions,但只会恢复连接交易,而最重要的是,它不需要用户登录。它具有与“http发布包含最后一笔交易的64位编码JSON”相同的安全保护,它允许在StoreKit中完成整个In App Purchase流程,而不需要网络发布代码。

如果这对你有意义,请建议如何让这个给苹果....谢谢。

+0

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

12

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

跟着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; 
    } 
} 

希望这有助于。

+1

谢谢。推荐的补充:NSURLSession教程,以便您可以执行异步检查https://www.raywenderlich.com/110458/nsurlsession-tutorial-getting-started以及如何测试Sandbox订阅(朝向结尾):https:// savvyapps .COM /博客/如何-设置 - 测试 - 自动可再生认购-IOS-应用 – Philosophistry

4

在对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) 
} 
相关问题