💳 In-App Purchases — Console Setup Guide (for Jeff)

HOOP 系统设计图纸 · 正文唯一真相是 docs/iap-setup-en.md;改 md 再跑 ./tools/deploy_docs.sh,这页是生成的

版本 a32cdf47a
2026-09-24 09:16
档案
name iap-setup-en
summary Console setup guide for in-app purchases, for Jeff to follow click by click — App Store Connect, Play Console and Google Cloud, ordered by when each step can be done, each step saying what to report back. Companion to /iap-en.

💳 In-App Purchases — Console Setup Guide (for Jeff)

What this is: on 2026-09-24 Leong decided that Jeff handles the consoles and asked for a clear guide. These are the steps of Phase 0 and §4 of the purchase plan /iap-en that only the account holder can do, ordered by when each can be done. Every step ends with what to report back.

🇨🇳 Chinese version: /iap-setup — same content.

Time: about half an hour for today's part; an hour for the Apple products; about twenty minutes for each Google part, once its precondition is met.

Three things never to do

  1. The key file never goes into chat or git. The Google JSON file goes straight onto the server with scp (step 12).
  2. Do not press "Create" for any product in either console until step 3 is answered. A product ID is taken forever once created, even if deleted.
  3. Do not submit or sell …34000 (the MYR 250 pack) yet. At a 30% commission it loses money; it waits until the Small Business Program's 15% is actually in effect (step 2).

What to send back (post in the ACodes room, @Tora Master)

  • [ ] Step 1: is the Apple Paid Apps agreement active (yes / what is missing)
  • [ ] Step 2: the date the Small Business Program application was submitted
  • [ ] Step 3: do products starting with com.hooptech.hoop.green. exist (yes / no; if yes, how many)
  • [ ] Step 5: Google 15% service fee enrolment done or not
  • [ ] Step 6: the six price points chosen + the proceeds Apple shows (a screenshot is fine)
  • [ ] Step 11: the Android tester's Gmail
  • [ ] Step 12: Google Cloud project id, service account email, and the key file's path on the server (the path only, never the contents)
  • [ ] Testers: the HOOP account of the person testing on iPhone and of the person testing on Android

1. Today (nothing to wait for)

Step 1 · Apple Paid Apps agreement

App Store Connect → Business (formerly Agreements, Tax, and Banking). The Paid Apps row must be Active. If not, complete the tax forms and the bank account.

Why first: without an active agreement the app finds no products at all, and the top-up screen only shows "The store isn't available right now".

Report: Active, or what is still missing.

Step 2 · Apply to Apple's Small Business Program (30% → 15% commission)

Signed in as the Account Holder, open https://developer.apple.com/app-store/small-business-program/ and follow Enroll. The form asks about Associated Developer Accounts — other Apple developer accounts you own or control; answer none if there are none.

⚠️ Approval is not the start date. Apple's wording: proceeds are adjusted from 15 days after the end of the fiscal month in which enrolment is approved (approved 10 February → 15% from 14 March). So the earlier the better; this is the highest-return step on the whole track.

Report: the submission date, and later the approval date.

Step 3 · Do the Apple products already exist? (decides the product IDs)

App Store Connect → Apps → HOOP → sidebar MonetizationIn-App Purchases. Look for products whose Product ID starts with com.hooptech.hoop.green..

You see Meaning Then
Yes (should be six: …green.500 to …green.34000) Created before Step 7: change prices only, create nothing
None Never created Step 7: create six as com.hooptech.hoop.spark.<amount>

Report: yes / no (if yes, how many and their status). Create nothing until you have reported this.

Step 4 · Google developer account + payments profile

Play Console (https://play.google.com/console) → SetupPayments profile: a verified payments profile must exist. If HOOP has no Google Play developer account yet, register one first (US$25, once).

Report: account exists, payments profile verified.

Step 5 · Enrol in Google's 15% service fee

Google charges 15% on the first US$1M of earnings each year, only once you enrol: Play Console → account settings → Account group → create an account group with HOOP's account as the primary account → declare any associated accounts (none if none) → accept the 15% service fee terms → enrol on the Associated developer accounts page.

Google's help page: https://support.google.com/googleplay/android-developer/answer/10627869

Report: enrolled or not.


2. Apple products (as soon as step 3 is answered, same day)

Step 6 · Malaysia as base storefront, then the price points

In each in-app purchase's Price Schedule, set Base Country or Region to Malaysia. Then pick a price point for each tier. Apple only allows its own points; the rule is the nearest point at or below the target.

Tier (Sparks) Target Pick
500 MYR 5.00 nearest ≤ 5.00
1,600 MYR 14.90 nearest ≤ 14.90
3,400 MYR 30.00 nearest ≤ 30.00
6,500 MYR 55.00 nearest ≤ 55.00
14,000 MYR 110.00 nearest ≤ 110.00
34,000 MYR 250.00 nearest ≤ 250.00

Next to each point Apple shows the Proceeds — what we actually receive. Screenshot all six for me: they confirm or correct the 8% tax the plan assumes, and I recompute the margin table from them.

Report: the six prices chosen + a screenshot of the proceeds.

Step 7 · Create the products (or only re-price them)

If step 3 was "yes": open each of the six …green.* products, apply step 6's price, and set Availability to Malaysia only. Change nothing else.

If step 3 was "none": click + next to In-App Purchases and create six:

  • Type: Consumable
  • Reference Name: anything for your own reference, e.g. Spark 500
  • Product ID: com.hooptech.hoop.spark.500, …spark.1600, …spark.3400, …spark.6500, …spark.14000, …spark.34000 (exactly — it can never be changed)
  • Price: from step 6
  • Availability: Malaysia only
  • App Store Localization: English and Simplified Chinese. Display name 500 Hoop Sparks in both; description Spend Sparks inside HOOP. / 在 HOOP 里使用的 Spark。
  • Review Information: one screenshot of the top-up screen (ask NOVA for the latest)

Each product must reach Ready to Submit. ⚠️ A product still in Missing Metadata is invisible even in TestFlight.

…34000 is special: create and complete it the same way (this fixes its ID and shows its proceeds), but do not submit it. I will say in the room when the 15% rate is in effect.

Report: all six at Ready to Submit.

Step 8 · Refund notification URL

App Store Connect → Apps → HOOP → App Information → scroll to App Store Server Notifications:

  • Production Server URLSet Up URLhttps://api.hoopcomm.com/v1/iap/apple/notify → choose Version 2
  • Sandbox Server URLleave empty (Apple then sends sandbox notifications to the production URL too; our backend tells them apart)

That endpoint is already live, so this works as soon as it is saved.

Report: done.


3. Google products (once NOVA has an Android build)

Step 9 · Upload the Android build to internal testing

NOVA produces an .aab with tools/tf-build/cut_android.sh (it builds; it does not upload). Play Console → HOOP → TestingInternal testingCreate new release → upload the .aabSaveReview releaseStart rollout. If Play first asks you to complete the App content questionnaires (privacy policy, content rating and so on), complete them and come back.

Why first: Google does not allow creating in-app products until a build has been uploaded.

Step 10 · Create the six products

Play Console → HOOP → MonetizeProductsIn-app products (called One-time products in the newer layout) → Create product:

  • Product ID: exactly the set Apple ended up with (step 3: green or spark)
  • Name / Description: as in step 7
  • Price: Google lets you type the price — enter 5.00 / 14.90 / 30.00 / 55.00 / 110.00 / 250.00 for Malaysia
  • Countries / regions: Malaysia only
  • Then Activate

…34000: if step 5's enrolment is confirmed, Activate it; if not, leave it inactive.

Step 11 · Licence testers

Play Console → SettingsLicense testing → add the Android tester's Gmail to a list. People on that list buy in the internal test build without being charged.

Report: the tester's Gmail.


4. The Google key (before Phase 3a starts)

Step 12 · Google Cloud project, APIs, service account, key file

  1. Open https://console.cloud.google.com/ and create a project, e.g. hoop-play (or use a suitable existing one). Note the project id.
  2. APIs & ServicesLibrary: enable Google Play Android Developer API and Cloud Pub/Sub API.
  3. IAM & AdminService AccountsCreate service account, name hoop-play-billing, no roles → done. Note its email (hoop-play-billing@<project-id>.iam.gserviceaccount.com).
  4. Open that service account → KeysAdd keyCreate new keyJSON. A .json file downloads.
  5. Put the file straight onto the server (do not send it to anyone, do not paste it anywhere):
scp ~/Downloads/<downloaded-file>.json root@139.180.208.52:/root/hoop/deploy/google-play-sa.json
ssh root@139.180.208.52 chmod 600 /root/hoop/deploy/google-play-sa.json

Once it is uploaded, delete the downloaded copy from your computer.

Report: project id, service account email, and that /root/hoop/deploy/google-play-sa.json is in place. Never the file's contents.

Step 13 · Give the service account access in Play Console

Play Console → Users and permissionsInvite new users → the service account email from step 12 → under Account permissions, tick only:

  • View financial data, orders, and cancellation survey responses (all the server needs to read purchases and refunds)

Nothing else — the app consumes purchases itself, so the server needs no more than this, and a key should carry as little as possible. → Invite user.


5. After I say in the room that the Google notification endpoint is live

Step 14 · Real-time developer notifications (RTDN)

① Create the topic. Google Cloud → Pub/SubTopicsCreate topic, name play-rtdn.

② Let Google Play publish to it. Open the topic's permissions → Add principalgoogle-play-developer-notifications@system.gserviceaccount.com → role Pub/Sub PublisherSave.

③ Create the push subscription. On that topic, Create subscription, filled in as follows:

Field Value
Delivery type Push
Endpoint URL https://api.hoopcomm.com/v1/iap/google/notify
Enable authentication ticked
Service account hoop-play-billing from step 12
Audience exactly the same string as the Endpoint URL

④ Enter the topic in Play Console. Play Console → HOOP → MonetizeMonetization setupReal-time developer notifications → tick Enable real-time notificationsTopic name projects/<project-id>/topics/play-rtdnSaveSend test notification.

Why wait for me: that endpoint (G4 in Phase 3a) is not written yet. Set this up now and Google keeps pushing to an address that does not exist.

Report: test notification sent. It counts as working once I see it arrive.


6. Testers (Phase 6)

  • iPhone: install the TestFlight build. Purchases in TestFlight are free; no separate sandbox account is needed.
  • Android: the Gmail on step 11's list, signed in on the phone, installs the internal test build.

⚠️ Today the server rejects every test purchase, and its only switch opens test purchases to everyone — which would hand out real Sparks for free to anyone with a test build. So the plan adds a list of tester accounts: only those HOOP accounts may make test purchases. Tell me the two testers' HOOP accounts and I will add them.


7. Later, at launch (nothing to do now, just know it)

  • Apple's first in-app purchases must be submitted together with a new app version. When NOVA's build goes for review, tick the five products (not …34000) in the version's In-App Purchases section so they are reviewed together.
  • …34000: submitted and put on sale only once the 15% rate is in effect (I will say so in the room).
  • Availability stays Malaysia only on both stores until the plan says otherwise.

If any screen does not match what is written here, drop a screenshot in the ACodes room and I will correct this guide.