From 3a82bea8fe59b53bc937f89decf5bf146fe49745 Mon Sep 17 00:00:00 2001 From: nikunjrCybage Date: Wed, 30 Jul 2025 12:18:13 +0530 Subject: [PATCH 1/5] [in_app_purchase_storekit] Add support for quantity in consumable product purchases (#171570) --- .../StoreKit2/InAppPurchasePlugin+StoreKit2.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift b/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift index 899f7262bda..c559970e8e3 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift +++ b/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift @@ -60,6 +60,9 @@ extension InAppPurchasePlugin: InAppPurchase2API { { purchaseOptions.insert(.appAccountToken(accountTokenUUID)) } + if let quantity = options?.quantity { + purchaseOptions.insert(.quantity(Int(quantity))) + } if #available(iOS 17.4, macOS 14.4, *) { if let promotionalOffer = options?.promotionalOffer { From 338f91ea401a763549ee10e8c439c288b8640e2b Mon Sep 17 00:00:00 2001 From: nikunjrCybage Date: Wed, 30 Jul 2025 12:50:18 +0530 Subject: [PATCH 2/5] [in_app_purchase_storekit] Add tests for Sk2PurchaseParam quantity support --- ...app_purchase_storekit_2_platform_test.dart | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart index b9228ccd6c3..21a3140a285 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart @@ -260,6 +260,41 @@ void main() { expect(lastPurchaseOptions.winBackOfferId, isNull); expect(lastPurchaseOptions.promotionalOffer, isNull); }); + + test('should pass quantity for consumable product with Sk2PurchaseParam', + () async { + final Sk2PurchaseParam purchaseParam = Sk2PurchaseParam( + productDetails: + AppStoreProduct2Details.fromSK2Product(dummyProductWrapper), + quantity: 3, + applicationUserName: 'testUser', + ); + + await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); + + final SK2ProductPurchaseOptionsMessage lastPurchaseOptions = + fakeStoreKit2Platform.lastPurchaseOptions!; + + expect(lastPurchaseOptions.appAccountToken, 'testUser'); + expect(lastPurchaseOptions.quantity, 3); + expect(lastPurchaseOptions.winBackOfferId, isNull); + expect(lastPurchaseOptions.promotionalOffer, isNull); + }); + test('should default to quantity = 1 when not provided in Sk2PurchaseParam', + () async { + final Sk2PurchaseParam purchaseParam = Sk2PurchaseParam( + productDetails: + AppStoreProduct2Details.fromSK2Product(dummyProductWrapper), + applicationUserName: 'testUser', + ); + + await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); + + final SK2ProductPurchaseOptionsMessage lastPurchaseOptions = + fakeStoreKit2Platform.lastPurchaseOptions!; + + expect(lastPurchaseOptions.quantity, 1); + }); }); group('restore purchases', () { From 41688660ce69640ee93f0145ca201b72051f4069 Mon Sep 17 00:00:00 2001 From: nikunjrCybage Date: Thu, 31 Jul 2025 08:52:53 +0530 Subject: [PATCH 3/5] [in_app_purchase_storekit] bump version and update changelog --- .../in_app_purchase/in_app_purchase_storekit/CHANGELOG.md | 4 ++++ .../in_app_purchase/in_app_purchase_storekit/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md index 606fd82a618..09fb7d5ed81 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.4 + +* Added support for specifying quantity in `SK2ProductPurchaseOptions` (consumable purchases on iOS). + ## 0.4.3 * Adds **Introductory Offer Eligibility** support for StoreKit2 diff --git a/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml index b04206ec231..53c27bdebf8 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml @@ -2,7 +2,7 @@ name: in_app_purchase_storekit description: An implementation for the iOS and macOS platforms of the Flutter `in_app_purchase` plugin. This uses the StoreKit Framework. repository: https://github.com/flutter/packages/tree/main/packages/in_app_purchase/in_app_purchase_storekit issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22 -version: 0.4.3 +version: 0.4.4 environment: sdk: ^3.6.0 From 5071a8d7ff230992330c49fa6ad56ca2c21bdffb Mon Sep 17 00:00:00 2001 From: nikunjrCybage Date: Fri, 1 Aug 2025 09:55:40 +0530 Subject: [PATCH 4/5] style(tests): add blank lines between test cases for readability --- .../test/in_app_purchase_storekit_2_platform_test.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart index 21a3140a285..6c197bcb904 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart @@ -280,6 +280,7 @@ void main() { expect(lastPurchaseOptions.winBackOfferId, isNull); expect(lastPurchaseOptions.promotionalOffer, isNull); }); + test('should default to quantity = 1 when not provided in Sk2PurchaseParam', () async { final Sk2PurchaseParam purchaseParam = Sk2PurchaseParam( From 54d0842906b44796c775ca79ae1d2061ed78cd40 Mon Sep 17 00:00:00 2001 From: nikunjrCybage Date: Mon, 4 Aug 2025 09:57:41 +0530 Subject: [PATCH 5/5] [in_app_purchase_storekit] fix dart formatting --- .../test/in_app_purchase_storekit_2_platform_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart index 6c197bcb904..75ad5311e8d 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart @@ -280,7 +280,7 @@ void main() { expect(lastPurchaseOptions.winBackOfferId, isNull); expect(lastPurchaseOptions.promotionalOffer, isNull); }); - + test('should default to quantity = 1 when not provided in Sk2PurchaseParam', () async { final Sk2PurchaseParam purchaseParam = Sk2PurchaseParam(