You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Unifying alternative billing across Android and iOS at the flow level
#493
I'm implementing Android alternative billing (user-choice billing with
local PG rails) in a production app as a live openiap test vehicle,
and looking at what the iOS side would take. Today the spec splits billing APIs
per platform (api-android.graphql has the billing-program APIs, api-ios.graphql has the external-purchase APIs), so every app
authors two completely different integrations. Question: can openiap
offer alternative billing under one shared spec for both stores?
Why UI-level unification is impossible
The store policies are opposites, so one shared "choice UI" would get
an app rejected on one side:
Google Play allows and encourages in-app billing choice
(user-choice billing screen, external offers).
Apple forbids in-app alternative-payment UI and mandates link-out
plus its own disclosure sheets (external purchase link / notice
sheet / custom link, depending on region and entitlement).
Proposal: unify at the flow level instead
Both platforms share the same abstract flow — check → disclose → handoff → report — and differ only in how each
step renders. Sketch:
Shared capability: isAlternativeBillingAvailable(program) in api.graphql. Android maps to the billing-program availability
check; iOS maps to entitlement/region eligibility
(canPresentExternalPurchaseNoticeIOS-style checks).
Shared flow type: one state machine with platform-divergent
rendering — Android presents in-app choice, iOS presents the
Apple sheet and opens the external URL.
Normalized report token: both stores hand back a
"report this transaction" token (Play's externalTransactionToken, Apple's externalPurchaseToken).
Normalize to something like AlternativeBillingReport { platform, reportToken } with
per-platform server reporting underneath.
Tiering: shared core = external-link flow (the greatest
common denominator); Android in-app choice stays as a platform
extension so Android UX is never sacrificed for parity.
One hard requirement: the iOS path must be safe by default —
skipping the Apple sheet or rendering PG options inside the app
should be inexpressible in the shared API, or apps will get
rejected following our docs.
Open questions
Naming and exact shape of the shared capability/flow/report types.
Where reporting lives: client helper, server guidance, or both?
How to represent the entitlement × region × OS-version matrix
(iOS gates features at 16+/17.4+/18.1+).
Whether the Android in-app extension needs any shared disclosure
primitives beyond what exists.
If there's interest, I'm happy to turn this into a spec sketch PR
against specs/client/src/api.graphql, and validate it against a real
implementation on both sides (Android side already exists).
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Context
I'm implementing Android alternative billing (user-choice billing with
local PG rails) in a production app as a live openiap test vehicle,
and looking at what the iOS side would take. Today the spec splits billing APIs
per platform (
api-android.graphqlhas the billing-program APIs,api-ios.graphqlhas the external-purchase APIs), so every appauthors two completely different integrations. Question: can openiap
offer alternative billing under one shared spec for both stores?
Why UI-level unification is impossible
The store policies are opposites, so one shared "choice UI" would get
an app rejected on one side:
(user-choice billing screen, external offers).
plus its own disclosure sheets (external purchase link / notice
sheet / custom link, depending on region and entitlement).
Proposal: unify at the flow level instead
Both platforms share the same abstract flow —
check → disclose → handoff → report — and differ only in how each
step renders. Sketch:
isAlternativeBillingAvailable(program)inapi.graphql. Android maps to the billing-program availabilitycheck; iOS maps to entitlement/region eligibility
(
canPresentExternalPurchaseNoticeIOS-style checks).rendering — Android presents in-app choice, iOS presents the
Apple sheet and opens the external URL.
"report this transaction" token (Play's
externalTransactionToken, Apple'sexternalPurchaseToken).Normalize to something like
AlternativeBillingReport { platform, reportToken }withper-platform server reporting underneath.
common denominator); Android in-app choice stays as a platform
extension so Android UX is never sacrificed for parity.
One hard requirement: the iOS path must be safe by default —
skipping the Apple sheet or rendering PG options inside the app
should be inexpressible in the shared API, or apps will get
rejected following our docs.
Open questions
(iOS gates features at 16+/17.4+/18.1+).
primitives beyond what exists.
If there's interest, I'm happy to turn this into a spec sketch PR
against
specs/client/src/api.graphql, and validate it against a realimplementation on both sides (Android side already exists).
All reactions