Skip to content

Conversation

@hyochan
Copy link
Owner

@hyochan hyochan commented Dec 29, 2025

https://www.openiap.dev/docs/updates/notes#gql-1-3-11-google-1-3-21-apple-1-3-9

Summary by CodeRabbit

  • Breaking Changes

    • Platform keys in purchase requests renamed from ios/android → apple/google.
    • PurchaseState simplified; removed legacy states (Restored/Failed/Deferred) and unified handling.
  • Deprecations

    • AlternativeBillingModeAndroid deprecated in favor of BillingProgramAndroid.
    • useAlternativeBilling marked deprecated; use new billing program / external-purchase flows.
  • New Features

    • RequestPurchaseProps.inApp() and .subs() factory surfaces.
    • Unified purchaseState property and new listener names.
  • Dependencies

    • OpenIAP GraphQL tooling bumped to v1.3.11.

✏️ Tip: You can customize this high-level summary in your review settings.

@hyochan hyochan added the 🎯 feature New feature label Dec 29, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 29, 2025

Warning

Rate limit exceeded

@hyochan has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 46 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 6fe3cd6 and 56b36b6.

📒 Files selected for processing (1)
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

v8.2.0 updates request payload keys from ios/android to apple/google, simplifies PurchaseState (removes Failed/Restored/Deferred), replaces AlternativeBillingModeAndroid with BillingProgramAndroid and adds enableBillingProgramAndroid to initConnection, and bumps OpenIAP dependency versions; extensive docs and examples updated accordingly.

Changes

Cohort / File(s) Summary
Changelog & Release Docs
CHANGELOG.md, docs/blog/2025-12-29-8.2.0.release.md, docs/docusaurus.config.ts
Add v8.2.0 release notes, breaking changes, deprecations, dependency bumps; update docs version label to 8.2.
Public API / Types
lib/types.dart, pubspec.yaml, openiap-versions.json
Rename RequestPurchaseProps platform keys from ios/androidapple/google; add BillingProgramAndroid variants; remove PurchaseState.Failed/Restored/Deferred; bump package version to 8.2.0 and OpenIAP sub-versions.
Request builders & serialization
lib/builders.dart, test/builders_unit_test.dart, test/flutter_inapp_purchase_channel_test.dart
Update builders/tests to emit/expect apple/google keys; validate builder → props JSON shapes and billing-program payloads.
Purchase parsing & state handling
lib/helpers.dart, lib/extensions/purchase_helpers.dart, test/helpers_unit_test.dart
Consolidate purchase-state parsing: treat deprecated states as Unknown; map restored to Purchased where applicable; remove explicit handling for Removed enums.
Init & Billing API surface (docs + examples)
docs/docs/api/methods/init-connection.md, docs/docs/guides/alternative-billing.md, docs/docs/examples/alternative-billing.md
Document initConnection({ BillingProgramAndroid? enableBillingProgramAndroid }), deprecate alternativeBillingModeAndroid/useAlternativeBilling, add presentExternalPurchaseLinkIOS guidance and billing-program flows.
Docs — API, guides, migration, examples
docs/docs/**, docs/versioned_docs/version-8.1/** (many files)
Large-scale documentation additions/updates: migrate examples and API docs to apple/google, unify purchaseState usage, add migration guides and extensive v8.1 reference content.
Example app updates
example/lib/src/screens/*, example/lib/src/app.dart, example/lib/src/screens/billing_programs_screen.dart, example/lib/src/screens/alternative_billing_screen.dart, example/lib/src/screens/home_screen.dart
Update example screens to use apple/google; refactor alternative-billing screen to new billing-program flows; remove dedicated BillingProgramsScreen and route/menu entries.
Tests
test/flutter_inapp_purchase_channel_test.dart, test/helpers_unit_test.dart
Adjust tests for apple/google payloads and new BillingProgramAndroid.UserChoiceBilling handling; add unit tests for purchase-state mapping.

Sequence Diagram(s)

(Skipped — changes are primarily API/type renames, docs, and example UI refactors; no new multi-component control flow diagram generated.)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 Hopping through code with a twitch of my nose,

apple and google now share the same prose.
Billing programs bloom, old modes step aside,
Purchase states simplified — a tidier stride.
Eight-point-two, I nibble the crate — docs polished and great!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: update to OpenIAP v1.3.11' directly reflects the main objective of updating the OpenIAP library version, which is the primary change in this changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

- Update openiap versions: gql 1.3.11, google 1.3.21, apple 1.3.9
- Simplify PurchaseState enum (remove Failed, Restored, Deferred)
- Deprecate AlternativeBillingModeAndroid in favor of BillingProgramAndroid
- Deprecate useAlternativeBilling field in RequestPurchaseProps
- Update alternative_billing_screen example to use BillingProgramAndroid
- Update documentation for v8.2.0 API changes
- Add versioned docs for v8.1 and migration guide from v8
@hyochan hyochan force-pushed the chore/openiap-1.3.11 branch from c74af65 to 1d5dd5e Compare December 29, 2025 15:06
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @hyochan, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request updates the project to OpenIAP v1.3.11, focusing on API consolidation and simplification. Key changes include a streamlined PurchaseState enum, unified alternative billing configurations for Android, and new factory constructors for purchase requests. These updates aim to enhance API clarity, improve type safety, and ensure compatibility with the latest platform billing features, alongside a significant overhaul of the project's documentation.

Highlights

  • PurchaseState Enum Simplified: The PurchaseState enum has been streamlined, removing Failed, Restored, and Deferred states. Failures are now handled via purchaseErrorListener, restored purchases are Purchased, and deferred purchases on Android are Pending.
  • Alternative Billing API Consolidation: Android's alternative billing modes (AlternativeBillingModeAndroid) are deprecated. The initConnection method now uses enableBillingProgramAndroid with the BillingProgramAndroid enum for a unified approach. iOS's RequestPurchaseProps.useAlternativeBilling is also deprecated in favor of presentExternalPurchaseLinkIOS.
  • New RequestPurchaseProps Factory Constructors: The requestPurchase method now supports factory constructors (RequestPurchaseProps.inApp and RequestPurchaseProps.subs) for type-safe and cleaner purchase requests, with ios/android fields being deprecated in favor of apple/google.
  • Dependencies Update: The project dependencies for openiap-gql, openiap-google, and openiap-apple have been updated to their latest versions (1.3.11, 1.3.21, and 1.3.9 respectively).
  • Comprehensive Documentation Update: Extensive updates have been made to the documentation, including a new v8.2.0 release blog post, a migration guide from v8.1, and new versioned documentation for v8.1 covering API references, guides, examples, and troubleshooting.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the library and its documentation to align with OpenIAP v1.3.11. The main changes include simplifying the PurchaseState enum and deprecating AlternativeBillingModeAndroid in favor of a more robust BillingProgramAndroid enum. The documentation has been extensively updated across API references, guides, and examples to reflect these new APIs. A new migration guide for v8.1 has also been added, which is very helpful.

My review focuses on the consistency and correctness of these updates. I've found a significant inconsistency between the updated documentation/examples and the actual implementation in lib/types.dart regarding the parameter names for RequestPurchaseProps factory constructors. The docs promote using apple and google, but the implementation expects ios and android, which will lead to compilation errors for users. I've left several comments on the affected files with suggestions for correction.

- Update types.dart generation to read field names from GQL schema
- Change RequestPurchaseProps.inApp/subs to use apple/google instead of ios/android
- Update all documentation to use new API
- Simplify example: remove billing_programs_screen, update alternative_billing_screen
- Add 8.2.0 CHANGELOG entry

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@codecov
Copy link

codecov bot commented Dec 29, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.01%. Comparing base (2ffefca) to head (56b36b6).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #604      +/-   ##
==========================================
+ Coverage   60.11%   67.01%   +6.90%     
==========================================
  Files           7        7              
  Lines        1429     1419      -10     
==========================================
+ Hits          859      951      +92     
+ Misses        570      468     -102     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (8)
docs/docs/api/core-methods.md (2)

79-79: Update alternative billing parameter from alternativeBillingModeAndroid to enableBillingProgramAndroid (v8.2.0+).

The documentation for initConnection() shows alternativeBillingModeAndroid which is deprecated in v8.2.0. This should be updated to enableBillingProgramAndroid with the new BillingProgramAndroid enum values. Cross-reference with docs/docs/api/methods/init-connection.md for consistency.

Also applies to: 920-932


266-267: Fix hyphenation in links.

Add hyphens to compound modifiers: "Platform-Specific Setup" instead of "Platform Specific Setup" (appears on lines 266 and 267).

🔎 Proposed fix
- [**Platform Specific Setup**](/getting-started/android-setup) - Android specific configuration
- [**Platform Specific Setup**](/getting-started/ios-setup) - iOS specific configuration
+ [**Platform-Specific Setup**](/getting-started/android-setup) - Android-specific configuration
+ [**Platform-Specific Setup**](/getting-started/ios-setup) - iOS-specific configuration
docs/docs/api/classes/purchase-item.md (1)

153-175: Update usage example to demonstrate new unified purchaseState API.

The example code still references the deprecated platform-specific properties (purchaseStateAndroid, purchaseStateIOS, transactionStateIOS, TransactionState). Update this example to demonstrate the new unified purchaseState property introduced in v8.2.0.

🔎 Proposed updated example
 // Listen to purchase updates
-FlutterInappPurchase.purchaseUpdated.listen((Purchase? purchase) async {
+FlutterInappPurchase.instance.purchaseUpdatedListener.listen((Purchase? purchase) async {
   if (purchase != null) {
     print('Product purchased: ${purchase.productId}');
     print('Transaction ID: ${purchase.transactionId}');
     print('Transaction Date: ${purchase.transactionDate}');

     // Unified purchase state handling (v8.2.0+)
-    if (Platform.isIOS) {
-      // Check iOS transaction state
-      if (purchase.transactionStateIOS == TransactionState.purchased) {
-        // Finish the transaction
-        await FlutterInappPurchase.instance.finishTransaction(purchase);
-      }
-    } else if (Platform.isAndroid) {
-      // Check if acknowledgment is needed
-      if (purchase.isAcknowledgedAndroid == false) {
-        await FlutterInappPurchase.instance.acknowledgePurchaseAndroid(
-          purchaseToken: purchase.purchaseToken!
-        );
-      }
-    }
+    switch (purchase.purchaseState) {
+      case PurchaseState.Purchased:
+        // Purchase completed - deliver content
+        await _deliverContent(purchase.productId);
+        await FlutterInappPurchase.instance.finishTransaction(purchase: purchase);
+        break;
+      case PurchaseState.Pending:
+        // Purchase pending - wait for completion
+        print('Purchase pending...');
+        break;
+      case PurchaseState.Unknown:
+        print('Unknown purchase state');
+        break;
+    }
   }
 });
docs/docs/api/classes/flutter-inapp-purchase.md (1)

142-155: Update requestPurchase signature/parameters to match current API

The examples correctly use the new RequestPurchaseProps API:

await FlutterInappPurchase.instance.requestPurchase(
  RequestPurchaseProps.inApp((
    apple: RequestPurchaseIosProps(sku: productId),
    google: RequestPurchaseAndroidProps(skus: [productId]),
    useAlternativeBilling: null,
  )),
);

However, the documented signature and parameter table above are now out of date:

Future<void> requestPurchase({
  required RequestPurchase request,
  required PurchaseType type,
})

In the current code, requestPurchase is a handler with the effective signature:

Future<RequestPurchaseResult?> requestPurchase(RequestPurchaseProps params)

Please update:

  • The signature block to show a single RequestPurchaseProps parameter (and the correct return type if you want to reflect RequestPurchaseResult?).
  • The parameters table and surrounding text to describe RequestPurchaseProps.inApp / .subs instead of request + type named parameters.

This will keep the docs consistent with both FlutterInappPurchase and the tests.

Also applies to: 156-169, 306-314

docs/examples/alternative-billing.md (4)

267-275: Update builder pattern to use the new v8.2.0 API.

Lines 271 uses the deprecated useAlternativeBilling field in the builder pattern. Update this example to reflect the new v8.2.0 API structure with enableBillingProgramAndroid.


296-301: Update configuration section to reflect v8.2.0 deprecations.

This section documents the deprecated AlternativeBillingModeAndroid enum and alternativeBillingModeAndroid parameter. Replace with documentation of the new BillingProgramAndroid enum and enableBillingProgramAndroid parameter, including the new enum variants (UserChoiceBilling, ExternalOffer, ExternalPayments) mentioned in the PR.


220-227: Remove deprecated useAlternativeBilling parameter.

Line 225 uses useAlternativeBilling: true, which is deprecated in v8.2.0. This parameter had no effect on the purchase flow and should be removed. To enable User Choice Billing on Android, configure it via initConnection(enableBillingProgramAndroid: BillingProgramAndroid.UserChoiceBilling) instead.

    try {
      // Google will show selection dialog automatically
      await _iap.requestPurchase(
        RequestPurchaseProps.inApp((
          google: RequestPurchaseAndroidProps(skus: [widget.product.id]),
        )),
      );

198-215: Update alternative billing initialization to use the new v8.2.0 API.

The alternativeBillingModeAndroid parameter and AlternativeBillingModeAndroid enum are deprecated. Replace with enableBillingProgramAndroid using BillingProgramAndroid.UserChoiceBilling:

await _iap.initConnection(
  enableBillingProgramAndroid: BillingProgramAndroid.UserChoiceBilling,
);
♻️ Duplicate comments (3)
docs/docs/getting-started/setup-horizon.md (1)

114-119: Code correctly uses the new apple/google API surface.

The example demonstrates the updated v8.2.0 API where platform-specific props are nested under apple and google keys (not ios/android). This aligns with the breaking changes introduced in this release.

docs/docs/guides/faq.md (1)

148-153: Same apple/google naming concern applies here.

This subscription example uses the same apple/google parameter pattern. The verification script above will confirm whether these parameter names are correct.

example/lib/src/screens/alternative_billing_screen.dart (1)

354-358: Same apple/google parameter naming applies here.

This example uses apple and google parameters in RequestPurchaseProps.inApp. The past review comment flagged this as inconsistent with lib/types.dart expecting ios and android. This will be clarified by the verification script from the first file.

🧹 Nitpick comments (8)
docs/versioned_docs/version-8.1/guides/offer-code-redemption.md (1)

49-49: Minor text redundancy: simplify "iOS system" to "iOS".

The phrase "The redemption sheet is handled by the iOS system" is slightly redundant since "iOS" already stands for "iOS Operating System." Consider simplifying to: "The redemption sheet is handled by iOS."

docs/versioned_docs/version-8.1/guides/faq.md (1)

329-329: Remove emoji from documentation.

Per coding guidelines, documentation should avoid emojis and keep text clean and professional. Replace the emoji with plain text.

-// ✅ Correct: Listen to both streams
+// Correct: Listen to both streams
docs/versioned_docs/version-8.1/api/classes/flutter-inapp-purchase.md (2)

40-51: Style: Reduce sentence repetition in stream descriptions.

Lines 40–51 have three successive sentences starting with "Stream that," which creates repetitive prose.

🔎 Suggested improvement
Stream that emits purchase updates when a transaction state changes.

```dart
Stream<PurchaseError?> purchaseError

Stream that emits purchase errors when a transaction fails.

Stream<ConnectionResult> connectionUpdated

Emits connection state updates.

Stream<String?> purchasePromoted

Emits promoted product IDs (iOS only).


</details>

---

`91-91`: **Grammar: Add missing subject to sentence.**

Line 91 starts with "Should be called..." but lacks a subject. Revise to "This method should be called..." or restructure for clarity.

</blockquote></details>
<details>
<summary>docs/docs/api/methods/request-subscription.md (1)</summary><blockquote>

`54-58`: **Consider noting deprecation of useAlternativeBilling.**

The migration example includes `useAlternativeBilling: null`, but according to the PR objectives, this field is deprecated in favor of `BillingProgramAndroid`. Consider adding a note about the deprecation or showing the new approach instead.



<details>
<summary>Optional: Update to reflect new API</summary>

If you want to show the latest recommended approach, you could add a note:

```dart
await FlutterInappPurchase.instance.requestPurchase(
  RequestPurchaseProps.subs((
    apple: RequestSubscriptionIosProps(sku: 'com.example.monthly'),
    google: RequestSubscriptionAndroidProps(skus: ['com.example.monthly']),
    // Note: useAlternativeBilling is deprecated. 
    // Use initConnection(enableBillingProgramAndroid: ...) instead
  )),
);
docs/versioned_docs/version-8.1/getting-started/android-setup.md (1)

84-84: Optional: Add blank lines around fenced code blocks.

Static analysis detected missing blank lines around fenced code blocks (MD031). While not critical, adding blank lines improves markdown readability.

Also applies to: 99-99

docs/versioned_docs/version-8.1/api/flutter-inapp-purchase.md (1)

119-124: Fix MD tables spacing; consider toning down emoji headings and align listener naming

  • The tables under the requestPurchase, requestPurchaseSimple, and finishTransaction sections are missing blank lines before/after the table blocks. This triggers MD058 (blanks-around-tables) and may fail markdownlint; insert a blank line before the header row and after each table.
  • Headings like # 🔧 FlutterInappPurchase API and ## 📦 Product Management use emojis in the title; project docs guidelines ask to keep headings emoji‑free. Consider moving emojis into the body text instead.
  • The finishTransaction example uses FlutterInappPurchase.purchaseUpdated.listen(...). Current guidance and other docs favor the instance streams FlutterInappPurchase.instance.purchaseUpdatedListener / purchaseErrorListener as the primary public API; consider updating this example to match that pattern. Based on learnings, purchaseUpdatedListener/purchaseErrorListener are the preferred listener names.

Also applies to: 153-160, 217-352

docs/docs/guides/faq.md (1)

263-275: Inconsistent API pattern compared to other examples.

This example uses RequestPurchaseProps.subs(request: RequestPurchasePropsByPlatforms(...)) while other examples in this file use the record syntax RequestPurchaseProps.subs((apple: ..., google: ...)). This inconsistency may confuse users.

Consider using a consistent pattern throughout the documentation, or clarify when each pattern should be used.

Comment on lines +40 to +50
handlePurchaseSuccess(purchase);
},
onError: (error) {
debugPrint('Purchase stream error: $error');
},
);
}
Future<void> handlePurchaseSuccess(Purchase purchase) async {
debugPrint('Purchase completed: ${purchase.productId}');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add blank lines around headings.

Lines 44 and 49 need blank lines before the headings per MD022 (blanks-around-headings). Apply the same to lines 336 and 341.

Example fix
## Examples**:
+
### Usage Examples

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

44-44: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


49-49: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🤖 Prompt for AI Agents
In docs/versioned_docs/version-8.1/api/listeners.md around lines 40 to 50 (and
also at lines ~336 and ~341), headings lack the required blank lines per MD022;
insert a single blank line immediately before each heading at lines 44 and 49
(and likewise before the headings at lines 336 and 341) so there is an empty
line separating the previous content from each heading, and save the file.

Comment on lines 414 to 420
// Initialize with user-choice mode
await FlutterInappPurchase.instance.initConnection(
alternativeBillingModeAndroid: AlternativeBillingModeAndroid.UserChoice,
);
_userChoiceSubscription = FlutterInappPurchase.instance
.userChoiceBillingListener.listen((details) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Update alternative billing reference to reflect v8.2.0 deprecations.

Line 416 references alternativeBillingModeAndroid: AlternativeBillingModeAndroid.UserChoice, which is deprecated in v8.2.0. Per the CHANGELOG, use enableBillingProgramAndroid: BillingProgramAndroid.UserChoiceBilling in initConnection() instead, or reference the new BillingProgramAndroid enum approach. Update this example to reflect the current recommended API.

🤖 Prompt for AI Agents
In docs/versioned_docs/version-8.1/api/listeners.md around lines 414 to 420, the
example uses the deprecated alternativeBillingModeAndroid:
AlternativeBillingModeAndroid.UserChoice; update the initConnection call to use
the new parameter enableBillingProgramAndroid with
BillingProgramAndroid.UserChoiceBilling (or the current BillingProgramAndroid
enum variant) instead, and adjust any surrounding text to reference the
BillingProgramAndroid enum approach so the example matches v8.2.0 API.

- Update request-purchase.md to use 'google' field for v8.2.0+
- Fix listener names: purchaseUpdated -> purchaseUpdatedListener
- Remove emojis from setup-horizon.md and sponsors.md
- Fix StoreKit-related hyphenation in troubleshooting.md
- Add v8.2.0+ note in version-8.1 listeners.md for enableBillingProgramAndroid
- Add note in 7.0.0 blog post about updated API field names
- Fix subscriptionOfferDetails -> subscriptionOfferDetailsAndroid in product-type.md
- Add blank lines around code blocks in troubleshooting.md and setup-horizon.md
- Add v8.2.0+ note in error-handling.md for apple/google field names
- Add test for 'restored' string state -> Purchased
- Add test for numeric state 3 -> Purchased (restored)
- Add test for unknown numeric states -> Unknown
- Add test for 'failed'/'deferred' states -> Unknown
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
docs/versioned_docs/version-8.1/api/listeners.md (1)

414-418: Versioned documentation note: Deprecated API referenced.

This is version-8.1 documentation, which may correctly reflect the API for that release. However, line 417 references alternativeBillingModeAndroid: AlternativeBillingModeAndroid.UserChoice, which is deprecated in v8.2.0+.

The inline comment on line 415 already notes the v8.2.0+ alternative. Since this is versioned historical documentation, this may be intentionally showing the 8.1 API.

Note: Similar issue was flagged in past review. This comment acknowledges that versioned docs may intentionally show older APIs.

🧹 Nitpick comments (2)
docs/versioned_docs/version-8.1/api/methods/init-connection.md (1)

144-144: Fix grammar and style issues in text.

Two style issues flagged:

  • Line 144: "requires initialized" is nonstandard; use "requires to be initialized" or "requires an initialized"
  • Line 150: "expo-iap compatible" should be hyphenated: "expo-iap-compatible"
🔎 Proposed fixes
- [`fetchProducts()`](./get-products.md) - Fetches available products (requires initialized connection)
+ [`fetchProducts()`](./get-products.md) - Fetches available products (requires an initialized connection)
- The method signature remains the same, but now includes expo-iap compatible error handling.
+ The method signature remains the same, but now includes expo-iap-compatible error handling.

Also applies to: 150-150

docs/docs/api/methods/request-purchase.md (1)

52-58: Add blank line before heading.

Line 52 needs a blank line before the heading to comply with Markdown formatting rules (MD022).

🔎 Proposed fix
 ))

RequestPurchase (Legacy)

As per coding guidelines, documentation should be clean and professional.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b946753 and 6fe3cd6.

📒 Files selected for processing (13)
  • docs/blog/2025-10-04-7.0.0.release.md
  • docs/docs/api/methods/request-purchase.md
  • docs/versioned_docs/version-8.1/api/listeners.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
  • docs/versioned_docs/version-8.1/api/types/product-type.md
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/getting-started/setup-horizon.md
  • docs/versioned_docs/version-8.1/guides/error-handling.md
  • docs/versioned_docs/version-8.1/sponsors.md
  • docs/versioned_docs/version-8.1/troubleshooting.md
  • test/builders_unit_test.dart
  • test/helpers_unit_test.dart
✅ Files skipped from review due to trivial changes (1)
  • docs/versioned_docs/version-8.1/guides/error-handling.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • docs/versioned_docs/version-8.1/sponsors.md
  • docs/versioned_docs/version-8.1/api/types/product-type.md
  • docs/blog/2025-10-04-7.0.0.release.md
  • docs/versioned_docs/version-8.1/troubleshooting.md
🧰 Additional context used
📓 Path-based instructions (3)
**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Avoid using emojis in documentation, especially in headings, and keep documentation clean and professional

Files:

  • docs/versioned_docs/version-8.1/getting-started/setup-horizon.md
  • docs/versioned_docs/version-8.1/api/listeners.md
  • docs/docs/api/methods/request-purchase.md
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
**/*.dart

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.dart: Use explicit type parameter for fetchProducts<T>() method: specify <Product> for InApp products, <ProductSubscription> for subscriptions, or <ProductCommon> for all products
Use getAvailablePurchases() with PurchaseOptions instead of deprecated getPurchaseHistories() method
Follow the generated-handler convention documented in CONVENTION.md when using lib/types.dart so exported APIs stay aligned with the OpenIAP schema
Format Dart code with dart format --page-width 80 before committing, excluding the generated lib/types.dart file
Run flutter analyze to fix all lint issues before committing, including type inference errors
Always specify explicit type arguments for generic functions like showModalBottomSheet<void>() to avoid type inference errors
Use IOS suffix for iOS-related code ending with platform name (e.g., PurchaseIOS), use Ios when iOS is not the final suffix (e.g., IosManager), and use Id before IOS for fields (e.g., subscriptionGroupIdIOS)
Use Android suffix for Android-related code (e.g., PurchaseAndroid, SubscriptionOfferAndroid)
Use Iap prefix when IAP is not the final suffix (e.g., IapPurchase, not IAPPurchase)
Use Id consistently for identifier fields across all platforms (e.g., productId, transactionId, offerId), with Id before platform suffixes (e.g., subscriptionGroupIdIOS, obfuscatedAccountIdAndroid)
Use request prefix for API functions that depend on event results (e.g., requestPurchase, requestPurchaseWithBuilder), following OpenIAP terminology
Do not use generic prefixes like get or find for API methods; refer to the official OpenIAP terminology at https://www.openiap.dev/docs/apis#terminology
All implementations must follow the OpenIAP specification: APIs (https://www.openiap.dev/docs/apis), Types (https://www.openiap.dev/docs/types), Events (https://www.openiap.dev/docs/events), and Errors (https://www.openiap.dev/docs/errors)

Files:

  • test/helpers_unit_test.dart
  • test/builders_unit_test.dart
**/*_test.dart

📄 CodeRabbit inference engine (CLAUDE.md)

Ensure all tests pass with flutter test before committing; use flutter test --coverage with dart run tool/filter_coverage.dart to generate coverage reports excluding lib/types.dart

Files:

  • test/helpers_unit_test.dart
  • test/builders_unit_test.dart
🧠 Learnings (26)
📓 Common learnings
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 598
File: docs/versioned_docs/version-7.1/getting-started/ios-setup.md:28-30
Timestamp: 2025-12-15T23:02:05.297Z
Learning: In flutter_inapp_purchase PRs, fixing broken links in versioned documentation (docs/versioned_docs/version-*/) is acceptable when the old links reference non-existent files that cause build failures or make the documentation unusable. This is considered necessary maintenance rather than content modification.
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/faq.md:164-172
Timestamp: 2025-08-21T02:01:17.634Z
Learning: When reviewing PRs for flutter_inapp_purchase, focus on the current version being developed rather than versioned documentation files, as those are historical snapshots.
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/api/classes/flutter-inapp-purchase.md:97-123
Timestamp: 2025-08-21T02:09:07.921Z
Learning: For flutter_inapp_purchase PRs, focus on the current version being developed (e.g., 6.4) and ignore versioned documentation files (e.g., version-6.3 folders) as those are historical snapshots that should not be modified.
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Before implementing new IAP features, discuss at https://github.com/hyochan/openiap.dev/discussions, get community feedback, and ensure alignment with OpenIAP standards
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : Use `request` prefix for API functions that depend on event results (e.g., `requestPurchase`, `requestPurchaseWithBuilder`), following OpenIAP terminology
📚 Learning: 2025-12-15T23:01:59.163Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 598
File: docs/versioned_docs/version-7.1/getting-started/ios-setup.md:28-30
Timestamp: 2025-12-15T23:01:59.163Z
Learning: In versioned documentation for flutter_inapp_purchase (docs/versioned_docs/version-*/), fix broken links in PRs when the old targets reference non-existent files that cause build failures or make the documentation unusable. Treat this as maintenance rather than content modification, and apply to all versioned docs (not just a single file) where the links are invalid.

Applied to files:

  • docs/versioned_docs/version-8.1/getting-started/setup-horizon.md
  • docs/versioned_docs/version-8.1/api/listeners.md
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
📚 Learning: 2025-12-07T09:28:12.233Z
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.md : Avoid using emojis in documentation, especially in headings, and keep documentation clean and professional

Applied to files:

  • docs/versioned_docs/version-8.1/getting-started/setup-horizon.md
📚 Learning: 2025-12-15T23:01:17.813Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 598
File: docs/versioned_docs/version-7.0/getting-started/android-setup.md:24-26
Timestamp: 2025-12-15T23:01:17.813Z
Learning: In versioned documentation (e.g., docs/versioned_docs/.../*.md), if a build break is caused by a broken link or a reference to a non-existent file, fix the link as maintenance work rather than modifying the documented content. The policy is to avoid content changes in versioned docs unless the content itself is incorrect; use targeted fixes for navigation and usability issues (e.g., broken URLs, missing files) and preserve the original content semantics.

Applied to files:

  • docs/versioned_docs/version-8.1/getting-started/setup-horizon.md
  • docs/versioned_docs/version-8.1/api/listeners.md
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
📚 Learning: 2025-12-07T09:28:12.233Z
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : Use `getAvailablePurchases()` with `PurchaseOptions` instead of deprecated `getPurchaseHistories()` method

Applied to files:

  • test/helpers_unit_test.dart
  • docs/versioned_docs/version-8.1/api/listeners.md
  • docs/docs/api/methods/request-purchase.md
  • test/builders_unit_test.dart
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
📚 Learning: 2025-12-07T09:28:12.233Z
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : Use `IOS` suffix for iOS-related code ending with platform name (e.g., `PurchaseIOS`), use `Ios` when iOS is not the final suffix (e.g., `IosManager`), and use `Id` before `IOS` for fields (e.g., `subscriptionGroupIdIOS`)

Applied to files:

  • test/helpers_unit_test.dart
  • docs/docs/api/methods/request-purchase.md
📚 Learning: 2025-12-07T09:28:12.233Z
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : Use `Iap` prefix when IAP is not the final suffix (e.g., `IapPurchase`, not `IAPPurchase`)

Applied to files:

  • test/helpers_unit_test.dart
  • docs/docs/api/methods/request-purchase.md
  • test/builders_unit_test.dart
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
📚 Learning: 2025-12-07T09:28:12.233Z
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*_test.dart : Ensure all tests pass with `flutter test` before committing; use `flutter test --coverage` with `dart run tool/filter_coverage.dart` to generate coverage reports excluding `lib/types.dart`

Applied to files:

  • test/helpers_unit_test.dart
  • test/builders_unit_test.dart
📚 Learning: 2025-11-12T05:57:05.449Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 588
File: macos/Classes/FlutterIapHelper.swift:160-173
Timestamp: 2025-11-12T05:57:05.449Z
Learning: In macos/Classes/FlutterIapHelper.swift, the fallbackPurchaseInput(for:) method intentionally hardcodes the platform as IapPlatform.ios. This is a last-resort fallback for corrupted or missing StoreKit transaction data where the actual platform cannot be reliably determined. Since the code path is shared between iOS and macOS (both using StoreKit) and this fallback is only triggered in exceptional error scenarios, using .ios is acceptable. Normal code paths use getCurrentPlatform() for accurate platform detection.

Applied to files:

  • test/helpers_unit_test.dart
  • docs/docs/api/methods/request-purchase.md
📚 Learning: 2025-09-09T06:04:46.743Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 545
File: lib/flutter_inapp_purchase.dart:1665-1665
Timestamp: 2025-09-09T06:04:46.743Z
Learning: In flutter_inapp_purchase project, prefer using iap_err.getCurrentPlatform() in error handling over hardcoded platform constants to ensure accurate runtime platform reporting in error messages and debugging.

Applied to files:

  • test/helpers_unit_test.dart
  • docs/versioned_docs/version-8.1/api/listeners.md
  • docs/docs/api/methods/request-purchase.md
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
📚 Learning: 2025-12-07T09:28:12.233Z
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : Use `request` prefix for API functions that depend on event results (e.g., `requestPurchase`, `requestPurchaseWithBuilder`), following OpenIAP terminology

Applied to files:

  • test/helpers_unit_test.dart
  • docs/versioned_docs/version-8.1/api/listeners.md
  • docs/docs/api/methods/request-purchase.md
  • test/builders_unit_test.dart
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
📚 Learning: 2025-12-09T06:00:53.274Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 596
File: docs/versioned_docs/version-7.1/api/listeners.md:110-142
Timestamp: 2025-12-09T06:00:53.274Z
Learning: Guideline: Enforce PascalCase for enum members in Dart code. Do not use lowerCamelCase for enum values (e.g., prefer ErrorCode.UserCancelled, ErrorCode.NetworkError, ErrorCode.AlreadyOwned). Apply to all Dart files in the repository where enums are defined to maintain consistency and readability.

Applied to files:

  • test/helpers_unit_test.dart
  • test/builders_unit_test.dart
📚 Learning: 2025-08-21T02:25:46.402Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/api/index.md:65-69
Timestamp: 2025-08-21T02:25:46.402Z
Learning: When reviewing flutter_inapp_purchase documentation, `purchaseUpdatedListener` and `purchaseErrorListener` are the correct listener names in the public API, not `purchaseUpdated` and `purchaseError`.

Applied to files:

  • docs/versioned_docs/version-8.1/api/listeners.md
  • docs/docs/api/methods/request-purchase.md
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
📚 Learning: 2025-08-20T23:53:15.912Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/api/methods/finish-transaction.md:66-77
Timestamp: 2025-08-20T23:53:15.912Z
Learning: In flutter_inapp_purchase, the correct way to listen to purchase updates is `FlutterInappPurchase.instance.purchaseUpdatedListener.listen`, not `FlutterInappPurchase.purchaseUpdated.listen`.

Applied to files:

  • docs/versioned_docs/version-8.1/api/listeners.md
  • docs/docs/api/methods/request-purchase.md
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
📚 Learning: 2025-12-15T23:02:05.297Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 598
File: docs/versioned_docs/version-7.1/getting-started/ios-setup.md:28-30
Timestamp: 2025-12-15T23:02:05.297Z
Learning: In flutter_inapp_purchase PRs, fixing broken links in versioned documentation (docs/versioned_docs/version-*/) is acceptable when the old links reference non-existent files that cause build failures or make the documentation unusable. This is considered necessary maintenance rather than content modification.

Applied to files:

  • docs/docs/api/methods/request-purchase.md
📚 Learning: 2025-08-21T02:01:17.634Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/faq.md:164-172
Timestamp: 2025-08-21T02:01:17.634Z
Learning: When reviewing PRs for flutter_inapp_purchase, focus on the current version being developed rather than versioned documentation files, as those are historical snapshots.

Applied to files:

  • docs/docs/api/methods/request-purchase.md
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
📚 Learning: 2025-12-07T09:28:12.233Z
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : Use explicit type parameter for `fetchProducts<T>()` method: specify `<Product>` for InApp products, `<ProductSubscription>` for subscriptions, or `<ProductCommon>` for all products

Applied to files:

  • docs/docs/api/methods/request-purchase.md
  • test/builders_unit_test.dart
📚 Learning: 2025-08-21T01:20:28.525Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/api/overview.md:128-131
Timestamp: 2025-08-21T01:20:28.525Z
Learning: The flutter_inapp_purchase library follows the OpenIAP specification for parameter naming. According to the specification at https://www.openiap.dev/docs/types#request-types, the parameter name should be "skus" (not "productIds") when requesting products, as confirmed by the project maintainer hyochan.

Applied to files:

  • docs/docs/api/methods/request-purchase.md
📚 Learning: 2025-08-21T01:20:28.525Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/api/overview.md:128-131
Timestamp: 2025-08-21T01:20:28.525Z
Learning: The flutter_inapp_purchase library follows the OpenIAP specification at https://www.openiap.dev/docs/types#request-types for parameter naming conventions. According to hyochan, "skus" is the correct parameter name based on this specification, not "productIds".

Applied to files:

  • docs/docs/api/methods/request-purchase.md
📚 Learning: 2025-12-07T09:28:12.233Z
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : Use `Id` consistently for identifier fields across all platforms (e.g., `productId`, `transactionId`, `offerId`), with `Id` before platform suffixes (e.g., `subscriptionGroupIdIOS`, `obfuscatedAccountIdAndroid`)

Applied to files:

  • docs/docs/api/methods/request-purchase.md
📚 Learning: 2025-12-09T06:01:03.702Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 596
File: docs/versioned_docs/version-7.1/api/listeners.md:110-142
Timestamp: 2025-12-09T06:01:03.702Z
Learning: In flutter_inapp_purchase, the ErrorCode enum uses PascalCase for its members (e.g., ErrorCode.UserCancelled, ErrorCode.NetworkError, ErrorCode.AlreadyOwned), not lowerCamelCase.

Applied to files:

  • docs/docs/api/methods/request-purchase.md
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
📚 Learning: 2025-12-07T09:28:12.233Z
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : Use `Android` suffix for Android-related code (e.g., `PurchaseAndroid`, `SubscriptionOfferAndroid`)

Applied to files:

  • docs/docs/api/methods/request-purchase.md
📚 Learning: 2025-12-15T22:41:01.985Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 598
File: lib/types.dart:2692-2721
Timestamp: 2025-12-15T22:41:01.985Z
Learning: In flutter_inapp_purchase and OpenIAP: Millisecond timestamp fields (e.g., startTimeMillis, endTimeMillis, preorderPresaleEndTimeMillis) are intentionally defined as String in the GraphQL schema and Dart types, not numeric types. This is by design for cross-platform compatibility—JavaScript Number type only supports 53-bit precision and cannot safely represent 64-bit Long values. The Android native Long values are converted to String in BillingConverters.kt, and helpers.dart applies .toString() for additional safety. This pattern is consistent across all microsecond/millisecond timestamp fields in the OpenIAP schema.

Applied to files:

  • docs/docs/api/methods/request-purchase.md
📚 Learning: 2025-08-21T01:20:28.525Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/api/overview.md:128-131
Timestamp: 2025-08-21T01:20:28.525Z
Learning: According to the OpenIAP specification at https://www.openiap.dev/docs/types#request-types, the parameter name for requesting products should be "skus" rather than "productIds" to maintain compliance with the OpenIAP standard.

Applied to files:

  • docs/docs/api/methods/request-purchase.md
📚 Learning: 2025-12-07T09:28:12.233Z
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : All implementations must follow the OpenIAP specification: APIs (https://www.openiap.dev/docs/apis), Types (https://www.openiap.dev/docs/types), Events (https://www.openiap.dev/docs/events), and Errors (https://www.openiap.dev/docs/errors)

Applied to files:

  • test/builders_unit_test.dart
  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
📚 Learning: 2025-08-21T02:09:07.921Z
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/api/classes/flutter-inapp-purchase.md:97-123
Timestamp: 2025-08-21T02:09:07.921Z
Learning: For flutter_inapp_purchase PRs, focus on the current version being developed (e.g., 6.4) and ignore versioned documentation files (e.g., version-6.3 folders) as those are historical snapshots that should not be modified.

Applied to files:

  • docs/versioned_docs/version-8.1/getting-started/quickstart.md
  • docs/versioned_docs/version-8.1/api/methods/finish-transaction.md
  • docs/versioned_docs/version-8.1/api/methods/init-connection.md
🪛 LanguageTool
docs/versioned_docs/version-8.1/api/methods/init-connection.md

[style] ~144-~144: The double modal “requires initialized” is nonstandard (only accepted in certain dialects). Consider “to be initialized”.
Context: ... - Fetches available products (requires initialized connection) - [requestPurchase()](./r...

(NEEDS_FIXED)


[grammar] ~150-~150: Use a hyphen to join words.
Context: ...ains the same, but now includes expo-iap compatible error handling. ### From exp...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)
docs/docs/api/methods/request-purchase.md

52-52: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

docs/versioned_docs/version-8.1/api/methods/init-connection.md

94-94: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


130-130: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build-ios
  • GitHub Check: test
  • GitHub Check: build-android
🔇 Additional comments (8)
docs/versioned_docs/version-8.1/getting-started/setup-horizon.md (1)

1-164: Documentation looks good overall.

The Horizon OS setup guide is well-structured, clearly written, and properly formatted. The external link to openiap.dev/docs/horizon-setup is valid, and the code examples (XML metadata, Gradle configuration, bash commands, and Dart usage) are accurate and helpful. The markdown formatting complies with style guidelines—no emojis, proper blank lines around code blocks, and consistent heading hierarchy.

The guide covers the essential steps (AndroidManifest configuration, platform selection via Gradle, Horizon enablement, build/run commands, testing on Meta Quest, and troubleshooting), which aligns well with the PR's focus on OpenIAP v1.3.11 updates.

docs/versioned_docs/version-8.1/api/methods/init-connection.md (1)

20-22: Version-8.1 documentation should reflect the API as it existed in version-8.1. The enableBillingProgramAndroid parameter was introduced in v8.2.0 (as indicated in the current documentation). The signature in version-8.1 docs is correct and should not be modified to include features from later versions.

Likely an incorrect or invalid review comment.

docs/versioned_docs/version-8.1/getting-started/quickstart.md (2)

17-84: LGTM on listener setup!

The listener names are correctly using purchaseUpdatedListener and purchaseErrorListener. The past review comment has been properly addressed.

However, note that the example uses Platform.isIOS (line 136) but doesn't show the required import 'dart:io'; at the top of the file.

// Add this import at the top with other imports
import 'dart:io';

343-362: Critical: Incorrect listener names in code examples.

Lines 343 and 350 use incorrect listener names that will cause runtime errors. The correct API names are purchaseUpdatedListener and purchaseErrorListener, not purchaseUpdated and purchaseError.

Additionally, lines 356-361 show a legacy API structure. For consistency with the rest of the document, consider using RequestPurchaseProps here as well.

🔎 Proposed fix
 // Listen to successful purchases
-FlutterInappPurchase.purchaseUpdated.listen((productItem) {
+FlutterInappPurchase.instance.purchaseUpdatedListener.listen((productItem) {
   // 1. Verify purchase
   // 2. Deliver content
   // 3. Finish transaction
 });

 // Listen to purchase errors
-FlutterInappPurchase.purchaseError.listen((error) {
+FlutterInappPurchase.instance.purchaseErrorListener.listen((error) {
   // Handle error
 });

 // Request a purchase
 await FlutterInappPurchase.instance.requestPurchase(
-  request: RequestPurchase(
-    ios: RequestPurchaseIOS(sku: 'product_id'),
-    android: RequestPurchaseAndroid(skus: ['product_id']),
-  ),
-  type: PurchaseType.inapp, // or PurchaseType.subs for subscriptions
+  RequestPurchaseProps.inApp((
+    ios: RequestPurchaseIosProps(sku: 'product_id'),
+    android: RequestPurchaseAndroidProps(skus: ['product_id']),
+  )),
 );

Based on learnings, purchaseUpdatedListener and purchaseErrorListener are the correct names across all versions.

⛔ Skipped due to learnings
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/api/index.md:65-69
Timestamp: 2025-08-21T02:25:46.402Z
Learning: When reviewing flutter_inapp_purchase documentation, `purchaseUpdatedListener` and `purchaseErrorListener` are the correct listener names in the public API, not `purchaseUpdated` and `purchaseError`.
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/faq.md:164-172
Timestamp: 2025-08-21T02:01:17.634Z
Learning: When reviewing PRs for flutter_inapp_purchase, focus on the current version being developed rather than versioned documentation files, as those are historical snapshots.
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/api/methods/finish-transaction.md:66-77
Timestamp: 2025-08-20T23:53:15.912Z
Learning: In flutter_inapp_purchase, the correct way to listen to purchase updates is `FlutterInappPurchase.instance.purchaseUpdatedListener.listen`, not `FlutterInappPurchase.purchaseUpdated.listen`.
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 598
File: docs/versioned_docs/version-7.1/getting-started/ios-setup.md:28-30
Timestamp: 2025-12-15T23:02:05.297Z
Learning: In flutter_inapp_purchase PRs, fixing broken links in versioned documentation (docs/versioned_docs/version-*/) is acceptable when the old links reference non-existent files that cause build failures or make the documentation unusable. This is considered necessary maintenance rather than content modification.
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : Use `request` prefix for API functions that depend on event results (e.g., `requestPurchase`, `requestPurchaseWithBuilder`), following OpenIAP terminology
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/api/classes/flutter-inapp-purchase.md:97-123
Timestamp: 2025-08-21T02:09:07.921Z
Learning: For flutter_inapp_purchase PRs, focus on the current version being developed (e.g., 6.4) and ignore versioned documentation files (e.g., version-6.3 folders) as those are historical snapshots that should not be modified.
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/api/overview.md:128-131
Timestamp: 2025-08-21T01:20:28.525Z
Learning: The flutter_inapp_purchase library follows the OpenIAP specification at https://www.openiap.dev/docs/types#request-types for parameter naming conventions. According to hyochan, "skus" is the correct parameter name based on this specification, not "productIds".
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : Use `getAvailablePurchases()` with `PurchaseOptions` instead of deprecated `getPurchaseHistories()` method
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 531
File: docs/versioned_docs/version-6.3/api/overview.md:128-131
Timestamp: 2025-08-21T01:20:28.525Z
Learning: The flutter_inapp_purchase library follows the OpenIAP specification for parameter naming. According to the specification at https://www.openiap.dev/docs/types#request-types, the parameter name should be "skus" (not "productIds") when requesting products, as confirmed by the project maintainer hyochan.
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : Use `Iap` prefix when IAP is not the final suffix (e.g., `IapPurchase`, not `IAPPurchase`)
Learnt from: hyochan
Repo: hyochan/flutter_inapp_purchase PR: 545
File: lib/flutter_inapp_purchase.dart:1665-1665
Timestamp: 2025-09-09T06:04:46.743Z
Learning: In flutter_inapp_purchase project, prefer using iap_err.getCurrentPlatform() in error handling over hardcoded platform constants to ensure accurate runtime platform reporting in error messages and debugging.
Learnt from: CR
Repo: hyochan/flutter_inapp_purchase PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T09:28:12.233Z
Learning: Applies to **/*.dart : Use explicit type parameter for `fetchProducts<T>()` method: specify `<Product>` for InApp products, `<ProductSubscription>` for subscriptions, or `<ProductCommon>` for all products
test/helpers_unit_test.dart (1)

395-502: Excellent test coverage for unified purchase state handling!

The new tests comprehensively validate the iOS purchase state mapping logic:

  • restored string and numeric 3 correctly map to PurchaseState.Purchased
  • Unknown numeric states map to PurchaseState.Unknown
  • failed and deferred states map to PurchaseState.Unknown

This aligns perfectly with the v8.2.0 unified PurchaseState simplification that removes platform-specific state variants.

test/builders_unit_test.dart (1)

1-292: Comprehensive builder test coverage!

The unit tests thoroughly validate the builder API surface:

  • iOS and Android builder functionality for both purchases and subscriptions
  • Type-safe construction with all fields and minimal fields
  • Proper handling of DeveloperBillingOptionParamsAndroid with the new BillingProgramAndroid enum
  • Type conversion and validation
  • Empty builder edge cases

The tests confirm the builder API correctly produces the expected JSON structure and validates all construction paths.

docs/docs/api/methods/request-purchase.md (2)

243-270: Excellent documentation of unified purchase state handling!

The examples correctly demonstrate:

  • Proper listener names (purchaseUpdatedListener and purchaseErrorListener)
  • The new unified PurchaseState enum with Purchased, Pending, and Unknown states
  • Clear switch-based state handling pattern

This aligns perfectly with the v8.2.0 simplification that removes platform-specific state variants.


38-50: Documentation examples are correct as written.

The factory constructors RequestPurchaseProps.inApp() and RequestPurchaseProps.subs() accept apple and google parameters, exactly as shown in the examples. The internal toJson() implementation transforms these to ios and android keys in the JSON representation, which is why the unit test checks for those keys. This design is intentional and correct.

Likely an incorrect or invalid review comment.

Comment on lines +92 to +95
}
```

## Best Practices
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add blank line before section heading.

Markdown linting requires blank lines around fenced code blocks. Add a blank line after line 92 (end of code block) and before the "## Best Practices" heading.

🔎 Proposed fix
   }
}

Best Practices

</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
}
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

94-94: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
In docs/versioned_docs/version-8.1/api/methods/init-connection.md around lines
92 to 95, there is no blank line between the end of the fenced code block and
the "## Best Practices" heading; add a single blank line after the closing ```
at line 92 so the markdown has an empty line separating the fenced code block
and the "## Best Practices" heading to satisfy linting.

Comment on lines +128 to +132
notifyListeners();
}
}
@override
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add blank line before section heading.

Markdown linting requires blank lines around fenced code blocks. Add a blank line after line 128 (end of code block) and before the "## Related Methods" heading.

🔎 Proposed fix
   }
}

Related Methods

</details>


> Committable suggestion skipped: line range outside the PR's diff.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.18.1)</summary>

130-130: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

In docs/versioned_docs/version-8.1/api/methods/init-connection.md around lines
128 to 132, the markdown is missing a blank line between the end of a fenced
code block and the "## Related Methods" heading; add a single empty line after
line 128 (the closing ``` or end of code block) so there is a blank line before
the "## Related Methods" heading to satisfy markdown linting.


</details>

<!-- fingerprinting:phantom:triton:mongoose -->

<!-- This is an auto-generated comment by CodeRabbit -->

- Change FlutterInappPurchase.purchaseUpdated to FlutterInappPurchase.instance.purchaseUpdatedListener
@hyochan hyochan merged commit 14a9876 into main Dec 29, 2025
6 checks passed
@hyochan hyochan deleted the chore/openiap-1.3.11 branch December 29, 2025 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🎯 feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant