For apps on FireOS, use the official OpenIAP Amazon integration. Follow the Amazon setup guide for your framework. The official Android artifact is io.github.hyochan.openiap:openiap-google-amazon.
openiap-google-amazon-community is an educational community package example for provider authors. It demonstrates external packaging, discovery and verification through Client Protocol 1.0.0. It is not the official FireOS package and is not recommended for production purchases.
The app keeps a COMMUNITY EXAMPLE badge in every screen header. Its home screen labels the learning-only purpose, links to the official Amazon setup and opens an installation guide.
Start here: Stable compatibility → Install and configure Expo → Run the example. In the app, tap How to use this package on the home screen.
This example requires public openiap-core:4.0.0 and openiap-conformance:4.0.0 from Maven Central, Expo IAP 6.0.0, and Client Protocol 1.0.0. package.json pins the Expo SDK; openiap-revision.txt pins the corresponding Google release. Rebuild the provider when adopting a new contract.
Provider 0.0.2 uses amazon_example. Install the exact GitHub Packages version below. Its guarded publication and fresh registry-consumer checks passed; see VERIFICATION.md. Earlier GitHub Packages retain the incompatible amazon-example id; those versions are listed in Registry installation. Keep the exact SDK peer version.
This provider supports compatible OpenIAP SDKs on Android/FireOS. The package contains an Android AAR, its Maven metadata and an Expo config plugin. It supplies a store provider, not a replacement for each framework's OpenIAP SDK. Keep using that SDK's purchase API.
| Consumer | Integration required | This package's verification |
|---|---|---|
| Expo | Install the exact GitHub Packages version, replace the expo-iap config plugin entry, then rebuild Android. |
Fresh GitHub Packages install and CI build passed; Fire purchase, verification, completion and approval-after-restart passed. |
| React Native | Use a compatible SDK, add the packaged Maven repository, set openiapStore and openiapProvider, and rebuild Android. |
Fire None retention, failed LOCAL verification and recovery through completion passed with the published AAR. |
| Flutter | Use a compatible SDK, add the packaged Maven repository, set openiapStore and openiapProvider, and rebuild Android. |
Fire failed LOCAL verification and recovery through completion passed with the published AAR; retry used Ignore then LOCAL. |
| KMP | Use the resolver plugin and the provider platform variant with a compatible SDK and the packaged Maven repository. |
The corrected community build passed Fire None retention, failed LOCAL verification and recovery through completion with the published AAR. |
| Godot | Add the provider repository and set openiap/android_store and openiap/android_provider for Android export. |
A direct Fire check retained a fresh consumable under None and failed LOCAL verification, then completed the identical full receipt after recovery. Same-method retry added no verification or grant. |
| .NET MAUI | Add the provider repository and set OpenIapStore and OpenIapProvider with a compatible Android binding. |
The current picker passed Fire None retention, failed LOCAL verification and same-method recovery through completion with the published AAR. |
| iOS / macOS | This Android AAR has no Apple implementation. | Unsupported by this package. |
Other Android frameworks can share the same native provider, but this Expo plugin does not configure them. Extract the package's maven/ directory, add it to the app's Maven repositories and select amazon_example with dev.openiap.providers:openiap-provider-amazon-example:0.0.2. See the provider guide for each SDK's configuration.
Use this example to:
- Build and discover an Android provider using public OpenIAP core artifacts and the store's native SDK.
- Follow purchase, restore, verification, and completion while preserving a custom provider identity and receipt.
- Run public provider conformance tests and check the Expo consumer in debug and minified Android builds.
The Amazon binding is adapted from upstream OpenIAP. The separate repository tests external packaging and integration; it is not a second independently designed implementation or proof that the protocol is complete. See scope and provenance.
VERIFICATION.md records observed device results, historical inputs, and remaining LAT subscription limits.
The provider uses storeId: 'amazon_example' and store: 'unknown'. It does not depend on openiap-google-amazon, Google Play Billing, or Meta Horizon. The community distribution targets GitHub Packages, not npmjs.org or Maven Central.
flowchart LR
App[Expo example] --> SDK[expo-iap]
SDK --> Core[Public openiap-core]
Core --> Factory[Manifest factory discovery]
Factory --> Provider[This repository's provider]
Provider --> Amazon[Amazon Appstore SDK]
App -->|Explicit Amazon verification payload| Backend[Local dev IAPKit]
Backend --> RVS[Amazon RVS sandbox]
Install the exact public SDK and community provider in your existing Expo app. Keep its application id, product catalog, purchase screens and other plugins.
The repository is named openiap-google-amazon-community; the installation name is @hyodotdev/openiap-provider-amazon-example. GitHub Packages requires authentication even for public npm packages. The token needs read:packages; package write and delete access are unnecessary. Never ship the registry token in the app.
Add this registry configuration to your app's .npmrc (the token remains an environment variable):
@hyodotdev:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}Set NODE_AUTH_TOKEN in your shell or CI secret store, then install:
bun add --exact expo-iap@6.0.0 @hyodotdev/openiap-provider-amazon-example@0.0.2This package includes the provider AAR, Maven metadata, sources and Expo config plugin. It bundles no OpenIAP core, official provider, app credentials or consumer app. provider-artifact.json records the tested source, contract input and AAR digest. OpenIAP core comes from Maven Central. Consumers do not clone this repository or build the provider; local preparation is for provider authors.
Remove the existing expo-iap plugin entry from your base configuration. In app.config.js, keep your current IAP options in one object and select one plugin per build. Keep your other plugins, application id, catalog and purchase screens:
Move store selection out of the shared options: remove old android.store, android.provider, modules.horizon, modules.amazon.fireOS, modules.amazon.vegaOS and android.amazon.vegaOS. Unset the old EXPO_IAP_FIREOS, EXPO_IAP_HORIZON and EXPO_IAP_VEGA environment flags. Preserve unrelated options, including your Appstore public-key path.
const iapOptions = {
android: {
amazon: { appstoreKey: "./keys/AppstoreAuthenticationKey.pem" },
},
};
const community =
process.env.ORG_GRADLE_PROJECT_openiapStore === "amazon_example";
module.exports = ({ config }) => ({
...config,
plugins: [
...(config.plugins ?? []),
community
? ["@hyodotdev/openiap-provider-amazon-example", iapOptions]
: [
"expo-iap",
{
...iapOptions,
android: { ...iapOptions.android, store: "play" },
enableLocalDev: false,
},
],
],
});The package supplies its provider Maven repository; OpenIAP core comes from Maven Central. Add the same store setting to your existing eas.json build profiles:
{
"build": {
"play": {
"env": { "ORG_GRADLE_PROJECT_openiapStore": "play" }
},
"amazon-community": {
"env": { "ORG_GRADLE_PROJECT_openiapStore": "amazon_example" }
}
}
}Use the same exact Expo SDK for both profiles. Both resolve public native packages and keep enableLocalDev: false. Supply the GitHub Packages token to EAS or other CI workers as a private build secret. It is used during dependency installation, never by Gradle or the mobile app.
The Play profile uses the ordinary expo-iap plugin with explicit Play selection. The community profile uses the installed provider and public core Maven artifacts, without native source includes. It selects amazon_example, derives the Maven version from the installed package, adds the package's own maven directory, replaces legacy store flags and disables local native-source mode. Do not list both IAP plugins: Expo runs its IAP plugin only once.
Before testing a purchase, adapt your app’s verification helper using this example’s Amazon receipt adapter. Route only unknown receipts with storeId: amazon_example to your backend’s Amazon verification, preserve that provider identity, and require a matching valid result before granting access or finishing. The native package does not install this application adapter; see Verify before finishing.
For a local community build:
export ORG_GRADLE_PROJECT_openiapStore=amazon_example
bunx expo prebuild --platform android
bunx expo run:android --deviceUse play for a local Play build. Rerun prebuild and rebuild after switching the profile or updating the provider. For registry installs, the token is used by the package manager, never by Gradle or the mobile app. See GitHub's registry instructions.
For Appstore-distributed builds, download the existing application's Public Key from Amazon Developer Console and retain android.amazon.appstoreKey in the shared options above.
The existing Expo IAP plugin copies this app-specific public key into Android assets on every prebuild. It belongs to the consumer application, not the community package. A missing or mismatched key prevents Amazon SDK authentication; see Amazon's troubleshooting guide.
This repository's consumer accepts the same path through AMAZON_APPSTORE_KEY when running prebuild. Leave it unset for App Tester simulation.
For LAT, keep the existing Amazon app and tester account. Set the term SKUs, subscriptionParent and subscriptionBase in example/amazon.sdktester.json to that app's registered catalog. Subscription Flow includes each parent in its Android queries and shows only purchasable terms. Verification uses the configured RVS base SKU. Production-RVS verification also needs the existing Amazon Shared Key on the developer backend. A new app or product catalog is not required.
Install the intended LAT track through the Appstore under the account that accepted its invitation. Amazon reduces LAT purchases to zero at the transaction. If checkout requires Add Payment Preference and disables the purchase button, the account owner must resolve that account setting before lifecycle testing. Displayed catalog prices and a successful native build do not prove that a LAT transaction completed.
Use these sibling directories:
hyodotdev/
├── openiap/
└── openiap-google-amazon-community/
Check out the exact Google release revision in openiap-revision.txt in the sibling OpenIAP directory. Preparation requires that clean checkout, downloads the pinned public Expo SDK to verify its native/protocol versions, and rejects mismatched inputs before rebuilding.
provider-artifact.json records the exact pinned input revision and core dependency. Packaging requires matching successful test inputs, AAR and report hashes. Publishing a different binary without retesting is rejected.
Requirements: Java 17, Android SDK 36 with NDK 27.1.12297006, Node.js, npm, Bun, and a Fire tablet with USB debugging. Configure ANDROID_HOME or an ignored local.properties with sdk.dir.
From this repository:
node scripts/prepare-openiap.mjs
cd example
bun install --ignore-scripts
bun run typecheck
bun run test
bunx expo prebuild --platform android --no-install
cd android
./gradlew -PreactNativeArchitectures=arm64-v8a,armeabi-v7a :app:assembleDebug
./gradlew -PreactNativeArchitectures=arm64-v8a,armeabi-v7a \
-Pandroid.enableMinifyInReleaseBuilds=true :app:assembleReleasePreparation tests and lints this provider against public core and conformance (for a prerelease core, only the conformance suite is built from the clean pinned checkout), publishes the tested provider into .local/maven, and packs a content-addressed tarball. It pins the consumer to public Expo. No local core or Expo build can shadow those inputs. Registry verification replaces the provider tarball with its exact GitHub Packages version and excludes the whole local Maven repository; neither consumer includes native source projects.
package.json owns the provider version used by the AAR and Expo plugin. Change it for every new distribution; published versions are immutable. Keep the compatible contract input in openiap-revision.txt and rerun provider conformance, lint, consumer tests, and the minified build before publishing.
This educational package has its own version; it does not track OpenIAP or framework SDK versions. 0.0.2 uses the corrected provider id. Historical 0.0.1, 0.1.1 and 0.1.2 distributions remain available with amazon-example; the example distribution tag keeps this reset from changing their latest channel.
- Push the verified source and wait for Verify example to pass at that exact commit.
- Create the immutable lightweight tag
community-provider-vVERSIONat that commit. - Dispatch Publish and verify GitHub package with that
expected_shaand its successfulverification_runID. - On the first publication, open the package's GitHub settings and change visibility to Public. GitHub defaults new npm packages to Private; access inherited from a public repository does not change that visibility.
- If the visibility gate failed before this change, rerun only the failed consumer job. Check the
registry-proofartifact and job results before using the version.
The publisher accepts only a successful main push run at the exact tagged source. It publishes the tested tarball through Actions and checks the registry SHA-512. A separate fresh runner requires public package visibility, installs from GitHub Packages, checks all consumer tests and types, builds with R8, and compares the actual resolved AAR against the tested package. The proof records visibility, versions, source, binary digest, and factory retention; the consumer uses the installed package’s Maven directory without provider source or separately built local artifacts. Retries accept an existing version only when its integrity matches exactly.
Consumers pin an exact version, update that pin deliberately, and rebuild the native app. Roll back by restoring the previous dependency and lockfile and rebuilding. Package credentials belong in developer or CI configuration; never commit them or put them in Expo public environment values.
Install and configure Amazon App Tester. The credential-free catalog fixture contains the five products used by the official comparison screens:
| SKU | Amazon type | Period |
|---|---|---|
dev.hyo.martie.10bulbs |
CONSUMABLE |
— |
dev.hyo.martie.30bulbs |
CONSUMABLE |
— |
dev.hyo.martie.certified |
ENTITLED |
— |
dev.hyo.martie.premium |
SUBSCRIPTION |
Monthly |
dev.hyo.martie.premium_year |
SUBSCRIPTION |
Yearly |
The subscription terms share parent dev.hyo.martie.premium.parent and base dev.hyo.martie.premium.base. The fixture matches the catalog used for the recorded comparison. If /sdcard/amazon.sdktester.json already exists, back it up before installing this fixture and restore it after testing. This command replaces that catalog:
adb -s DEVICE push example/amazon.sdktester.json /sdcard/amazon.sdktester.jsonOpen App Tester → Appstore SDK APIs → IAP Items in JSON File and confirm all five entries. App Tester works with debug apps and simulates purchases. Live App Testing is a separate validation with an Appstore-distributed candidate.
adb -s DEVICE shell setprop debug.amazon.sandboxmode debug
adb -s DEVICE reverse --no-rebind tcp:8081 tcp:8082
adb -s DEVICE install -r example/android/app/build/outputs/apk/debug/app-debug.apk
adb -s DEVICE shell am start -n dev.openiap.provider.fireos.example/.MainActivityApp Tester mode does not survive a reboot. After restarting or reconnecting the Fire, rerun adb -s DEVICE shell setprop debug.amazon.sandboxmode debug before launching the debuggable app. See the Amazon sample setup.
In another terminal, run cd example && bun start. Metro uses host port 8082; the Android debug app reaches it through device port 8081. Preserve existing reverse rules and remove only mappings you create when finished.
The consumer copies OpenIAP’s official Expo Router example screens and shared UI from the upstream revision recorded in its provenance manifest. It changes public package imports, provider selection, branding and the community verification adapter. example/upstream-example.json records the source and adaptations.
| Screen | Purpose in this reference |
|---|---|
| All Products | Compare the same catalog view against the external Amazon binding. |
| In-App Purchase Flow | Use the official purchase, verification, completion and retry flow. |
| Subscription Flow | Inspect the official subscription UI and supported provider reads; a screen is not proof of the full subscription lifecycle. |
| Available Purchases | Compare owned purchases and restore results. |
| Offer Code / Alternative Billing | Show unsupported capability for this provider without opening Google Play. |
| Provider Acceptance | Inspect custom identity, unchanged restored receipt, Sandbox verification and consumable completion. |
Start with Provider Acceptance: Load products → Purchase → Restore / owned → Verify & finish. Connection and catalog are separate checks; restore before completion proves receipt continuity. Pending approval and failed verification grant no entitlement and remain unfinished.
The purchase and subscription flows default to server verification. Missing configuration or a rejected response leaves the purchase unfinished. None (Skip) also retains the receipt without granting access or finishing it; choose verification to retry. The strict acceptance screen requires a local development URL and a publishable key.
Tap 01 Expo app, 02 Public core or 03 Amazon SDK in Provider Acceptance. Compact displays open a guide panel; displays at least 768 logical pixels wide show the selected explanation beside the menu. Both layouts read the same tutorial data; layout and interaction live in ProviderTutorial.tsx.
| Compact guide | Wide guide |
|---|---|
![]() |
![]() |
These are actual Fire tablet captures. The wide capture uses a temporary display-density override; the original device settings were restored. It is layout evidence, not a separate device purchase run.
The example deliberately requires a local development IAPKit server at http://127.0.0.1:3100. Configure Amazon RVS sandbox support on its dev project, then supply its publishable openiap-kit_pk_… key through the environment:
export EXPO_PUBLIC_IAPKIT_BASE_URL=http://127.0.0.1:3100
export EXPO_PUBLIC_IAPKIT_API_KEY=YOUR_DEV_PUBLISHABLE_KEY
adb -s DEVICE reverse --no-rebind tcp:3100 tcp:3100
cd example
bunx expo run:android --deviceRebuild the Android app after changing these values; restarting Metro alone can leave the installed configuration unchanged. Expo public environment values are bundled into the app. Never use a secret/admin key. This repository includes no server credentials or app signing keys.
Verify & finish sends an explicit Amazon payload to verifyPurchaseWithProvider, checks validity, product, sandbox environment, completion state, and amazon_example identity, then consumes the purchase through finishTransaction. In an application, grant the entitlement after verification and before completion.
Subscription checkout uses a term SKU. Restore may return the shared base SKU with that term in currentPlanId; the example accepts only exact catalog matches and keeps the raw purchase for verification and completion. RVS verification uses the catalog base SKU, so update the adapter's mapping when changing the catalog. SDK ownership and autoRenewingAndroid do not prove renewal or access; verify through your backend before granting access.
A LAT candidate must use the package and catalog registered for that Amazon app, an Appstore installation, and production RVS. Set EXPO_PUBLIC_AMAZON_RVS_SANDBOX=false when building it; the default is true for App Tester. Keep IAPKit on a development deployment with the matching application identity and Amazon verification configuration. The Provider Acceptance screen deliberately remains a Sandbox check; use Subscription Flow for LAT verification.
Verify a fresh subscription, an accelerated renewal, cancellation while access remains valid, and expiry with access revoked. Record the store and RVS response for each state. An App Tester cancellation that removes local ownership while RVS Sandbox still returns entitled does not pass this lifecycle gate. See Amazon's LAT for IAP and accelerated subscriptions.
sequenceDiagram
participant App
participant Provider as Amazon example provider
participant Store as Amazon SDK / App Tester
participant Backend as Dev IAPKit / Amazon RVS sandbox
App->>Provider: requestPurchase(request.google)
Provider->>Store: purchase(sku)
Store-->>Provider: receipt
Provider-->>App: purchaseUpdated(unknown, amazon_example)
App->>Provider: verifyPurchaseWithProvider(iapkit.amazon)
Provider->>Backend: Amazon receipt + user identity
Backend-->>Provider: Valid sandbox verification
Provider-->>App: Verified result preserving amazon_example
App->>Provider: finishTransaction(purchase)
Provider->>Store: notifyFulfillment(FULFILLED)
The device provider contract does not add a backend verification adapter. A backend must explicitly support the underlying store. request.google is the Android platform request binding even for this Amazon provider; the store enum alone cannot route a community receipt.
Preparation runs :provider:testDebugUnitTest and :provider:lintRelease against the pinned inputs. Use that entry point to repeat checks without introducing a second version configuration.
The public ProviderConformanceSuite runs the actual provider and its production mappers. A Robolectric shadow replaces only Amazon SDK transport. It exercises required lifecycle, identity, errors, receipt continuity, completion, and declared pending-purchase behavior. This is automated simulation, not a sandbox purchase.
The provider also rejects Apple-only purchase and subscription inputs with exactly one canonical error event and no purchase. Community providers must deliver that event before returning or throwing a failure so event-based SDK callers can complete.
The generated report is provider/build/reports/openiap/amazon_example.json. VERIFICATION.md records observed results and remaining limits. Optional capabilities not declared by this provider are reported as not applicable. Passing this profile does not certify every Amazon subscription or server lifecycle.
The installed Expo plugin selects store: "amazon_example" and provider: "dev.openiap.providers:openiap-provider-amazon-example:VERSION", using the installed package version. The Maven installation name also remains unchanged after the repository rename.
The same Android AAR can be connected to compatible React Native, Flutter, Godot, KMP and MAUI SDKs through their store-provider configuration. Each app still needs its framework's OpenIAP SDK, the package's maven directory in its Maven repositories, and the store/provider pair above. The bundled config plugin automates Expo only; installing this JavaScript package does not automatically configure another framework.
Follow Amazon's SDK integration requirements, including the existing app's public authentication key. The library manifest supplies factory discovery, early listener registration and the protected response receiver. Preserve its consumer R8 rules. This Android AAR supplies no iOS or Vega implementation.
The public 0.0.2 GitHub Packages installation, consumer tests and minified-build verification passed for Expo. Applications also need an explicit server verification adapter for amazon_example; the native package does not install it. This example’s helper preserves provider identity and checks the Amazon result before finishing. Fire consumer checks are recorded per framework in VERIFICATION.md; the Expo build job alone does not certify the other frameworks. For ordinary FireOS apps, use the official integration linked at the top.
The consumer includes OpenIAP’s exact-receipt recovery correction, with public SDK imports and Amazon-specific guidance preserved. Verification precedes completion; an acknowledged Android non-consumable is not acknowledged again, while consumables still require consumption. The consumer screens, shared UI and inherited tests were copied from the official Expo example; the added acceptance screen checks the external-provider boundary. The Amazon binding and its regression tests were extracted and adapted from MIT-licensed OpenIAP at f8926acba6145862382e3bbbe63f0a6694a92645, the input revision recorded when they were extracted, and later aligned with the stable revision in openiap-revision.txt. They compile against public contracts with a separate namespace, provider identity, Maven artifact, and consumer app.
The maintained official Amazon integration is openiap-google-amazon and is recommended for FireOS apps. This repository is an educational community example for provider authors. See LICENSE.



