Ask Rork for "an app that lists products and takes payment with Stripe at checkout," and it assembles the payment screen too. Watching it run, shipping it as-is feels reasonable.
Then comes the App Store submission, and many people stall. If the app sells something, isn't in-app purchase (IAP) mandatory?
A disclosure first. As an indie developer, my own apps lean on ads and in-app purchase, and I have never submitted a shop or booking payment flow for review. So this is not a story of getting rejected. It is my reading of Apple's App Review Guidelines and Google Play's payments policy, redrawn by what you sell.
The short version: Stripe versus IAP is not decided by fees or taste. It is decided by whether what the customer bought is used outside the app or inside it. That is how I read it.
The first fork: is it used outside the app?
Guideline 3.1.1 asks you to use IAP for things whose value lives inside the app: unlocked features, subscriptions, in-game currency, premium content.
Guideline 3.1.3(e) points the other way. If people buy physical goods, or services consumed outside the app, you must collect payment by means other than IAP. The wording is not "you may" but "use something else." Apple Pay and card entry are the examples given.
So using IAP for a physical product runs against the intended direction. Many people find that surprising.
A routing table by what you sell
Here are eight combinations that tend to cause hesitation.
| What you sell | Where it is used | How Apple reads it | Payment direction |
|---|---|---|---|
| Goods such as stationery or food | Outside the app (shipping) | 3.1.3(e) | External payment such as Stripe |
| Salon or restaurant booking and payment | Outside the app (the venue) | 3.1.3(e) | External payment |
| Event admission tickets | Outside the app (the venue) | 3.1.3(e) | External payment |
| One-to-one online tutoring | Real-time, individual delivery | 3.1.3(d) | External payment, explained in review notes |
| A live class for about 10 people | One-to-many delivery | Outside 3.1.3(d) | IAP |
| Paid wallpaper packs, articles, video | Inside the app | 3.1.1 | IAP |
| Ad removal, feature unlocks, monthly membership | Inside the app | 3.1.1 | IAP |
| Credit bought in the app, spent later at a store | Could be read either way | Interpretation varies | Write a review note and keep an IAP path ready |
The last row is where disagreements happen. "It's a shop app, so external payment is fine" is too coarse. The work is checking each item: whose hands is it in, and where is it consumed?
Why fees should not decide it
Apple's IAP commission is 30% by default and 15% under the small business program. Stripe can look like a way to keep that margin.
As an indie developer I understand the temptation to push digital content through Stripe. But that is a direct hit on 3.1.1. It can be rejected at review, and if it is noticed after release, an update can be blocked and the whole app's revenue stops.
Looking at it from the other side helps. The IAP fee is the price of selling value that exists only inside the app. Goods and in-person bookings sit outside that value, so they were never IAP territory.
One more note: around Japan's law taking effect in December 2025, there have been moves to broaden external-payment options for Japan. Conditions and fees can change by country and by date, so this article assumes ordinary review on the Japanese storefront. Check the primary text right before you submit.
A small helper for drawing the line
With more items, the judgment drifts if it lives only in your head. When I add a new sale item, I would suggest running it through a function like the one below and keeping the result. It is not a copy of Apple's interpretation; it is a ledger of which way you decided to lean for each item.
// lib/paymentRoute.ts
export type SaleKind =
| "physical-good"
| "in-person-service"
| "live-one-to-one"
| "live-group"
| "digital-content"
| "digital-feature"
| "subscription-access"
| "credit-for-later";
export type PaymentRoute =
| "external" // Stripe etc. Physical goods, services used outside the app
| "external-with-note" // External payment; explain the one-to-one nature in review notes
| "iap" // In-app purchase
| "review-note"; // Interpretation varies. Write a note and prepare IAP as well
export function paymentRoute(kind: SaleKind): PaymentRoute {
switch (kind) {
case "physical-good":
case "in-person-service":
return "external";
case "live-one-to-one":
return "external-with-note";
case "credit-for-later":
return "review-note";
default:
return "iap";
}
}The default branch catches the digital kinds, from live-group to subscription-access. That fixes "when in doubt, IAP" in the shape of the code. Only physical goods are sent out explicitly, so forgetting to update the function when you add an item will not push a digital item toward external payment by accident.
Three lines for the review notes
If any item uses external payment, leave these three lines in the review notes. They shorten the reviewer's guesswork.
- What you sell (for example, booking and payment for a haircut provided at a salon)
- Where it is consumed (for example, inside the booked salon; nothing is unlocked in the app)
- Whether digital features are billed separately (for example, ad removal is offered through IAP)
The third line matters more than it looks. If a shop app also has a members-only page or an ad-free option, say plainly that those parts go through IAP. Mixed apps without that explanation tend to be read as one big external-payment app.
How it looks on Android
Google Play has a payments policy that points the same way. Digital items inside the app use Google Play's billing system, while physical goods and services delivered outside the app are out of its scope.
The two stores' lines do not overlap perfectly. For example, Apple puts one-to-many live classes on the IAP side. If you ship to both stores, give the table two columns, one per store, and keep each store's call on record for later.
Next steps
First, list the items your app sells or plans to sell. Next, use the function or the table to decide "outside" or "inside" for each one. Last, write the three review-note lines only for the items that use external payment.
For what reviewers tend to ask, see The Complete App Store Review Checklist for Rork Apps — How to Get Approved on Your First Try. For holding subscription entitlements on the IAP side, Validating StoreKit 2 Subscriptions Server-Side: Granting Access Without Trusting the Device is useful. And for using Stripe on the web side, see Building a Complete Stripe SaaS Payment System with Rork: Next.js × Cloudflare Workers × Supabase.
Guideline text gets revised from time to time. Before you submit, please read Apple's original wording yourself once more.