| Start a pending test purchase, then complete or cancel it | No entitlement while PENDING; grant only after verified PURCHASED | Starting access, pending state, final state, and whether access changed | Hold the release if a pending or cancelled payment grants access |
| Verified purchase | Grant the agreed benefit, then acknowledge or consume as required | License-tester record plus backend audit event | Repeated processing must not grant the benefit twice |
| Renewal or expiry | Entitlement follows current purchase state and configured grace/account-hold rules | API response, scheduled reconciliation, and state transition | Retry safely and surface stale-state alerts |
| Upgrade, downgrade, or replacement | Old and new products follow the selected replacement behavior | Plan-change cases with effective-date assertions | Hold release when proration or access outcome is unclear |
| Subscription cancellation | Renewal stops; access normally continues until the verified expiry | Cancellation and expiry tested as separate transitions | Do not treat cancellation as immediate revocation |
| Refund or revocation | Access follows the authoritative purchase state and the action taken | API recheck, notification when available, and idempotent audit trail | Reconcile missed, duplicate, or delayed events |
| Restart the app after payment but before the client receives the result | Purchase recovery reconciles the verified purchase with the correct user entitlement | App restart, purchase re-query, backend result where in scope, and final access | Do not ask the user to buy again before checking the existing purchase |
| Replay an RTDN message or deliver a stale event after a newer one | The handler queries current purchase state and applies the entitlement idempotently | Message ID, purchase-state lookup, processing outcome, and unchanged grant count on replay | Do not grant from the notification alone or let an old event overwrite newer verified state |