Payments
If your app charges money. Even just once, even just a dollar. You need to do it the right way for the platform.
There are two ways apps take money on mobile, and picking the wrong one will get your app rejected by Apple. This page will get the right one for your situation in two minutes.
Which one do I need?
Answer one question: is the thing you're selling used inside the app, or outside it?
"Inside the app". Digital things people use in the app itself
A subscription that unlocks features. Coins or gems. A pack of credits. Premium themes. Anything where the user pays you, and the thing they get is on their phone, in your app.
→ You must use Apple In-App Purchase (on iPhone) and Google Play Billing (on Android). Apple and Google take a cut (15-30%). You don't get to choose; their rules.
To make this easier, we use a service called RevenueCat that handles both platforms with one set of code.
"Outside the app". Physical goods, real-world services, web purchases
A pair of shoes. A cleaning booking. A B2B subscription to a SaaS product. Anything where what the user pays for happens off-phone.
→ You use Stripe. Stripe takes a small percentage (around 2.9% + a few cents per transaction). Apple and Google don't get a cut.
Both?
Some apps need both. A marketplace app might sell physical goods (Stripe) but also offer a premium membership inside the app (Apple/Google). That's allowed. You just have to keep them separate. The agent handles both.
Adding Stripe (for real-world goods and services)
"Let users upgrade to a Pro plan at $9.99/month or $99/year. Use Stripe Checkout, with cancel anytime. Remember on each user whether they're Pro so I can unlock features for them."
What the agent does:
- Adds a Pro/Free flag to your user records.
- Builds a "Subscribe" screen that opens Stripe's secure payment page.
- Sets up the back-and-forth so when a user pays, your app knows they paid.
- Handles the awkward cases. Refunds, failed payments, cancellations. Automatically.
- Wires up the unlock logic so Pro users see Pro features.
What you do on Stripe's side
After the agent sets things up, you finish on Stripe:
- Create a free Stripe account at stripe.com.
- Connect it in Dashboard → Connectors → Stripe. One-click Connect with Stripe where available, or paste your keys into the form (the page shows you exactly where to find them). You connect once for your whole account; every project can use it.
- Decide who creates the products. You can build the Pro plan and its prices in the Stripe dashboard yourself - or turn on Account Access on the Stripe connector page and the agent creates the products and webhook for you, in your account. Every action it takes there is listed in the Activity feed at the bottom of that page.
If the agent needs Stripe mid-build and it isn't connected yet, it pauses and drops a connect card into the chat - connecting happens in a modal on the same page, and the build resumes on its own.
Testing without spending real money
Stripe has a test mode with fake credit card numbers (the famous one is 4242 4242 4242 4242). Run through the full purchase flow with test cards before flipping the switch to real money.
Adding Apple/Google in-app purchases (via RevenueCat)
This is required if you're selling things consumed inside the app.
"Let users subscribe to a Pro tier from inside the app using in-app purchases. Monthly and annual options. Use RevenueCat for cross-platform receipt handling."
What the agent does:
- Installs RevenueCat's library.
- Builds a paywall screen with your subscription options.
- Handles "buy," "restore previous purchase," and "subscription state."
- Adds a check you can use anywhere in the app: "is this user a paying member?"
What you do on the platform side
This is the slightly tedious part. You only do it once:
- Create a free RevenueCat account at revenuecat.com.
- In App Store Connect (Apple's dashboard) and Google Play Console, create your subscription products. Both stores require this.
- Link those products to RevenueCat by their codes.
- Connect RevenueCat in Dashboard → Connectors → RevenueCat with your public SDK key (it's designed to be bundled into apps). Connect once and every project in your account can use it.
Testing in-app purchases
You can test without spending real money:
- iPhone: use a Sandbox Apple ID set up in App Store Connect. Sandbox purchases flow through every step except the real charge.
- Android: add tester emails in Play Console and use a "License Tester" account.
Both are walked through in RevenueCat's onboarding.
A few things that catch people out
- Don't mix the two. Don't charge for in-app subscriptions via Stripe on iPhone. Apple will reject your app. Don't sell a physical product via Apple's in-app purchase. They don't do refunds for things the app didn't deliver. If you're not sure, ask the agent.
- Test keys vs live keys. Both Stripe and RevenueCat have a "test/sandbox" mode and a "live" mode. Each has its own keys. Keep them separate so you don't accidentally launch with test keys (no money) or test with live keys (real money).
- Tax. Stripe handles sales tax in most countries via "Stripe Tax." Apple and Google handle their own tax. They're the merchant of record, you receive the post-tax amount.
Refunds
- Stripe: you issue refunds from the Stripe dashboard. The app gets notified and revokes access automatically.
- Apple/Google: they decide on refunds (you can't override them). When they refund, RevenueCat tells your app and access is revoked.
Your own Refund Policy still applies. Australian customers keep their Consumer Law rights either way.
Under the hood (for engineers)
Stripe and RevenueCat are both managed connectors - connected once per account in Dashboard → Connectors, keys encrypted at rest. The agent scaffolds the in-app flow on top.
Stripe:
- A webhook endpoint at
/api/stripe/webhookwith HMAC signature verification. - A
/api/billing/checkoutroute that creates a Stripe Checkout Session. - Handlers for
checkout.session.completed,customer.subscription.updated,customer.subscription.deleted,invoice.payment_succeeded,invoice.payment_failed,charge.refunded. - A
hasAccess(user, feature)helper for gating. - With Account Access on, the agent creates products and registers the webhook through server-side tools in your Stripe account - it never sees your secret key, and every action lands in the connector's Activity feed.
RevenueCat (for IAP):
react-native-purchasesinstalled and aPurchasesProviderat the root.- A paywall component reading the configured offerings.
- A
hasEntitlement(user, "pro")helper.
Webhook deduplication uses the provider's event ID, so a redelivered event never double-grants.
Next
Read Push Notifications so you can let users know about purchases and other events.
