52 lines
3.9 KiB
Markdown
52 lines
3.9 KiB
Markdown
---
|
|
name: store-iap-setup
|
|
description: Create and price in-app purchases (consumables, non-consumables like "remove ads", coin/gem packs, starter packs) on Google Play and App Store Connect from one product list - regional prices, local overrides, activation, review screenshots, submitting first IAPs with a version, license/sandbox testers. Use when the user sets up, prices, updates or tests in-app products/IAPs, or hits Play onetimeproducts / inappproducts 403 or App Store IAP submission errors.
|
|
---
|
|
|
|
# In-app purchases on both stores
|
|
|
|
CLI: `storebound` (or `bun ${CLAUDE_PLUGIN_ROOT}/cli/index.ts`). One list in `storebound.config.ts` `products[]` drives
|
|
both stores: `id` (same on both), `type` (consumable | non_consumable), `usd` base price, optional `overrides`
|
|
(`{ region: 'TR', currency: 'TRY', price: 99.99 }`), `listings` per language (title <= 30, description <= 55 for
|
|
Apple), `reviewScreenshot`.
|
|
|
|
## Prerequisites
|
|
- Play: a build with `com.android.vending.BILLING` uploaded to any track; payments profile set up.
|
|
- Apple: Paid Applications agreement + banking + tax active (Business > Agreements), the app record exists.
|
|
|
|
## Google Play (API)
|
|
1. `storebound check`, then `storebound play products --dry` (shows create/update and region count per product).
|
|
2. `storebound play products`. Per product: `pricing:convertRegionPrices` (USD -> every region at local price points,
|
|
and the `regionsVersion`), your overrides on top, `PATCH .../onetimeproducts/{id}?allowMissing=true®ionsVersion.version=...`
|
|
(create or update), then `oneTimeProducts/{id}/purchaseOptions:batchUpdateStates` to activate (new options are DRAFT).
|
|
3. Verify: `storebound play status` lists every product with `buy:ACTIVE`.
|
|
4. Test: Play Console > Settings > License testing: add tester Gmail accounts; install from the internal testing
|
|
link; purchases are free test orders.
|
|
|
|
## App Store (API + UI)
|
|
1. `storebound apple iap --dry`, then `storebound apple iap`: creates missing products, localizations, a price schedule
|
|
(USA base + overrides; Apple equalizes the rest) and availability. Existing schedules are not changed (change prices
|
|
in the UI if needed).
|
|
2. Review screenshot per product (a real device size, e.g. 1290 x 2796, showing the item in the shop):
|
|
`storebound apple iap-review`. States move to READY_TO_SUBMIT when complete.
|
|
3. **UI**: each IAP page > "Add for Review"; this puts them into the version's draft submission. Then submit the
|
|
version (owner, see appstore-first-release).
|
|
4. Test: Sandbox testers (Users and Access > Sandbox) on device; or a StoreKit configuration file in Xcode for local
|
|
runs (those transactions are signed locally and fail server-side receipt checks).
|
|
|
|
## Gotchas
|
|
- Play legacy `inappproducts` returns 403 "Please migrate to the new publishing API" -> use
|
|
`monetization.onetimeproducts`.
|
|
- Path casing: PATCH works on `onetimeproducts`, but list + `purchaseOptions:batchUpdateStates` need `oneTimeProducts`;
|
|
the wrong casing answers with an HTML 404 page.
|
|
- Play has no consumable flag: the app consumes the purchase after granting it. Use `legacyCompatible: true` so older
|
|
billing libraries see the product by id.
|
|
- Apple: first IAPs must ship with an app version ("FIRST_*_MUST_BE_SUBMITTED_ON_VERSION" from
|
|
inAppPurchaseSubmissions). If the version is already in review without them: cancel the review submission
|
|
(`storebound apple status --cancel-submission <id>`, ask the owner), re-add via "Add for Review", resubmit.
|
|
- Apple needs an exact existing price point for each manual price; the error lists the nearest ones.
|
|
- Apple IAP description max 55 characters, display name max 30.
|
|
- Product ids can never be reused after deletion on either store. Never delete without the owner.
|
|
- Do not put prices or product names in store descriptions; say "offers optional in-app purchases".
|
|
- If the game ships without real billing yet, hide every purchase surface in store builds (review rejects mock
|
|
purchases) and answer "digital purchases: No" in IARC.
|