Hello.
This also happens to me. I detected it yesterday.
Initially I thought I might have a problem with the app after making some changes to it, but I did a subscription renewal using the native test subscriptions interface in IOS 14 (in Settings -> App Store) and I wasn't getting notifications either. When I went back to look at the logs, I saw that they were about 4 or 5 hours late. I made other purchases though, and nothing has arrived even though it's been over 8 hours.
While waiting for the notifications to arrive, I tested by calling the verifyReceipt URL (using a "latest_receipt" that I had saved from a previous notification), and in the response the new purchases did appear, although they appeared in a state EXPIRED_BUT_IN_RETRY_PERIOD. And in that state they have remained.
This JSON corresponds to the output of processing the verifyReceipt response with a modified version of the processReceiptJSON() function available in the code example that you can download from the URL
https://developer.apple.com/documentation/storekit/in-app_purchase/subscriptions_and_offers/determining_service_entitlement_on_the_serverThis URL corresponds to one of the resource links available in the article
Architecting for subscriptionsSpecifically, to
Determining Service Entitlement on the Server.
(I recommend that you download the example to see how you can obtain a summary of the information obtained from the verifyReceipt queries, although it could also be applied to a notification)
I have modified the code of the example so that besides showing the numerical values, it shows me an explanatory text that shows in a simple way to which state the numerical value corresponds (I have also modified the text strings that come in the example, to make them more intelligible).
Code Block json{ |
"subscriptions" : [ |
{ |
"product_id" : "IDPPAR0001", |
"entitlementCode" : -1, |
"expiration" : 1621518754000, |
"entitlementMainStateDescription" : "EXPIRED_BUT_IN_RETRY_PERIOD", |
"expirationAsISOString" : "2021-05-20T13:52:34.000Z", |
"entitlementSubstateDescription" : "STANDARD_SUBSCRIPTION", |
"web_order_line_item_id" : "10000000xxxxxxxx", |
"transaction_id" : "10000000xxxxxxxx", |
"totalRenewals" : 12, |
"groupID" : "20xxxxxx", |
"originalTransactions" : [ |
{ |
"originalTX" : "10000000xxxxxxxx", |
"start" : 1600943224000, |
"startAsISOString" : "2020-09-24T10:27:04.000Z", |
"expiration" : 1621518754000, |
"expirationAsISOString" : "2021-05-20T13:52:34.000Z", |
"renewals" : 12 |
} |
] |
}, |
{ |
"product_id" : "IDPPAR00000001BR", |
"entitlementCode" : -1, |
"expiration" : 1621515085000, |
"entitlementMainStateDescription" : "EXPIRED_BUT_IN_RETRY_PERIOD", |
"expirationAsISOString" : "2021-05-20T12:51:25.000Z", |
"entitlementSubstateDescription" : "STANDARD_SUBSCRIPTION", |
"web_order_line_item_id" : "10000000xxxxxxxx", |
"transaction_id" : "10000000xxxxxxxx", |
"totalRenewals" : 17, |
"groupID" : "20xxxxxx", |
"originalTransactions" : [ |
{ |
"originalTX" : "10000000xxxxxxxx", |
"start" : 1614640470000, |
"startAsISOString" : "2021-03-01T23:14:30.000Z", |
"expiration" : 1621515085000, |
"expirationAsISOString" : "2021-05-20T12:51:25.000Z", |
"renewals" : 17 |
} |
] |
}, |
{ |
"product_id" : "IDPPARES0001", |
"entitlementCode" : -5, |
"expiration" : 1620837172000, |
"entitlementMainStateDescription" : "USER_LET_EXPIRE_VOLUNTARILY", |
"expirationAsISOString" : "2021-05-12T16:32:52.000Z", |
"entitlementSubstateDescription" : "STANDARD_SUBSCRIPTION", |
"web_order_line_item_id" : "10000000xxxxxxxx", |
"transaction_id" : "10000000xxxxxxxx", |
"totalRenewals" : 56, |
"groupID" : "20577648", |
"originalTransactions" : [ |
{ |
"originalTX" : "10000000xxxxxxxx", |
"start" : 1614640470000, |
"startAsISOString" : "2021-03-01T23:14:30.000Z", |
"expiration" : 1620837172000, |
"expirationAsISOString" : "2021-05-12T16:32:52.000Z", |
"renewals" : 56 |
} |
] |
}, |
], |
"trialConsumedForGroup" : [] |
} |
Until these problems occurred yesterday, the final status of the sandbox subscriptions I had seen was always USER_LET_EXPIRE_VOLUNTARILY. But the ones purchased yesterday, stay in the EXPIRED_BUT_IN_RETRY_PERIOD state.