How do I determine if a user has never suscribed?

So, if a user hits "Restore Subscription" I have this script:


if (SKPaymentQueue.canMakePayments()){
              
     if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL, FileManager.default.fileExists(atPath: appStoreReceiptURL.path) == false {
         let refreshRequest = SKReceiptRefreshRequest()
         refreshRequest.delegate = self
         refreshRequest.start()
     }
      else{
          SKPaymentQueue.default().add(self)
          SKPaymentQueue.default().restoreCompletedTransactions()
     }
}


Now, if the user has never subcribed before it'll still get a receipt that looks like this:


environment = Sandbox;
    receipt =     {
        "adam_id" = 0;
        "app_item_id" = 0;
        "application_version" = 10;
        "bundle_id" = "xxxxxx";
        "download_id" = 0;
        "in_app" =         (
        );
        "original_application_version" = "1.0";
        "original_purchase_date" = "2013-08-01 07:00:00 Etc/GMT";
        "original_purchase_date_ms" = 1375340400000;
        "original_purchase_date_pst" = "2013-08-01 00:00:00 America/Los_Angeles";
        "receipt_creation_date" = "2018-05-07 23:35:06 Etc/GMT";
        "receipt_creation_date_ms" = 1525736106000;
        "receipt_creation_date_pst" = "2018-05-07 16:35:06 America/Los_Angeles";
        "receipt_type" = ProductionSandbox;
        "request_date" = "2018-05-07 23:49:17 Etc/GMT";
        "request_date_ms" = 1525736957273;
        "request_date_pst" = "2018-05-07 16:49:17 America/Los_Angeles";
        "version_external_identifier" = 0;
    };
    status = 0;


That's the whole thing. Comparing this to a receipt from a suscribed sandbox user, there's some missing things. Like "Latest_receipt_info" and "Pendng_renewal_info." I ASSUME that I need to check for "Latest_receipt_info" to determine if they've ever susbribed before so that I can display a message stating such. Is this the right way though?

Accepted Reply

It is unclear why you use the logic you are using (i.e. if (no receipt) then (refresh the receipt) else (restore completed transactions)).

It is best to use restoreCompletedTransactions. It will return the latest receipt.

Having gotten the most recent receipt there is no need to worry about the whole latest_receipt_info thing. You do that only if you chose not to refresh the receipt.


If a refreshed receipt has no "in_app" then no purchases were made from that device*. If a restoreCompletedTransaction returns a receipt with no "in_app" then no purchases were made by that Apple ID.


* This is why restoreCompletedTransactions is better. It is possible that sending this receipt (from a device that never made a purchase) to the Apple Servers will generate a receipt with latest_receipt_info including IAPs made from a different device - I am not sure since I use restoreCompletedTransactions.

Replies

It is unclear why you use the logic you are using (i.e. if (no receipt) then (refresh the receipt) else (restore completed transactions)).

It is best to use restoreCompletedTransactions. It will return the latest receipt.

Having gotten the most recent receipt there is no need to worry about the whole latest_receipt_info thing. You do that only if you chose not to refresh the receipt.


If a refreshed receipt has no "in_app" then no purchases were made from that device*. If a restoreCompletedTransaction returns a receipt with no "in_app" then no purchases were made by that Apple ID.


* This is why restoreCompletedTransactions is better. It is possible that sending this receipt (from a device that never made a purchase) to the Apple Servers will generate a receipt with latest_receipt_info including IAPs made from a different device - I am not sure since I use restoreCompletedTransactions.

I used that logic because according to documentation "SKReceiptRefreshRequest" is used if the receipt is invalid or MISSING, and "restoreCompletedTransactions" is used to restore previously purchased IAPs. So is receipt refresh to only be used when the receipt is invalid?


Thanks for the answer on "in_app"!

You can use either but if you use restoreCompletedTransactions then the device will be subscribed for future renewal transactions

Got it! Thanks PBK!!