2011-02-25 73 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) 
} 
相關問題