← Back to Blake
AgentBlake

Skill · Version 1.0.0

Mobile purchases and RevenueCat

Connects store transactions and RevenueCat events to verified account entitlements and recoverable purchase states.

mobile-purchases-revenuecat

See how it helps

When is it useful?

Use when subscriptions must survive restores, account changes and delayed store events.

What does it help you do?

  • Verifies purchases server-side and finishes transactions appropriately.
  • Defines anonymous-user linking and restore-purchase behavior.
  • Deduplicates provider events and reconciles entitlement changes.

Try asking this

Test subscription restoration after reinstall, including account mismatch and a delayed cancellation notification.

Detailed documentation

Read the skill’s original instructions, examples and checks in their authored language.

Details…Show less

Mobile Purchases & RevenueCat Integration

Mobile in-app purchases (Apple App Store In-App Purchase / StoreKit 2, Google Play Billing Library and RevenueCat) operate under store-controlled billing engines: users can upgrade, downgrade, cancel, request refunds or share subscriptions via Family Sharing directly inside OS Settings while your app is closed.

1. Server-Side Verification & Transaction Finishing

  • Never unlock persistent backend entitlements solely from client-side purchase callbacks: always verify the signed transaction/purchase token on your backend (or via RevenueCat's server API/webhooks) before granting server-side entitlements.
  • Acknowledge / Finish Transactions Only After Server Persistence:
    • Google Play Billing: every purchase must be acknowledged within 3 days (acknowledgePurchase for subscriptions/non-consumables, consumeAsync for consumables), otherwise Google Play automatically refunds and revokes the purchase! Only acknowledge after your server has recorded the purchaseToken and granted the entitlement.
    • Apple StoreKit 2: verify the JWS (JSON Web Signature) Transaction signed by Apple (App Store Server API / root certificate chain) and call transaction.finish() only after server fulfillment succeeds.

2. Account Binding, Anonymous Users & "Restore Purchases"

Mobile store accounts (originalTransactionId on iOS, purchaseToken / obfuscatedAccountId on Android) are tied to the user's Apple ID or Google Play account, which may differ from the application's logged-in user account:

  • Pass obfuscated app user IDs: set appAccountToken (UUID) in StoreKit 2 and setObfuscatedAccountId in Google Play Billing (or Purchases.logIn(appUserId) in RevenueCat) so store server notifications map deterministically to your backend user.
  • Mandatory "Restore Purchases" Flow: App Store Review requires a visible "Restore Purchases" action that syncs store transactions and restores entitlements on a new device without charging the user again.
  • Account Transfer / Aliasing Policy: define clearly what happens when User A logs out on a device and User B logs in and taps "Restore Purchases" on the same Apple/Google store account (keep bound to original owner, transfer entitlement, or reject with a clear message).

3. Store Server Notifications & RevenueCat Webhooks

Handle real-time lifecycle events pushed by the stores or RevenueCat:

  • Apple App Store Server Notifications V2 (signedPayload JWS):
    • SUBSCRIBED, DID_RENEW, DID_CHANGE_RENEWAL_STATUS, DID_CHANGE_RENEWAL_PREF (upgrade/downgrade), DID_FAIL_TO_RENEW (check isInBillingRetryPeriod and gracePeriodExpiresDate), GRACE_PERIOD_EXPIRED, EXPIRED, REFUND (revoke access immediately), REVOKE (Family Sharing revoked).
  • Google Play Real-Time Developer Notifications (RTDN via Cloud Pub/Sub):
    • RTDN sends only a purchaseToken and notificationType (SUBSCRIPTION_PURCHASED, SUBSCRIPTION_RENEWED, SUBSCRIPTION_IN_GRACE_PERIOD, SUBSCRIPTION_ON_HOLD, SUBSCRIPTION_CANCELED, SUBSCRIPTION_EXPIRED, SUBSCRIPTION_REVOKED). Your backend must call purchases.subscriptionsv2.get in the Google Play Developer API to read the authoritative state and expiryTime.
  • RevenueCat Integration:
    • Verify the webhook Authorization header, deduplicate by event.id, and process INITIAL_PURCHASE, RENEWAL, CANCELLATION (keep access until expiration_at_ms!), UNCANCELLATION, BILLING_ISSUE, PRODUCT_CHANGE, EXPIRATION and TRANSFER.
    • Unify web (Stripe/Paddle) and mobile (App Store/Play Store) entitlements into your single internal Entitlement model so a user who subscribes on iOS gets immediate access on web and desktop.

Included files 1

  • SKILL.md