Hello I'm working on integrating renewable subscriptions statuses from apple into our cloud and I have found some inconsistent behavior that is making very hard to properly create a deserializer for the verification receipt endpoint. I am following the documentation found in here https://developer.apple.com/documentation/appstorereceipts/responsebody
We are testing only renweables subscriptions right now, nothing else. According to the documentation latest_expired_receipt_info and latest_receipt_info should be an array of receipts, which is sometimes the case, however, sometimes the response from the verification receipt endpoint returns latest_expired_receipt_info and latest_receipt_info not as an array, but as a single receipt object.
This is the first time I'm integrating with apple subscription, I'm using golang and this non consistent responses break the deserializer i have for the response, all this behavior is from the Sandbox environment using the endpoint https://sandbox.itunes.apple.com/verifyReceipt
to verify the receipts and setting the exclude-old-transactions option to true in the request.
I would appreacite it if anyone would point me to the right direction as of why the inconsistent response JSONs.
Here is an example where the property is not an array
{
"auto_renew_status": 0,
"latest_expired_receipt_info": {
"original_purchase_date_pst": "2019-11-12 10:01:07 America/Los_Angeles",
"quantity": "1",
"unique_vendor_identifier": "removed for this post",
"bvrs": "removed for this post",
"expires_date_formatted": "2019-11-12 22:41:18 Etc/GMT",
"is_in_intro_offer_period": "false",
"purchase_date_ms": "1573598178000",
"expires_date_formatted_pst": "2019-11-12 14:41:18 America/Los_Angeles",
"is_trial_period": "false",
"item_id": "removed for this post",
"unique_identifier": "removed for this post",
"original_transaction_id": "removed for this post",
"subscription_group_identifier": "removed for this post",
"transaction_id": "removed for this post",
"bid": "removed for this post",
"web_order_line_item_id": "removed for this post",
"purchase_date": "2019-11-12 22:36:18 Etc/GMT",
"product_id": "removed for this post",
"expires_date": "1573598478000",
"original_purchase_date": "2019-11-12 18:01:07 Etc/GMT",
"purchase_date_pst": "2019-11-12 14:36:18 America/Los_Angeles",
"original_purchase_date_ms": "1573581667000"
},
"status": 21006,
"auto_renew_product_id": "removed for this post",
"receipt": {
"original_purchase_date_pst": "2019-11-12 10:01:07 America/Los_Angeles",
"quantity": "1",
"unique_vendor_identifier": "removed for this post",
"bvrs": "removed for this post",
"expires_date_formatted": "2019-11-12 22:41:18 Etc/GMT",
"is_in_intro_offer_period": "false",
"purchase_date_ms": "1573598178000",
"expires_date_formatted_pst": "2019-11-12 14:41:18 America/Los_Angeles",
"is_trial_period": "false",
"item_id": "removed for this post",
"unique_identifier": "removed for this post",
"original_transaction_id": "removed for this post",
"subscription_group_identifier": "removed for this post",
"transaction_id": "removed for this post",
"web_order_line_item_id": "removed for this post",
"version_external_identifier": "0",
"purchase_date": "2019-11-12 22:36:18 Etc/GMT",
"product_id": "removed for this post",
"expires_date": "1573598478000",
"original_purchase_date": "2019-11-12 18:01:07 Etc/GMT",
"purchase_date_pst": "2019-11-12 14:36:18 America/Los_Angeles",
"bid": "removed for this post",
"original_purchase_date_ms": "1573581667000"
},
"expiration_intent": "1",
"is_in_billing_retry_period": "0"
}
However, according to the documentation it should be always returned this way.
{
"status": 0,
"environment": "Production",
"receipt": {
"receipt_type": "Production",
"adam_id": 0000000000,//changed for this post
"app_item_id": 0000000000,//changed for this post
"bundle_id": "com.foo.product",
"application_version": "000", //changed for this post
"download_id": 0000000000,//changed for this post
"version_external_identifier": 0000000000,//changed for this post
"receipt_creation_date": "2019-11-26 17:01:33 Etc/GMT",
"receipt_creation_date_ms": "1574787693000",
"receipt_creation_date_pst": "2019-11-26 09:01:33 America/Los_Angeles",
"request_date": "2019-12-02 23:09:39 Etc/GMT",
"request_date_ms": "1575328179029",
"request_date_pst": "2019-12-02 15:09:39 America/Los_Angeles",
"original_purchase_date": "2019-11-07 05:57:29 Etc/GMT",
"original_purchase_date_ms": "1573106249000",
"original_purchase_date_pst": "2019-11-06 21:57:29 America/Los_Angeles",
"original_application_version": "99",
"in_app": [
{
"quantity": "1",
"product_id": "com.foo.p", //changed for this post
"transaction_id": " 0000000000",//changed for this post ",
"original_transaction_id": " 0000000000",//changed for this post ,
"purchase_date": "2019-11-26 17:01:30 Etc/GMT",
"purchase_date_ms": "1574787690000",
"purchase_date_pst": "2019-11-26 09:01:30 America/Los_Angeles",
"original_purchase_date": "2019-11-26 17:01:31 Etc/GMT",
"original_purchase_date_ms": "1574787691000",
"original_purchase_date_pst": "2019-11-26 09:01:31 America/Los_Angeles",
"expires_date": "2020-11-26 17:01:30 Etc/GMT",
"expires_date_ms": "1606410090000",
"expires_date_pst": "2020-11-26 09:01:30 America/Los_Angeles",
"web_order_line_item_id": "240000240409401",
"is_trial_period": "false",
"is_in_intro_offer_period": "false"
}
]
},
"latest_receipt_info": [
{
"quantity": "1",
"product_id": "com.foo.prod", //changed for this post
"transaction_id": "0000000000",//changed for this post
"original_transaction_id": "0000000000",//changed for this post
"purchase_date": "2019-11-26 17:01:30 Etc/GMT",
"purchase_date_ms": "1574787690000",
"purchase_date_pst": "2019-11-26 09:01:30 America/Los_Angeles",
"original_purchase_date": "2019-11-26 17:01:31 Etc/GMT",
"original_purchase_date_ms": "1574787691000",
"original_purchase_date_pst": "2019-11-26 09:01:31 America/Los_Angeles",
"expires_date": "2020-11-26 17:01:30 Etc/GMT",
"expires_date_ms": "1606410090000",
"expires_date_pst": "2020-11-26 09:01:30 America/Los_Angeles",
"web_order_line_item_id": " 0000000000",//changed for this post
"is_trial_period": "false",
"is_in_intro_offer_period": "false",
"subscription_group_identifier": "0000000000",//changed for this post
}
],
"latest_receipt": "encoded receipt removed for this post ",
"pending_renewal_info": [
{
"auto_renew_product_id": "com.fooapp.fooprod",
"original_transaction_id": " 0000000000",//changed for this post
"product_id": "com.fooapp.fooprod",
"auto_renew_status": "1"
}
]
}
So I need to know why it returns the property as an array sometimes and as a single receipt object other times.
Thanks in advance.