Testing

Test mode vs live, store sandbox accounts, seeded data, and a go-live checklist.

CashSDK gives you a full test environment that mirrors production: separate data, separate server keys, and the same APIs, so you can validate the entire purchase flow before a single real charge.

Sandbox vs Production#

Do not build two variants of your app. There is one publishable key per app (csk_pk_…), it has no test/live split, and it belongs in every build configuration you ship:

swift
CashSDK.configure(publishableKey: "csk_pk_…")
kotlin
CashSDK.configure(context = this, publishableKey = "csk_pk_…")

The reason is that the choice does not exist to make. TestFlight distributes the exact binary you submit to the App Store, and Play internal testing distributes the exact APK from your listing. One key is compiled into both, so pinning it to one environment would lock out every user of the other.

The store decides which environment a purchase belongs to, per purchase:

How the build runsStore environment
From Xcode, or installed via TestFlightApple Sandbox
Installed from the App StoreProduction
Google Play internal/closed testing track with a licence testerPlay test purchase

CashSDK reads that out of the store's own signed payload, so a client cannot spoof it. Entitlements and consumable balances are resolved per environment: a Sandbox purchase never grants Production access to the same user, a coin pack bought in TestFlight is not spendable in the App Store build, and sandbox revenue never mixes into your production numbers. The SDK works out which environment it is running in on its own, from Transaction.environment on iOS and from the verify response on Android, and asks for that one on every subsequent read.

You almost never need to set environment: in configure(...). Set it only to pin a QA build that must read one environment before it has made any purchase at all; a pinned value always wins over what the store reports, so a wrong one shows an empty entitlement list.

Your server keys are still split, and there you want them to be: csk_sk_test_… reaches Sandbox data, csk_sk_live_… reaches Production, and neither can reach the other. Point your staging backend at the test key and no config mistake can have it writing to real customers. See Authentication.

Store sandbox accounts#

Native store purchases in test mode require a store sandbox tester:

  • Apple: create a Sandbox Apple Account in App Store Connect (Users and Access → Sandbox) and sign into it on the device under Settings → Developer.
  • Google: add the tester's Google account to your app's license testers in the Play Console, and use an internal testing track.

Sandbox subscriptions renew on an accelerated clock (minutes, not months), so you can watch renewals, expirations, and grace periods play out quickly.

Seeded sandbox data#

Test mode comes pre-populated with real seeded rows (apps, a product catalog, paywalls, customers, and transactions) so the dashboard, APIs, and analytics are fully populated on day one. It's real data in your database, not mocks, so GET /v1/apps/{app}/customers and friends return exactly what production would.

Verify your setup#

1
Run the doctor

The CLI checks keys, store credentials, webhook endpoints, and catalog wiring in one pass.

bash
cashsdk doctor
2
Review the checklist

See exactly what's left before go-live, live-computed from your workspace.

bash
cashsdk checklist

The same data is available at GET /v1/apps/{app}/setup/checklist.

3
Request an Apple test notification

Confirm your App Store Server Notification pipeline end to end with the MCP request_apple_test_notification tool. Apple sends a test notification to your instance, which verifies it and emits the corresponding webhook.

text
request_apple_test_notification(app="my-app")
4
Fire a test webhook

Use send_test_webhook (or the dashboard) to confirm your endpoint verifies the CashSDK-Signature and handles the event. See Webhooks.

Go-live checklist#

1
Swap your backend to the live secret key

Replace csk_sk_test_… with csk_sk_live_… on your server, sourced from an environment variable, never hard-coded. Your app does not change: the publishable key it already ships is the one that goes live with it.

2
Confirm store credentials

Production App Store Connect and Google Play credentials are connected and validated (cashsdk doctor passes).

3
Point store notifications at production

App Store Server Notifications and Google Play RTDN target your live instance, and your webhook endpoint is registered and verifying signatures. A separate Mac App Store record needs the same notification URL and its Mac Apple App ID before Production purchases from it verify.

4
Smoke-test a real purchase

Buy and refund once in production, confirm the entitlement grants and revokes, and check the event lands on your webhook.

Next steps#