We experienced an issue with delayed App Store Server notifications for an Auto-Renewable Subscription purchase in our app.
On September 27, 2024, at 22:28:28 GMT+0900, a user successfully purchased a Premium membership subscription (transaction ID: 190002223966278, webOrderLineItemId: 190001007274949).
However, our server did not receive the corresponding App Store notification for this transaction after purchase.
The App Store Server Notification was only received 66 minutes later, at 23:35:16 (transaction ID: 190002224000004, webOrderLineItemId: 190001007274949).
The delayed notification contained a different transaction ID than the initial purchase.
We would like to inquire about the cause of this delay and request assistance in understanding why the notification took 66 minutes to be delivered to our server, instead of arriving immediately after the transaction was completed.
Additionally, we would appreciate your guidance on how to prevent or mitigate such delays in the future, ensuring a seamless experience for our users.
Are there any best practices or recommended approaches we should implement to handle potential notification delays more effectively?
We have provided detailed information about the received notification and the related transactions in the Feedback Assistant (FB15330451).
Thank you for your assistance in resolving this matter.
Key Details
Purchase time: 2024-09-27T22:28:28 GMT+0900 (1727443708000)
Notification received: 2024-09-27T23:35:16 GMT+0900 (1727447716463)
Delay: 66 minutes and 48 seconds
Initial Purchase Transaction ID: 190002223966278
Initial Purchase Web Order Line Item ID: 190001007274949
Transaction ID in Delayed Notification: 190002224000004
Web Order Line Item ID in Delayed Notification: 190001007274949
Additional info
Bundle ID: com.reppley.ReppleyApp
SKU: com.reppley.ReppleyApp
Feedback Assistant Number: FB15330451
Post
Replies
Boosts
Views
Activity
Hello,
I am encountering an issue where I receive an App Store Server Notification V2 upon the purchase of a consumable item.
I have configured the App Store Server Notification V2 endpoint to handle notifications related to subscription products.
However, I did not expect to receive notifications for consumable purchases.
The notification includes the following signedPayload decoded into the ResponseBodyV2DecodedPayload object with the following values:
notificationUUID: 3cd6410b-0c89-4247-aba5-20710e79895e
notificationType: null
subtype: null
The transaction information decoded from the ResponseBodyV2DecodedPayload object is as follows:
transactionId: 2000000633622618
webOrderLineItemId: null
productId: heart_2
To debug, I called the Get Notification History API of the App Store Server API, and the mentioned notification for the consumable product purchase is not included in the history. Only notifications related to subscription product purchases are retrieved.
According to the notification type documentation, there is no explanation for cases where both notificationType and subtype are null, nor is there any mention of receiving notifications for consumable purchases. Therefore, I am uncertain how to interpret and handle this notification.
Could you please provide an explanation or guidance on this issue?
Thank you.
References:
https://developer.apple.com/forums/thread/737592
https://developer.apple.com/documentation/appstoreservernotifications/notificationtype
Hello,
I am currently implementing server-side handling for in-app subscription payments and using App Store Server Notifications V2 to receive notifications with a TestFlight account.
However, I am not receiving EXPIRED notifications, although I am successfully receiving other notifications such as SUBSCRIBED, DID_RENEW, and DID_CHANGE_RENEWAL_PREF.
Here are some details of my observations:
Until a certain point, I was receiving EXPIRED notifications without any issues, but they stopped coming in after that point.
Each subscription renews every 3 minutes in TestFlight account, and I receive DID_RENEW notifications 7 to 12 times. According to the official documentation, the subscriptions should renew up to 12 times, but I am not receiving exactly 12 DID_RENEW notifications. This inconsistency might be related to the issue.
Other notifications (SUBSCRIBED, DID_RENEW, DID_CHANGE_RENEWAL_PREF) are received without any issues.
Could anyone provide insight into why this might be happening and suggest any alternative methods to handle subscription expirations in case the EXPIRED notifications are not reliable?
Thank you for your assistance.
Relevant Official Documentation
App Store Server Notifications V2
App Store Server Notifications V2_notificationType
Testing in-app purchases with sandbox
Current Server Implementation
Below is the Kotlin Spring Boot server code currently implemented for handling App Store Server Notifications V2:
@RestController
class ProductIosController(
private val productIosService: ProductIosService,
private val appStoreNotificationService: AppStoreNotificationService,
) : BaseController {
@PostMapping("/api/v1/ios-products/app-store-notifications-v2")
fun handleNotification(@RequestBody @Valid notification: AppStoreNotificationRequest): CustomResponse {
appStoreNotificationService.processNotification(notification)
return CustomResponse.ok()
}
}
@Service
class AppStoreNotificationService(
@Qualifier("appStoreClient") private val appStoreServerAPIClient: AppStoreServerAPIClient,
@Qualifier("signedVerifier") private val signedDataVerifier: SignedDataVerifier,
) {
@Transactional
fun processNotification(notification: AppStoreNotificationRequest) {
logger.info("signedPayload: ${notification.signedPayload}")
val decodedPayload = verifyAndDecodeSignedPayload(notification.signedPayload)
val notificationType = decodedPayload.notificationType
val signedTransactionInfo = decodedPayload.data.signedTransactionInfo
val transaction = signedDataVerifier.verifyAndDecodeTransaction(signedTransactionInfo)
val (user, product) = fetchUserAndProduct(transaction)
when (notificationType) {
SUBSCRIBED -> processSubscriptionPurchase(user, product, decodedPayload, transaction)
DID_CHANGE_RENEWAL_PREF -> processSubscriptionGradeChange(user, product, decodedPayload, transaction)
DID_CHANGE_RENEWAL_STATUS -> processRenewalStatusChange(transaction)
OFFER_REDEEMED -> processOfferRedeemed(transaction)
DID_RENEW -> processSubscriptionRenewal(user, product, decodedPayload, transaction)
EXPIRED -> processSubscriptionExpiration(user, product)
DID_FAIL_TO_RENEW -> processFailedRenewal(transaction)
GRACE_PERIOD_EXPIRED -> processSubscriptionGracePeriodExpiration(transaction)
PRICE_INCREASE -> processPriceIncrease(transaction)
REFUND -> processSubscriptionRefund(transaction)
REFUND_DECLINED -> processRefundDeclined(transaction)
CONSUMPTION_REQUEST -> processConsumptionRequest(transaction)
RENEWAL_EXTENDED -> processRenewalExtension(transaction)
REVOKE -> processSubscriptionRevocation(transaction)
TEST -> processTestNotification(transaction)
RENEWAL_EXTENSION -> processRenewalExtension(transaction)
REFUND_REVERSED -> processRefundReversed(transaction)
EXTERNAL_PURCHASE_TOKEN -> processExternalPurchaseToken(transaction)
else -> logger.warn("Unsupported notification type: ${notificationType.value}")
}
}