I'm in the process of setting up receipt validation for Apple's auto-renewable subscriptions on our server and noticed some inconsistencies with the official documentation. When verifying a sandbox receipt with the sandbox verifyReceipt endpoint, the response looks as follows:
{
"auto_renew_status": 1,
"status": 0,
"auto_renew_product_id": "app.xxx",
"receipt": {
"original_purchase_date_pst": "2020-03-18 01:11:45 America/Los_Angeles",
"quantity": "1",
"unique_vendor_identifier": "6D2xxx194",
"bvrs": "2",
"expires_date_formatted": "2020-03-20 12:27:07 Etc/GMT",
"is_in_intro_offer_period": "false",
"purchase_date_ms": "1584703627636",
"expires_date_formatted_pst": "2020-03-20 05:27:07 America/Los_Angeles",
"is_trial_period": "false",
"item_id": "15xxx27",
"unique_identifier": "cd5xxx424",
"original_transaction_id": "100xxx735",
"subscription_group_identifier": "20xxx02",
"transaction_id": "100xxx439",
"web_order_line_item_id": "100xxx419",
"version_external_identifier": "0",
"purchase_date": "2020-03-20 11:27:07 Etc/GMT",
"product_id": "app.xxx",
"expires_date": "1584707227636",
"original_purchase_date": "2020-03-18 08:11:45 Etc/GMT",
"purchase_date_pst": "2020-03-20 04:27:07 America/Los_Angeles",
"bid": "app.xxx",
"original_purchase_date_ms": "1584519105000"
},
"latest_receipt_info": {
"original_purchase_date_pst": "2020-03-18 01:11:45 America/Los_Angeles",
"quantity": "1",
"unique_vendor_identifier": "6D2xxx194",
"bvrs": "2",
"expires_date_formatted": "2020-03-20 12:27:07 Etc/GMT",
"is_in_intro_offer_period": "false",
"purchase_date_ms": "1584703627000",
"expires_date_formatted_pst": "2020-03-20 05:27:07 America/Los_Angeles",
"is_trial_period": "false",
"item_id": "15xxx27",
"unique_identifier": "cd5xxx424",
"original_transaction_id": "100xxx735",
"subscription_group_identifier": "20xxx02",
"transaction_id": "100xxx439",
"bid": "app.xxx",
"web_order_line_item_id": "100xxx419",
"purchase_date": "2020-03-20 11:27:07 Etc/GMT",
"product_id": "app.xxx",
"expires_date": "1584707227000",
"original_purchase_date": "2020-03-18 08:11:45 Etc/GMT",
"purchase_date_pst": "2020-03-20 04:27:07 America/Los_Angeles",
"original_purchase_date_ms": "1584519105000"
},
"latest_receipt": "xxx"
}
I especially want to point out the following fields of that response:
{
...
"latest_receipt_info": {
...
"expires_date": "1584707227000",
"expires_date_formatted": "2020-03-20 12:27:07 Etc/GMT",
"expires_date_formatted_pst": "2020-03-20 05:27:07 America/Los_Angeles",
"subscription_group_identifier": "20xxx02",
"bid": "app.xxx",
...
},
"receipt": {
...
"expires_date": "1584707227636",
"expires_date_formatted": "2020-03-20 12:27:07 Etc/GMT",
"expires_date_formatted_pst": "2020-03-20 05:27:07 America/Los_Angeles",
"subscription_group_identifier": "20xxx02",
"bid": "app.xxx",
...
},
...
}
The inconsistencies with the official documentation are:
latest_receipt_info
is documented to be an array, however, it is a single json object.- In the
latest_receipt_info
, theexpires_date
is not in "date-time format similar to the ISO 8601" as the documentation says, but looks like it is in milliseconds since epoch (what should be theexpires_date_ms
). However, we can find the keyexpires_date_formatted
that is in date-time format. - The same fields as in (2) can be also found in the receipt, however, the documentation states only a key
expiration_date
(analogue to theexpires_date
in thelatest_receipt_info
in date-time format) andexpiration_date_ms
(in milliseconds since epoch). - The documented
bundle_id
key (here and here) is not present, but a keybid
is, that contains the bundle id. - The key
subscription_group_identifer
does not contain the exact string entered in AppStoreConnect as subscription group identifer, as documented (here and here), but contains some integer value.
So according to the documentation, the response should look like this, for me:
{
...
"latest_receipt_info": [
{
...
"expires_date": "2020-03-20 12:27:07 Etc/GMT",
"expires_date_ms": "1584707227000",
"expires_date_pst": "2020-03-20 05:27:07 America/Los_Angeles",
"subscription_group_identifier": "MY_SUBSCRIPTION_GROUP_ID",
"bundle_id": "app.xxx",
...
}
],
"receipt": {
...
"expiration_date": "2020-03-20 12:27:07 Etc/GMT",
"expiration_date_ms": "1584707227636",
"expiration_date_pst": "2020-03-20 05:27:07 America/Los_Angeles",
"subscription_group_identifier": "MY_SUBSCRIPTION_GROUP_ID",
"bundle_id": "app.xxx",
...
},
...
}
- I am not sure how to cope with that situation, is that a bug in the API or is the documentation simply wrong?
- Can I expect the same inconsistencies for the production endpoint (can someone share a sample response please)?
- How about the notifications in server-to-server notifications, are there also inconsistencies?
Thanks in advance!