Skip to content

[in_app_purchase]Fixes StoreKit 2 purchase flow to send cancelled/pending/unverified results to purchaseStream.#10736

Merged
auto-submit[bot] merged 11 commits intoflutter:mainfrom
linchen00:main
Mar 6, 2026
Merged

[in_app_purchase]Fixes StoreKit 2 purchase flow to send cancelled/pending/unverified results to purchaseStream.#10736
auto-submit[bot] merged 11 commits intoflutter:mainfrom
linchen00:main

Conversation

@linchen00
Copy link
Contributor

Fixes StoreKit 2 purchase flow to send cancelled/pending/unverified results to purchaseStream.

flutter/flutter#176757

Pre-Review Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. 2 3

…celled/pending/unverified results to purchaseStream.
Copy link

@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 effectively addresses an issue where certain StoreKit 2 purchase outcomes (cancelled, pending) were not being reported on the purchaseStream. The approach of manually creating and emitting PurchaseDetails for these cases is sound and correctly implemented. The accompanying changes to the fake platform and the new tests are thorough, ensuring the new logic is well-verified. I have one suggestion to improve the maintainability of the new tests by reducing code duplication.

Copy link
Contributor

@LongCatIsLooong LongCatIsLooong left a comment

Choose a reason for hiding this comment

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

Thanks for contributing! The changes make sense but I wonder if it should be implemented in the swift code instead?

// For userCancelled and pending results, manually send update to the stream
// since native side only sends transaction for success cases (both verified and unverified).
// Note: unverified is handled by native side as it's part of .success case in StoreKit.
if (result == SK2ProductPurchaseResult.userCancelled ||
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: prefer using switch statements for the analyzer's exhaustiveness check / feedback.

);

// For userCancelled and pending results, manually send update to the stream
// since native side only sends transaction for success cases (both verified and unverified).
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make more sense to change the native side to send transactions for both cancel / pending cases then?

@LongCatIsLooong
Copy link
Contributor

Hmm I do have some concerns regarding adding this to the purchaseStream, right now it seems purchaseStream only emits verified transactions? So is it possible that some developers might not be checking the status of the transaction / purchase detail and just assume it's verified? Or in most cases existing users of the API should already be checking the status since the Android playstore implementation is already sending the events to the purchase stream?

@linchen00
Copy link
Contributor Author

Hmm I do have some concerns regarding adding this to the purchaseStream, right now it seems purchaseStream only emits verified transactions? So is it possible that some developers might not be checking the status of the transaction / purchase detail and just assume it's verified? Or in most cases existing users of the API should already be checking the status since the Android playstore implementation is already sending the events to the purchase stream?

Thanks for raising this — that’s a valid concern.

While it may look like purchaseStream only emits verified transactions today, consumers are already expected to rely on the status field rather than assume verification. In particular, the Android Play Store implementation already emits non-success states (e.g. pending, canceled) through the same stream.

From that perspective, this change is less about expanding the contract and more about bringing StoreKit 2 in line with the existing cross-platform behavior, avoiding a situation where certain outcomes are silently dropped on iOS.

if you think this needs further adjustment, I’m happy to revise the implementation and move the handling to the Swift side instead.

…send cancelled/pending/unverified results to purchaseStream."

This reverts commit 2cc27d0.
…ll purchase states to purchaseStream:

  - PurchaseStatus.canceled when user cancels purchase
  - PurchaseStatus.pending when purchase is pending (e.g., Ask to Buy)
  - PurchaseStatus.purchased for successful purchases
  Also removed redundant restoring field, replaced with status field.
@linchen00 linchen00 changed the title Fixes StoreKit 2 purchase flow to send cancelled/pending/unverified results to purchaseStream. [in_app_purchase]Fixes StoreKit 2 purchase flow to send cancelled/pending/unverified results to purchaseStream. Jan 12, 2026
@linchen00
Copy link
Contributor Author

linchen00 commented Jan 19, 2026

I’ve already completed it in Swift.

Copy link
Contributor

@LouiseHsu LouiseHsu left a comment

Choose a reason for hiding this comment

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

lgtm! thank you for reimplementing in swift.

linchen00 and others added 2 commits January 22, 2026 09:48
…us` for StoreKit 2 transactions

The `SK2TransactionMessage` type no longer has a `restoring` property. Updated tests to use `status != .restored` and `status == .restored` instead.

This fixes the build error:
    Value of type 'SK2TransactionMessage' has no member 'restoring'
Copy link
Contributor

@LongCatIsLooong LongCatIsLooong left a comment

Choose a reason for hiding this comment

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

Ah I didn't know that we didn't have a dart representation for a pending transaction and thought it was going to be an one-line change. Thank you!

@linchen00
Copy link
Contributor Author

I suspect this may be caused by an intermittent issue with the StoreKit testing environment or its state, which occasionally leads to the check failing. At the moment, I’m not sure how best to handle this.

@stuartmorgan-g stuartmorgan-g added the triage-ios Should be looked at in iOS triage label Feb 3, 2026
m4hmoud added a commit to m4hmoud/packages that referenced this pull request Feb 12, 2026
…ent to purchaseStream

Apply fix from flutter#10736 — StoreKit 2 purchase flow now sends
cancelled, pending, and unverified results to purchaseStream instead of
silently dropping them.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@hellohuanlin
Copy link
Contributor

From triage: you may wanna increase the time-out for network related calls

@basnetjiten
Copy link

Hi @linchen00, any update regarding this one?

@linchen00
Copy link
Contributor Author

Hi @linchen00, any update regarding this one?

I still haven’t figured out what’s causing the ‘check failed’ error — I’m stuck at this point.

@linchen00
Copy link
Contributor Author

From triage: you may wanna increase the time-out for network related calls

I’ve already ruled out network latency as the cause.

@vashworth
Copy link
Contributor

from triage: cc @LouiseHsu can you take a look at the test failure?

@LouiseHsu LouiseHsu added the autosubmit Merge PR when tree becomes green via auto submit App label Mar 5, 2026
@LouiseHsu
Copy link
Contributor

I think the tests are flaky. I could not repro it locally, but when I reran the test last week, it was consistently failing on ci. In the meantime, I've tagged autosubmit on this so this should merge when the tree is green.

Thanks for your patience, @linchen00 💙

@linchen00
Copy link
Contributor Author

我认为这些测试不稳定。我在本地无法复现这个问题,但上周我重新运行测试时,它在持续集成环境中一直失败。同时,我已经为此添加了自动提交的标签,所以当代码树正常时,它应该会被合并。

感谢您的耐心等待。@linchen00💙

Got it, thanks for your hard work.

@auto-submit auto-submit bot merged commit ff15dfd into flutter:main Mar 6, 2026
80 checks passed
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 9, 2026
github-merge-queue bot pushed a commit to flutter/flutter that referenced this pull request Mar 9, 2026
flutter/packages@fe3de64...c717018

2026-03-09 [email protected] [pigeon] Support
javax.annotation.Generated annotation in Kotlin generator
(flutter/packages#10961)
2026-03-09 49699333+dependabot[bot]@users.noreply.github.com
[dependabot]: Bump gradle-wrapper from 8.13 to 9.4.0 in
/packages/path_provider/path_provider/example/android/app
(flutter/packages#11206)
2026-03-09 49699333+dependabot[bot]@users.noreply.github.com
[dependabot]: Bump com.android.tools.build:gradle from 8.9.1 to 9.1.0 in
/packages/shared_preferences/shared_preferences_android/example/android/app
(flutter/packages#11208)
2026-03-09 49699333+dependabot[bot]@users.noreply.github.com
[dependabot]: Bump gradle-wrapper from 8.13 to 9.4.0 in
/packages/path_provider/path_provider_android/example/android/app
(flutter/packages#11207)
2026-03-06 [email protected] [various] Plugin Gradle pre-Kotlin
standardization (flutter/packages#11173)
2026-03-06 [email protected] Updated AGP and KGP to align with
flutter/flutter templates (flutter/packages#10423)
2026-03-06 [email protected] Roll Flutter from
d3dd774 to d182143 (33 revisions) (flutter/packages#11191)
2026-03-06 [email protected]
[google_maps_flutter] Add Advanced Markers support
(flutter/packages#7882)
2026-03-06 [email protected]
[in_app_purchase]Fixes StoreKit 2 purchase flow to send
cancelled/pending/unverified results to purchaseStream.
(flutter/packages#10736)
2026-03-06 [email protected] [flutter_svg] Update README with an
example to scale images (flutter/packages#10547)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC [email protected] on the revert to ensure that a
human
is aware of the problem.

To file a bug in Flutter:
https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
xxxOVALxxx pushed a commit to xxxOVALxxx/flutter that referenced this pull request Mar 10, 2026
…er#183396)

flutter/packages@fe3de64...c717018

2026-03-09 [email protected] [pigeon] Support
javax.annotation.Generated annotation in Kotlin generator
(flutter/packages#10961)
2026-03-09 49699333+dependabot[bot]@users.noreply.github.com
[dependabot]: Bump gradle-wrapper from 8.13 to 9.4.0 in
/packages/path_provider/path_provider/example/android/app
(flutter/packages#11206)
2026-03-09 49699333+dependabot[bot]@users.noreply.github.com
[dependabot]: Bump com.android.tools.build:gradle from 8.9.1 to 9.1.0 in
/packages/shared_preferences/shared_preferences_android/example/android/app
(flutter/packages#11208)
2026-03-09 49699333+dependabot[bot]@users.noreply.github.com
[dependabot]: Bump gradle-wrapper from 8.13 to 9.4.0 in
/packages/path_provider/path_provider_android/example/android/app
(flutter/packages#11207)
2026-03-06 [email protected] [various] Plugin Gradle pre-Kotlin
standardization (flutter/packages#11173)
2026-03-06 [email protected] Updated AGP and KGP to align with
flutter/flutter templates (flutter/packages#10423)
2026-03-06 [email protected] Roll Flutter from
d3dd774 to d182143 (33 revisions) (flutter/packages#11191)
2026-03-06 [email protected]
[google_maps_flutter] Add Advanced Markers support
(flutter/packages#7882)
2026-03-06 [email protected]
[in_app_purchase]Fixes StoreKit 2 purchase flow to send
cancelled/pending/unverified results to purchaseStream.
(flutter/packages#10736)
2026-03-06 [email protected] [flutter_svg] Update README with an
example to scale images (flutter/packages#10547)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC [email protected] on the revert to ensure that a
human
is aware of the problem.

To file a bug in Flutter:
https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App p: in_app_purchase platform-ios platform-macos triage-ios Should be looked at in iOS triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants