Thanks for your reply. The product purchased is of a Auto-Renew Subscription type, which this customer had purchased originally years ago (on a old device), who had "cancelled only the subscription's auto renewal" (under their AppleID Settings, Subscriptions), then tried to "Buy" (re-subscribe) same subscription option within the App's latest update (on a new device). They did not have Apple Cancel & refund previously their subscription. Under their "Purchase History", only one OrderID shows up, and on the date they re-purchased / did a "Buy" again on their new device, Purchase History shows the same OrderID with "Renewal" stated. Other customers can see their first purchase & date with an OrderID stating "Initial" and same OrderID with subsequent dates of Auto-renewal stating "Renewal."
Within the App, this customer's transaction went through the regular prompts to the user and finished with "You're all Set" which they were able to confirm as an active subscription selection (checkmarked) to the Auto-renew Subscription selected under their AppleID, Subscriptions.
The App's code does verify and process valid receipts when received from StoreKit's queue entering purchased state: it verifies the signature of a PKCS7 receipt; parses the receipt's payload and extracts the 1708 field's date (transaction's Subscription Expiration Date) to unlock subcribed data. But for this one customer's "Renewal" transaction, the App does not extract any 1708 field's date at a minimun ....or StoreKit's Purchased State is not sending a receipt containing a 1708 field???
This customer's OrderID, as I stated originally was first purchased years ago, likely with multiple transactions under it, and the transaction made today should be contained in its latest receipt's payload after "Buy" enters purchased state, correct? For some reason, I suspect a receipt is not getting received when its a "Renewal" of a Auto-Renew Subscription that is being purchased (from StoreKit's queue, entering purchased state). Is it possibly becuase they are using a new device different from their original purchase, buying a Renewal?
Another fact, I do know the customer had deleted the App prior, and was running a new install on their device before they tried to Buy the subscription option within the App.
The best user experience is for the App to processes all transaction's receipts when a "Buy" completes within StoreKit ...Intital Purchases, and Renewals. I'm trying to figure out why Initial purchases work fine and Renewals apparently do not? Is there 4th option I need to add or possible to SKPaymentTransactionObserver protocol beyond "Purchased" "Failed" and "Restored"?
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction * transaction in transactions) {
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
default: break;
}
}
}
My completeTransaction method verifies transactions and their receipts as valid properly for all other purchases. But if it can not handle "Renewals" from old subscribers in a unsubcribed state who want to subscribe again, that can be a big issue for me. Given the App was a fresh install (was deleted) for this user, why would their Buy (re-subscribe) be any different from a new user buying their first purchase??
When do we use or need to address StoreKit's SKPaymentTransactionStateDeferred? Is that the case I need to consider here?
If not, and all users with Renewals need to be told to do a "Restore." Is calling:
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
my only option for Auto-Renew Subscription products too?
I may have wrongly thought I could utilize:
SKReceiptRefreshRequest *request = [[SKReceiptRefreshRequest alloc] init];
request.delegate = self;
[request start];
to only extract just the latest transaction & receipt to lesson the burden on processing all transactions on the app, but this does not work for this user?
It was my understanding that restoreCompletedTransactions restores "All" receipts and is generally used when app unlocks numerous features from multiple purchases, while SKReceiptRefreshRequest, restores just the latest receipt and stores it locally on the device. I'm thinking the issue possibly may be because they are using a new device, and SKReceiptRefreshRequest does NOT send the correct receipt even though last purchase was completed on the new device??
If its not a SKPaymentTransctionStateXXXX issue, or SKReceiptRefreshRequest could it remotely be the receipt's format? Its hard for me to debug what's truly going on here in production environment for this user.
I'm thinking I should make my Restore Subscriptions function, only utilize restoreCompletedTransactions method and see if then a proper receipt gets received for this user (They will likely though have to do two steps: 1. Buy, then 2. Restore Subscriptions).
With other users who have purchased a subscription recently (but on same device), who I had unsubscribe, then after the expiration bought again, their purchased state, the app properly validates, processes a receipt + extracts the 1708 subscription expiration date field and unlocks data properly in one step (1. Buy)
Thanks to all of you for your help.