We are seeking clarification on the behavior of App Store Server Notifications V2
.
Summary
In our production environment, we received a notification with notificationType: DID_FAIL_TO_RENEW
and subtype: GRACE_PERIOD
. However, the gracePeriodExpiresDate
field in the payload was null
.
We understand this notification indicates that a user's subscription has entered a grace period. The null
value for its expiration date is unexpected, and we are looking for an official explanation of this behavior and the correct way to handle it.
The Scenario
Here are the details of the notification we received:
- Notification Type:
DID_FAIL_TO_RENEW
- Notification Subtype:
GRACE_PERIOD
- Environment: Production
Upon decoding the signedRenewalInfo
JWS from the responseBodyV2
, we found that the gracePeriodExpiresDate
field inside the JWSRenewalInfoDecodedPayload
was null
.
The notificationUUID
for this event was in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
.
Our Implementation and its Impact
Our backend is designed to ensure service continuity during a grace period, as recommended in the documentation.
Current Logic:
- Receive the
DID_FAIL_TO_RENEW
/GRACE_PERIOD
notification. - Extract the
gracePeriodExpiresDate
. - Extend the user's subscription expiration date in our database to match this date.
Because the gracePeriodExpiresDate
was null
in this case, our logic failed, creating a risk of service interruption for the user.
Context and Investigation
We have performed the following checks:
- App Store Connect Settings: We have confirmed that Billing Grace Period is enabled for the relevant subscription group.
- Sandbox Environment: We have been unable to reproduce this scenario in the Sandbox.
- User Context: We believe the user in this case was experiencing a failed payment when attempting to renew for the first time after a free trial period.
Questions
To ensure we handle this scenario correctly, we would appreciate clarification on the following points:
- Conditions for Null: Under what specific conditions does a
DID_FAIL_TO_RENEW
notification with aGRACE_PERIOD
subtype contain anull
gracePeriodExpiresDate
? - Expected Behavior: Is this
null
value an expected behavior for certain scenarios, such as the first failed renewal after a free trial? - Best Practice: If this is an expected behavior, what is the correct way to handle it? How should our backend interpret a
null
gracePeriodExpiresDate
to ensure service continuity for the user?