feat(google): support Play Billing 9.1 Billing Choice#212
Conversation
|
Important Review skippedToo many files! This PR contains 198 files, which is 48 over the limit of 150. To get a review, narrow the scope: Upgrade to a paid plan to raise the limit. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (7)
📒 Files selected for processing (198)
You can disable this status message by setting the Use the checkbox below for a quick retry:
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR adds Billing Choice, billing-program dialog, and in-app message support across shared schemas, native modules, SDK wrappers, tests, and docs. It also updates reporting-details APIs to accept ChangesBilling Choice and in-app message feature implementation
Documentation and reference updates
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request upgrades the Google Play Billing Library from 8.3.0 to 9.1.0 across the repository, introducing comprehensive support for Billing Choice on Android. It adds new APIs (getBillingChoiceInfoAndroid, showBillingProgramInformationDialogAndroid, and showInAppMessagesAndroid) and updates generated types and documentation across all supported frameworks (React Native, Expo, Flutter, Godot, KMP, and MAUI). The code review identified critical issues, including a type mismatch and serialization bug in the GDScript implementation of InAppMessageParamsAndroid, as well as potential coroutine hangs in both the native Play and KMP Android implementations of showBillingProgramInformationDialog if the synchronous call fails.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
1 similar comment
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
There was a problem hiding this comment.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
libraries/kmp-iap/example/composeApp/src/commonMain/kotlin/dev/hyo/martie/screens/AlternativeBillingScreen.kt (1)
363-372: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy liftRoute
BillingChoicethrough a dedicated Billing Choice flow.Line 369 sends Billing Choice through the generic billing-program flow, which only checks availability, launches an external link, and creates reporting details. The Billing Choice instructions added in this file describe fetching choice metadata, showing the required information dialog, using a billing type, and showing Play in-app messages, so the example’s primary button won’t validate the new APIs.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libraries/kmp-iap/example/composeApp/src/commonMain/kotlin/dev/hyo/martie/screens/AlternativeBillingScreen.kt` around lines 363 - 372, Route BillingProgramAndroid.BillingChoice through its own Billing Choice purchase flow instead of handleAndroidBillingPrograms in AlternativeBillingScreen.handlePurchase. Update the Android branch to call a dedicated Billing Choice handler that performs the metadata fetch, required information dialog, billing type selection, and Play in-app message steps described in this screen, while leaving BillingProgramAndroid.ExternalOffer, BillingProgramAndroid.ExternalPayments, and BillingProgramAndroid.ExternalContentLink on the generic flow.
♻️ Duplicate comments (1)
packages/google/openiap/src/horizon/java/dev/hyo/openiap/OpenIapModule.kt (1)
1207-1233: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winSame responseCode/consistency issue as the Amazon flavor.
showBillingProgramInformationDialoghere also returnsresponseCode = 2(SERVICE_UNAVAILABLE) instead ofFEATURE_NOT_SUPPORTED(-2) for an unsupported-platform condition, andshowInAppMessagesreturns a success-lookingNoActionNeededresult rather than signaling the feature is unsupported — while the siblinggetBillingChoiceInfothrowsFeatureNotSupported. Same root cause as flagged inpackages/google/openiap/src/amazon/java/dev/hyo/openiap/OpenIapModule.kt.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/google/openiap/src/horizon/java/dev/hyo/openiap/OpenIapModule.kt` around lines 1207 - 1233, Align the unsupported-platform handling in OpenIapModule’s showBillingProgramInformationDialog and showInAppMessages with getBillingChoiceInfo and the Amazon variant: these Meta Horizon-only stubs should signal FEATURE_NOT_SUPPORTED instead of returning a success-like BillingResultAndroid/InAppMessageResultAndroid. Update the response in showBillingProgramInformationDialog to the unsupported-feature code and make showInAppMessages use the same unsupported-path pattern (throwing OpenIapError.FeatureNotSupported or an equivalent unsupported result), so all three methods report the same platform limitation consistently.
🧹 Nitpick comments (6)
packages/gql/src/api-android.graphql (1)
69-81: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDocument the new
developerBillingTypeparameter and its BILLING_CHOICE default behavior.The doc block for
createBillingProgramReportingDetailsAndroid(lines 69-75) doesn't mention the newdeveloperBillingTypeargument at all. Per the native implementation (OpenIapModule.kt), whenprogram == BILLING_CHOICEanddeveloperBillingTypeis omitted, it silently defaults toIN_APP— non-obvious behavior that should be surfaced in the public API contract for downstream consumers/SDK authors.📝 Suggested doc addition
""" Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+). Replaces the deprecated createExternalOfferReportingDetailsAsync API. Returns external transaction token needed for reporting external transactions. + developerBillingType is required context for BILLING_CHOICE (Play Billing Library 9.1.0+); if omitted for BILLING_CHOICE, defaults to IN_APP. Throws OpenIapError.NotPrepared if billing client not ready. See: https://openiap.dev/docs/apis/android/create-billing-program-reporting-details-android """🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/gql/src/api-android.graphql` around lines 69 - 81, Update the doc block for createBillingProgramReportingDetailsAndroid to document the developerBillingType argument and its default behavior. Mention that this parameter is optional, and when program is BILLING_CHOICE and developerBillingType is omitted, the native OpenIapModule.kt behavior defaults it to IN_APP. Keep the public API contract clear for consumers by reflecting this behavior in the schema comments near createBillingProgramReportingDetailsAndroid and BillingProgramAndroid.packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt (1)
4601-4612: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
GetBillingChoiceInfoParamsAndroid.fromJsonis declared nullable but never returns null.Unlike the neighboring
BillingProgramInformationDialogParamsAndroid.fromJson(which legitimately returnsnullwhenexternalTransactionTokenis missing), this function always constructs a value via defaults. The?on the return type is misleading and forces unnecessary null-handling on every caller.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt` around lines 4601 - 4612, The companion object method GetBillingChoiceInfoParamsAndroid.fromJson is marked nullable even though it always returns a constructed GetBillingChoiceInfoParamsAndroid using defaults. Update the return type to non-nullable and keep the existing parsing/defaulting logic intact, mirroring how the method actually behaves; use the fromJson symbol in GetBillingChoiceInfoParamsAndroid to locate and adjust the signature.libraries/expo-iap/src/modules/android.ts (1)
396-416: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
createBillingProgramReportingDetailsAndroidlosesMutationFieldtype safety.Every other Android wrapper in this file (
getBillingChoiceInfoAndroid,showBillingProgramInformationDialogAndroid,showInAppMessagesAndroid,isBillingProgramAvailableAndroid,launchExternalLinkAndroid) is typed asQueryField<'...'>/MutationField<'...'>, tying its signature to the canonicalMutationArgsMap/Mutationcontract intypes.ts. This function instead uses an untyped union parameter (BillingProgramAndroid | { program; developerBillingType? }) plus a second positional parameter, so it no longer type-checks againstMutationCreateBillingProgramReportingDetailsAndroidArgs. If the schema contract changes again, this function won't get a compile-time signal like its siblings do.If backward compatibility with the old single-string call style is required, consider using proper TypeScript function overloads that still resolve to a
MutationField-compatible implementation, so the canonical object-based contract is enforced.As per coding guidelines,
libraries/expo-iap/**/*.{ts,tsx}: "Use type annotations and maintain type safety in TypeScript projects."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libraries/expo-iap/src/modules/android.ts` around lines 396 - 416, `createBillingProgramReportingDetailsAndroid` should be aligned with the same `MutationField` type-safety used by the other Android wrappers in this file. Update its signature to match the canonical `MutationCreateBillingProgramReportingDetailsAndroidArgs` contract from `types.ts`, and if you must preserve the old string-style call, use TypeScript overloads so the implementation still conforms to the mutation field shape. Keep the implementation in `createBillingProgramReportingDetailsAndroid` and `ExpoIapModule.createBillingProgramReportingDetailsAndroid` compatible with the generated args map, rather than relying on an untyped union plus a second positional parameter.Source: Coding guidelines
libraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt (1)
1819-1945: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueSwallowed exceptions lose original stack trace (detekt hint).
The new catch blocks in
getBillingChoiceInfoAndroid,showBillingProgramInformationDialogAndroid, andshowInAppMessagesAndroidlogerrand reuseerr.message, but don't passerras thecauseof the thrownOpenIapException, so the original stack trace is lost for crash reporting. This matches the pre-existing pattern elsewhere in the class (e.g.checkAlternativeBillingAvailabilityAndroid), so it's a style consistency item rather than a regression introduced by this PR.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt` around lines 1819 - 1945, The catch blocks in getBillingChoiceInfoAndroid, showBillingProgramInformationDialogAndroid, and showInAppMessagesAndroid are swallowing the original exception cause, so the stack trace is lost. Update the thrown OpenIapException in each of these methods to include the caught err as the cause, matching the existing pattern used elsewhere in HybridRnIap. Keep the current logging and parseOpenIapError/toErrorJson flow, but preserve the original throwable when rethrowing.Source: Linters/SAST tools
libraries/react-native-iap/src/__tests__/index.test.ts (1)
2254-2305: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd non-Android rejection tests for parity with
getBillingChoiceInfoAndroid.
createBillingProgramReportingDetailsAndroid,showBillingProgramInformationDialogAndroid, andshowInAppMessagesAndroidonly get Android happy-path tests here, whilegetBillingChoiceInfoAndroidalso has a "should throw on non-Android" test. For consistency and full coverage of the new Android-only surface, consider adding the same negative-path assertion to these three.As per path instructions,
libraries/react-native-iap/**/*.test.{ts,tsx,js,jsx}should "Write tests for all public functions and critical paths."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libraries/react-native-iap/src/__tests__/index.test.ts` around lines 2254 - 2305, Add non-Android rejection coverage for the Android-only APIs to match the existing `getBillingChoiceInfoAndroid` pattern. In `index.test.ts`, extend the test blocks for `IAP.createBillingProgramReportingDetailsAndroid`, `IAP.showBillingProgramInformationDialogAndroid`, and `IAP.showInAppMessagesAndroid` with assertions that they throw or reject when `Platform.OS` is not android, using the same style already used for `getBillingChoiceInfoAndroid`. Keep the focus on the public wrapper methods and verify no native mock calls are made on non-Android paths.Source: Path instructions
libraries/maui-iap/android/openiap/src/main/java/dev/hyo/openiap/maui/OpenIapMauiModule.kt (1)
230-244: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueMinor duplication between the two overloads.
createBillingProgramReportingDetailsAndroidandcreateBillingProgramReportingDetailsAndroidWithTypeshare the sameparseProgram+module.createBillingProgramReportingDetailscall shape. Consider having the old method delegate to the new one with a null type to avoid drift if the underlying call signature changes again.♻️ Suggested consolidation
fun createBillingProgramReportingDetailsAndroid(programJson: String, callback: ResultCallback) = run(callback) { - val program = parseProgram(programJson) - gson.toJson(module.createBillingProgramReportingDetails(program).toJson()) + val program = parseProgram(programJson) + gson.toJson(module.createBillingProgramReportingDetails(program, null).toJson()) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libraries/maui-iap/android/openiap/src/main/java/dev/hyo/openiap/maui/OpenIapMauiModule.kt` around lines 230 - 244, `createBillingProgramReportingDetailsAndroid` and `createBillingProgramReportingDetailsAndroidWithType` duplicate the same `parseProgram` plus `module.createBillingProgramReportingDetails` flow, so the overloads can drift. Update `OpenIapMauiModule.createBillingProgramReportingDetailsAndroid` to delegate to `createBillingProgramReportingDetailsAndroidWithType` with a null developerBillingTypeJson, keeping the parsing and JSON conversion in one place.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@libraries/expo-iap/android/src/main/java/expo/modules/iap/ExpoIapModule.kt`:
- Around line 678-706: The categories handling in showInAppMessagesAndroid
currently uses mapNotNull, which silently drops invalid category strings instead
of surfacing a bad input or preserving native default behavior. Update the
categories parsing in ExpoIapModule.kt to either reject unknown values with a
promise.reject/exception or return null when no supplied categories map
successfully, and keep valid categories mapped through mapInAppMessageCategory.
Make the behavior explicit in the AsyncFunction("showInAppMessagesAndroid") flow
so callers don’t get an empty list when they passed only unsupported values.
In `@libraries/godot-iap/addons/godot-iap/types.gd`:
- Around line 4069-4085: `InAppMessageParamsAndroid` is serializing and
deserializing `categories` with raw enum values instead of the JSON string
format expected by Android. Update the generator that produces `types.gd` so
`InAppMessageParamsAndroid.to_dict()` converts each
`InAppMessageCategoryAndroid` entry to its string/json representation, and
`from_dict()` maps each incoming string back through
`InAppMessageCategoryAndroid.fromJson(...)` when populating `categories`.
In `@libraries/godot-iap/android/src/main/java/dev/hyo/godotiap/GodotIap.kt`:
- Around line 861-868: The Billing Choice dialog flow in
GodotIap.showBillingProgramInformationDialog currently falls back to an empty
externalTransactionToken, which hides a required input from callers. Update the
JSON parsing logic to validate externalTransactionToken before constructing
BillingProgramInformationDialogParamsAndroid, and if it is missing or blank,
return a local error/result immediately instead of calling
store.showBillingProgramInformationDialog. Keep the check alongside the existing
billingProgram parsing so the failure is handled in the same GodotIap code path.
In
`@libraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.kt`:
- Around line 1847-2059: The new reflective entry points in
getBillingChoiceInfoAndroid, showBillingProgramInformationDialogAndroid, and
showInAppMessagesAndroid only check billingClient for null, so a disconnected
stale client can still be used. Add a readiness guard using client.isReady
alongside the existing billingClient check, and fail fast with the same
NotPrepared PurchaseException path before any reflective invocation if the
client is not ready.
- Around line 2063-2072: The reflection-based setup in the In-App message
request builder is constructing InAppMessageParams.Builder with a no-arg
constructor, which will fail at runtime. Update the logic in the
InAppPurchaseAndroid InAppMessageParams setup to obtain the builder via
InAppMessageParams.newBuilder() instead of
Class.forName(...Builder).getConstructor().newInstance(), then keep the existing
category population and build flow unchanged.
In `@libraries/maui-iap/src/OpenIap.Maui/Types.cs`:
- Around line 4081-4092: The MAUI Billing Choice parameter types are stricter
than the underlying schema and other bindings, so callers cannot omit fields
that already have defaults. Update the Android parameter models, especially
BillingProgramInformationDialogParamsAndroid and
GetBillingChoiceInfoParamsAndroid, to either make billingProgram and
playBillingChoiceImageLayout optional or apply their schema defaults before
serialization so the public C# API matches the existing behavior.
In `@packages/docs/src/pages/docs/types/billing-programs.tsx`:
- Around line 412-468: The Android billing docs currently claim billingProgram
defaults to BILLING_CHOICE, but both
BillingProgramInformationDialogParamsAndroid.billingProgram and
GetBillingChoiceInfoParamsAndroid.billingProgram are required and fromJson()
uses BillingProgramAndroid.Unspecified when omitted. Update the summaries in
billing-programs.tsx and the related Android API docs to reflect the required
parameter and the Unspecified fallback, not a BILLING_CHOICE default.
In `@packages/google/openiap/src/amazon/java/dev/hyo/openiap/OpenIapModule.kt`:
- Around line 668-687: The Billing Choice stubs in OpenIapModule should all
return the same unsupported signal so callers can handle Amazon-only behavior
consistently. Update showBillingProgramInformationDialog and showInAppMessages
to use the same permanent not-supported/error path as getBillingChoiceInfo,
instead of returning SERVICE_UNAVAILABLE or NoActionNeeded. Keep the
platform-specific behavior explicit in these methods and align the
returned/raised result with the existing OpenIapError.FeatureNotSupported
pattern.
In `@packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt`:
- Around line 4621-4643: The InAppMessageParamsAndroid.fromJson deserializer
currently relies on InAppMessageCategoryAndroid.fromJson, which can throw on
unknown values and break forward compatibility. Update the categories parsing in
InAppMessageParamsAndroid.Companion.fromJson to safely handle unrecognized
strings by mapping them to UnknownInAppMessageCategoryId instead of calling the
throwing path. Keep the toJson behavior unchanged and make the fallback logic
explicit where the categories list is built.
In `@packages/google/openiap/src/play/java/dev/hyo/openiap/OpenIapModule.kt`:
- Around line 1018-1042: The showInAppMessages flow in OpenIapModule should not
turn a non-OK BillingResult into InAppMessageResultAndroid(NoActionNeeded).
Update the submitResult handling so any immediate failure from the reflective
showInAppMessages invocation is surfaced as an exception or failure result
instead of resuming success; use the existing OpenIapLog and
resumer.resumeWithException/OpenIapError paths alongside showInAppMessages,
BillingResult, and InAppMessageResultAndroid to keep the error visible to
callers.
---
Outside diff comments:
In
`@libraries/kmp-iap/example/composeApp/src/commonMain/kotlin/dev/hyo/martie/screens/AlternativeBillingScreen.kt`:
- Around line 363-372: Route BillingProgramAndroid.BillingChoice through its own
Billing Choice purchase flow instead of handleAndroidBillingPrograms in
AlternativeBillingScreen.handlePurchase. Update the Android branch to call a
dedicated Billing Choice handler that performs the metadata fetch, required
information dialog, billing type selection, and Play in-app message steps
described in this screen, while leaving BillingProgramAndroid.ExternalOffer,
BillingProgramAndroid.ExternalPayments, and
BillingProgramAndroid.ExternalContentLink on the generic flow.
---
Duplicate comments:
In `@packages/google/openiap/src/horizon/java/dev/hyo/openiap/OpenIapModule.kt`:
- Around line 1207-1233: Align the unsupported-platform handling in
OpenIapModule’s showBillingProgramInformationDialog and showInAppMessages with
getBillingChoiceInfo and the Amazon variant: these Meta Horizon-only stubs
should signal FEATURE_NOT_SUPPORTED instead of returning a success-like
BillingResultAndroid/InAppMessageResultAndroid. Update the response in
showBillingProgramInformationDialog to the unsupported-feature code and make
showInAppMessages use the same unsupported-path pattern (throwing
OpenIapError.FeatureNotSupported or an equivalent unsupported result), so all
three methods report the same platform limitation consistently.
---
Nitpick comments:
In `@libraries/expo-iap/src/modules/android.ts`:
- Around line 396-416: `createBillingProgramReportingDetailsAndroid` should be
aligned with the same `MutationField` type-safety used by the other Android
wrappers in this file. Update its signature to match the canonical
`MutationCreateBillingProgramReportingDetailsAndroidArgs` contract from
`types.ts`, and if you must preserve the old string-style call, use TypeScript
overloads so the implementation still conforms to the mutation field shape. Keep
the implementation in `createBillingProgramReportingDetailsAndroid` and
`ExpoIapModule.createBillingProgramReportingDetailsAndroid` compatible with the
generated args map, rather than relying on an untyped union plus a second
positional parameter.
In
`@libraries/maui-iap/android/openiap/src/main/java/dev/hyo/openiap/maui/OpenIapMauiModule.kt`:
- Around line 230-244: `createBillingProgramReportingDetailsAndroid` and
`createBillingProgramReportingDetailsAndroidWithType` duplicate the same
`parseProgram` plus `module.createBillingProgramReportingDetails` flow, so the
overloads can drift. Update
`OpenIapMauiModule.createBillingProgramReportingDetailsAndroid` to delegate to
`createBillingProgramReportingDetailsAndroidWithType` with a null
developerBillingTypeJson, keeping the parsing and JSON conversion in one place.
In
`@libraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt`:
- Around line 1819-1945: The catch blocks in getBillingChoiceInfoAndroid,
showBillingProgramInformationDialogAndroid, and showInAppMessagesAndroid are
swallowing the original exception cause, so the stack trace is lost. Update the
thrown OpenIapException in each of these methods to include the caught err as
the cause, matching the existing pattern used elsewhere in HybridRnIap. Keep the
current logging and parseOpenIapError/toErrorJson flow, but preserve the
original throwable when rethrowing.
In `@libraries/react-native-iap/src/__tests__/index.test.ts`:
- Around line 2254-2305: Add non-Android rejection coverage for the Android-only
APIs to match the existing `getBillingChoiceInfoAndroid` pattern. In
`index.test.ts`, extend the test blocks for
`IAP.createBillingProgramReportingDetailsAndroid`,
`IAP.showBillingProgramInformationDialogAndroid`, and
`IAP.showInAppMessagesAndroid` with assertions that they throw or reject when
`Platform.OS` is not android, using the same style already used for
`getBillingChoiceInfoAndroid`. Keep the focus on the public wrapper methods and
verify no native mock calls are made on non-Android paths.
In `@packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt`:
- Around line 4601-4612: The companion object method
GetBillingChoiceInfoParamsAndroid.fromJson is marked nullable even though it
always returns a constructed GetBillingChoiceInfoParamsAndroid using defaults.
Update the return type to non-nullable and keep the existing parsing/defaulting
logic intact, mirroring how the method actually behaves; use the fromJson symbol
in GetBillingChoiceInfoParamsAndroid to locate and adjust the signature.
In `@packages/gql/src/api-android.graphql`:
- Around line 69-81: Update the doc block for
createBillingProgramReportingDetailsAndroid to document the developerBillingType
argument and its default behavior. Mention that this parameter is optional, and
when program is BILLING_CHOICE and developerBillingType is omitted, the native
OpenIapModule.kt behavior defaults it to IN_APP. Keep the public API contract
clear for consumers by reflecting this behavior in the schema comments near
createBillingProgramReportingDetailsAndroid and BillingProgramAndroid.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f12a2a3f-5d9d-4a90-9b62-9929ac6b8272
⛔ Files ignored due to path filters (7)
packages/docs/src/generated/version-metadata.jsonis excluded by!**/generated/**packages/gql/src/generated/Types.csis excluded by!**/generated/**packages/gql/src/generated/Types.ktis excluded by!**/generated/**packages/gql/src/generated/Types.swiftis excluded by!**/generated/**packages/gql/src/generated/types.dartis excluded by!**/generated/**packages/gql/src/generated/types.gdis excluded by!**/generated/**packages/gql/src/generated/types.tsis excluded by!**/generated/**
📒 Files selected for processing (75)
knowledge/_claude-context/context.mdknowledge/external/google-billing-api.mdknowledge/external/horizon-api.mdknowledge/external/storekit2-api.mdlibraries/expo-iap/android/src/main/java/expo/modules/iap/ExpoIapModule.ktlibraries/expo-iap/src/__mocks__/expo-modules-core.jslibraries/expo-iap/src/index.kepler.tslibraries/expo-iap/src/modules/__tests__/android.test.tslibraries/expo-iap/src/modules/android.tslibraries/expo-iap/src/types.tslibraries/flutter_inapp_purchase/android/src/main/kotlin/io/github/hyochan/flutter_inapp_purchase/AndroidInappPurchasePlugin.ktlibraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dartlibraries/flutter_inapp_purchase/lib/types.dartlibraries/flutter_inapp_purchase/test/flutter_inapp_purchase_channel_test.dartlibraries/godot-iap/addons/godot-iap/godot_iap.gdlibraries/godot-iap/addons/godot-iap/types.gdlibraries/godot-iap/android/build.gradle.ktslibraries/godot-iap/android/settings.gradle.ktslibraries/godot-iap/android/src/main/java/dev/hyo/godotiap/GodotIap.ktlibraries/kmp-iap/example/composeApp/src/commonMain/kotlin/dev/hyo/martie/screens/AlternativeBillingScreen.ktlibraries/kmp-iap/library/build.gradle.ktslibraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/AmazonInAppPurchaseAndroid.ktlibraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/Helper.ktlibraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.ktlibraries/kmp-iap/library/src/commonMain/kotlin/io/github/hyochan/kmpiap/openiap/Types.ktlibraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseIOS.ktlibraries/maui-iap/android/openiap/src/main/java/dev/hyo/openiap/maui/OpenIapMauiModule.ktlibraries/maui-iap/src/Directory.Build.propslibraries/maui-iap/src/OpenIap.Maui/Platforms/Android/OpenIapAndroid.Resolvers.cslibraries/maui-iap/src/OpenIap.Maui/Platforms/iOS/OpenIapIOS.cslibraries/maui-iap/src/OpenIap.Maui/Types.cslibraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.ktlibraries/react-native-iap/example/android/build.gradlelibraries/react-native-iap/ios/HybridRnIap.swiftlibraries/react-native-iap/src/__tests__/index.test.tslibraries/react-native-iap/src/index.kepler.tslibraries/react-native-iap/src/index.tslibraries/react-native-iap/src/specs/RnIap.nitro.tslibraries/react-native-iap/src/types.tslibraries/react-native-iap/src/vega-adapter.tspackages/apple/CONVENTION.mdpackages/apple/Sources/Models/Types.swiftpackages/docs/public/llms-full.txtpackages/docs/public/llms.txtpackages/docs/src/components/CodeBlock.tsxpackages/docs/src/lib/searchData.tspackages/docs/src/pages/docs/android-setup.tsxpackages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsxpackages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsxpackages/docs/src/pages/docs/apis/android/get-billing-choice-info-android.tsxpackages/docs/src/pages/docs/apis/android/is-billing-program-available-android.tsxpackages/docs/src/pages/docs/apis/android/show-billing-program-information-dialog-android.tsxpackages/docs/src/pages/docs/apis/android/show-in-app-messages-android.tsxpackages/docs/src/pages/docs/apis/index.tsxpackages/docs/src/pages/docs/apis/init-connection.tsxpackages/docs/src/pages/docs/index.tsxpackages/docs/src/pages/docs/types/alternative-billing-types.tsxpackages/docs/src/pages/docs/types/billing-programs.tsxpackages/docs/src/pages/docs/updates/releases.tsxpackages/google/README.mdpackages/google/gradle.propertiespackages/google/openiap/build.gradle.ktspackages/google/openiap/src/amazon/java/dev/hyo/openiap/OpenIapModule.ktpackages/google/openiap/src/horizon/java/dev/hyo/openiap/OpenIapModule.ktpackages/google/openiap/src/main/java/dev/hyo/openiap/OpenIapProtocol.ktpackages/google/openiap/src/main/java/dev/hyo/openiap/Types.ktpackages/google/openiap/src/main/java/dev/hyo/openiap/store/OpenIapStore.ktpackages/google/openiap/src/play/java/dev/hyo/openiap/OpenIapModule.ktpackages/google/openiap/src/test/java/dev/hyo/openiap/BillingChoiceAndroidTypesTest.ktpackages/google/openiap/src/test/java/dev/hyo/openiap/BillingLibraryClassPathTest.ktpackages/google/openiap/src/test/java/dev/hyo/openiap/BillingProgramAndroidTest.ktpackages/google/openiap/src/testPlay/java/dev/hyo/openiap/QueryPurchasesRaceTest.ktpackages/gql/src/api-android.graphqlpackages/gql/src/type-android.graphqlscripts/audit-non-godot-parity.mjs
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@libraries/flutter_inapp_purchase/scripts/verify-android-consumer-build.sh`:
- Around line 42-68: Add validation in verify-android-consumer-build.sh around
read_google_plugin_version and the perl -0pi edits: after reading the
com.android.library, org.jetbrains.kotlin.plugin.compose, and
com.vanniktech.maven.publish versions, fail fast if any value is empty instead
of writing a blank version into settings.gradle(.kts). Also check each perl
substitution against the settings_file update in both branches so the script
errors out if the plugins block pattern is not found, with a clear message
identifying the affected settings file.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1b583d5c-a0b2-442b-9198-6ef9c738f59c
⛔ Files ignored due to path filters (1)
packages/gql/src/generated/types.gdis excluded by!**/generated/**
📒 Files selected for processing (5)
libraries/flutter_inapp_purchase/scripts/verify-android-consumer-build.shlibraries/godot-iap/addons/godot-iap/types.gdlibraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.ktpackages/google/openiap/src/play/java/dev/hyo/openiap/OpenIapModule.ktpackages/gql/codegen/plugins/gdscript.ts
✅ Files skipped from review due to trivial changes (1)
- libraries/godot-iap/addons/godot-iap/types.gd
🚧 Files skipped from review as they are similar to previous changes (2)
- libraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.kt
- packages/google/openiap/src/play/java/dev/hyo/openiap/OpenIapModule.kt
There was a problem hiding this comment.
Code Review
This pull request introduces support for Google Play Billing Library 9.1.0, specifically adding the Billing Choice API and associated features such as in-app messaging and reporting details. The changes span across the core Android library, documentation, and various framework wrappers (React Native, Expo, Flutter, KMP, Godot, and MAUI). A code review comment regarding nullable enum parsing in the Kotlin generator was identified as a valid improvement opportunity and should be addressed.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Code Review
This pull request upgrades the Google Play Billing Library integration from version 8.3.0 to 9.1.0 across all supported frameworks (React Native, Expo, Flutter, Godot, KMP, and MAUI). It introduces comprehensive support for the Billing Choice API, including new endpoints and types for fetching choice display assets, showing information dialogs, and handling in-app messages. Codegen plugins have also been updated to support default values from the GraphQL schema. The reviewer feedback suggests adding default empty object initializers to the getBillingChoiceInfoAndroid parameters in the React Native and Expo wrappers to prevent potential runtime TypeErrors when called without arguments.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Code Review
This pull request upgrades the Google Play Billing Library dependency from 8.3.0 to 9.1.0 and implements support for Google Play Billing Choice across all framework libraries (React Native, Expo, Flutter, KMP, Godot, and MAUI). Key additions include new Android-specific APIs: getBillingChoiceInfoAndroid for developer-rendered choice screens, showBillingProgramInformationDialogAndroid for Google-rendered choice flows, and showInAppMessagesAndroid for displaying Play Billing in-app messages. Additionally, createBillingProgramReportingDetailsAndroid now accepts an optional developerBillingType parameter. Documentation, generated types, and test suites have been updated accordingly to maintain platform parity. There are no review comments, and I have no feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/google/openiap/src/horizon/java/dev/hyo/openiap/OpenIapModule.kt (1)
810-831: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winMake Horizon’s unsupported Billing Choice paths consistent
showBillingProgramInformationDialogAndroidandshowInAppMessagesAndroidreturn placeholder results whenActivityis missing, but the Horizon overrides still throwFeatureNotSupported. Use one failure shape for both branches so callers don’t have to handle result-vs-exception behavior differently.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/google/openiap/src/horizon/java/dev/hyo/openiap/OpenIapModule.kt` around lines 810 - 831, The Horizon overrides for showBillingProgramInformationDialogAndroid and showInAppMessagesAndroid currently mix placeholder result returns with FeatureNotSupported exceptions, which creates inconsistent failure handling. Update the OpenIapModule.kt implementations so both unsupported paths use the same failure shape as the rest of the API, either by consistently returning the corresponding result object or consistently throwing FeatureNotSupported from the named lambdas, and make the behavior match across both functions.packages/gql/codegen/plugins/dart.ts (1)
838-849: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winList cast crashes before default fallback can apply for non-nullable lists with schema defaults.
listCastonly appends?whentype.nullableis true. When a field is a non-null list ([X!]!) that also has a GraphQL default value (e.g.categories: [Category!]! = [FOO], a real and common GraphQL pattern),defaultExpressionis set buttype.nullableis false, solistCastbecomes(${sourceExpr} as List<dynamic>)— a non-nullable cast. In Dart, castingnullto a non-nullable type throws aTypeErrorimmediately, so the${listCast} == null ? ${defaultExpression} : ...check never gets a chance to apply the fallback — it crashes instead of using the default.🐛 Proposed fix
if (type.kind === 'list') { - const listCast = `(${sourceExpr} as List<dynamic>${type.nullable ? '?' : ''})`; + const listCast = `(${sourceExpr} as List<dynamic>${type.nullable || defaultExpression ? '?' : ''})`; const elementExpr = this.buildFromJsonExpression(type.elementType!, 'e'); const mapCall = (target: string) => `${target}.map((e) => ${elementExpr}).toList()`; if (defaultExpression) { - return `${listCast} == null ? ${defaultExpression} : ${mapCall(`${listCast}${type.nullable ? '!' : ''}`)}`; + return `${listCast} == null ? ${defaultExpression} : ${mapCall(`${listCast}!`)}`; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/gql/codegen/plugins/dart.ts` around lines 838 - 849, The buildFromJsonExpression list branch currently applies a non-nullable cast before checking defaultExpression, so non-null list fields with schema defaults can throw on null before the fallback runs. Update the list handling in buildFromJsonExpression so the null check happens on the raw sourceExpr (or use a nullable cast whenever defaultExpression is present), then only cast/map after the default fallback has been selected. Keep the behavior aligned for both nullable and non-nullable list types, especially when defaultExpression is set.
♻️ Duplicate comments (1)
packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt (1)
4441-4467: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winPast-review pattern not applied to the new Billing Choice enum parsers.
GetBillingChoiceInfoParamsAndroid.fromJson(Lines 4602-4609) andBillingProgramInformationDialogParamsAndroid.fromJson(Line 4453) parsebillingProgram/playBillingChoiceImageLayoutwithoutrunCatching, unlike the pervasiverunCatching { EnumType.fromJson(it) }.getOrNull() ?: Unknownpattern used elsewhere in this file (and unlike the fix already applied toInAppMessageParamsAndroid.categories). If these enums throw on unrecognized/future raw values, these deserializers will crash instead of degrading gracefully.Please confirm whether
BillingProgramAndroid/BillingChoiceImageLayoutAndroidhave anUnknown-style fallback member; if so, wrap theirfromJsoncalls inrunCatchingthe same way as the other enums in this file.Also applies to: 4587-4616
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt` around lines 4441 - 4467, The Billing Choice enum parsing in BillingProgramInformationDialogParamsAndroid.fromJson and GetBillingChoiceInfoParamsAndroid.fromJson is still calling fromJson directly, unlike the rest of this file’s safe enum parsing pattern. Update the parsing in these methods to use runCatching around BillingProgramAndroid.fromJson and BillingChoiceImageLayoutAndroid.fromJson, then fall back to the corresponding Unknown-style member if present; if no fallback exists, add one consistently. Keep the fix aligned with the existing enum deserializers in Types.kt and with the already-correct InAppMessageParamsAndroid.categories handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/gql/codegen/plugins/csharp.ts`:
- Around line 411-417: In csharp.ts, fix the non-nullable property emission in
the branch that uses buildDefaultValueExpression so that if the default cannot
be converted, the property falls back to being marked required instead of being
emitted without required or an initializer. Also update
buildDefaultValueForType’s string handling to escape C# string literal
characters such as " and \ before interpolating the default value, so generated
properties in emit stay valid.
In `@packages/gql/codegen/plugins/kotlin.ts`:
- Around line 895-901: The scalar default formatting in the Kotlin codegen path
is treating all numeric defaults the same, which causes whole-number
Float/Double defaults to emit invalid Kotlin literals. Update the default-value
formatting logic in the scalar-handling branch of the Kotlin plugin so it checks
the target GraphQL scalar type before serializing numbers, and when the field
maps to Float/Double, emit a Kotlin floating-point literal instead of using
String(defaultValue). Keep the existing string/boolean handling intact, and
adjust the helper that formats defaults so it can distinguish the Float scalar
case.
---
Outside diff comments:
In `@packages/google/openiap/src/horizon/java/dev/hyo/openiap/OpenIapModule.kt`:
- Around line 810-831: The Horizon overrides for
showBillingProgramInformationDialogAndroid and showInAppMessagesAndroid
currently mix placeholder result returns with FeatureNotSupported exceptions,
which creates inconsistent failure handling. Update the OpenIapModule.kt
implementations so both unsupported paths use the same failure shape as the rest
of the API, either by consistently returning the corresponding result object or
consistently throwing FeatureNotSupported from the named lambdas, and make the
behavior match across both functions.
In `@packages/gql/codegen/plugins/dart.ts`:
- Around line 838-849: The buildFromJsonExpression list branch currently applies
a non-nullable cast before checking defaultExpression, so non-null list fields
with schema defaults can throw on null before the fallback runs. Update the list
handling in buildFromJsonExpression so the null check happens on the raw
sourceExpr (or use a nullable cast whenever defaultExpression is present), then
only cast/map after the default fallback has been selected. Keep the behavior
aligned for both nullable and non-nullable list types, especially when
defaultExpression is set.
---
Duplicate comments:
In `@packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt`:
- Around line 4441-4467: The Billing Choice enum parsing in
BillingProgramInformationDialogParamsAndroid.fromJson and
GetBillingChoiceInfoParamsAndroid.fromJson is still calling fromJson directly,
unlike the rest of this file’s safe enum parsing pattern. Update the parsing in
these methods to use runCatching around BillingProgramAndroid.fromJson and
BillingChoiceImageLayoutAndroid.fromJson, then fall back to the corresponding
Unknown-style member if present; if no fallback exists, add one consistently.
Keep the fix aligned with the existing enum deserializers in Types.kt and with
the already-correct InAppMessageParamsAndroid.categories handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4bba7c7e-56d7-463b-870b-b719b9ac702a
⛔ Files ignored due to path filters (5)
packages/gql/src/generated/Types.csis excluded by!**/generated/**packages/gql/src/generated/Types.ktis excluded by!**/generated/**packages/gql/src/generated/Types.swiftis excluded by!**/generated/**packages/gql/src/generated/types.dartis excluded by!**/generated/**packages/gql/src/generated/types.tsis excluded by!**/generated/**
📒 Files selected for processing (28)
libraries/expo-iap/android/src/main/java/expo/modules/iap/ExpoIapModule.ktlibraries/expo-iap/src/modules/__tests__/android.test.tslibraries/expo-iap/src/modules/android.tslibraries/expo-iap/src/types.tslibraries/flutter_inapp_purchase/lib/types.dartlibraries/flutter_inapp_purchase/scripts/verify-android-consumer-build.shlibraries/godot-iap/android/src/main/java/dev/hyo/godotiap/GodotIap.ktlibraries/kmp-iap/example/composeApp/src/commonMain/kotlin/dev/hyo/martie/screens/AlternativeBillingScreen.ktlibraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.ktlibraries/kmp-iap/library/src/commonMain/kotlin/io/github/hyochan/kmpiap/openiap/Types.ktlibraries/maui-iap/android/openiap/src/main/java/dev/hyo/openiap/maui/OpenIapMauiModule.ktlibraries/maui-iap/src/OpenIap.Maui/Types.cslibraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.ktlibraries/react-native-iap/src/__tests__/index.test.tslibraries/react-native-iap/src/index.tslibraries/react-native-iap/src/types.tspackages/apple/Sources/Models/Types.swiftpackages/google/openiap/src/amazon/java/dev/hyo/openiap/OpenIapModule.ktpackages/google/openiap/src/horizon/java/dev/hyo/openiap/OpenIapModule.ktpackages/google/openiap/src/main/java/dev/hyo/openiap/Types.ktpackages/google/openiap/src/play/java/dev/hyo/openiap/OpenIapModule.ktpackages/gql/codegen/core/transformer.tspackages/gql/codegen/core/types.tspackages/gql/codegen/plugins/csharp.tspackages/gql/codegen/plugins/dart.tspackages/gql/codegen/plugins/kotlin.tspackages/gql/codegen/plugins/swift.tspackages/gql/src/api-android.graphql
✅ Files skipped from review due to trivial changes (6)
- libraries/flutter_inapp_purchase/lib/types.dart
- libraries/react-native-iap/src/types.ts
- libraries/expo-iap/src/types.ts
- packages/apple/Sources/Models/Types.swift
- libraries/kmp-iap/library/src/commonMain/kotlin/io/github/hyochan/kmpiap/openiap/Types.kt
- libraries/maui-iap/src/OpenIap.Maui/Types.cs
🚧 Files skipped from review as they are similar to previous changes (13)
- libraries/flutter_inapp_purchase/scripts/verify-android-consumer-build.sh
- libraries/expo-iap/src/modules/tests/android.test.ts
- libraries/maui-iap/android/openiap/src/main/java/dev/hyo/openiap/maui/OpenIapMauiModule.kt
- packages/gql/src/api-android.graphql
- packages/google/openiap/src/amazon/java/dev/hyo/openiap/OpenIapModule.kt
- libraries/react-native-iap/src/index.ts
- libraries/expo-iap/src/modules/android.ts
- libraries/expo-iap/android/src/main/java/expo/modules/iap/ExpoIapModule.kt
- libraries/godot-iap/android/src/main/java/dev/hyo/godotiap/GodotIap.kt
- libraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt
- libraries/react-native-iap/src/tests/index.test.ts
- libraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.kt
- packages/google/openiap/src/play/java/dev/hyo/openiap/OpenIapModule.kt
There was a problem hiding this comment.
Code Review
This pull request upgrades the Google Play Billing Library from version 8.3.0 to 9.1.0 across multiple frameworks (React Native, Expo, Flutter, KMP, Godot, and MAUI) and introduces support for Billing Choice APIs. The code review feedback suggests simplifying a ternary operator in the React Native implementation of createBillingProgramReportingDetailsAndroid and removing a dead synchronous return value check on showBillingProgramInformationDialog in the Android KMP implementation.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
1 similar comment
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
dd1afdd to
11fb5c8
Compare
Bump the OpenIAP spec to 2.1.0, align framework hooks and store-specific unsupported behavior, consolidate stable release notes, and preserve verification lifecycle guidance. Closes #221
11fb5c8 to
94bd0a7
Compare
There was a problem hiding this comment.
Code Review
This pull request upgrades the Google Play Billing Library integration to version 9.1.0 and the Meta Horizon Billing Compatibility SDK to version 2.0.0 across the monorepo wrapper libraries, introducing Billing Choice APIs, developer billing reporting, and in-app billing messages. The code review identified two critical issues: a backward-compatibility bug in the Kotlin Multiplatform reflective listener proxy for Play Billing 8.3.0 that could prevent token emission, and a serialization failure in the GDScript wrapper where custom RefCounted objects are passed directly to JSON.stringify without being converted to dictionaries first.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Keep KMP developer billing payload extraction compatible with Billing 8.3 details and serialize nested Godot purchase parameters before crossing the native bridge.
There was a problem hiding this comment.
Code Review
This pull request upgrades the Google Play Billing Library integration from version 8.x to 9.1.0 across the monorepo, introducing support for Billing Choice APIs, developer-provided billing options, and transactional in-app messages. It also updates the Meta Horizon Billing Compatibility SDK to version 2.0.0, transitioning to the canonical Horizon App ID manifest key, and adds experimental support for Amazon Fire OS and Vega OS. Corresponding updates, types, and tests have been added across all wrapper libraries (React Native, Expo, Flutter, Godot, KMP, and MAUI). Feedback was provided regarding a style guide violation where the shared spec version was bumped to 2.1.0 in openiap-versions.json without the corresponding update to packages/gql/package.json.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Code Review
This pull request updates the OpenIAP project to support Google Play Billing 9.1.0, including the new Billing Choice APIs, in-app messaging, and developer-provided billing enhancements. It also updates the Amazon Fire OS and Vega OS integrations, improves the IAPKit verification logic with timeouts, and updates documentation and SDK parity checklists. Several review comments identified critical issues regarding the use of withTimeout in retry loops, reflection-based compatibility fallbacks for Billing Library versions, and missing await keywords in Godot tests, which are addressed by the review indices marked for removal.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Summary
BILLING_CHOICE, developer-rendered choice metadata/dialog/reporting,originalExternalTransactionId, andshowInAppMessagesAndroid.Versioning
2.3.0-rc.1until CI promotion)2.2.5-rc.1until CI promotion)Related
Verification
yarn specsfor Nitrobun audit:parity,bun audit:docs, and staged diff checks, repeated after a five-minute no-change intervalswift buildand 104 Swift testsConnected-device E2E
showInAppMessagesAndroid; the test account returned program-unavailable andno-action-needed, both handled correctly.adb unauthorized; the headset must accept the USB debugging prompt.Preview
The visible changes are API/reference documentation and native SDK examples. Documentation production build and connected example-app launch checks cover those surfaces.