Post

Replies

Boosts

Views

Activity

Is there any status code indicate that transactionId is from sandbox?
In the old verifyReceipt endpoint doc, there is an important desc As a best practice, always call the production URL https://buy.itunes.apple.com/verifyReceipt first and proceed to verify with the sandbox URL if you receive a 21007 status code. Following this approach ensures that you don’t have to switch between URLs while your app is in testing, in review by App Review, or live in the App Store. So I can know the transactionId is for sandbox if return back 21007. And I am about to access to new App Store Server API, so the same, I wonder how can I recognize the transactionId is from sandbox by status code? The most likely desc is this: If you don’t have environment information, follow these steps: Call the endpoint using the production URL. If the call succeeds, the original transaction identifier belongs to the production environment. If you receive an [errorCode 4040005] with errorMessage as OriginalTransactionIdNotFoundError, (or HTTP response code 404 from the Send Consumption Information endpoint), call the endpoint using the sandbox environment. If the call succeeds, the original transaction identifier belongs to the sandbox environment. If the call fails with the same error code, the original transaction identifier isn’t present in either environment. And I have a try for Get Transaction Info API, but actually get 4040010, Transaction id not found. as return. So I just wanna clear that is there any doc clarify this point that I miss? Looking forward to your response, sincerely!! :)
1
0
1.8k
Aug ’23
There are some field describe missing sth in App Store Server Api
here are some field in JWSTransactionDecodedPayload and JWSRenewalInfoDecodedPayload, miss this kind of desc: This field is present only for xxxxx Such as revocationReason in JWSTransactionDecodedPayload, this field is present only when transaction is refunded. And its possible value is 0 and 1, when this field not present, golang would still unmarshal to default 0 for int32 type isInBillingRetryPeriod in JWSRenewalInfoDecodedPayload, this field is present only when transaction in billing-retry state(relative doc), and because this field type is boolean, so possible value is true and false, base on the old api desc, true - The App Store is attempting to renew the subscription. false - The App Store has stopped attempting to renew the subscription. When this field not present, golang would still unmarshal to default false for bool type priceIncreaseStatus in JWSRenewalInfoDecodedPayload, this field is present only when an auto-renewable subscription price increase that requires customer consent. Its possible value is 0 - The customer hasn’t yet responded to an auto-renewable subscription price increase that requires customer consent. 1 - The customer consented to an auto-renewable subscription price increase that requires customer consent, or the App Store has notified the customer of an auto-renewable subscription price increase that doesn’t require consent.
0
0
510
Aug ’23
How to guarantee that user won't be able to makeup transaction_id to call new api
If my user purchase and get transaction_id: 2000000395609292, and then another user just makeup a same transaction_id to call the App Store Server API If in the old way, the receipt seems impossiable to makeup, how about now? Is that equally safe as before? Or is there any way to protect transaction_id. I am not that good at security, so please forgive me about missing any point. o(╥﹏╥)o Looking forward to your response, sincerely!! :)
3
0
667
Aug ’23
Why Non-Consumable product has originalTransactionId?
I try to call Get Transaction Info from App Store Server API, and the transactionId is for a Non-consumable type product, but it is odd that there are so many different transactionId and they have a same originalTransactionId { "bundleId": "${bundleId}", "environment": "Production", "inAppOwnershipType": "PURCHASED", "originalPurchaseDate": 1691220528000, "originalTransactionId": "${originalTransactionId}", "productId": "${productId}", "purchaseDate": 1691220528000, "quantity": 1, "signedDate": 1692590989925, "storefront": "USA", "storefrontId": "143441", "transactionId": "${originalTransactionId}", "transactionReason": "PURCHASE", "type": "Non-Consumable" } the defination of Non-Consumable is can only purchase once for same apple account. But why there would have originalTransactionId?
2
0
777
Aug ’23
Does CANCEL would turn off renewal?
Cause in sandbox env I notice a receipt like this { "environment": "Sandbox", "unified_receipt": { "status": 0, "environment": "Sandbox", "latest_receipt_info": [ { "quantity": "1", "product_id": "3monthplan", "expires_date": "2023-07-25 04:50:29 Etc/GMT", "purchase_date": "2023-07-25 04:41:29 Etc/GMT", "transaction_id": "2000000375156349", "expires_date_ms": "1690260629000", "is_trial_period": "false", "expires_date_pst": "2023-07-24 21:50:29 America/Los_Angeles", "purchase_date_ms": "1690260089000", "purchase_date_pst": "2023-07-24 21:41:29 America/Los_Angeles", "in_app_ownership_type": "PURCHASED", "original_purchase_date": "2023-07-25 03:20:41 Etc/GMT", "web_order_line_item_id": "2000000032603282", "original_transaction_id": "2000000375122102", "is_in_intro_offer_period": "false", "original_purchase_date_ms": "1690255241000", "original_purchase_date_pst": "2023-07-24 20:20:41 America/Los_Angeles", "subscription_group_identifier": "20572434" }, .... { "quantity": "1", "product_id": "3monthplan", "expires_date": "2023-07-25 04:03:49 Etc/GMT", "purchase_date": "2023-07-25 03:54:49 Etc/GMT", "transaction_id": "2000000375136003", "expires_date_ms": "1690257829000", "is_trial_period": "false", "expires_date_pst": "2023-07-24 21:03:49 America/Los_Angeles", "purchase_date_ms": "1690257289000", "purchase_date_pst": "2023-07-24 20:54:49 America/Los_Angeles", "in_app_ownership_type": "PURCHASED", "original_purchase_date": "2023-07-25 03:20:41 Etc/GMT", "web_order_line_item_id": "2000000032600544", "original_transaction_id": "2000000375122102", "is_in_intro_offer_period": "false", "original_purchase_date_ms": "1690255241000", "original_purchase_date_pst": "2023-07-24 20:20:41 America/Los_Angeles", "subscription_group_identifier": "20572434" }, { "quantity": "1", "product_id": "monthlyplan", "expires_date": "2023-07-25 03:38:37 Etc/GMT", "purchase_date": "2023-07-25 03:35:37 Etc/GMT", "transaction_id": "2000000375127458", "expires_date_ms": "1690256317000", "is_trial_period": "false", "expires_date_pst": "2023-07-24 20:38:37 America/Los_Angeles", "purchase_date_ms": "1690256137000", "cancellation_date": "2023-07-25 04:38:50 Etc/GMT", "purchase_date_pst": "2023-07-24 20:35:37 America/Los_Angeles", "cancellation_reason": "0", "cancellation_date_ms": "1690259930000", "cancellation_date_pst": "2023-07-24 21:38:50 America/Los_Angeles", "in_app_ownership_type": "PURCHASED", "original_purchase_date": "2023-07-25 03:20:41 Etc/GMT", "web_order_line_item_id": "2000000032600434", "original_transaction_id": "2000000375122102", "is_in_intro_offer_period": "false", "original_purchase_date_ms": "1690255241000", "original_purchase_date_pst": "2023-07-24 20:20:41 America/Los_Angeles", "subscription_group_identifier": "20572434" }, ... ] }, "auto_renew_status": "false", "cancellation_date": "2023-07-25 04:38:50 Etc/GMT", "notification_type": "CANCEL", "cancellation_date_ms": "1690259930000", "auto_renew_product_id": "3monthplan", "cancellation_date_pst": "2023-07-24 21:38:50 America/Los_Angeles", "web_order_line_item_id": "2000000032600434", "original_transaction_id": 2000000375122102 } plan is keeping renew. What if I refund in prod env, and after refund agree, is that my subscription would auto turn off?
0
0
451
Jul ’23
INTERACTIVE_RENEWAL notification is sent while user resubscribed to another SKU
It is in sandbox environment, and our serice is using v1 Base on this doc, the INTERACTIVE_RENEWAL notification would be sent: Subscription is active; customer upgraded to another SKU Subscription has expired; customer resubscribed to another SKU (upgrade or downgrade) { "environment": "Sandbox", "receipt": { "receipt_type": "ProductionSandbox", "bundle_id": "co.appeconomy.alarm", "receipt_creation_date": "2023-04-26 10:13:24 Etc/GMT", "request_date": "2023-04-26 10:17:11 Etc/GMT", "original_purchase_date": "2013-08-01 07:00:00 Etc/GMT", "original_application_version": "1.0" }, "latest_receipt_info": [ { "quantity": "1", "product_id": "co.appeconomy.alarm.monthly", "transaction_id": "2000000320391970", "original_transaction_id": "2000000320390725", "purchase_date": "2023-04-26 10:11:53 Etc/GMT", "original_purchase_date": "2023-04-26 10:09:59 Etc/GMT", "expires_date": "2023-04-26 10:16:53 Etc/GMT", "web_order_line_item_id": "2000000026088214", "is_trial_period": "false", "is_in_intro_offer_period": "false", "in_app_ownership_type": "PURCHASED", "subscription_group_identifier": "20906883" }, { "quantity": "1", "product_id": "co.appeconomy.alarm.monthly", "transaction_id": "2000000320390725", "original_transaction_id": "2000000320390725", "purchase_date": "2023-04-26 10:09:53 Etc/GMT", "original_purchase_date": "2023-04-26 10:09:59 Etc/GMT", "expires_date": "2023-04-26 10:11:53 Etc/GMT", "web_order_line_item_id": "2000000026088213", "is_trial_period": "true", "is_in_intro_offer_period": "false", "in_app_ownership_type": "PURCHASED", "subscription_group_identifier": "20906883" } ], "pending_renewal_info": [ { "auto_renew_product_id": "co.appeconomy.alarm.monthly", "is_in_billing_retry_period": "0", "product_id": "co.appeconomy.alarm.monthly", "original_transaction_id": "2000000320390725", "auto_renew_status": "0" } ], "status": 0 } these is the response from verifyReceipt api Can notice that I request at '2023-04-26 10:17:11 Etc/GMT' and latest receipt shows that subscription is expired at '2023-04-26 10:16:53 Etc/GMT'. So obviously this subscription is expired already But when I resubscribed the same sku(in this case is co.appeconomy.alarm.monthly) in the Setting > App Store > Edit Subscription. My server can still receive INTERACTIVE_RENEWAL notification. { "bid": "co.appeconomy.alarm", "bvrs": "2", "environment": "Sandbox", "unified_receipt": { "status": 0, "environment": "Sandbox", "latest_receipt_info": [ { "quantity": "1", "product_id": "co.appeconomy.alarm.monthly", "expires_date": "2023-04-26 10:23:47 Etc/GMT", "purchase_date": "2023-04-26 10:18:47 Etc/GMT", "transaction_id": "2000000320398679", "is_trial_period": "false", "in_app_ownership_type": "PURCHASED", "web_order_line_item_id": "2000000026088350", "original_transaction_id": "2000000320390725", "is_in_intro_offer_period": "false", "subscription_group_identifier": "20906883" }, { "quantity": "1", "product_id": "co.appeconomy.alarm.monthly", "expires_date": "2023-04-26 10:16:53 Etc/GMT", "purchase_date": "2023-04-26 10:11:53 Etc/GMT", "transaction_id": "2000000320391970", "is_trial_period": "false", "in_app_ownership_type": "PURCHASED", "web_order_line_item_id": "2000000026088214", "original_transaction_id": "2000000320390725", "is_in_intro_offer_period": "false", "subscription_group_identifier": "20906883" }, { "quantity": "1", "product_id": "co.appeconomy.alarm.monthly", "expires_date": "2023-04-26 10:11:53 Etc/GMT", "purchase_date": "2023-04-26 10:09:53 Etc/GMT", "transaction_id": "2000000320390725", "is_trial_period": "true", "in_app_ownership_type": "PURCHASED", "web_order_line_item_id": "2000000026088213", "original_transaction_id": "2000000320390725", "is_in_intro_offer_period": "false", "subscription_group_identifier": "20906883" } ], "pending_renewal_info": [ { "product_id": "co.appeconomy.alarm.monthly", "auto_renew_status": "1", "auto_renew_product_id": "co.appeconomy.alarm.monthly", "original_transaction_id": "2000000320390725" } ] }, "auto_renew_status": "true", "notification_type": "INTERACTIVE_RENEWAL", "auto_renew_product_id": "co.appeconomy.alarm.monthly", "original_transaction_id": 2000000320390725 } From the product_id and subscription_group_identifier can recognize that I really resubscribed the same sku, so why? Does I miss any exceptional case in document?
2
0
1k
Apr ’23
Why is_in_billing_retry_period field appear while my subscription normal expired
I turn off the auto renwal, and after the current subscription expired, I call verifyReceipt api to check the latest status. I just found that "pending_renewal_info": [ { "auto_renew_product_id": "co.ringalarm.swtich.monthly", "is_in_billing_retry_period": "0", "product_id": "co.ringalarm.swtich.monthly", "original_transaction_id": "2000000333327838", "auto_renew_status": "0" } ], It is odd cause I thought this field is appear while subscription is into the billing retry. Does this field can help me to decide whether the subscription is expired?
0
0
559
May ’23
How to recognize upgrade, downgrade, crossgrade in notification v1
assume that I have this 5 PRODUCT I purchase Weekly, then I switch to Monthly, it is upgrade, will receive INTERACTIVE_RENEWAL, indicate that new plan takes effect immediately. I purchase Yearly, then I switch to Monthly, it is downgrade, will receive DID_CHANGE_RENEWAL_PREF, indicate that new plan takes effect at the next renewal. I purchase Quarterly, then I switch to Quarterly2, it is crossgrade, will receive INTERACTIVE_RENEWAL, indicate that new plan takes effect immediately; Because the subscriptions are the same duration. I purchase Quarterly, then I switch to Monthly, it is crossgrade, will receive DID_CHANGE_RENEWAL_PREF, indicate that new plan takes effect at the next renewal; Because the durations are different. So, if I receive INTERACTIVE_RENEWAL notification, how can I recognize it is upgrade, or crossgrade to same duration product. If I receive DID_CHANGE_RENEWAL_PREF, how can I recognized it is downgrade, or crossgrade to different duration product. Does anyone can help me, thanks so much!! Orz
2
0
1.3k
May ’23
why our server received DID_CHANGE_RENEWAL_STATUS notification long time after use's grace period expired?
I am still using App Store Server Notifications 1.0, i wanna to recognized the situation that user didn't fix while pay issue occur, so he is expired after grace period. But I notice that there will be a long time after his grace period I received the notification. Such as: { "auto_renew_product_id": "com.protect.adpatrol.weekly2", "auto_renew_status": "false", "auto_renew_status_change_date": "2023-01-03 16:50:59 Etc/GMT", "auto_renew_status_change_date_ms": "1672764659000", "auto_renew_status_change_date_pst": "2023-01-03 08:50:59 America/Los_Angeles", "environment": "PROD", "notification_type": "DID_CHANGE_RENEWAL_STATUS", "original_transaction_id": 150001223579830, "unified_receipt": { "environment": "Production", "latest_receipt_info": [ { "expires_date": "2022-11-01 09:15:38 Etc/GMT", "expires_date_ms": "1667294138000", "expires_date_pst": "2022-11-01 02:15:38 America/Los_Angeles", "in_app_ownership_type": "PURCHASED", "is_in_intro_offer_period": "false", "is_trial_period": "true", "original_purchase_date": "2022-10-29 09:15:42 Etc/GMT", "original_purchase_date_ms": "1667034942000", "original_purchase_date_pst": "2022-10-29 02:15:42 America/Los_Angeles", "original_transaction_id": "150001223579830", "product_id": "com.protect.adpatrol.weekly2", "purchase_date": "2022-10-29 09:15:38 Etc/GMT", "purchase_date_ms": "1667034938000", "purchase_date_pst": "2022-10-29 02:15:38 America/Los_Angeles", "quantity": "1", "subscription_group_identifier": "20900376", "transaction_id": "150001223579830", "web_order_line_item_id": "150000550680992" } ], "pending_renewal_info": [ { "auto_renew_product_id": "com.protect.adpatrol.weekly2", "auto_renew_status": "0", "expiration_intent": "2", "grace_period_expires_date": "2022-11-07 10:15:38 Etc/GMT", "grace_period_expires_date_ms": "1667816138000", "grace_period_expires_date_pst": "2022-11-07 02:15:38 America/Los_Angeles", "is_in_billing_retry_period": "0", "original_transaction_id": "150001223579830", "product_id": "com.protect.adpatrol.weekly2" } ], "status": 0 } } Notice that his grace period is expire at '2022-11-07 10:15:38 Etc/GMT', but his renew status change at '2023-01-03 16:50:59 Etc/GMT'. It is almost 60 days. So this message is sent after billing retry attempts(up to 60 days) fail?
2
0
772
Apr ’23