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.latest_receipt_info
, the expires_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 the expires_date_ms
). However, we can find the key expires_date_formatted
that is in date-time format.expiration_date
(analogue to the expires_date
in the latest_receipt_info
in date-time format) and expiration_date_ms
(in milliseconds since epoch).bundle_id
key (here and here) is not present, but a key bid
is, that contains the bundle id.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",
...
},
...
}
Thanks in advance!
For everyone that faces the same problem: We sent the wrong receipt data to our backend since we requested the receipt via the deprecated transactionReceipt and not via appStoreReceiptURL.