diff --git a/packages/in_app_purchase/in_app_purchase/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase/CHANGELOG.md index d1eecbd831e..8d8182da7fa 100644 --- a/packages/in_app_purchase/in_app_purchase/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.27/Dart 3.6. +* Updates minimum supported SDK version to Flutter 3.29/Dart 3.7. ## 3.2.3 * Updates minimum `in_app_purchase_storekit` version to 0.4.0. diff --git a/packages/in_app_purchase/in_app_purchase/example/lib/main.dart b/packages/in_app_purchase/in_app_purchase/example/lib/main.dart index 1662b97989b..c39cc869e99 100644 --- a/packages/in_app_purchase/in_app_purchase/example/lib/main.dart +++ b/packages/in_app_purchase/in_app_purchase/example/lib/main.dart @@ -57,14 +57,17 @@ class _MyAppState extends State<_MyApp> { void initState() { final Stream> purchaseUpdated = _inAppPurchase.purchaseStream; - _subscription = - purchaseUpdated.listen((List purchaseDetailsList) { - _listenToPurchaseUpdated(purchaseDetailsList); - }, onDone: () { - _subscription.cancel(); - }, onError: (Object error) { - // handle error here. - }); + _subscription = purchaseUpdated.listen( + (List purchaseDetailsList) { + _listenToPurchaseUpdated(purchaseDetailsList); + }, + onDone: () { + _subscription.cancel(); + }, + onError: (Object error) { + // handle error here. + }, + ); initStoreInfo(); super.initState(); } @@ -91,8 +94,8 @@ class _MyAppState extends State<_MyApp> { await iosPlatformAddition.setDelegate(ExamplePaymentQueueDelegate()); } - final ProductDetailsResponse productDetailResponse = - await _inAppPurchase.queryProductDetails(_kProductIds.toSet()); + final ProductDetailsResponse productDetailResponse = await _inAppPurchase + .queryProductDetails(_kProductIds.toSet()); if (productDetailResponse.error != null) { setState(() { _queryProductError = productDetailResponse.error!.message; @@ -159,9 +162,7 @@ class _MyAppState extends State<_MyApp> { ), ); } else { - stack.add(Center( - child: Text(_queryProductError!), - )); + stack.add(Center(child: Text(_queryProductError!))); } if (_purchasePending) { stack.add( @@ -171,9 +172,7 @@ class _MyAppState extends State<_MyApp> { opacity: 0.3, child: ModalBarrier(dismissible: false, color: Colors.grey), ), - Center( - child: CircularProgressIndicator(), - ), + Center(child: CircularProgressIndicator()), ], ), ); @@ -181,12 +180,8 @@ class _MyAppState extends State<_MyApp> { return MaterialApp( home: Scaffold( - appBar: AppBar( - title: const Text('IAP Example'), - ), - body: Stack( - children: stack, - ), + appBar: AppBar(title: const Text('IAP Example')), + body: Stack(children: stack), ), ); } @@ -196,12 +191,14 @@ class _MyAppState extends State<_MyApp> { return const Card(child: ListTile(title: Text('Trying to connect...'))); } final Widget storeHeader = ListTile( - leading: Icon(_isAvailable ? Icons.check : Icons.block, - color: _isAvailable - ? Colors.green - : ThemeData.light().colorScheme.error), - title: - Text('The store is ${_isAvailable ? 'available' : 'unavailable'}.'), + leading: Icon( + _isAvailable ? Icons.check : Icons.block, + color: + _isAvailable ? Colors.green : ThemeData.light().colorScheme.error, + ), + title: Text( + 'The store is ${_isAvailable ? 'available' : 'unavailable'}.', + ), ); final List children = [storeHeader]; @@ -209,10 +206,13 @@ class _MyAppState extends State<_MyApp> { children.addAll([ const Divider(), ListTile( - title: Text('Not connected', - style: TextStyle(color: ThemeData.light().colorScheme.error)), + title: Text( + 'Not connected', + style: TextStyle(color: ThemeData.light().colorScheme.error), + ), subtitle: const Text( - 'Unable to connect to the payments processor. Has this app been configured correctly? See the example README for instructions.'), + 'Unable to connect to the payments processor. Has this app been configured correctly? See the example README for instructions.', + ), ), ]); } @@ -222,9 +222,11 @@ class _MyAppState extends State<_MyApp> { Card _buildProductList() { if (_loading) { return const Card( - child: ListTile( - leading: CircularProgressIndicator(), - title: Text('Fetching products...'))); + child: ListTile( + leading: CircularProgressIndicator(), + title: Text('Fetching products...'), + ), + ); } if (!_isAvailable) { return const Card(); @@ -232,11 +234,17 @@ class _MyAppState extends State<_MyApp> { const ListTile productHeader = ListTile(title: Text('Products for Sale')); final List productList = []; if (_notFoundIds.isNotEmpty) { - productList.add(ListTile( - title: Text('[${_notFoundIds.join(", ")}] not found', - style: TextStyle(color: ThemeData.light().colorScheme.error)), + productList.add( + ListTile( + title: Text( + '[${_notFoundIds.join(", ")}] not found', + style: TextStyle(color: ThemeData.light().colorScheme.error), + ), subtitle: const Text( - 'This app needs special configuration to run. Please see example/README.md for instructions.'))); + 'This app needs special configuration to run. Please see example/README.md for instructions.', + ), + ), + ); } // This loading previous purchases code is just a demo. Please do not use this as it is. @@ -244,113 +252,124 @@ class _MyAppState extends State<_MyApp> { // We recommend that you use your own server to verify the purchase data. final Map purchases = Map.fromEntries( - _purchases.map((PurchaseDetails purchase) { - if (purchase.pendingCompletePurchase) { - _inAppPurchase.completePurchase(purchase); - } - return MapEntry(purchase.productID, purchase); - })); - productList.addAll(_products.map( - (ProductDetails productDetails) { + _purchases.map((PurchaseDetails purchase) { + if (purchase.pendingCompletePurchase) { + _inAppPurchase.completePurchase(purchase); + } + return MapEntry( + purchase.productID, + purchase, + ); + }), + ); + productList.addAll( + _products.map((ProductDetails productDetails) { final PurchaseDetails? previousPurchase = purchases[productDetails.id]; return ListTile( - title: Text( - productDetails.title, - ), - subtitle: Text( - productDetails.description, - ), - trailing: previousPurchase != null && Platform.isIOS - ? IconButton( - onPressed: () => confirmPriceChange(context), - icon: const Icon(Icons.upgrade)) - : TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.green[800], - foregroundColor: Colors.white, - ), - onPressed: () { - late PurchaseParam purchaseParam; - - if (Platform.isAndroid) { - // NOTE: If you are making a subscription purchase/upgrade/downgrade, we recommend you to - // verify the latest status of you your subscription by using server side receipt validation - // and update the UI accordingly. The subscription purchase status shown - // inside the app may not be accurate. - final GooglePlayPurchaseDetails? oldSubscription = - _getOldSubscription(productDetails, purchases); - - purchaseParam = GooglePlayPurchaseParam( + title: Text(productDetails.title), + subtitle: Text(productDetails.description), + trailing: + previousPurchase != null && Platform.isIOS + ? IconButton( + onPressed: () => confirmPriceChange(context), + icon: const Icon(Icons.upgrade), + ) + : TextButton( + style: TextButton.styleFrom( + backgroundColor: Colors.green[800], + foregroundColor: Colors.white, + ), + onPressed: () { + late PurchaseParam purchaseParam; + + if (Platform.isAndroid) { + // NOTE: If you are making a subscription purchase/upgrade/downgrade, we recommend you to + // verify the latest status of you your subscription by using server side receipt validation + // and update the UI accordingly. The subscription purchase status shown + // inside the app may not be accurate. + final GooglePlayPurchaseDetails? oldSubscription = + _getOldSubscription(productDetails, purchases); + + purchaseParam = GooglePlayPurchaseParam( productDetails: productDetails, - changeSubscriptionParam: (oldSubscription != null) - ? ChangeSubscriptionParam( - oldPurchaseDetails: oldSubscription, - replacementMode: - ReplacementMode.withTimeProration, - ) - : null); - } else { - purchaseParam = PurchaseParam( - productDetails: productDetails, - ); - } - - if (productDetails.id == _kConsumableId) { - _inAppPurchase.buyConsumable( + changeSubscriptionParam: + (oldSubscription != null) + ? ChangeSubscriptionParam( + oldPurchaseDetails: oldSubscription, + replacementMode: + ReplacementMode.withTimeProration, + ) + : null, + ); + } else { + purchaseParam = PurchaseParam( + productDetails: productDetails, + ); + } + + if (productDetails.id == _kConsumableId) { + _inAppPurchase.buyConsumable( + purchaseParam: purchaseParam, + autoConsume: _kAutoConsume, + ); + } else { + _inAppPurchase.buyNonConsumable( purchaseParam: purchaseParam, - autoConsume: _kAutoConsume); - } else { - _inAppPurchase.buyNonConsumable( - purchaseParam: purchaseParam); - } - }, - child: Text(productDetails.price), - ), + ); + } + }, + child: Text(productDetails.price), + ), ); - }, - )); + }), + ); return Card( - child: Column( - children: [productHeader, const Divider()] + productList)); + child: Column( + children: [productHeader, const Divider()] + productList, + ), + ); } Card _buildConsumableBox() { if (_loading) { return const Card( - child: ListTile( - leading: CircularProgressIndicator(), - title: Text('Fetching consumables...'))); + child: ListTile( + leading: CircularProgressIndicator(), + title: Text('Fetching consumables...'), + ), + ); } if (!_isAvailable || _notFoundIds.contains(_kConsumableId)) { return const Card(); } - const ListTile consumableHeader = - ListTile(title: Text('Purchased consumables')); - final List tokens = _consumables.map((String id) { - return GridTile( - child: IconButton( - icon: const Icon( - Icons.stars, - size: 42.0, - color: Colors.orange, - ), - splashColor: Colors.yellowAccent, - onPressed: () => consume(id), - ), - ); - }).toList(); + const ListTile consumableHeader = ListTile( + title: Text('Purchased consumables'), + ); + final List tokens = + _consumables.map((String id) { + return GridTile( + child: IconButton( + icon: const Icon(Icons.stars, size: 42.0, color: Colors.orange), + splashColor: Colors.yellowAccent, + onPressed: () => consume(id), + ), + ); + }).toList(); return Card( - child: Column(children: [ - consumableHeader, - const Divider(), - GridView.count( - crossAxisCount: 5, - shrinkWrap: true, - padding: const EdgeInsets.all(16.0), - children: tokens, - ) - ])); + child: Column( + children: [ + consumableHeader, + const Divider(), + GridView.count( + crossAxisCount: 5, + shrinkWrap: true, + padding: const EdgeInsets.all(16.0), + children: tokens, + ), + ], + ), + ); } Widget _buildRestoreButton() { @@ -424,7 +443,8 @@ class _MyAppState extends State<_MyApp> { } Future _listenToPurchaseUpdated( - List purchaseDetailsList) async { + List purchaseDetailsList, + ) async { for (final PurchaseDetails purchaseDetails in purchaseDetailsList) { if (purchaseDetails.status == PurchaseStatus.pending) { showPendingUI(); @@ -444,8 +464,10 @@ class _MyAppState extends State<_MyApp> { if (Platform.isAndroid) { if (!_kAutoConsume && purchaseDetails.productID == _kConsumableId) { final InAppPurchaseAndroidPlatformAddition androidAddition = - _inAppPurchase.getPlatformAddition< - InAppPurchaseAndroidPlatformAddition>(); + _inAppPurchase + .getPlatformAddition< + InAppPurchaseAndroidPlatformAddition + >(); await androidAddition.consumePurchase(purchaseDetails); } } @@ -470,7 +492,9 @@ class _MyAppState extends State<_MyApp> { } GooglePlayPurchaseDetails? _getOldSubscription( - ProductDetails productDetails, Map purchases) { + ProductDetails productDetails, + Map purchases, + ) { // This is just to demonstrate a subscription upgrade or downgrade. // This method assumes that you have only 2 subscriptions under a group, 'subscription_silver' & 'subscription_gold'. // The 'subscription_silver' subscription can be upgraded to 'subscription_gold' and @@ -500,7 +524,9 @@ class _MyAppState extends State<_MyApp> { class ExamplePaymentQueueDelegate implements SKPaymentQueueDelegateWrapper { @override bool shouldContinueTransaction( - SKPaymentTransactionWrapper transaction, SKStorefrontWrapper storefront) { + SKPaymentTransactionWrapper transaction, + SKStorefrontWrapper storefront, + ) { return true; } diff --git a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml index 129f412fa6f..3c17c3a108c 100644 --- a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the in_app_purchase plugin. publish_to: none environment: - sdk: ^3.6.0 - flutter: ">=3.27.0" + sdk: ^3.7.0 + flutter: ">=3.29.0" dependencies: flutter: diff --git a/packages/in_app_purchase/in_app_purchase/lib/in_app_purchase.dart b/packages/in_app_purchase/in_app_purchase/lib/in_app_purchase.dart index 1cb3beda4e1..23d553b5e9c 100644 --- a/packages/in_app_purchase/in_app_purchase/lib/in_app_purchase.dart +++ b/packages/in_app_purchase/in_app_purchase/lib/in_app_purchase.dart @@ -159,11 +159,10 @@ class InAppPurchase implements InAppPurchasePlatformAdditionProvider { Future buyConsumable({ required PurchaseParam purchaseParam, bool autoConsume = true, - }) => - InAppPurchasePlatform.instance.buyConsumable( - purchaseParam: purchaseParam, - autoConsume: autoConsume, - ); + }) => InAppPurchasePlatform.instance.buyConsumable( + purchaseParam: purchaseParam, + autoConsume: autoConsume, + ); /// Mark that purchased content has been delivered to the user. /// diff --git a/packages/in_app_purchase/in_app_purchase/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/pubspec.yaml index b215e16a73d..098173dc138 100644 --- a/packages/in_app_purchase/in_app_purchase/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 3.2.3 environment: - sdk: ^3.6.0 - flutter: ">=3.27.0" + sdk: ^3.7.0 + flutter: ">=3.29.0" flutter: plugin: diff --git a/packages/in_app_purchase/in_app_purchase/test/in_app_purchase_test.dart b/packages/in_app_purchase/in_app_purchase/test/in_app_purchase_test.dart index c4ed8198899..1f244cca44d 100644 --- a/packages/in_app_purchase/in_app_purchase/test/in_app_purchase_test.dart +++ b/packages/in_app_purchase/in_app_purchase/test/in_app_purchase_test.dart @@ -72,8 +72,8 @@ void main() { }); test('queryProductDetails', () async { - final ProductDetailsResponse response = - await inAppPurchase.queryProductDetails({}); + final ProductDetailsResponse response = await inAppPurchase + .queryProductDetails({}); expect(response.notFoundIDs.isEmpty, true); expect(response.productDetails.isEmpty, true); expect(fakePlatform.log, [ @@ -83,9 +83,7 @@ void main() { test('buyNonConsumable', () async { final bool result = await inAppPurchase.buyNonConsumable( - purchaseParam: PurchaseParam( - productDetails: productDetails, - ), + purchaseParam: PurchaseParam(productDetails: productDetails), ); expect(result, true); @@ -95,24 +93,29 @@ void main() { }); test('buyConsumable', () async { - final PurchaseParam purchaseParam = - PurchaseParam(productDetails: productDetails); + final PurchaseParam purchaseParam = PurchaseParam( + productDetails: productDetails, + ); final bool result = await inAppPurchase.buyConsumable( purchaseParam: purchaseParam, ); expect(result, true); expect(fakePlatform.log, [ - isMethodCall('buyConsumable', arguments: { - 'purchaseParam': purchaseParam, - 'autoConsume': true, - }), + isMethodCall( + 'buyConsumable', + arguments: { + 'purchaseParam': purchaseParam, + 'autoConsume': true, + }, + ), ]); }); test('buyConsumable with autoConsume=false', () async { - final PurchaseParam purchaseParam = - PurchaseParam(productDetails: productDetails); + final PurchaseParam purchaseParam = PurchaseParam( + productDetails: productDetails, + ); final bool result = await inAppPurchase.buyConsumable( purchaseParam: purchaseParam, autoConsume: false, @@ -120,10 +123,13 @@ void main() { expect(result, true); expect(fakePlatform.log, [ - isMethodCall('buyConsumable', arguments: { - 'purchaseParam': purchaseParam, - 'autoConsume': false, - }), + isMethodCall( + 'buyConsumable', + arguments: { + 'purchaseParam': purchaseParam, + 'autoConsume': false, + }, + ), ]); }); @@ -165,10 +171,12 @@ class MockInAppPurchasePlatform extends Fake @override Future queryProductDetails(Set identifiers) { log.add(const MethodCall('queryProductDetails')); - return Future.value(ProductDetailsResponse( - productDetails: [], - notFoundIDs: [], - )); + return Future.value( + ProductDetailsResponse( + productDetails: [], + notFoundIDs: [], + ), + ); } @override @@ -182,10 +190,12 @@ class MockInAppPurchasePlatform extends Fake required PurchaseParam purchaseParam, bool autoConsume = true, }) { - log.add(MethodCall('buyConsumable', { - 'purchaseParam': purchaseParam, - 'autoConsume': autoConsume, - })); + log.add( + MethodCall('buyConsumable', { + 'purchaseParam': purchaseParam, + 'autoConsume': autoConsume, + }), + ); return Future.value(true); } diff --git a/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md index ea98e542059..94e9c3ac1f2 100644 --- a/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.29/Dart 3.7. + ## 0.4.0+3 * Updates kotlin version to 2.2.0 to enable gradle 8.11 support. diff --git a/packages/in_app_purchase/in_app_purchase_android/example/integration_test/in_app_purchase_test.dart b/packages/in_app_purchase/in_app_purchase_android/example/integration_test/in_app_purchase_test.dart index c528c7f87a9..05285b884fa 100644 --- a/packages/in_app_purchase/in_app_purchase_android/example/integration_test/in_app_purchase_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/example/integration_test/in_app_purchase_test.dart @@ -16,8 +16,9 @@ void main() { InAppPurchaseAndroidPlatform.registerPlatform(); }); - testWidgets('Can create InAppPurchaseAndroid instance', - (WidgetTester tester) async { + testWidgets('Can create InAppPurchaseAndroid instance', ( + WidgetTester tester, + ) async { final InAppPurchasePlatform androidPlatform = InAppPurchasePlatform.instance; expect(androidPlatform, isNotNull); @@ -28,11 +29,14 @@ void main() { setUpAll(() { billingClient = BillingClient( - (PurchasesResultWrapper _) {}, (UserChoiceDetailsWrapper _) {}); + (PurchasesResultWrapper _) {}, + (UserChoiceDetailsWrapper _) {}, + ); }); - testWidgets('BillingClient.acknowledgePurchase', - (WidgetTester tester) async { + testWidgets('BillingClient.acknowledgePurchase', ( + WidgetTester tester, + ) async { try { await billingClient.acknowledgePurchase('purchaseToken'); } on MissingPluginException { @@ -56,11 +60,13 @@ void main() { } }); - testWidgets('BillingClient.isFeatureSupported', - (WidgetTester tester) async { + testWidgets('BillingClient.isFeatureSupported', ( + WidgetTester tester, + ) async { try { - await billingClient - .isFeatureSupported(BillingClientFeature.productDetails); + await billingClient.isFeatureSupported( + BillingClientFeature.productDetails, + ); } on MissingPluginException { fail('Method channel is not setup correctly'); } @@ -87,11 +93,13 @@ void main() { } }); - testWidgets('BillingClient.queryProductDetails', - (WidgetTester tester) async { + testWidgets('BillingClient.queryProductDetails', ( + WidgetTester tester, + ) async { try { - await billingClient - .queryProductDetails(productList: []); + await billingClient.queryProductDetails( + productList: [], + ); } on MissingPluginException { fail('Method channel is not setup correctly'); } on PlatformException catch (e) { @@ -103,8 +111,9 @@ void main() { } }); - testWidgets('BillingClient.queryPurchaseHistory', - (WidgetTester tester) async { + testWidgets('BillingClient.queryPurchaseHistory', ( + WidgetTester tester, + ) async { try { // Intentional use of a deprecated method to make sure it still works. // ignore: deprecated_member_use @@ -125,7 +134,8 @@ void main() { testWidgets('BillingClient.startConnection', (WidgetTester tester) async { try { await billingClient.startConnection( - onBillingServiceDisconnected: () {}); + onBillingServiceDisconnected: () {}, + ); } on MissingPluginException { fail('Method channel is not setup correctly'); } diff --git a/packages/in_app_purchase/in_app_purchase_android/example/lib/main.dart b/packages/in_app_purchase/in_app_purchase_android/example/lib/main.dart index 04e8e23d262..bace68927cc 100644 --- a/packages/in_app_purchase/in_app_purchase_android/example/lib/main.dart +++ b/packages/in_app_purchase/in_app_purchase_android/example/lib/main.dart @@ -63,28 +63,34 @@ class _MyAppState extends State<_MyApp> { void initState() { final Stream> purchaseUpdated = _inAppPurchasePlatform.purchaseStream; - _subscription = - purchaseUpdated.listen((List purchaseDetailsList) { - _listenToPurchaseUpdated(purchaseDetailsList); - }, onDone: () { - _subscription.cancel(); - }, onError: (Object error) { - // handle error here. - }); + _subscription = purchaseUpdated.listen( + (List purchaseDetailsList) { + _listenToPurchaseUpdated(purchaseDetailsList); + }, + onDone: () { + _subscription.cancel(); + }, + onError: (Object error) { + // handle error here. + }, + ); initStoreInfo(); final InAppPurchaseAndroidPlatformAddition addition = InAppPurchasePlatformAddition.instance! as InAppPurchaseAndroidPlatformAddition; final Stream userChoiceDetailsUpdated = addition.userChoiceDetailsStream; - _userChoiceDetailsStream = - userChoiceDetailsUpdated.listen((GooglePlayUserChoiceDetails details) { - deliverUserChoiceDetails(details); - }, onDone: () { - _userChoiceDetailsStream.cancel(); - }, onError: (Object error) { - // handle error here. - }); + _userChoiceDetailsStream = userChoiceDetailsUpdated.listen( + (GooglePlayUserChoiceDetails details) { + deliverUserChoiceDetails(details); + }, + onDone: () { + _userChoiceDetailsStream.cancel(); + }, + onError: (Object error) { + // handle error here. + }, + ); super.initState(); } @@ -171,9 +177,7 @@ class _MyAppState extends State<_MyApp> { ), ); } else { - stack.add(Center( - child: Text(_queryProductError!), - )); + stack.add(Center(child: Text(_queryProductError!))); } if (_purchasePending) { stack.add( @@ -183,9 +187,7 @@ class _MyAppState extends State<_MyApp> { opacity: 0.3, child: ModalBarrier(dismissible: false, color: Colors.grey), ), - Center( - child: CircularProgressIndicator(), - ), + Center(child: CircularProgressIndicator()), ], ), ); @@ -193,12 +195,8 @@ class _MyAppState extends State<_MyApp> { return MaterialApp( home: Scaffold( - appBar: AppBar( - title: const Text('IAP Example'), - ), - body: Stack( - children: stack, - ), + appBar: AppBar(title: const Text('IAP Example')), + body: Stack(children: stack), ), ); } @@ -208,12 +206,14 @@ class _MyAppState extends State<_MyApp> { return const Card(child: ListTile(title: Text('Trying to connect...'))); } final Widget storeHeader = ListTile( - leading: Icon(_isAvailable ? Icons.check : Icons.block, - color: _isAvailable - ? Colors.green - : ThemeData.light().colorScheme.error), - title: - Text('The store is ${_isAvailable ? 'available' : 'unavailable'}.'), + leading: Icon( + _isAvailable ? Icons.check : Icons.block, + color: + _isAvailable ? Colors.green : ThemeData.light().colorScheme.error, + ), + title: Text( + 'The store is ${_isAvailable ? 'available' : 'unavailable'}.', + ), ); final List children = [storeHeader]; @@ -221,10 +221,13 @@ class _MyAppState extends State<_MyApp> { children.addAll([ const Divider(), ListTile( - title: Text('Not connected', - style: TextStyle(color: ThemeData.light().colorScheme.error)), + title: Text( + 'Not connected', + style: TextStyle(color: ThemeData.light().colorScheme.error), + ), subtitle: const Text( - 'Unable to connect to the payments processor. Has this app been configured correctly? See the example README for instructions.'), + 'Unable to connect to the payments processor. Has this app been configured correctly? See the example README for instructions.', + ), ), ]); } @@ -234,100 +237,142 @@ class _MyAppState extends State<_MyApp> { Card _buildFetchButtons() { const ListTile header = ListTile(title: Text('AlternativeBilling Info')); final List entries = []; - entries.add(ListTile( - title: Text('User Country Code', - style: TextStyle(color: ThemeData.light().colorScheme.primary)), - subtitle: Text(_countryCode))); - entries.add(ListTile( - title: Text('isAlternativeBillingOnlyAvailable response code', - style: TextStyle(color: ThemeData.light().colorScheme.primary)), - subtitle: Text(_isAlternativeBillingOnlyAvailableResponseCode))); - entries.add(ListTile( - title: Text('showAlternativeBillingOnlyDialog response code', - style: TextStyle(color: ThemeData.light().colorScheme.primary)), - subtitle: Text(_showAlternativeBillingOnlyDialogResponseCode))); - entries.add(ListTile( - title: Text('createAlternativeBillingOnlyReportingDetails contents', - style: TextStyle(color: ThemeData.light().colorScheme.primary)), - subtitle: Text(_alternativeBillingOnlyReportingDetailsToken))); + entries.add( + ListTile( + title: Text( + 'User Country Code', + style: TextStyle(color: ThemeData.light().colorScheme.primary), + ), + subtitle: Text(_countryCode), + ), + ); + entries.add( + ListTile( + title: Text( + 'isAlternativeBillingOnlyAvailable response code', + style: TextStyle(color: ThemeData.light().colorScheme.primary), + ), + subtitle: Text(_isAlternativeBillingOnlyAvailableResponseCode), + ), + ); + entries.add( + ListTile( + title: Text( + 'showAlternativeBillingOnlyDialog response code', + style: TextStyle(color: ThemeData.light().colorScheme.primary), + ), + subtitle: Text(_showAlternativeBillingOnlyDialogResponseCode), + ), + ); + entries.add( + ListTile( + title: Text( + 'createAlternativeBillingOnlyReportingDetails contents', + style: TextStyle(color: ThemeData.light().colorScheme.primary), + ), + subtitle: Text(_alternativeBillingOnlyReportingDetailsToken), + ), + ); final List buttons = []; - buttons.add(ListTile( - title: TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.green[800], - foregroundColor: Colors.white, + buttons.add( + ListTile( + title: TextButton( + style: TextButton.styleFrom( + backgroundColor: Colors.green[800], + foregroundColor: Colors.white, + ), + onPressed: () { + unawaited(deliverCountryCode(_inAppPurchasePlatform.countryCode())); + }, + child: const Text('Fetch Country Code'), ), - onPressed: () { - unawaited(deliverCountryCode(_inAppPurchasePlatform.countryCode())); - }, - child: const Text('Fetch Country Code'), ), - )); - buttons.add(ListTile( - title: TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.green[800], - foregroundColor: Colors.white, + ); + buttons.add( + ListTile( + title: TextButton( + style: TextButton.styleFrom( + backgroundColor: Colors.green[800], + foregroundColor: Colors.white, + ), + onPressed: () { + final InAppPurchaseAndroidPlatformAddition addition = + InAppPurchasePlatformAddition.instance! + as InAppPurchaseAndroidPlatformAddition; + unawaited( + deliverIsAlternativeBillingOnlyAvailable( + addition.isAlternativeBillingOnlyAvailable(), + ), + ); + }, + child: const Text('isAlternativeBillingOnlyAvailable'), ), - onPressed: () { - final InAppPurchaseAndroidPlatformAddition addition = - InAppPurchasePlatformAddition.instance! - as InAppPurchaseAndroidPlatformAddition; - unawaited(deliverIsAlternativeBillingOnlyAvailable( - addition.isAlternativeBillingOnlyAvailable())); - }, - child: const Text('isAlternativeBillingOnlyAvailable'), ), - )); - buttons.add(ListTile( - title: TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.green[800], - foregroundColor: Colors.white, + ); + buttons.add( + ListTile( + title: TextButton( + style: TextButton.styleFrom( + backgroundColor: Colors.green[800], + foregroundColor: Colors.white, + ), + onPressed: () { + final InAppPurchaseAndroidPlatformAddition addition = + InAppPurchasePlatformAddition.instance! + as InAppPurchaseAndroidPlatformAddition; + unawaited( + deliverShowAlternativeBillingOnlyInformationDialogResult( + addition.showAlternativeBillingOnlyInformationDialog(), + ), + ); + }, + child: const Text('showAlternativeBillingOnlyInformationDialog'), ), - onPressed: () { - final InAppPurchaseAndroidPlatformAddition addition = - InAppPurchasePlatformAddition.instance! - as InAppPurchaseAndroidPlatformAddition; - unawaited(deliverShowAlternativeBillingOnlyInformationDialogResult( - addition.showAlternativeBillingOnlyInformationDialog())); - }, - child: const Text('showAlternativeBillingOnlyInformationDialog'), ), - )); - buttons.add(ListTile( - title: TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.green[800], - foregroundColor: Colors.white, + ); + buttons.add( + ListTile( + title: TextButton( + style: TextButton.styleFrom( + backgroundColor: Colors.green[800], + foregroundColor: Colors.white, + ), + onPressed: () { + final InAppPurchaseAndroidPlatformAddition addition = + InAppPurchasePlatformAddition.instance! + as InAppPurchaseAndroidPlatformAddition; + unawaited( + addition.setBillingChoice( + BillingChoiceMode.alternativeBillingOnly, + ), + ); + }, + child: const Text('setBillingChoice alternativeBillingOnly'), ), - onPressed: () { - final InAppPurchaseAndroidPlatformAddition addition = - InAppPurchasePlatformAddition.instance! - as InAppPurchaseAndroidPlatformAddition; - unawaited(addition - .setBillingChoice(BillingChoiceMode.alternativeBillingOnly)); - }, - child: const Text('setBillingChoice alternativeBillingOnly'), ), - )); - buttons.add(ListTile( - title: TextButton( - style: TextButton.styleFrom( - backgroundColor: Colors.green[800], - foregroundColor: Colors.white, + ); + buttons.add( + ListTile( + title: TextButton( + style: TextButton.styleFrom( + backgroundColor: Colors.green[800], + foregroundColor: Colors.white, + ), + onPressed: () { + final InAppPurchaseAndroidPlatformAddition addition = + InAppPurchasePlatformAddition.instance! + as InAppPurchaseAndroidPlatformAddition; + unawaited( + deliverCreateAlternativeBillingOnlyReportingDetails( + addition.createAlternativeBillingOnlyReportingDetails(), + ), + ); + }, + child: const Text('createAlternativeBillingOnlyReportingDetails'), ), - onPressed: () { - final InAppPurchaseAndroidPlatformAddition addition = - InAppPurchasePlatformAddition.instance! - as InAppPurchaseAndroidPlatformAddition; - unawaited(deliverCreateAlternativeBillingOnlyReportingDetails( - addition.createAlternativeBillingOnlyReportingDetails())); - }, - child: const Text('createAlternativeBillingOnlyReportingDetails'), ), - )); + ); return Card( child: Column( children: [ @@ -345,28 +390,29 @@ class _MyAppState extends State<_MyApp> { const ListTile header = ListTile(title: Text('UserChoiceDetails')); final List entries = []; for (final String item in _userChoiceDetailsList) { - entries.add(ListTile( - title: Text(item, - style: TextStyle(color: ThemeData.light().colorScheme.primary)), - subtitle: Text(_countryCode))); + entries.add( + ListTile( + title: Text( + item, + style: TextStyle(color: ThemeData.light().colorScheme.primary), + ), + subtitle: Text(_countryCode), + ), + ); } return Card( - child: Column( - children: [ - header, - const Divider(), - ...entries, - ], - ), + child: Column(children: [header, const Divider(), ...entries]), ); } Card _buildProductList() { if (_loading) { return const Card( - child: ListTile( - leading: CircularProgressIndicator(), - title: Text('Fetching products...'))); + child: ListTile( + leading: CircularProgressIndicator(), + title: Text('Fetching products...'), + ), + ); } if (!_isAvailable) { return const Card(); @@ -374,11 +420,17 @@ class _MyAppState extends State<_MyApp> { const ListTile productHeader = ListTile(title: Text('Products for Sale')); final List productList = []; if (_notFoundIds.isNotEmpty) { - productList.add(ListTile( - title: Text('[${_notFoundIds.join(", ")}] not found', - style: TextStyle(color: ThemeData.light().colorScheme.error)), + productList.add( + ListTile( + title: Text( + '[${_notFoundIds.join(", ")}] not found', + style: TextStyle(color: ThemeData.light().colorScheme.error), + ), subtitle: const Text( - 'This app needs special configuration to run. Please see example/README.md for instructions.'))); + 'This app needs special configuration to run. Please see example/README.md for instructions.', + ), + ), + ); } // This loading previous purchases code is just a demo. Please do not use this as it is. @@ -386,25 +438,26 @@ class _MyAppState extends State<_MyApp> { // We recommend that you use your own server to verify the purchase data. final Map purchases = Map.fromEntries( - _purchases.map((PurchaseDetails purchase) { - if (purchase.pendingCompletePurchase) { - _inAppPurchasePlatform.completePurchase(purchase); - } - return MapEntry(purchase.productID, purchase); - })); - productList.addAll(_products.map( - (ProductDetails productDetails) { + _purchases.map((PurchaseDetails purchase) { + if (purchase.pendingCompletePurchase) { + _inAppPurchasePlatform.completePurchase(purchase); + } + return MapEntry( + purchase.productID, + purchase, + ); + }), + ); + productList.addAll( + _products.map((ProductDetails productDetails) { final PurchaseDetails? previousPurchase = purchases[productDetails.id]; return ListTile( - title: Text( - productDetails.title, - ), - subtitle: Text( - productDetails.description, - ), - trailing: previousPurchase != null - ? const SizedBox.shrink() - : TextButton( + title: Text(productDetails.title), + subtitle: Text(productDetails.description), + trailing: + previousPurchase != null + ? const SizedBox.shrink() + : TextButton( style: TextButton.styleFrom( backgroundColor: Colors.green[800], foregroundColor: Colors.white, @@ -416,73 +469,85 @@ class _MyAppState extends State<_MyApp> { // inside the app may not be accurate. final GooglePlayPurchaseDetails? oldSubscription = _getOldSubscription( - productDetails as GooglePlayProductDetails, - purchases); + productDetails as GooglePlayProductDetails, + purchases, + ); final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( - productDetails: productDetails, - changeSubscriptionParam: oldSubscription != null - ? ChangeSubscriptionParam( + productDetails: productDetails, + changeSubscriptionParam: + oldSubscription != null + ? ChangeSubscriptionParam( oldPurchaseDetails: oldSubscription, replacementMode: - ReplacementMode.withTimeProration) - : null); + ReplacementMode.withTimeProration, + ) + : null, + ); if (productDetails.id == _kConsumableId) { _inAppPurchasePlatform.buyConsumable( - purchaseParam: purchaseParam, - // ignore: avoid_redundant_argument_values - autoConsume: _kAutoConsume); + purchaseParam: purchaseParam, + // ignore: avoid_redundant_argument_values + autoConsume: _kAutoConsume, + ); } else { _inAppPurchasePlatform.buyNonConsumable( - purchaseParam: purchaseParam); + purchaseParam: purchaseParam, + ); } }, child: Text(productDetails.price), - )); - }, - )); + ), + ); + }), + ); return Card( - child: Column( - children: [productHeader, const Divider()] + productList)); + child: Column( + children: [productHeader, const Divider()] + productList, + ), + ); } Card _buildConsumableBox() { if (_loading) { return const Card( - child: ListTile( - leading: CircularProgressIndicator(), - title: Text('Fetching consumables...'))); + child: ListTile( + leading: CircularProgressIndicator(), + title: Text('Fetching consumables...'), + ), + ); } if (!_isAvailable || _notFoundIds.contains(_kConsumableId)) { return const Card(); } - const ListTile consumableHeader = - ListTile(title: Text('Purchased consumables')); - final List tokens = _consumables.map((String id) { - return GridTile( - child: IconButton( - icon: const Icon( - Icons.stars, - size: 42.0, - color: Colors.orange, - ), - splashColor: Colors.yellowAccent, - onPressed: () => consume(id), - ), - ); - }).toList(); + const ListTile consumableHeader = ListTile( + title: Text('Purchased consumables'), + ); + final List tokens = + _consumables.map((String id) { + return GridTile( + child: IconButton( + icon: const Icon(Icons.stars, size: 42.0, color: Colors.orange), + splashColor: Colors.yellowAccent, + onPressed: () => consume(id), + ), + ); + }).toList(); return Card( - child: Column(children: [ - consumableHeader, - const Divider(), - GridView.count( - crossAxisCount: 5, - shrinkWrap: true, - padding: const EdgeInsets.all(16.0), - children: tokens, - ) - ])); + child: Column( + children: [ + consumableHeader, + const Divider(), + GridView.count( + crossAxisCount: 5, + shrinkWrap: true, + padding: const EdgeInsets.all(16.0), + children: tokens, + ), + ], + ), + ); } Future consume(String id) async { @@ -507,7 +572,8 @@ class _MyAppState extends State<_MyApp> { } Future deliverIsAlternativeBillingOnlyAvailable( - Future billingOnly) async { + Future billingOnly, + ) async { final BillingResultWrapper wrapper = await billingOnly; setState(() { _isAlternativeBillingOnlyAvailableResponseCode = @@ -516,7 +582,8 @@ class _MyAppState extends State<_MyApp> { } Future deliverShowAlternativeBillingOnlyInformationDialogResult( - Future billingResult) async { + Future billingResult, + ) async { final BillingResultWrapper wrapper = await billingResult; setState(() { _showAlternativeBillingOnlyDialogResponseCode = wrapper.responseCode.name; @@ -524,8 +591,8 @@ class _MyAppState extends State<_MyApp> { } Future deliverCreateAlternativeBillingOnlyReportingDetails( - Future - futureWrapper) async { + Future futureWrapper, + ) async { final AlternativeBillingOnlyReportingDetailsWrapper wrapper = await futureWrapper; setState(() { @@ -573,7 +640,8 @@ class _MyAppState extends State<_MyApp> { } Future deliverUserChoiceDetails( - GooglePlayUserChoiceDetails details) async { + GooglePlayUserChoiceDetails details, + ) async { final String detailDescription = '${details.externalTransactionToken}, ${details.originalExternalTransactionId}, ${details.products.length}'; setState(() { @@ -582,7 +650,8 @@ class _MyAppState extends State<_MyApp> { } Future _listenToPurchaseUpdated( - List purchaseDetailsList) async { + List purchaseDetailsList, + ) async { for (final PurchaseDetails purchaseDetails in purchaseDetailsList) { if (purchaseDetails.status == PurchaseStatus.pending) { showPendingUI(); @@ -615,8 +684,9 @@ class _MyAppState extends State<_MyApp> { } GooglePlayPurchaseDetails? _getOldSubscription( - GooglePlayProductDetails productDetails, - Map purchases) { + GooglePlayProductDetails productDetails, + Map purchases, + ) { // This is just to demonstrate a subscription upgrade or downgrade. // This method assumes that you have only 2 subscriptions under a group, 'subscription_silver' & 'subscription_gold'. // The 'subscription_silver' subscription can be upgraded to 'subscription_gold' and @@ -648,15 +718,17 @@ class _FeatureCard extends StatelessWidget { @override Widget build(BuildContext context) { return Card( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ const ListTile(title: Text('Available features')), const Divider(), for (final BillingClientFeature feature in BillingClientFeature.values) _buildFeatureWidget(feature), - ])); + ], + ), + ); } Widget _buildFeatureWidget(BillingClientFeature feature) { diff --git a/packages/in_app_purchase/in_app_purchase_android/example/lib/migration_guide_examples.dart b/packages/in_app_purchase/in_app_purchase_android/example/lib/migration_guide_examples.dart index 05eda2f3bd8..d05969177dd 100644 --- a/packages/in_app_purchase/in_app_purchase_android/example/lib/migration_guide_examples.dart +++ b/packages/in_app_purchase/in_app_purchase_android/example/lib/migration_guide_examples.dart @@ -59,4 +59,5 @@ void handleIntroductoryPricePeriod(ProductDetails productDetails) { } } } + // #enddocregion subscription-introductory-price diff --git a/packages/in_app_purchase/in_app_purchase_android/example/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_android/example/pubspec.yaml index 252140bcce8..1c803ec27da 100644 --- a/packages/in_app_purchase/in_app_purchase_android/example/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_android/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the in_app_purchase_android plugin. publish_to: none environment: - sdk: ^3.6.0 - flutter: ">=3.27.0" + sdk: ^3.7.0 + flutter: ">=3.29.0" dependencies: flutter: diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/alternative_billing_only_reporting_details_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/alternative_billing_only_reporting_details_wrapper.dart index 50162f62466..b78b8b56dfc 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/alternative_billing_only_reporting_details_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/alternative_billing_only_reporting_details_wrapper.dart @@ -18,10 +18,11 @@ const String kInvalidAlternativeBillingReportingDetailsErrorMessage = class AlternativeBillingOnlyReportingDetailsWrapper implements HasBillingResponse { /// Constructs the object with [responseCode] and [debugMessage]. - const AlternativeBillingOnlyReportingDetailsWrapper( - {required this.responseCode, - this.debugMessage, - this.externalTransactionToken = ''}); + const AlternativeBillingOnlyReportingDetailsWrapper({ + required this.responseCode, + this.debugMessage, + this.externalTransactionToken = '', + }); /// Response code returned in the Play Billing API calls. @override diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_manager.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_manager.dart index 0c63080686a..c3d23407a17 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_manager.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_manager.dart @@ -22,9 +22,11 @@ abstract class HasBillingResponse { /// Factory for creating BillingClient instances, to allow injection of /// custom billing clients in tests. @visibleForTesting -typedef BillingClientFactory = BillingClient Function( - PurchasesUpdatedListener onPurchasesUpdated, - UserSelectedAlternativeBillingListener? alternativeBillingListener); +typedef BillingClientFactory = + BillingClient Function( + PurchasesUpdatedListener onPurchasesUpdated, + UserSelectedAlternativeBillingListener? alternativeBillingListener, + ); /// Utility class that manages a [BillingClient] connection. /// @@ -42,12 +44,13 @@ class BillingClientManager { /// Creates the [BillingClientManager]. /// /// Immediately initializes connection to the underlying [BillingClient]. - BillingClientManager( - {@visibleForTesting BillingClientFactory? billingClientFactory}) - : _billingChoiceMode = BillingChoiceMode.playBillingOnly, - _pendingPurchasesParams = - const PendingPurchasesParamsWrapper(enablePrepaidPlans: false), - _billingClientFactory = billingClientFactory ?? _createBillingClient { + BillingClientManager({ + @visibleForTesting BillingClientFactory? billingClientFactory, + }) : _billingChoiceMode = BillingChoiceMode.playBillingOnly, + _pendingPurchasesParams = const PendingPurchasesParamsWrapper( + enablePrepaidPlans: false, + ), + _billingClientFactory = billingClientFactory ?? _createBillingClient { _connect(); } @@ -71,19 +74,22 @@ class BillingClientManager { /// and [runWithClientNonRetryable] methods. @visibleForTesting late final BillingClient client = _billingClientFactory( - _onPurchasesUpdated, onUserChoiceAlternativeBilling); + _onPurchasesUpdated, + onUserChoiceAlternativeBilling, + ); // Default (non-test) implementation of _billingClientFactory. static BillingClient _createBillingClient( - PurchasesUpdatedListener onPurchasesUpdated, - UserSelectedAlternativeBillingListener? onUserChoiceAlternativeBilling) { + PurchasesUpdatedListener onPurchasesUpdated, + UserSelectedAlternativeBillingListener? onUserChoiceAlternativeBilling, + ) { return BillingClient(onPurchasesUpdated, onUserChoiceAlternativeBilling); } final StreamController _purchasesUpdatedController = StreamController.broadcast(); final StreamController - _userChoiceAlternativeBillingController = + _userChoiceAlternativeBillingController = StreamController.broadcast(); BillingChoiceMode _billingChoiceMode; @@ -163,14 +169,16 @@ class BillingClientManager { /// available by calling [BillingClientWrapper.isAlternativeBillingOnlyAvailable] /// first. Future reconnectWithBillingChoiceMode( - BillingChoiceMode billingChoiceMode) async { + BillingChoiceMode billingChoiceMode, + ) async { _billingChoiceMode = billingChoiceMode; await _reconnect(); } /// Ends connection to [BillingClient] and reconnects with [pendingPurchasesParams]. Future reconnectWithPendingPurchasesParams( - PendingPurchasesParamsWrapper pendingPurchasesParams) async { + PendingPurchasesParamsWrapper pendingPurchasesParams, + ) async { _pendingPurchasesParams = pendingPurchasesParams; await _reconnect(); } diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart index 17dfbf29c19..f6f101f4c68 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart @@ -28,12 +28,12 @@ import 'pending_purchases_params_wrapper.dart'; /// /// Wraps a /// [`PurchasesUpdatedListener`](https://developer.android.com/reference/com/android/billingclient/api/PurchasesUpdatedListener.html). -typedef PurchasesUpdatedListener = void Function( - PurchasesResultWrapper purchasesResult); +typedef PurchasesUpdatedListener = + void Function(PurchasesResultWrapper purchasesResult); /// Wraps a [UserChoiceBillingListener](https://developer.android.com/reference/com/android/billingclient/api/UserChoiceBillingListener) -typedef UserSelectedAlternativeBillingListener = void Function( - UserChoiceDetailsWrapper userChoiceDetailsWrapper); +typedef UserSelectedAlternativeBillingListener = + void Function(UserChoiceDetailsWrapper userChoiceDetailsWrapper); /// This class can be used directly instead of [InAppPurchaseConnection] to call /// Play-specific billing APIs. @@ -59,9 +59,11 @@ class BillingClient { PurchasesUpdatedListener onPurchasesUpdated, UserSelectedAlternativeBillingListener? alternativeBillingListener, { @visibleForTesting InAppPurchaseApi? api, - }) : _hostApi = api ?? InAppPurchaseApi(), - hostCallbackHandler = HostBillingClientCallbackHandler( - onPurchasesUpdated, alternativeBillingListener) { + }) : _hostApi = api ?? InAppPurchaseApi(), + hostCallbackHandler = HostBillingClientCallbackHandler( + onPurchasesUpdated, + alternativeBillingListener, + ) { InAppPurchaseCallbackApi.setUp(hostCallbackHandler); } @@ -102,7 +104,7 @@ class BillingClient { switch (pendingPurchasesParams) { final PendingPurchasesParamsWrapper params => pendingPurchasesParamsFromWrapper(params), - null => PlatformPendingPurchasesParams(enablePrepaidPlans: false) + null => PlatformPendingPurchasesParams(enablePrepaidPlans: false), }, ), ); @@ -133,10 +135,15 @@ class BillingClient { required List productList, }) async { return productDetailsResponseWrapperFromPlatform( - await _hostApi.queryProductDetailsAsync(productList - .map((ProductWrapper product) => - platformQueryProductFromWrapper(product)) - .toList())); + await _hostApi.queryProductDetailsAsync( + productList + .map( + (ProductWrapper product) => + platformQueryProductFromWrapper(product), + ) + .toList(), + ), + ); } /// Attempt to launch the Play Billing Flow for a given [productDetails]. @@ -178,28 +185,34 @@ class BillingClient { /// [purchaseToken] must not be `null` if [oldProduct] is not `null`. /// The [replacementMode](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.Builder#setSubscriptionReplacementMode(int)) is the mode of replacement during subscription upgrade/downgrade. /// This value will only be effective if the `oldProduct` is also set. - Future launchBillingFlow( - {required String product, - String? offerToken, - String? accountId, - String? obfuscatedProfileId, - String? oldProduct, - String? purchaseToken, - ReplacementMode? replacementMode}) async { - assert((oldProduct == null) == (purchaseToken == null), - 'oldProduct and purchaseToken must both be set, or both be null.'); + Future launchBillingFlow({ + required String product, + String? offerToken, + String? accountId, + String? obfuscatedProfileId, + String? oldProduct, + String? purchaseToken, + ReplacementMode? replacementMode, + }) async { + assert( + (oldProduct == null) == (purchaseToken == null), + 'oldProduct and purchaseToken must both be set, or both be null.', + ); return resultWrapperFromPlatform( - await _hostApi.launchBillingFlow(PlatformBillingFlowParams( - product: product, - replacementMode: replacementModeFromWrapper( - replacementMode ?? ReplacementMode.unknownReplacementMode, + await _hostApi.launchBillingFlow( + PlatformBillingFlowParams( + product: product, + replacementMode: replacementModeFromWrapper( + replacementMode ?? ReplacementMode.unknownReplacementMode, + ), + offerToken: offerToken, + accountId: accountId, + obfuscatedProfileId: obfuscatedProfileId, + oldProduct: oldProduct, + purchaseToken: purchaseToken, + ), ), - offerToken: offerToken, - accountId: accountId, - obfuscatedProfileId: obfuscatedProfileId, - oldProduct: oldProduct, - purchaseToken: purchaseToken, - ))); + ); } /// Fetches recent purchases for the given [ProductType]. @@ -229,9 +242,11 @@ class BillingClient { // broken by the original change to hard-code this on the Java side (instead // of making it a forwarding getter on the Dart side). return purchasesResultWrapperFromPlatform( - await _hostApi - .queryPurchasesAsync(platformProductTypeFromWrapper(productType)), - forceOkResponseCode: true); + await _hostApi.queryPurchasesAsync( + platformProductTypeFromWrapper(productType), + ), + forceOkResponseCode: true, + ); } /// Fetches purchase history for the given [ProductType]. @@ -248,10 +263,13 @@ class BillingClient { /// [`BillingClient#queryPurchaseHistoryAsync(QueryPurchaseHistoryParams, PurchaseHistoryResponseListener)`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient#queryPurchaseHistoryAsync(com.android.billingclient.api.QueryPurchaseHistoryParams,%20com.android.billingclient.api.PurchaseHistoryResponseListener)). @Deprecated('Use queryPurchases') Future queryPurchaseHistory( - ProductType productType) async { + ProductType productType, + ) async { return purchaseHistoryResultFromPlatform( - await _hostApi.queryPurchaseHistoryAsync( - platformProductTypeFromWrapper(productType))); + await _hostApi.queryPurchaseHistoryAsync( + platformProductTypeFromWrapper(productType), + ), + ); } /// Consumes a given in-app product. @@ -263,7 +281,8 @@ class BillingClient { /// [`BillingClient#consumeAsync(ConsumeParams, ConsumeResponseListener)`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.html#consumeAsync(java.lang.String,%20com.android.billingclient.api.ConsumeResponseListener)) Future consumeAsync(String purchaseToken) async { return resultWrapperFromPlatform( - await _hostApi.consumeAsync(purchaseToken)); + await _hostApi.consumeAsync(purchaseToken), + ); } /// Acknowledge an in-app purchase. @@ -286,41 +305,47 @@ class BillingClient { /// [`BillingClient#acknowledgePurchase(AcknowledgePurchaseParams, AcknowledgePurchaseResponseListener)`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.html#acknowledgePurchase(com.android.billingclient.api.AcknowledgePurchaseParams,%20com.android.billingclient.api.AcknowledgePurchaseResponseListener)) Future acknowledgePurchase(String purchaseToken) async { return resultWrapperFromPlatform( - await _hostApi.acknowledgePurchase(purchaseToken)); + await _hostApi.acknowledgePurchase(purchaseToken), + ); } /// Checks if the specified feature or capability is supported by the Play Store. /// Call this to check if a [BillingClientFeature] is supported by the device. Future isFeatureSupported(BillingClientFeature feature) async { - return _hostApi - .isFeatureSupported(billingClientFeatureFromWrapper(feature)); + return _hostApi.isFeatureSupported( + billingClientFeatureFromWrapper(feature), + ); } /// Fetches billing config info into a [BillingConfigWrapper] object. Future getBillingConfig() async { return billingConfigWrapperFromPlatform( - await _hostApi.getBillingConfigAsync()); + await _hostApi.getBillingConfigAsync(), + ); } /// Checks if "AlterntitiveBillingOnly" feature is available. Future isAlternativeBillingOnlyAvailable() async { return resultWrapperFromPlatform( - await _hostApi.isAlternativeBillingOnlyAvailableAsync()); + await _hostApi.isAlternativeBillingOnlyAvailableAsync(), + ); } /// Shows the alternative billing only information dialog on top of the calling app. Future - showAlternativeBillingOnlyInformationDialog() async { + showAlternativeBillingOnlyInformationDialog() async { return resultWrapperFromPlatform( - await _hostApi.showAlternativeBillingOnlyInformationDialog()); + await _hostApi.showAlternativeBillingOnlyInformationDialog(), + ); } /// The details used to report transactions made via alternative billing /// without user choice to use Google Play billing. Future - createAlternativeBillingOnlyReportingDetails() async { + createAlternativeBillingOnlyReportingDetails() async { return alternativeBillingOnlyReportingDetailsWrapperFromPlatform( - await _hostApi.createAlternativeBillingOnlyReportingDetailsAsync()); + await _hostApi.createAlternativeBillingOnlyReportingDetailsAsync(), + ); } } @@ -335,7 +360,9 @@ class HostBillingClientCallbackHandler implements InAppPurchaseCallbackApi { /// Creates a new handler with the given singleton handlers, and no /// per-connection handlers. HostBillingClientCallbackHandler( - this.purchasesUpdatedCallback, this.alternativeBillingListener); + this.purchasesUpdatedCallback, + this.alternativeBillingListener, + ); /// The handler for PurchasesUpdatedListener#onPurchasesUpdated. final PurchasesUpdatedListener purchasesUpdatedCallback; diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_config_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_config_wrapper.dart index 1062466932e..9751a93872e 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_config_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_config_wrapper.dart @@ -17,8 +17,11 @@ const String kInvalidBillingConfigErrorMessage = @immutable class BillingConfigWrapper implements HasBillingResponse { /// Constructs the object with [responseCode] and [debugMessage]. - const BillingConfigWrapper( - {required this.responseCode, this.debugMessage, this.countryCode = ''}); + const BillingConfigWrapper({ + required this.responseCode, + this.debugMessage, + this.countryCode = '', + }); /// Response code returned in the Play Billing API calls. @override diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/pending_purchases_params_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/pending_purchases_params_wrapper.dart index d702cae27bf..765755e21ff 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/pending_purchases_params_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/pending_purchases_params_wrapper.dart @@ -10,9 +10,7 @@ import 'package:flutter/foundation.dart'; @immutable class PendingPurchasesParamsWrapper { /// Creates a [PendingPurchasesParamsWrapper]. - const PendingPurchasesParamsWrapper({ - required this.enablePrepaidPlans, - }); + const PendingPurchasesParamsWrapper({required this.enablePrepaidPlans}); /// Enables pending purchase for prepaid plans. /// diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/product_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/product_wrapper.dart index 65833bcb61c..d9d77b2514c 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/product_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/product_wrapper.dart @@ -10,10 +10,7 @@ import '../../billing_client_wrappers.dart'; @immutable class ProductWrapper { /// Creates a new [ProductWrapper]. - const ProductWrapper({ - required this.productId, - required this.productType, - }); + const ProductWrapper({required this.productId, required this.productType}); /// The product identifier. final String productId; diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart index 1572be847cf..3fd614db32c 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart @@ -58,17 +58,18 @@ class PurchaseWrapper { @override int get hashCode => Object.hash( - orderId, - packageName, - purchaseTime, - purchaseToken, - signature, - products.hashCode, - isAutoRenewing, - originalJson, - isAcknowledged, - purchaseState, - pendingPurchaseUpdate); + orderId, + packageName, + purchaseTime, + purchaseToken, + signature, + products.hashCode, + isAutoRenewing, + originalJson, + isAcknowledged, + purchaseState, + pendingPurchaseUpdate, + ); /// The unique ID for this purchase. Corresponds to the Google Payments order /// ID. @@ -149,7 +150,6 @@ class PurchaseWrapper { } @immutable - /// Represents a pending change/update to the existing purchase. /// /// This wraps [`com.android.billingclient.api.Purchase.PendingPurchaseUpdate`](https://developer.android.com/reference/com/android/billingclient/api/Purchase.PendingPurchaseUpdate). @@ -180,10 +180,7 @@ class PendingPurchaseUpdateWrapper { } @override - int get hashCode => Object.hash( - purchaseToken, - products.hashCode, - ); + int get hashCode => Object.hash(purchaseToken, products.hashCode); } /// Data structure representing a purchase history record. @@ -252,13 +249,13 @@ class PurchaseHistoryRecordWrapper { @override int get hashCode => Object.hash( - purchaseTime, - purchaseToken, - signature, - products.hashCode, - originalJson, - developerPayload, - ); + purchaseTime, + purchaseToken, + signature, + products.hashCode, + originalJson, + developerPayload, + ); } /// A data struct representing the result of a transaction. @@ -271,10 +268,11 @@ class PurchaseHistoryRecordWrapper { @immutable class PurchasesResultWrapper implements HasBillingResponse { /// Creates a [PurchasesResultWrapper] with the given purchase result details. - const PurchasesResultWrapper( - {required this.responseCode, - required this.billingResult, - required this.purchasesList}); + const PurchasesResultWrapper({ + required this.responseCode, + required this.billingResult, + required this.purchasesList, + }); @override bool operator ==(Object other) { @@ -316,8 +314,10 @@ class PurchasesResultWrapper implements HasBillingResponse { @immutable class PurchasesHistoryResult implements HasBillingResponse { /// Creates a [PurchasesHistoryResult] with the provided history. - const PurchasesHistoryResult( - {required this.billingResult, required this.purchaseHistoryRecordList}); + const PurchasesHistoryResult({ + required this.billingResult, + required this.purchaseHistoryRecordList, + }); @override BillingResponse get responseCode => billingResult.responseCode; diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/subscription_offer_details_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/subscription_offer_details_wrapper.dart index f31757e922f..abd7e076cb9 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/subscription_offer_details_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/subscription_offer_details_wrapper.dart @@ -123,13 +123,13 @@ class PricingPhaseWrapper { @override int get hashCode => Object.hash( - billingCycleCount, - billingPeriod, - formattedPrice, - priceAmountMicros, - priceCurrencyCode, - recurrenceMode, - ); + billingCycleCount, + billingPeriod, + formattedPrice, + priceAmountMicros, + priceCurrencyCode, + recurrenceMode, + ); } /// Represents additional details of an installment subscription plan. diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/user_choice_details_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/user_choice_details_wrapper.dart index 01654519f64..15edbf6b85a 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/user_choice_details_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/user_choice_details_wrapper.dart @@ -34,10 +34,10 @@ class UserChoiceDetailsWrapper { @override int get hashCode => Object.hash( - originalExternalTransactionId, - externalTransactionToken, - products.hashCode, - ); + originalExternalTransactionId, + externalTransactionToken, + products.hashCode, + ); /// Returns the external transaction Id of the originating subscription, if /// the purchase is a subscription upgrade/downgrade. @@ -91,9 +91,5 @@ class UserChoiceDetailsProductWrapper { } @override - int get hashCode => Object.hash( - id, - offerToken, - productType, - ); + int get hashCode => Object.hash(id, offerToken, productType); } diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart index 92f34c3d54a..9004c6fbc87 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart @@ -33,12 +33,12 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { /// Creates a new InAppPurchaseAndroidPlatform instance, and configures it /// for use. @visibleForTesting - InAppPurchaseAndroidPlatform( - {@visibleForTesting BillingClientManager? manager}) - : billingClientManager = manager ?? BillingClientManager() { + InAppPurchaseAndroidPlatform({ + @visibleForTesting BillingClientManager? manager, + }) : billingClientManager = manager ?? BillingClientManager() { // Register [InAppPurchaseAndroidPlatformAddition]. - InAppPurchasePlatformAddition.instance = - InAppPurchaseAndroidPlatformAddition(billingClientManager); + InAppPurchasePlatformAddition + .instance = InAppPurchaseAndroidPlatformAddition(billingClientManager); billingClientManager.purchasesUpdatedStream .asyncMap(_getPurchaseDetailsFromResult) @@ -69,8 +69,9 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { @override Future isAvailable() async { - return billingClientManager - .runWithClientNonRetryable((BillingClient client) => client.isReady()); + return billingClientManager.runWithClientNonRetryable( + (BillingClient client) => client.isReady(), + ); } /// Performs a network query for the details of products available. @@ -82,61 +83,85 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { PlatformException? exception; try { - productResponses = await Future.wait( - >[ - billingClientManager.runWithClient( - (BillingClient client) => client.queryProductDetails( - productList: identifiers - .map((String productId) => ProductWrapper( - productId: productId, productType: ProductType.inapp)) - .toList(), + productResponses = + await Future.wait(>[ + billingClientManager.runWithClient( + (BillingClient client) => client.queryProductDetails( + productList: + identifiers + .map( + (String productId) => ProductWrapper( + productId: productId, + productType: ProductType.inapp, + ), + ) + .toList(), + ), ), - ), - billingClientManager.runWithClient( - (BillingClient client) => client.queryProductDetails( - productList: identifiers - .map((String productId) => ProductWrapper( - productId: productId, productType: ProductType.subs)) - .toList(), + billingClientManager.runWithClient( + (BillingClient client) => client.queryProductDetails( + productList: + identifiers + .map( + (String productId) => ProductWrapper( + productId: productId, + productType: ProductType.subs, + ), + ) + .toList(), + ), ), - ), - ], - ); + ]); } on PlatformException catch (e) { exception = e; productResponses = [ ProductDetailsResponseWrapper( - billingResult: BillingResultWrapper( - responseCode: BillingResponse.error, debugMessage: e.code), - productDetailsList: const []), + billingResult: BillingResultWrapper( + responseCode: BillingResponse.error, + debugMessage: e.code, + ), + productDetailsList: const [], + ), ProductDetailsResponseWrapper( - billingResult: BillingResultWrapper( - responseCode: BillingResponse.error, debugMessage: e.code), - productDetailsList: const []) + billingResult: BillingResultWrapper( + responseCode: BillingResponse.error, + debugMessage: e.code, + ), + productDetailsList: const [], + ), ]; } final List productDetailsList = - productResponses.expand((ProductDetailsResponseWrapper response) { - return response.productDetailsList; - }).expand((ProductDetailsWrapper productDetailWrapper) { - return GooglePlayProductDetails.fromProductDetails(productDetailWrapper); - }).toList(); - - final Set successIDS = productDetailsList - .map((ProductDetails productDetails) => productDetails.id) - .toSet(); + productResponses + .expand((ProductDetailsResponseWrapper response) { + return response.productDetailsList; + }) + .expand((ProductDetailsWrapper productDetailWrapper) { + return GooglePlayProductDetails.fromProductDetails( + productDetailWrapper, + ); + }) + .toList(); + + final Set successIDS = + productDetailsList + .map((ProductDetails productDetails) => productDetails.id) + .toSet(); final List notFoundIDS = identifiers.difference(successIDS).toList(); return ProductDetailsResponse( - productDetails: productDetailsList, - notFoundIDs: notFoundIDS, - error: exception == null - ? null - : IAPError( + productDetails: productDetailsList, + notFoundIDs: notFoundIDS, + error: + exception == null + ? null + : IAPError( source: kIAPSource, code: exception.code, message: exception.message ?? '', - details: exception.details)); + details: exception.details, + ), + ); } @override @@ -155,23 +180,29 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { (purchaseParam.productDetails as GooglePlayProductDetails).offerToken; } - final BillingResultWrapper billingResultWrapper = - await billingClientManager.runWithClient( - (BillingClient client) => client.launchBillingFlow( - product: purchaseParam.productDetails.id, - offerToken: offerToken, - accountId: purchaseParam.applicationUserName, - oldProduct: changeSubscriptionParam?.oldPurchaseDetails.productID, - purchaseToken: changeSubscriptionParam - ?.oldPurchaseDetails.verificationData.serverVerificationData, - replacementMode: changeSubscriptionParam?.replacementMode), - ); + final BillingResultWrapper billingResultWrapper = await billingClientManager + .runWithClient( + (BillingClient client) => client.launchBillingFlow( + product: purchaseParam.productDetails.id, + offerToken: offerToken, + accountId: purchaseParam.applicationUserName, + oldProduct: changeSubscriptionParam?.oldPurchaseDetails.productID, + purchaseToken: + changeSubscriptionParam + ?.oldPurchaseDetails + .verificationData + .serverVerificationData, + replacementMode: changeSubscriptionParam?.replacementMode, + ), + ); return billingResultWrapper.responseCode == BillingResponse.ok; } @override - Future buyConsumable( - {required PurchaseParam purchaseParam, bool autoConsume = true}) { + Future buyConsumable({ + required PurchaseParam purchaseParam, + bool autoConsume = true, + }) { if (autoConsume) { _productIdsToConsume.add(purchaseParam.productDetails.id); } @@ -180,7 +211,8 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { @override Future completePurchase( - PurchaseDetails purchase) async { + PurchaseDetails purchase, + ) async { assert( purchase is GooglePlayPurchaseDetails, 'On Android, the `purchase` should always be of type `GooglePlayPurchaseDetails`.', @@ -195,14 +227,13 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { return billingClientManager.runWithClient( (BillingClient client) => client.acknowledgePurchase( - purchase.verificationData.serverVerificationData), + purchase.verificationData.serverVerificationData, + ), ); } @override - Future restorePurchases({ - String? applicationUserName, - }) async { + Future restorePurchases({String? applicationUserName}) async { List responses; responses = await Future.wait(>[ @@ -214,23 +245,33 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { ), ]); - final Set errorCodeSet = responses - .where((PurchasesResultWrapper response) => - response.responseCode != BillingResponse.ok) - .map((PurchasesResultWrapper response) => - response.responseCode.toString()) - .toSet(); + final Set errorCodeSet = + responses + .where( + (PurchasesResultWrapper response) => + response.responseCode != BillingResponse.ok, + ) + .map( + (PurchasesResultWrapper response) => + response.responseCode.toString(), + ) + .toSet(); final String errorMessage = errorCodeSet.isNotEmpty ? errorCodeSet.join(', ') : ''; - final List pastPurchases = responses - .expand((PurchasesResultWrapper response) => response.purchasesList) - .expand((PurchaseWrapper purchaseWrapper) => - GooglePlayPurchaseDetails.fromPurchase(purchaseWrapper)) - .map((GooglePlayPurchaseDetails details) => - details..status = PurchaseStatus.restored) - .toList(); + final List pastPurchases = + responses + .expand((PurchasesResultWrapper response) => response.purchasesList) + .expand( + (PurchaseWrapper purchaseWrapper) => + GooglePlayPurchaseDetails.fromPurchase(purchaseWrapper), + ) + .map( + (GooglePlayPurchaseDetails details) => + details..status = PurchaseStatus.restored, + ) + .toList(); if (errorMessage.isNotEmpty) { throw InAppPurchaseException( @@ -244,7 +285,8 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { } Future _maybeAutoConsumePurchase( - PurchaseDetails purchaseDetails) async { + PurchaseDetails purchaseDetails, + ) async { if (!(purchaseDetails.status == PurchaseStatus.purchased && _productIdsToConsume.contains(purchaseDetails.productID))) { return purchaseDetails; @@ -270,7 +312,8 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { } Future> _getPurchaseDetailsFromResult( - PurchasesResultWrapper resultWrapper) async { + PurchasesResultWrapper resultWrapper, + ) async { IAPError? error; if (resultWrapper.responseCode != BillingResponse.ok) { error = IAPError( @@ -280,16 +323,20 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { details: resultWrapper.billingResult.debugMessage, ); } - final List> purchases = resultWrapper.purchasesList - .expand((PurchaseWrapper purchase) => - GooglePlayPurchaseDetails.fromPurchase(purchase)) - .map((GooglePlayPurchaseDetails purchaseDetails) { - purchaseDetails.error = error; - if (resultWrapper.responseCode == BillingResponse.userCanceled) { - purchaseDetails.status = PurchaseStatus.canceled; - } - return _maybeAutoConsumePurchase(purchaseDetails); - }).toList(); + final List> purchases = + resultWrapper.purchasesList + .expand( + (PurchaseWrapper purchase) => + GooglePlayPurchaseDetails.fromPurchase(purchase), + ) + .map((GooglePlayPurchaseDetails purchaseDetails) { + purchaseDetails.error = error; + if (resultWrapper.responseCode == BillingResponse.userCanceled) { + purchaseDetails.status = PurchaseStatus.canceled; + } + return _maybeAutoConsumePurchase(purchaseDetails); + }) + .toList(); if (purchases.isNotEmpty) { return Future.wait(purchases); } else { @@ -310,7 +357,7 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { serverVerificationData: '', source: kIAPSource, ), - )..error = error + )..error = error, ]; } } diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform_addition.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform_addition.dart index cc94285eb98..e0d7283b143 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform_addition.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform_addition.dart @@ -24,7 +24,7 @@ class InAppPurchaseAndroidPlatformAddition } final StreamController - _userChoiceDetailsStreamController = + _userChoiceDetailsStreamController = StreamController.broadcast(); /// [GooglePlayUserChoiceDetails] emits each time user selects alternative billing. @@ -59,8 +59,9 @@ class InAppPurchaseAndroidPlatformAddition /// /// * [refreshPurchaseVerificationData], for reloading failed /// [PurchaseDetails.verificationData]. - Future queryPastPurchases( - {String? applicationUserName}) async { + Future queryPastPurchases({ + String? applicationUserName, + }) async { List responses; PlatformException? exception; @@ -91,42 +92,54 @@ class InAppPurchaseAndroidPlatformAddition responseCode: BillingResponse.error, debugMessage: e.details.toString(), ), - ) + ), ]; } - final Set errorCodeSet = responses - .where((PurchasesResultWrapper response) => - response.responseCode != BillingResponse.ok) - .map((PurchasesResultWrapper response) => - response.responseCode.toString()) - .toSet(); + final Set errorCodeSet = + responses + .where( + (PurchasesResultWrapper response) => + response.responseCode != BillingResponse.ok, + ) + .map( + (PurchasesResultWrapper response) => + response.responseCode.toString(), + ) + .toSet(); final String errorMessage = errorCodeSet.isNotEmpty ? errorCodeSet.join(', ') : ''; - final List pastPurchases = responses - .expand((PurchasesResultWrapper response) => response.purchasesList) - .expand((PurchaseWrapper purchaseWrapper) => - GooglePlayPurchaseDetails.fromPurchase(purchaseWrapper)) - .toList(); + final List pastPurchases = + responses + .expand((PurchasesResultWrapper response) => response.purchasesList) + .expand( + (PurchaseWrapper purchaseWrapper) => + GooglePlayPurchaseDetails.fromPurchase(purchaseWrapper), + ) + .toList(); IAPError? error; if (exception != null) { error = IAPError( - source: kIAPSource, - code: exception.code, - message: exception.message ?? '', - details: exception.details); + source: kIAPSource, + code: exception.code, + message: exception.message ?? '', + details: exception.details, + ); } else if (errorMessage.isNotEmpty) { error = IAPError( - source: kIAPSource, - code: kRestoredPurchaseErrorCode, - message: errorMessage); + source: kIAPSource, + code: kRestoredPurchaseErrorCode, + message: errorMessage, + ); } return QueryPurchaseDetailsResponse( - pastPurchases: pastPurchases, error: error); + pastPurchases: pastPurchases, + error: error, + ); } /// Checks if the specified feature or capability is supported by the Play Store. @@ -153,9 +166,10 @@ class InAppPurchaseAndroidPlatformAddition /// /// See: https://developer.android.com/reference/com/android/billingclient/api/BillingClient#isAlternativeBillingOnlyAvailableAsync(com.android.billingclient.api.AlternativeBillingOnlyAvailabilityListener) Future isAlternativeBillingOnlyAvailable() async { - final BillingResultWrapper wrapper = - await _billingClientManager.runWithClient((BillingClient client) => - client.isAlternativeBillingOnlyAvailable()); + final BillingResultWrapper wrapper = await _billingClientManager + .runWithClient( + (BillingClient client) => client.isAlternativeBillingOnlyAvailable(), + ); return wrapper; } @@ -163,10 +177,12 @@ class InAppPurchaseAndroidPlatformAddition /// /// See: https://developer.android.com/reference/com/android/billingclient/api/BillingClient#showAlternativeBillingOnlyInformationDialog(android.app.Activity,%20com.android.billingclient.api.AlternativeBillingOnlyInformationDialogListener) Future - showAlternativeBillingOnlyInformationDialog() async { - final BillingResultWrapper wrapper = - await _billingClientManager.runWithClient((BillingClient client) => - client.showAlternativeBillingOnlyInformationDialog()); + showAlternativeBillingOnlyInformationDialog() async { + final BillingResultWrapper wrapper = await _billingClientManager + .runWithClient( + (BillingClient client) => + client.showAlternativeBillingOnlyInformationDialog(), + ); return wrapper; } @@ -175,10 +191,12 @@ class InAppPurchaseAndroidPlatformAddition /// /// See: https://developer.android.com/reference/com/android/billingclient/api/AlternativeBillingOnlyReportingDetails Future - createAlternativeBillingOnlyReportingDetails() async { + createAlternativeBillingOnlyReportingDetails() async { final AlternativeBillingOnlyReportingDetailsWrapper wrapper = - await _billingClientManager.runWithClient((BillingClient client) => - client.createAlternativeBillingOnlyReportingDetails()); + await _billingClientManager.runWithClient( + (BillingClient client) => + client.createAlternativeBillingOnlyReportingDetails(), + ); return wrapper; } @@ -191,7 +209,8 @@ class InAppPurchaseAndroidPlatformAddition /// Play apis have requirements for when this method can be called. /// See: https://developer.android.com/google/play/billing/alternative/alternative-billing-without-user-choice-in-app Future setBillingChoice(BillingChoiceMode billingChoiceMode) { - return _billingClientManager - .reconnectWithBillingChoiceMode(billingChoiceMode); + return _billingClientManager.reconnectWithBillingChoiceMode( + billingChoiceMode, + ); } } diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/messages.g.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/messages.g.dart index 72e3ab5c16c..9414d8e9840 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/messages.g.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/messages.g.dart @@ -18,8 +18,11 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse( - {Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({ + Object? result, + PlatformException? error, + bool empty = false, +}) { if (empty) { return []; } @@ -56,10 +59,7 @@ enum PlatformReplacementMode { } /// Pigeon version of Java BillingClient.ProductType. -enum PlatformProductType { - inapp, - subs, -} +enum PlatformProductType { inapp, subs } /// Pigeon version of billing_client_wrapper.dart's BillingChoiceMode. enum PlatformBillingChoiceMode { @@ -87,35 +87,21 @@ enum PlatformBillingClientFeature { } /// Pigeon version of Java Purchase.PurchaseState. -enum PlatformPurchaseState { - unspecified, - purchased, - pending, -} +enum PlatformPurchaseState { unspecified, purchased, pending } /// Pigeon version of Java ProductDetails.RecurrenceMode. -enum PlatformRecurrenceMode { - finiteRecurring, - infiniteRecurring, - nonRecurring, -} +enum PlatformRecurrenceMode { finiteRecurring, infiniteRecurring, nonRecurring } /// Pigeon version of Java QueryProductDetailsParams.Product. class PlatformQueryProduct { - PlatformQueryProduct({ - required this.productId, - required this.productType, - }); + PlatformQueryProduct({required this.productId, required this.productType}); String productId; PlatformProductType productType; Object encode() { - return [ - productId, - productType, - ]; + return [productId, productType]; } static PlatformQueryProduct decode(Object result) { @@ -139,10 +125,7 @@ class PlatformAccountIdentifiers { String? obfuscatedProfileId; Object encode() { - return [ - obfuscatedAccountId, - obfuscatedProfileId, - ]; + return [obfuscatedAccountId, obfuscatedProfileId]; } static PlatformAccountIdentifiers decode(Object result) { @@ -166,10 +149,7 @@ class PlatformBillingResult { String debugMessage; Object encode() { - return [ - responseCode, - debugMessage, - ]; + return [responseCode, debugMessage]; } static PlatformBillingResult decode(Object result) { @@ -196,11 +176,7 @@ class PlatformOneTimePurchaseOfferDetails { String priceCurrencyCode; Object encode() { - return [ - priceAmountMicros, - formattedPrice, - priceCurrencyCode, - ]; + return [priceAmountMicros, formattedPrice, priceCurrencyCode]; } static PlatformOneTimePurchaseOfferDetails decode(Object result) { @@ -261,8 +237,9 @@ class PlatformProductDetails { title: result[4]! as String, oneTimePurchaseOfferDetails: result[5] as PlatformOneTimePurchaseOfferDetails?, - subscriptionOfferDetails: (result[6] as List?) - ?.cast(), + subscriptionOfferDetails: + (result[6] as List?) + ?.cast(), ); } } @@ -280,10 +257,7 @@ class PlatformProductDetailsResponse { List productDetails; Object encode() { - return [ - billingResult, - productDetails, - ]; + return [billingResult, productDetails]; } static PlatformProductDetailsResponse decode(Object result) { @@ -310,14 +284,12 @@ class PlatformAlternativeBillingOnlyReportingDetailsResponse { String externalTransactionToken; Object encode() { - return [ - billingResult, - externalTransactionToken, - ]; + return [billingResult, externalTransactionToken]; } static PlatformAlternativeBillingOnlyReportingDetailsResponse decode( - Object result) { + Object result, + ) { result as List; return PlatformAlternativeBillingOnlyReportingDetailsResponse( billingResult: result[0]! as PlatformBillingResult, @@ -339,10 +311,7 @@ class PlatformBillingConfigResponse { String countryCode; Object encode() { - return [ - billingResult, - countryCode, - ]; + return [billingResult, countryCode]; } static PlatformBillingConfigResponse decode(Object result) { @@ -556,10 +525,7 @@ class PlatformPendingPurchaseUpdate { String purchaseToken; Object encode() { - return [ - products, - purchaseToken, - ]; + return [products, purchaseToken]; } static PlatformPendingPurchaseUpdate decode(Object result) { @@ -638,10 +604,7 @@ class PlatformPurchaseHistoryResponse { List purchases; Object encode() { - return [ - billingResult, - purchases, - ]; + return [billingResult, purchases]; } static PlatformPurchaseHistoryResponse decode(Object result) { @@ -667,10 +630,7 @@ class PlatformPurchasesResponse { List purchases; Object encode() { - return [ - billingResult, - purchases, - ]; + return [billingResult, purchases]; } static PlatformPurchasesResponse decode(Object result) { @@ -778,11 +738,7 @@ class PlatformUserChoiceProduct { PlatformProductType type; Object encode() { - return [ - id, - offerToken, - type, - ]; + return [id, offerToken, type]; } static PlatformUserChoiceProduct decode(Object result) { @@ -825,16 +781,12 @@ class PlatformInstallmentPlanDetails { /// Pigeon version of Java PendingPurchasesParams. class PlatformPendingPurchasesParams { - PlatformPendingPurchasesParams({ - required this.enablePrepaidPlans, - }); + PlatformPendingPurchasesParams({required this.enablePrepaidPlans}); bool enablePrepaidPlans; Object encode() { - return [ - enablePrepaidPlans, - ]; + return [enablePrepaidPlans]; } static PlatformPendingPurchasesParams decode(Object result) { @@ -979,7 +931,8 @@ class _PigeonCodec extends StandardMessageCodec { return PlatformProductDetailsResponse.decode(readValue(buffer)!); case 142: return PlatformAlternativeBillingOnlyReportingDetailsResponse.decode( - readValue(buffer)!); + readValue(buffer)!, + ); case 143: return PlatformBillingConfigResponse.decode(readValue(buffer)!); case 144: @@ -1016,11 +969,12 @@ class InAppPurchaseApi { /// Constructor for [InAppPurchaseApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - InAppPurchaseApi( - {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = - messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + InAppPurchaseApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -1033,10 +987,10 @@ class InAppPurchaseApi { 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.isReady$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -1059,20 +1013,25 @@ class InAppPurchaseApi { /// Wraps BillingClient#startConnection(BillingClientStateListener). Future startConnection( - int callbackHandle, - PlatformBillingChoiceMode billingMode, - PlatformPendingPurchasesParams pendingPurchasesParams) async { + int callbackHandle, + PlatformBillingChoiceMode billingMode, + PlatformPendingPurchasesParams pendingPurchasesParams, + ) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.startConnection$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = await pigeonVar_channel.send( - [callbackHandle, billingMode, pendingPurchasesParams]) - as List?; + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send([ + callbackHandle, + billingMode, + pendingPurchasesParams, + ]) + as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -1097,10 +1056,10 @@ class InAppPurchaseApi { 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.endConnection$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -1122,10 +1081,10 @@ class InAppPurchaseApi { 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.getBillingConfigAsync$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -1148,15 +1107,16 @@ class InAppPurchaseApi { /// Wraps BillingClient#launchBillingFlow(Activity, BillingFlowParams). Future launchBillingFlow( - PlatformBillingFlowParams params) async { + PlatformBillingFlowParams params, + ) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.launchBillingFlow$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send([params]) as List?; if (pigeonVar_replyList == null) { @@ -1179,17 +1139,19 @@ class InAppPurchaseApi { /// Wraps BillingClient#acknowledgePurchase(AcknowledgePurchaseParams, AcknowledgePurchaseResponseListener). Future acknowledgePurchase( - String purchaseToken) async { + String purchaseToken, + ) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.acknowledgePurchase$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([purchaseToken]) as List?; + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send([purchaseToken]) + as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -1214,12 +1176,13 @@ class InAppPurchaseApi { 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.consumeAsync$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([purchaseToken]) as List?; + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send([purchaseToken]) + as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -1240,15 +1203,16 @@ class InAppPurchaseApi { /// Wraps BillingClient#queryPurchasesAsync(QueryPurchaseParams, PurchaseResponseListener). Future queryPurchasesAsync( - PlatformProductType productType) async { + PlatformProductType productType, + ) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.queryPurchasesAsync$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send([productType]) as List?; if (pigeonVar_replyList == null) { @@ -1271,15 +1235,16 @@ class InAppPurchaseApi { /// Wraps BillingClient#queryPurchaseHistoryAsync(QueryPurchaseHistoryParams, PurchaseHistoryResponseListener). Future queryPurchaseHistoryAsync( - PlatformProductType productType) async { + PlatformProductType productType, + ) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.queryPurchaseHistoryAsync$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send([productType]) as List?; if (pigeonVar_replyList == null) { @@ -1302,15 +1267,16 @@ class InAppPurchaseApi { /// Wraps BillingClient#queryProductDetailsAsync(QueryProductDetailsParams, ProductDetailsResponseListener). Future queryProductDetailsAsync( - List products) async { + List products, + ) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.queryProductDetailsAsync$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send([products]) as List?; if (pigeonVar_replyList == null) { @@ -1337,10 +1303,10 @@ class InAppPurchaseApi { 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.isFeatureSupported$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send([feature]) as List?; if (pigeonVar_replyList == null) { @@ -1367,10 +1333,10 @@ class InAppPurchaseApi { 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.isAlternativeBillingOnlyAvailableAsync$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -1393,15 +1359,15 @@ class InAppPurchaseApi { /// Wraps BillingClient#showAlternativeBillingOnlyInformationDialog(). Future - showAlternativeBillingOnlyInformationDialog() async { + showAlternativeBillingOnlyInformationDialog() async { final String pigeonVar_channelName = 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.showAlternativeBillingOnlyInformationDialog$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -1424,15 +1390,15 @@ class InAppPurchaseApi { /// Wraps BillingClient#createAlternativeBillingOnlyReportingDetailsAsync(AlternativeBillingOnlyReportingDetailsListener). Future - createAlternativeBillingOnlyReportingDetailsAsync() async { + createAlternativeBillingOnlyReportingDetailsAsync() async { final String pigeonVar_channelName = 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.createAlternativeBillingOnlyReportingDetailsAsync$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -1475,22 +1441,26 @@ abstract class InAppPurchaseCallbackApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.onBillingServiceDisconnected$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.onBillingServiceDisconnected$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.onBillingServiceDisconnected was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.onBillingServiceDisconnected was null.', + ); final List args = (message as List?)!; final int? arg_callbackHandle = (args[0] as int?); - assert(arg_callbackHandle != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.onBillingServiceDisconnected was null, expected non-null int.'); + assert( + arg_callbackHandle != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.onBillingServiceDisconnected was null, expected non-null int.', + ); try { api.onBillingServiceDisconnected(arg_callbackHandle!); return wrapResponse(empty: true); @@ -1498,29 +1468,34 @@ abstract class InAppPurchaseCallbackApi { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.onPurchasesUpdated$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.onPurchasesUpdated$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.onPurchasesUpdated was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.onPurchasesUpdated was null.', + ); final List args = (message as List?)!; final PlatformPurchasesResponse? arg_update = (args[0] as PlatformPurchasesResponse?); - assert(arg_update != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.onPurchasesUpdated was null, expected non-null PlatformPurchasesResponse.'); + assert( + arg_update != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.onPurchasesUpdated was null, expected non-null PlatformPurchasesResponse.', + ); try { api.onPurchasesUpdated(arg_update!); return wrapResponse(empty: true); @@ -1528,29 +1503,34 @@ abstract class InAppPurchaseCallbackApi { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.userSelectedalternativeBilling$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.userSelectedalternativeBilling$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.userSelectedalternativeBilling was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.userSelectedalternativeBilling was null.', + ); final List args = (message as List?)!; final PlatformUserChoiceDetails? arg_details = (args[0] as PlatformUserChoiceDetails?); - assert(arg_details != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.userSelectedalternativeBilling was null, expected non-null PlatformUserChoiceDetails.'); + assert( + arg_details != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseCallbackApi.userSelectedalternativeBilling was null, expected non-null PlatformUserChoiceDetails.', + ); try { api.userSelectedalternativeBilling(arg_details!); return wrapResponse(empty: true); @@ -1558,7 +1538,8 @@ abstract class InAppPurchaseCallbackApi { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/pigeon_converters.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/pigeon_converters.dart index 78393f94c20..f3687f78ecd 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/pigeon_converters.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/pigeon_converters.dart @@ -24,23 +24,26 @@ PlatformBillingChoiceMode platformBillingChoiceMode(BillingChoiceMode mode) { /// Creates a [BillingResultWrapper] from the Pigeon equivalent. BillingResultWrapper resultWrapperFromPlatform(PlatformBillingResult result) { return BillingResultWrapper( - responseCode: billingResponseFromPlatform(result.responseCode), - debugMessage: result.debugMessage); + responseCode: billingResponseFromPlatform(result.responseCode), + debugMessage: result.debugMessage, + ); } /// Creates a [ProductDetailsResponseWrapper] from the Pigeon equivalent. ProductDetailsResponseWrapper productDetailsResponseWrapperFromPlatform( - PlatformProductDetailsResponse response) { + PlatformProductDetailsResponse response, +) { return ProductDetailsResponseWrapper( - billingResult: resultWrapperFromPlatform(response.billingResult), - productDetailsList: response.productDetails - .map(productDetailsWrapperFromPlatform) - .toList()); + billingResult: resultWrapperFromPlatform(response.billingResult), + productDetailsList: + response.productDetails.map(productDetailsWrapperFromPlatform).toList(), + ); } /// Creates a [ProductDetailsWrapper] from the Pigeon equivalent. ProductDetailsWrapper productDetailsWrapperFromPlatform( - PlatformProductDetails product) { + PlatformProductDetails product, +) { return ProductDetailsWrapper( description: product.description, name: product.name, @@ -48,17 +51,20 @@ ProductDetailsWrapper productDetailsWrapperFromPlatform( productType: productTypeFromPlatform(product.productType), title: product.title, oneTimePurchaseOfferDetails: oneTimePurchaseOfferDetailsWrapperFromPlatform( - product.oneTimePurchaseOfferDetails), - subscriptionOfferDetails: product.subscriptionOfferDetails - ?.map(subscriptionOfferDetailsWrapperFromPlatform) - .toList(), + product.oneTimePurchaseOfferDetails, + ), + subscriptionOfferDetails: + product.subscriptionOfferDetails + ?.map(subscriptionOfferDetailsWrapperFromPlatform) + .toList(), ); } /// Creates a [OneTimePurchaseOfferDetailsWrapper] from the Pigeon equivalent. OneTimePurchaseOfferDetailsWrapper? - oneTimePurchaseOfferDetailsWrapperFromPlatform( - PlatformOneTimePurchaseOfferDetails? details) { +oneTimePurchaseOfferDetailsWrapperFromPlatform( + PlatformOneTimePurchaseOfferDetails? details, +) { if (details == null) { return null; } @@ -71,18 +77,21 @@ OneTimePurchaseOfferDetailsWrapper? /// Creates a [PurchaseHistoryResult] from the Pigeon equivalent. PurchasesHistoryResult purchaseHistoryResultFromPlatform( - PlatformPurchaseHistoryResponse response) { + PlatformPurchaseHistoryResponse response, +) { return PurchasesHistoryResult( billingResult: resultWrapperFromPlatform(response.billingResult), - purchaseHistoryRecordList: response.purchases - .map(purchaseHistoryRecordWrapperFromPlatform) - .toList(), + purchaseHistoryRecordList: + response.purchases + .map(purchaseHistoryRecordWrapperFromPlatform) + .toList(), ); } /// Creates a [PurchaseHistoryRecordWrapper] from the Pigeon equivalent. PurchaseHistoryRecordWrapper purchaseHistoryRecordWrapperFromPlatform( - PlatformPurchaseHistoryRecord record) { + PlatformPurchaseHistoryRecord record, +) { return PurchaseHistoryRecordWrapper( purchaseTime: record.purchaseTime, purchaseToken: record.purchaseToken, @@ -95,22 +104,25 @@ PurchaseHistoryRecordWrapper purchaseHistoryRecordWrapperFromPlatform( /// Creates a [PurchasesResultWrapper] from the Pigeon equivalent. PurchasesResultWrapper purchasesResultWrapperFromPlatform( - PlatformPurchasesResponse response, - {bool forceOkResponseCode = false}) { + PlatformPurchasesResponse response, { + bool forceOkResponseCode = false, +}) { return PurchasesResultWrapper( billingResult: resultWrapperFromPlatform(response.billingResult), purchasesList: response.purchases.map(purchaseWrapperFromPlatform).toList(), - responseCode: forceOkResponseCode - ? BillingResponse.ok - : billingResponseFromPlatform(response.billingResult.responseCode), + responseCode: + forceOkResponseCode + ? BillingResponse.ok + : billingResponseFromPlatform(response.billingResult.responseCode), ); } /// Creates an [AlternativeBillingOnlyReportingDetailsWrapper] from the Pigeon /// equivalent. AlternativeBillingOnlyReportingDetailsWrapper - alternativeBillingOnlyReportingDetailsWrapperFromPlatform( - PlatformAlternativeBillingOnlyReportingDetailsResponse response) { +alternativeBillingOnlyReportingDetailsWrapperFromPlatform( + PlatformAlternativeBillingOnlyReportingDetailsResponse response, +) { return AlternativeBillingOnlyReportingDetailsWrapper( responseCode: billingResponseFromPlatform( response.billingResult.responseCode, @@ -122,7 +134,8 @@ AlternativeBillingOnlyReportingDetailsWrapper /// Creates a [BillingConfigWrapper] from the Pigeon equivalent. BillingConfigWrapper billingConfigWrapperFromPlatform( - PlatformBillingConfigResponse response) { + PlatformBillingConfigResponse response, +) { return BillingConfigWrapper( responseCode: billingResponseFromPlatform( response.billingResult.responseCode, @@ -150,7 +163,8 @@ PlatformProductType platformProductTypeFromWrapper(ProductType type) { /// Creates a [PricingPhaseWrapper] from its Pigeon equivalent. PricingPhaseWrapper pricingPhaseWrapperFromPlatform( - PlatformPricingPhase phase) { + PlatformPricingPhase phase, +) { return PricingPhaseWrapper( billingCycleCount: phase.billingCycleCount, billingPeriod: phase.billingPeriod, @@ -185,26 +199,30 @@ PurchaseWrapper purchaseWrapperFromPlatform(PlatformPurchase purchase) { developerPayload: purchase.developerPayload, obfuscatedAccountId: purchase.accountIdentifiers?.obfuscatedAccountId, obfuscatedProfileId: purchase.accountIdentifiers?.obfuscatedProfileId, - pendingPurchaseUpdate: - pendingPurchaseUpdateFromPlatform(purchase.pendingPurchaseUpdate), + pendingPurchaseUpdate: pendingPurchaseUpdateFromPlatform( + purchase.pendingPurchaseUpdate, + ), ); } /// Creates a [PendingPurchaseUpdateWrapper] from the Pigeon equivalent. PendingPurchaseUpdateWrapper? pendingPurchaseUpdateFromPlatform( - PlatformPendingPurchaseUpdate? pendingPurchaseUpdate) { + PlatformPendingPurchaseUpdate? pendingPurchaseUpdate, +) { if (pendingPurchaseUpdate == null) { return null; } return PendingPurchaseUpdateWrapper( - purchaseToken: pendingPurchaseUpdate.purchaseToken, - products: pendingPurchaseUpdate.products); + purchaseToken: pendingPurchaseUpdate.purchaseToken, + products: pendingPurchaseUpdate.products, + ); } /// Creates a [PurchaseStateWrapper] from the Pigeon equivalent. PurchaseStateWrapper purchaseStateWrapperFromPlatform( - PlatformPurchaseState state) { + PlatformPurchaseState state, +) { return switch (state) { PlatformPurchaseState.unspecified => PurchaseStateWrapper.unspecified_state, PlatformPurchaseState.purchased => PurchaseStateWrapper.purchased, @@ -233,7 +251,8 @@ RecurrenceMode recurrenceModeFromPlatform(PlatformRecurrenceMode mode) { /// Creates a [SubscriptionOfferDetailsWrapper] from the Pigeon equivalent. SubscriptionOfferDetailsWrapper subscriptionOfferDetailsWrapperFromPlatform( - PlatformSubscriptionOfferDetails offer) { + PlatformSubscriptionOfferDetails offer, +) { return SubscriptionOfferDetailsWrapper( basePlanId: offer.basePlanId, offerId: offer.offerId, @@ -241,14 +260,16 @@ SubscriptionOfferDetailsWrapper subscriptionOfferDetailsWrapperFromPlatform( offerIdToken: offer.offerToken, pricingPhases: offer.pricingPhases.map(pricingPhaseWrapperFromPlatform).toList(), - installmentPlanDetails: - installmentPlanDetailsFromPlatform(offer.installmentPlanDetails), + installmentPlanDetails: installmentPlanDetailsFromPlatform( + offer.installmentPlanDetails, + ), ); } /// Creates a [UserChoiceDetailsWrapper] from the Pigeon equivalent. UserChoiceDetailsWrapper userChoiceDetailsFromPlatform( - PlatformUserChoiceDetails details) { + PlatformUserChoiceDetails details, +) { return UserChoiceDetailsWrapper( originalExternalTransactionId: details.originalExternalTransactionId ?? '', externalTransactionToken: details.externalTransactionToken, @@ -259,7 +280,8 @@ UserChoiceDetailsWrapper userChoiceDetailsFromPlatform( /// Creates a [UserChoiceDetailsProductWrapper] from the Pigeon equivalent. UserChoiceDetailsProductWrapper userChoiceDetailsProductFromPlatform( - PlatformUserChoiceProduct product) { + PlatformUserChoiceProduct product, +) { return UserChoiceDetailsProductWrapper( id: product.id, offerToken: product.offerToken ?? '', @@ -269,7 +291,8 @@ UserChoiceDetailsProductWrapper userChoiceDetailsProductFromPlatform( /// Creates a [InstallmentPlanDetailsWrapper] from the Pigeon equivalent. InstallmentPlanDetailsWrapper? installmentPlanDetailsFromPlatform( - PlatformInstallmentPlanDetails? details) { + PlatformInstallmentPlanDetails? details, +) { if (details == null) { return null; } @@ -283,7 +306,8 @@ InstallmentPlanDetailsWrapper? installmentPlanDetailsFromPlatform( /// Converts a [PendingPurchasesParamsWrapper] to its Pigeon equivalent. PlatformPendingPurchasesParams pendingPurchasesParamsFromWrapper( - PendingPurchasesParamsWrapper params) { + PendingPurchasesParamsWrapper params, +) { return PlatformPendingPurchasesParams( enablePrepaidPlans: params.enablePrepaidPlans, ); @@ -291,7 +315,8 @@ PlatformPendingPurchasesParams pendingPurchasesParamsFromWrapper( /// Converts [PlatformBillingResponse] to its public API enum equivalent. BillingResponse billingResponseFromPlatform( - PlatformBillingResponse responseCode) { + PlatformBillingResponse responseCode, +) { return switch (responseCode) { PlatformBillingResponse.serviceTimeout => BillingResponse.serviceTimeout, PlatformBillingResponse.featureNotSupported => @@ -316,7 +341,8 @@ BillingResponse billingResponseFromPlatform( /// Converts a [BillingResponse] to its Pigeon equivalent. PlatformBillingResponse billingResponseFromWrapper( - BillingResponse responseCode) { + BillingResponse responseCode, +) { return switch (responseCode) { BillingResponse.serviceTimeout => PlatformBillingResponse.serviceTimeout, BillingResponse.featureNotSupported => @@ -341,7 +367,8 @@ PlatformBillingResponse billingResponseFromWrapper( /// Converts [ReplacementMode] enum to its Pigeon equivalent. PlatformReplacementMode replacementModeFromWrapper( - ReplacementMode replacementMode) { + ReplacementMode replacementMode, +) { return switch (replacementMode) { ReplacementMode.unknownReplacementMode => PlatformReplacementMode.unknownReplacementMode, @@ -358,7 +385,8 @@ PlatformReplacementMode replacementModeFromWrapper( /// Converts [BillingClientFeature] enum to its Pigeon equivalent. PlatformBillingClientFeature billingClientFeatureFromWrapper( - BillingClientFeature feature) { + BillingClientFeature feature, +) { return switch (feature) { BillingClientFeature.alternativeBillingOnly => PlatformBillingClientFeature.alternativeBillingOnly, diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_product_details.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_product_details.dart index 0d3beaea513..cc45f8617ba 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_product_details.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_product_details.dart @@ -104,18 +104,23 @@ class GooglePlayProductDetails extends ProductDetails { if (productDetails.productType == ProductType.inapp) { return [ GooglePlayProductDetails._fromOneTimePurchaseProductDetails( - productDetails), + productDetails, + ), ]; } else { final List productDetailList = []; - for (int subscriptionIndex = 0; - subscriptionIndex < productDetails.subscriptionOfferDetails!.length; - subscriptionIndex++) { - productDetailList.add(GooglePlayProductDetails._fromSubscription( - productDetails, - subscriptionIndex, - )); + for ( + int subscriptionIndex = 0; + subscriptionIndex < productDetails.subscriptionOfferDetails!.length; + subscriptionIndex++ + ) { + productDetailList.add( + GooglePlayProductDetails._fromSubscription( + productDetails, + subscriptionIndex, + ), + ); } return productDetailList; @@ -153,9 +158,11 @@ class GooglePlayProductDetails extends ProductDetails { /// The offerToken of the subscription this [GooglePlayProductDetails] /// object was contructed for, or `null` if it was not a subscription. - String? get offerToken => subscriptionIndex != null && - productDetails.subscriptionOfferDetails != null - ? productDetails - .subscriptionOfferDetails![subscriptionIndex!].offerIdToken - : null; + String? get offerToken => + subscriptionIndex != null && + productDetails.subscriptionOfferDetails != null + ? productDetails + .subscriptionOfferDetails![subscriptionIndex!] + .offerIdToken + : null; } diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_details.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_details.dart index 1dbe4305fa5..4fe5d5ea4bd 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_details.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_details.dart @@ -27,20 +27,22 @@ class GooglePlayPurchaseDetails extends PurchaseDetails { /// /// The list contains one entry per product. static List fromPurchase( - PurchaseWrapper purchase) { + PurchaseWrapper purchase, + ) { return purchase.products.map((String productId) { final GooglePlayPurchaseDetails purchaseDetails = GooglePlayPurchaseDetails( - purchaseID: purchase.orderId, - productID: productId, - verificationData: PurchaseVerificationData( - localVerificationData: purchase.originalJson, - serverVerificationData: purchase.purchaseToken, - source: kIAPSource), - transactionDate: purchase.purchaseTime.toString(), - billingClientPurchase: purchase, - status: purchaseStatusFromWrapper(purchase.purchaseState), - ); + purchaseID: purchase.orderId, + productID: productId, + verificationData: PurchaseVerificationData( + localVerificationData: purchase.originalJson, + serverVerificationData: purchase.purchaseToken, + source: kIAPSource, + ), + transactionDate: purchase.purchaseTime.toString(), + billingClientPurchase: purchase, + status: purchaseStatusFromWrapper(purchase.purchaseState), + ); if (purchaseDetails.status == PurchaseStatus.error) { purchaseDetails.error = IAPError( diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_user_choice_details.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_user_choice_details.dart index 97553b34575..4f18bde8fbb 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_user_choice_details.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_user_choice_details.dart @@ -45,10 +45,10 @@ class GooglePlayUserChoiceDetails { @override int get hashCode => Object.hash( - originalExternalTransactionId, - externalTransactionToken, - products.hashCode, - ); + originalExternalTransactionId, + externalTransactionToken, + products.hashCode, + ); } /// Data structure representing a UserChoiceDetails product. @@ -57,8 +57,11 @@ class GooglePlayUserChoiceDetails { @immutable class GooglePlayUserChoiceDetailsProduct { /// Creates UserChoiceDetailsProduct. - const GooglePlayUserChoiceDetailsProduct( - {required this.id, required this.offerToken, required this.productType}); + const GooglePlayUserChoiceDetailsProduct({ + required this.id, + required this.offerToken, + required this.productType, + }); /// Returns the id of the product being purchased. final String id; @@ -84,11 +87,7 @@ class GooglePlayUserChoiceDetailsProduct { } @override - int get hashCode => Object.hash( - id, - offerToken, - productType, - ); + int get hashCode => Object.hash(id, offerToken, productType); } /// This wraps [`com.android.billingclient.api.BillingClient.ProductType`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.ProductType) @@ -97,5 +96,5 @@ enum GooglePlayProductType { inapp, /// A Product type for Android apps subscriptions. - subs + subs, } diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/translator.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/translator.dart index f6461afc2c2..eb675ffd700 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/translator.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/translator.dart @@ -13,25 +13,32 @@ class Translator { /// Converts from [UserChoiceDetailsWrapper] to [GooglePlayUserChoiceDetails]. static GooglePlayUserChoiceDetails convertToUserChoiceDetails( - UserChoiceDetailsWrapper detailsWrapper) { + UserChoiceDetailsWrapper detailsWrapper, + ) { return GooglePlayUserChoiceDetails( - originalExternalTransactionId: - detailsWrapper.originalExternalTransactionId, - externalTransactionToken: detailsWrapper.externalTransactionToken, - products: detailsWrapper.products - .map((UserChoiceDetailsProductWrapper e) => - convertToUserChoiceDetailsProduct(e)) - .toList()); + originalExternalTransactionId: + detailsWrapper.originalExternalTransactionId, + externalTransactionToken: detailsWrapper.externalTransactionToken, + products: + detailsWrapper.products + .map( + (UserChoiceDetailsProductWrapper e) => + convertToUserChoiceDetailsProduct(e), + ) + .toList(), + ); } /// Converts from [UserChoiceDetailsProductWrapper] to [GooglePlayUserChoiceDetailsProduct]. @visibleForTesting static GooglePlayUserChoiceDetailsProduct convertToUserChoiceDetailsProduct( - UserChoiceDetailsProductWrapper productWrapper) { + UserChoiceDetailsProductWrapper productWrapper, + ) { return GooglePlayUserChoiceDetailsProduct( - id: productWrapper.id, - offerToken: productWrapper.offerToken, - productType: convertToPlayProductType(productWrapper.productType)); + id: productWrapper.id, + offerToken: productWrapper.offerToken, + productType: convertToPlayProductType(productWrapper.productType), + ); } /// Coverts from [ProductType] to [GooglePlayProductType]. diff --git a/packages/in_app_purchase/in_app_purchase_android/migration_guide.md b/packages/in_app_purchase/in_app_purchase_android/migration_guide.md index 8f0f69b55aa..5d0ef0a7d91 100644 --- a/packages/in_app_purchase/in_app_purchase_android/migration_guide.md +++ b/packages/in_app_purchase/in_app_purchase_android/migration_guide.md @@ -142,6 +142,7 @@ void handleIntroductoryPricePeriod(ProductDetails productDetails) { } } } + ``` ## Removal of `launchPriceChangeConfirmationFlow` diff --git a/packages/in_app_purchase/in_app_purchase_android/pigeons/messages.dart b/packages/in_app_purchase/in_app_purchase_android/pigeons/messages.dart index 1e15f2ad8e3..d9083af1ab8 100644 --- a/packages/in_app_purchase/in_app_purchase_android/pigeons/messages.dart +++ b/packages/in_app_purchase/in_app_purchase_android/pigeons/messages.dart @@ -4,14 +4,15 @@ import 'package:pigeon/pigeon.dart'; -@ConfigurePigeon(PigeonOptions( - dartOut: 'lib/src/messages.g.dart', - javaOptions: JavaOptions(package: 'io.flutter.plugins.inapppurchase'), - javaOut: - 'android/src/main/java/io/flutter/plugins/inapppurchase/Messages.java', - copyrightHeader: 'pigeons/copyright.txt', -)) - +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/src/messages.g.dart', + javaOptions: JavaOptions(package: 'io.flutter.plugins.inapppurchase'), + javaOut: + 'android/src/main/java/io/flutter/plugins/inapppurchase/Messages.java', + copyrightHeader: 'pigeons/copyright.txt', + ), +) /// Pigeon version of Java QueryProductDetailsParams.Product. class PlatformQueryProduct { PlatformQueryProduct({required this.productId, required this.productType}); @@ -33,8 +34,10 @@ class PlatformAccountIdentifiers { /// Pigeon version of Java BillingResult. class PlatformBillingResult { - PlatformBillingResult( - {required this.responseCode, required this.debugMessage}); + PlatformBillingResult({ + required this.responseCode, + required this.debugMessage, + }); final PlatformBillingResponse responseCode; final String debugMessage; } @@ -106,8 +109,10 @@ class PlatformProductDetailsResponse { /// contains the components of the Java /// AlternativeBillingOnlyReportingDetailsListener callback. class PlatformAlternativeBillingOnlyReportingDetailsResponse { - PlatformAlternativeBillingOnlyReportingDetailsResponse( - {required this.billingResult, required this.externalTransactionToken}); + PlatformAlternativeBillingOnlyReportingDetailsResponse({ + required this.billingResult, + required this.externalTransactionToken, + }); final PlatformBillingResult billingResult; final String externalTransactionToken; @@ -116,8 +121,10 @@ class PlatformAlternativeBillingOnlyReportingDetailsResponse { /// Pigeon version of BillingConfigWrapper, which contains the components of the /// Java BillingConfigResponseListener callback. class PlatformBillingConfigResponse { - PlatformBillingConfigResponse( - {required this.billingResult, required this.countryCode}); + PlatformBillingConfigResponse({ + required this.billingResult, + required this.countryCode, + }); final PlatformBillingResult billingResult; final String countryCode; @@ -332,18 +339,13 @@ class PlatformInstallmentPlanDetails { /// Pigeon version of Java PendingPurchasesParams. class PlatformPendingPurchasesParams { - PlatformPendingPurchasesParams({ - required this.enablePrepaidPlans, - }); + PlatformPendingPurchasesParams({required this.enablePrepaidPlans}); final bool enablePrepaidPlans; } /// Pigeon version of Java BillingClient.ProductType. -enum PlatformProductType { - inapp, - subs, -} +enum PlatformProductType { inapp, subs } /// Pigeon version of billing_client_wrapper.dart's BillingChoiceMode. enum PlatformBillingChoiceMode { @@ -372,18 +374,10 @@ enum PlatformBillingClientFeature { } /// Pigeon version of Java Purchase.PurchaseState. -enum PlatformPurchaseState { - unspecified, - purchased, - pending, -} +enum PlatformPurchaseState { unspecified, purchased, pending } /// Pigeon version of Java ProductDetails.RecurrenceMode. -enum PlatformRecurrenceMode { - finiteRecurring, - infiniteRecurring, - nonRecurring, -} +enum PlatformRecurrenceMode { finiteRecurring, infiniteRecurring, nonRecurring } @HostApi() abstract class InAppPurchaseApi { @@ -393,9 +387,10 @@ abstract class InAppPurchaseApi { /// Wraps BillingClient#startConnection(BillingClientStateListener). @async PlatformBillingResult startConnection( - int callbackHandle, - PlatformBillingChoiceMode billingMode, - PlatformPendingPurchasesParams pendingPurchasesParams); + int callbackHandle, + PlatformBillingChoiceMode billingMode, + PlatformPendingPurchasesParams pendingPurchasesParams, + ); /// Wraps BillingClient#endConnection(BillingClientStateListener). void endConnection(); @@ -418,17 +413,20 @@ abstract class InAppPurchaseApi { /// Wraps BillingClient#queryPurchasesAsync(QueryPurchaseParams, PurchaseResponseListener). @async PlatformPurchasesResponse queryPurchasesAsync( - PlatformProductType productType); + PlatformProductType productType, + ); /// Wraps BillingClient#queryPurchaseHistoryAsync(QueryPurchaseHistoryParams, PurchaseHistoryResponseListener). @async PlatformPurchaseHistoryResponse queryPurchaseHistoryAsync( - PlatformProductType productType); + PlatformProductType productType, + ); /// Wraps BillingClient#queryProductDetailsAsync(QueryProductDetailsParams, ProductDetailsResponseListener). @async PlatformProductDetailsResponse queryProductDetailsAsync( - List products); + List products, + ); /// Wraps BillingClient#isFeatureSupported(String). bool isFeatureSupported(PlatformBillingClientFeature feature); @@ -444,7 +442,7 @@ abstract class InAppPurchaseApi { /// Wraps BillingClient#createAlternativeBillingOnlyReportingDetailsAsync(AlternativeBillingOnlyReportingDetailsListener). @async PlatformAlternativeBillingOnlyReportingDetailsResponse - createAlternativeBillingOnlyReportingDetailsAsync(); + createAlternativeBillingOnlyReportingDetailsAsync(); } @FlutterApi() diff --git a/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml index 1d3801d3b5d..839b3dfc23a 100644 --- a/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml @@ -6,8 +6,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.4.0+3 environment: - sdk: ^3.6.0 - flutter: ">=3.27.0" + sdk: ^3.7.0 + flutter: ">=3.29.0" flutter: plugin: diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_manager_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_manager_test.dart index 59eb1d01f5c..e515ab6da1a 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_manager_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_manager_test.dart @@ -22,14 +22,20 @@ void main() { setUp(() { WidgetsFlutterBinding.ensureInitialized(); mockApi = MockInAppPurchaseApi(); - when(mockApi.startConnection(any, any, any)).thenAnswer((_) async => - PlatformBillingResult( - responseCode: PlatformBillingResponse.ok, debugMessage: '')); + when(mockApi.startConnection(any, any, any)).thenAnswer( + (_) async => PlatformBillingResult( + responseCode: PlatformBillingResponse.ok, + debugMessage: '', + ), + ); manager = BillingClientManager( - billingClientFactory: (PurchasesUpdatedListener listener, - UserSelectedAlternativeBillingListener? - alternativeBillingListener) => - BillingClient(listener, alternativeBillingListener, api: mockApi)); + billingClientFactory: + ( + PurchasesUpdatedListener listener, + UserSelectedAlternativeBillingListener? alternativeBillingListener, + ) => + BillingClient(listener, alternativeBillingListener, api: mockApi), + ); }); group('BillingClientWrapper', () { @@ -42,18 +48,24 @@ void main() { when(mockApi.startConnection(any, any, any)).thenAnswer((_) async { connectedCompleter.complete(); return PlatformBillingResult( - responseCode: PlatformBillingResponse.ok, debugMessage: ''); + responseCode: PlatformBillingResponse.ok, + debugMessage: '', + ); }); final Completer calledCompleter1 = Completer(); final Completer calledCompleter2 = Completer(); - unawaited(manager.runWithClient((BillingClient _) async { - calledCompleter1.complete(); - return const BillingResultWrapper(responseCode: BillingResponse.ok); - })); - unawaited(manager.runWithClientNonRetryable( - (BillingClient _) async => calledCompleter2.complete(), - )); + unawaited( + manager.runWithClient((BillingClient _) async { + calledCompleter1.complete(); + return const BillingResultWrapper(responseCode: BillingResponse.ok); + }), + ); + unawaited( + manager.runWithClientNonRetryable( + (BillingClient _) async => calledCompleter2.complete(), + ), + ); expect(calledCompleter1.isCompleted, equals(false)); expect(calledCompleter1.isCompleted, equals(false)); connectedCompleter.complete(); @@ -61,61 +73,75 @@ void main() { await expectLater(calledCompleter2.future, completes); }); - test('re-connects when client sends onBillingServiceDisconnected', - () async { - // Ensures all asynchronous connected code finishes. - await manager.runWithClientNonRetryable((_) async {}); + test( + 're-connects when client sends onBillingServiceDisconnected', + () async { + // Ensures all asynchronous connected code finishes. + await manager.runWithClientNonRetryable((_) async {}); - manager.client.hostCallbackHandler.onBillingServiceDisconnected(0); - verify(mockApi.startConnection(any, any, any)).called(2); - }); + manager.client.hostCallbackHandler.onBillingServiceDisconnected(0); + verify(mockApi.startConnection(any, any, any)).called(2); + }, + ); - test('re-connects when host calls reconnectWithBillingChoiceMode', - () async { - // Ensures all asynchronous connected code finishes. - await manager.runWithClientNonRetryable((_) async {}); + test( + 're-connects when host calls reconnectWithBillingChoiceMode', + () async { + // Ensures all asynchronous connected code finishes. + await manager.runWithClientNonRetryable((_) async {}); - await manager.reconnectWithBillingChoiceMode( - BillingChoiceMode.alternativeBillingOnly); - // Verify that connection was ended. - verify(mockApi.endConnection()).called(1); + await manager.reconnectWithBillingChoiceMode( + BillingChoiceMode.alternativeBillingOnly, + ); + // Verify that connection was ended. + verify(mockApi.endConnection()).called(1); - clearInteractions(mockApi); + clearInteractions(mockApi); - /// Fake the disconnect that we would expect from a endConnectionCall. - manager.client.hostCallbackHandler.onBillingServiceDisconnected(0); - // Verify that after connection ended reconnect was called. - final VerificationResult result = - verify(mockApi.startConnection(any, captureAny, any)); - expect(result.captured.single, - PlatformBillingChoiceMode.alternativeBillingOnly); - }); + /// Fake the disconnect that we would expect from a endConnectionCall. + manager.client.hostCallbackHandler.onBillingServiceDisconnected(0); + // Verify that after connection ended reconnect was called. + final VerificationResult result = verify( + mockApi.startConnection(any, captureAny, any), + ); + expect( + result.captured.single, + PlatformBillingChoiceMode.alternativeBillingOnly, + ); + }, + ); - test('re-connects when host calls reconnectWithPendingPurchasesParams', - () async { - // Ensures all asynchronous connected code finishes. - await manager.runWithClientNonRetryable((_) async {}); + test( + 're-connects when host calls reconnectWithPendingPurchasesParams', + () async { + // Ensures all asynchronous connected code finishes. + await manager.runWithClientNonRetryable((_) async {}); - await manager.reconnectWithPendingPurchasesParams( - const PendingPurchasesParamsWrapper(enablePrepaidPlans: true)); - // Verify that connection was ended. - verify(mockApi.endConnection()).called(1); + await manager.reconnectWithPendingPurchasesParams( + const PendingPurchasesParamsWrapper(enablePrepaidPlans: true), + ); + // Verify that connection was ended. + verify(mockApi.endConnection()).called(1); - clearInteractions(mockApi); + clearInteractions(mockApi); - /// Fake the disconnect that we would expect from a endConnectionCall. - manager.client.hostCallbackHandler.onBillingServiceDisconnected(0); - // Verify that after connection ended reconnect was called. - final VerificationResult result = - verify(mockApi.startConnection(any, any, captureAny)); - expect( + /// Fake the disconnect that we would expect from a endConnectionCall. + manager.client.hostCallbackHandler.onBillingServiceDisconnected(0); + // Verify that after connection ended reconnect was called. + final VerificationResult result = verify( + mockApi.startConnection(any, any, captureAny), + ); + expect( result.captured.single, isA().having( - (PlatformPendingPurchasesParams params) => - params.enablePrepaidPlans, - 'enablePrepaidPlans', - true)); - }); + (PlatformPendingPurchasesParams params) => + params.enablePrepaidPlans, + 'enablePrepaidPlans', + true, + ), + ); + }, + ); test( 're-connects when operation returns BillingResponse.serviceDisconnected', @@ -123,16 +149,17 @@ void main() { clearInteractions(mockApi); int timesCalled = 0; - final BillingResultWrapper result = await manager.runWithClient( - (BillingClient _) async { - timesCalled++; - return BillingResultWrapper( - responseCode: timesCalled == 1 - ? BillingResponse.serviceDisconnected - : BillingResponse.ok, - ); - }, - ); + final BillingResultWrapper result = await manager.runWithClient(( + BillingClient _, + ) async { + timesCalled++; + return BillingResultWrapper( + responseCode: + timesCalled == 1 + ? BillingResponse.serviceDisconnected + : BillingResponse.ok, + ); + }); verify(mockApi.startConnection(any, any, any)).called(1); expect(timesCalled, equals(2)); expect(result.responseCode, equals(BillingResponse.ok)); @@ -147,29 +174,32 @@ void main() { }); test( - 'Emits UserChoiceDetailsWrapper when onUserChoiceAlternativeBilling is called', - () async { - // Ensures all asynchronous connected code finishes. - await manager.runWithClientNonRetryable((_) async {}); - - const UserChoiceDetailsWrapper expected = UserChoiceDetailsWrapper( - originalExternalTransactionId: 'TransactionId', - externalTransactionToken: 'TransactionToken', - products: [ - UserChoiceDetailsProductWrapper( + 'Emits UserChoiceDetailsWrapper when onUserChoiceAlternativeBilling is called', + () async { + // Ensures all asynchronous connected code finishes. + await manager.runWithClientNonRetryable((_) async {}); + + const UserChoiceDetailsWrapper expected = UserChoiceDetailsWrapper( + originalExternalTransactionId: 'TransactionId', + externalTransactionToken: 'TransactionToken', + products: [ + UserChoiceDetailsProductWrapper( id: 'id1', offerToken: 'offerToken1', - productType: ProductType.inapp), - UserChoiceDetailsProductWrapper( + productType: ProductType.inapp, + ), + UserChoiceDetailsProductWrapper( id: 'id2', offerToken: 'offerToken2', - productType: ProductType.inapp), - ], - ); - final Future detailsFuture = - manager.userChoiceDetailsStream.first; - manager.onUserChoiceAlternativeBilling(expected); - expect(await detailsFuture, expected); - }); + productType: ProductType.inapp, + ), + ], + ); + final Future detailsFuture = + manager.userChoiceDetailsStream.first; + manager.onUserChoiceAlternativeBilling(expected); + expect(await detailsFuture, expected); + }, + ); }); } diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart index 2b4989a43e9..67d7f73c53b 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart @@ -41,12 +41,17 @@ void main() { setUp(() { mockApi = MockInAppPurchaseApi(); - when(mockApi.startConnection(any, any, any)).thenAnswer((_) async => - PlatformBillingResult( - responseCode: PlatformBillingResponse.ok, debugMessage: '')); + when(mockApi.startConnection(any, any, any)).thenAnswer( + (_) async => PlatformBillingResult( + responseCode: PlatformBillingResponse.ok, + debugMessage: '', + ), + ); billingClient = BillingClient( - (PurchasesResultWrapper _) {}, (UserChoiceDetailsWrapper _) {}, - api: mockApi); + (PurchasesResultWrapper _) {}, + (UserChoiceDetailsWrapper _) {}, + api: mockApi, + ); }); group('isReady', () { @@ -73,66 +78,80 @@ void main() { ); const BillingResultWrapper billingResult = BillingResultWrapper( - responseCode: responseCode, debugMessage: debugMessage); + responseCode: responseCode, + debugMessage: debugMessage, + ); expect( - await billingClient.startConnection( - onBillingServiceDisconnected: () {}), - equals(billingResult)); + await billingClient.startConnection( + onBillingServiceDisconnected: () {}, + ), + equals(billingResult), + ); }); test('passes default values to onBillingServiceDisconnected', () async { await billingClient.startConnection(onBillingServiceDisconnected: () {}); - final VerificationResult result = - verify(mockApi.startConnection(captureAny, captureAny, captureAny)); + final VerificationResult result = verify( + mockApi.startConnection(captureAny, captureAny, captureAny), + ); expect(result.captured[0], 0); expect(result.captured[1], PlatformBillingChoiceMode.playBillingOnly); expect( - result.captured[2], - isA().having( - (PlatformPendingPurchasesParams params) => - params.enablePrepaidPlans, - 'enablePrepaidPlans', - false)); + result.captured[2], + isA().having( + (PlatformPendingPurchasesParams params) => params.enablePrepaidPlans, + 'enablePrepaidPlans', + false, + ), + ); }); test('passes billingChoiceMode alternativeBillingOnly when set', () async { await billingClient.startConnection( - onBillingServiceDisconnected: () {}, - billingChoiceMode: BillingChoiceMode.alternativeBillingOnly); + onBillingServiceDisconnected: () {}, + billingChoiceMode: BillingChoiceMode.alternativeBillingOnly, + ); expect( - verify(mockApi.startConnection(any, captureAny, any)).captured.first, - PlatformBillingChoiceMode.alternativeBillingOnly); + verify(mockApi.startConnection(any, captureAny, any)).captured.first, + PlatformBillingChoiceMode.alternativeBillingOnly, + ); }); test('passes billingChoiceMode userChoiceBilling when set', () async { final Completer completer = Completer(); - billingClient = BillingClient((PurchasesResultWrapper _) {}, - (UserChoiceDetailsWrapper details) => completer.complete(details), - api: mockApi); + billingClient = BillingClient( + (PurchasesResultWrapper _) {}, + (UserChoiceDetailsWrapper details) => completer.complete(details), + api: mockApi, + ); await billingClient.startConnection( - onBillingServiceDisconnected: () {}, - billingChoiceMode: BillingChoiceMode.alternativeBillingOnly); + onBillingServiceDisconnected: () {}, + billingChoiceMode: BillingChoiceMode.alternativeBillingOnly, + ); expect( - verify(mockApi.startConnection(any, captureAny, any)).captured.first, - PlatformBillingChoiceMode.alternativeBillingOnly); + verify(mockApi.startConnection(any, captureAny, any)).captured.first, + PlatformBillingChoiceMode.alternativeBillingOnly, + ); const UserChoiceDetailsWrapper expected = UserChoiceDetailsWrapper( originalExternalTransactionId: 'TransactionId', externalTransactionToken: 'TransactionToken', products: [ UserChoiceDetailsProductWrapper( - id: 'id1', - offerToken: 'offerToken1', - productType: ProductType.inapp), + id: 'id1', + offerToken: 'offerToken1', + productType: ProductType.inapp, + ), UserChoiceDetailsProductWrapper( - id: 'id2', - offerToken: 'offerToken2', - productType: ProductType.inapp), + id: 'id2', + offerToken: 'offerToken2', + productType: ProductType.inapp, + ), ], ); billingClient.hostCallbackHandler.alternativeBillingListener!(expected); @@ -142,18 +161,21 @@ void main() { test('passes pendingPurchasesParams when set', () async { await billingClient.startConnection( - onBillingServiceDisconnected: () {}, - billingChoiceMode: BillingChoiceMode.alternativeBillingOnly, - pendingPurchasesParams: - const PendingPurchasesParamsWrapper(enablePrepaidPlans: true)); + onBillingServiceDisconnected: () {}, + billingChoiceMode: BillingChoiceMode.alternativeBillingOnly, + pendingPurchasesParams: const PendingPurchasesParamsWrapper( + enablePrepaidPlans: true, + ), + ); expect( - verify(mockApi.startConnection(any, any, captureAny)).captured.first, - isA().having( - (PlatformPendingPurchasesParams params) => - params.enablePrepaidPlans, - 'enablePrepaidPlans', - true)); + verify(mockApi.startConnection(any, any, captureAny)).captured.first, + isA().having( + (PlatformPendingPurchasesParams params) => params.enablePrepaidPlans, + 'enablePrepaidPlans', + true, + ), + ); }); }); @@ -167,22 +189,30 @@ void main() { test('handles empty productDetails', () async { const String debugMessage = 'dummy message'; const BillingResponse responseCode = BillingResponse.developerError; - when(mockApi.queryProductDetailsAsync(any)) - .thenAnswer((_) async => PlatformProductDetailsResponse( - billingResult: PlatformBillingResult( - responseCode: PlatformBillingResponse.developerError, - debugMessage: debugMessage), - productDetails: [], - )); + when(mockApi.queryProductDetailsAsync(any)).thenAnswer( + (_) async => PlatformProductDetailsResponse( + billingResult: PlatformBillingResult( + responseCode: PlatformBillingResponse.developerError, + debugMessage: debugMessage, + ), + productDetails: [], + ), + ); final ProductDetailsResponseWrapper response = await billingClient - .queryProductDetails(productList: [ - const ProductWrapper( - productId: 'invalid', productType: ProductType.inapp) - ]); + .queryProductDetails( + productList: [ + const ProductWrapper( + productId: 'invalid', + productType: ProductType.inapp, + ), + ], + ); const BillingResultWrapper billingResult = BillingResultWrapper( - responseCode: responseCode, debugMessage: debugMessage); + responseCode: responseCode, + debugMessage: debugMessage, + ); expect(response.billingResult, equals(billingResult)); expect(response.productDetailsList, isEmpty); }); @@ -190,26 +220,32 @@ void main() { test('returns ProductDetailsResponseWrapper', () async { const String debugMessage = 'dummy message'; const BillingResponse responseCode = BillingResponse.ok; - when(mockApi.queryProductDetailsAsync(any)) - .thenAnswer((_) async => PlatformProductDetailsResponse( - billingResult: PlatformBillingResult( - responseCode: PlatformBillingResponse.ok, - debugMessage: debugMessage), - productDetails: [ - convertToPigeonProductDetails(dummyOneTimeProductDetails) - ], - )); - - final ProductDetailsResponseWrapper response = - await billingClient.queryProductDetails( - productList: [ - const ProductWrapper( - productId: 'invalid', productType: ProductType.inapp), - ], + when(mockApi.queryProductDetailsAsync(any)).thenAnswer( + (_) async => PlatformProductDetailsResponse( + billingResult: PlatformBillingResult( + responseCode: PlatformBillingResponse.ok, + debugMessage: debugMessage, + ), + productDetails: [ + convertToPigeonProductDetails(dummyOneTimeProductDetails), + ], + ), ); + final ProductDetailsResponseWrapper response = await billingClient + .queryProductDetails( + productList: [ + const ProductWrapper( + productId: 'invalid', + productType: ProductType.inapp, + ), + ], + ); + const BillingResultWrapper billingResult = BillingResultWrapper( - responseCode: responseCode, debugMessage: debugMessage); + responseCode: responseCode, + debugMessage: debugMessage, + ); expect(response.billingResult, equals(billingResult)); expect(response.productDetailsList, contains(dummyOneTimeProductDetails)); }); @@ -220,22 +256,28 @@ void main() { const String debugMessage = 'dummy message'; const BillingResponse responseCode = BillingResponse.ok; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: responseCode, debugMessage: debugMessage); - when(mockApi.launchBillingFlow(any)).thenAnswer( - (_) async => convertToPigeonResult(expectedBillingResult)); + responseCode: responseCode, + debugMessage: debugMessage, + ); + when( + mockApi.launchBillingFlow(any), + ).thenAnswer((_) async => convertToPigeonResult(expectedBillingResult)); const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; const String accountId = 'hashedAccountId'; const String profileId = 'hashedProfileId'; expect( - await billingClient.launchBillingFlow( - product: productDetails.productId, - accountId: accountId, - obfuscatedProfileId: profileId), - equals(expectedBillingResult)); + await billingClient.launchBillingFlow( + product: productDetails.productId, + accountId: accountId, + obfuscatedProfileId: profileId, + ), + equals(expectedBillingResult), + ); - final VerificationResult result = - verify(mockApi.launchBillingFlow(captureAny)); + final VerificationResult result = verify( + mockApi.launchBillingFlow(captureAny), + ); final PlatformBillingFlowParams params = result.captured.single as PlatformBillingFlowParams; expect(params.product, equals(productDetails.productId)); @@ -244,153 +286,185 @@ void main() { }); test( - 'Change subscription throws assertion error `oldProduct` and `purchaseToken` has different nullability', - () async { - const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; - const String accountId = 'hashedAccountId'; - const String profileId = 'hashedProfileId'; + 'Change subscription throws assertion error `oldProduct` and `purchaseToken` has different nullability', + () async { + const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; + const String accountId = 'hashedAccountId'; + const String profileId = 'hashedProfileId'; - expect( + expect( billingClient.launchBillingFlow( - product: productDetails.productId, - accountId: accountId, - obfuscatedProfileId: profileId, - oldProduct: dummyOldPurchase.products.first), - throwsAssertionError); - - expect( + product: productDetails.productId, + accountId: accountId, + obfuscatedProfileId: profileId, + oldProduct: dummyOldPurchase.products.first, + ), + throwsAssertionError, + ); + + expect( billingClient.launchBillingFlow( - product: productDetails.productId, - accountId: accountId, - obfuscatedProfileId: profileId, - purchaseToken: dummyOldPurchase.purchaseToken), - throwsAssertionError); - }); + product: productDetails.productId, + accountId: accountId, + obfuscatedProfileId: profileId, + purchaseToken: dummyOldPurchase.purchaseToken, + ), + throwsAssertionError, + ); + }, + ); test( - 'serializes and deserializes data on change subscription without proration', - () async { - const String debugMessage = 'dummy message'; - const BillingResponse responseCode = BillingResponse.ok; - const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: responseCode, debugMessage: debugMessage); - when(mockApi.launchBillingFlow(any)).thenAnswer( - (_) async => convertToPigeonResult(expectedBillingResult)); - const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; - const String accountId = 'hashedAccountId'; - const String profileId = 'hashedProfileId'; - - expect( + 'serializes and deserializes data on change subscription without proration', + () async { + const String debugMessage = 'dummy message'; + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( + responseCode: responseCode, + debugMessage: debugMessage, + ); + when( + mockApi.launchBillingFlow(any), + ).thenAnswer((_) async => convertToPigeonResult(expectedBillingResult)); + const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; + const String accountId = 'hashedAccountId'; + const String profileId = 'hashedProfileId'; + + expect( await billingClient.launchBillingFlow( - product: productDetails.productId, - accountId: accountId, - obfuscatedProfileId: profileId, - oldProduct: dummyOldPurchase.products.first, - purchaseToken: dummyOldPurchase.purchaseToken), - equals(expectedBillingResult)); - final VerificationResult result = - verify(mockApi.launchBillingFlow(captureAny)); - final PlatformBillingFlowParams params = - result.captured.single as PlatformBillingFlowParams; - expect(params.product, equals(productDetails.productId)); - expect(params.accountId, equals(accountId)); - expect(params.oldProduct, equals(dummyOldPurchase.products.first)); - expect(params.purchaseToken, equals(dummyOldPurchase.purchaseToken)); - expect(params.obfuscatedProfileId, equals(profileId)); - }); + product: productDetails.productId, + accountId: accountId, + obfuscatedProfileId: profileId, + oldProduct: dummyOldPurchase.products.first, + purchaseToken: dummyOldPurchase.purchaseToken, + ), + equals(expectedBillingResult), + ); + final VerificationResult result = verify( + mockApi.launchBillingFlow(captureAny), + ); + final PlatformBillingFlowParams params = + result.captured.single as PlatformBillingFlowParams; + expect(params.product, equals(productDetails.productId)); + expect(params.accountId, equals(accountId)); + expect(params.oldProduct, equals(dummyOldPurchase.products.first)); + expect(params.purchaseToken, equals(dummyOldPurchase.purchaseToken)); + expect(params.obfuscatedProfileId, equals(profileId)); + }, + ); test( - 'serializes and deserializes data on change subscription with proration', - () async { - const String debugMessage = 'dummy message'; - const BillingResponse responseCode = BillingResponse.ok; - const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: responseCode, debugMessage: debugMessage); - when(mockApi.launchBillingFlow(any)).thenAnswer( - (_) async => convertToPigeonResult(expectedBillingResult)); - const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; - const String accountId = 'hashedAccountId'; - const String profileId = 'hashedProfileId'; - const ReplacementMode replacementMode = - ReplacementMode.chargeProratedPrice; - - expect( + 'serializes and deserializes data on change subscription with proration', + () async { + const String debugMessage = 'dummy message'; + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( + responseCode: responseCode, + debugMessage: debugMessage, + ); + when( + mockApi.launchBillingFlow(any), + ).thenAnswer((_) async => convertToPigeonResult(expectedBillingResult)); + const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; + const String accountId = 'hashedAccountId'; + const String profileId = 'hashedProfileId'; + const ReplacementMode replacementMode = + ReplacementMode.chargeProratedPrice; + + expect( await billingClient.launchBillingFlow( - product: productDetails.productId, - accountId: accountId, - obfuscatedProfileId: profileId, - oldProduct: dummyOldPurchase.products.first, - replacementMode: replacementMode, - purchaseToken: dummyOldPurchase.purchaseToken), - equals(expectedBillingResult)); - final VerificationResult result = - verify(mockApi.launchBillingFlow(captureAny)); - final PlatformBillingFlowParams params = - result.captured.single as PlatformBillingFlowParams; - expect(params.product, equals(productDetails.productId)); - expect(params.accountId, equals(accountId)); - expect(params.oldProduct, equals(dummyOldPurchase.products.first)); - expect(params.obfuscatedProfileId, equals(profileId)); - expect(params.purchaseToken, equals(dummyOldPurchase.purchaseToken)); - expect( - params.replacementMode, - replacementModeFromWrapper(replacementMode), - ); - }); + product: productDetails.productId, + accountId: accountId, + obfuscatedProfileId: profileId, + oldProduct: dummyOldPurchase.products.first, + replacementMode: replacementMode, + purchaseToken: dummyOldPurchase.purchaseToken, + ), + equals(expectedBillingResult), + ); + final VerificationResult result = verify( + mockApi.launchBillingFlow(captureAny), + ); + final PlatformBillingFlowParams params = + result.captured.single as PlatformBillingFlowParams; + expect(params.product, equals(productDetails.productId)); + expect(params.accountId, equals(accountId)); + expect(params.oldProduct, equals(dummyOldPurchase.products.first)); + expect(params.obfuscatedProfileId, equals(profileId)); + expect(params.purchaseToken, equals(dummyOldPurchase.purchaseToken)); + expect( + params.replacementMode, + replacementModeFromWrapper(replacementMode), + ); + }, + ); test( - 'serializes and deserializes data when using immediateAndChargeFullPrice', - () async { - const String debugMessage = 'dummy message'; - const BillingResponse responseCode = BillingResponse.ok; - const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: responseCode, debugMessage: debugMessage); - when(mockApi.launchBillingFlow(any)).thenAnswer( - (_) async => convertToPigeonResult(expectedBillingResult)); - const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; - const String accountId = 'hashedAccountId'; - const String profileId = 'hashedProfileId'; - const ReplacementMode replacementMode = ReplacementMode.chargeFullPrice; - - expect( + 'serializes and deserializes data when using immediateAndChargeFullPrice', + () async { + const String debugMessage = 'dummy message'; + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( + responseCode: responseCode, + debugMessage: debugMessage, + ); + when( + mockApi.launchBillingFlow(any), + ).thenAnswer((_) async => convertToPigeonResult(expectedBillingResult)); + const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; + const String accountId = 'hashedAccountId'; + const String profileId = 'hashedProfileId'; + const ReplacementMode replacementMode = ReplacementMode.chargeFullPrice; + + expect( await billingClient.launchBillingFlow( - product: productDetails.productId, - accountId: accountId, - obfuscatedProfileId: profileId, - oldProduct: dummyOldPurchase.products.first, - replacementMode: replacementMode, - purchaseToken: dummyOldPurchase.purchaseToken), - equals(expectedBillingResult)); - final VerificationResult result = - verify(mockApi.launchBillingFlow(captureAny)); - final PlatformBillingFlowParams params = - result.captured.single as PlatformBillingFlowParams; - expect(params.product, equals(productDetails.productId)); - expect(params.accountId, equals(accountId)); - expect(params.oldProduct, equals(dummyOldPurchase.products.first)); - expect(params.obfuscatedProfileId, equals(profileId)); - expect(params.purchaseToken, equals(dummyOldPurchase.purchaseToken)); - expect( - params.replacementMode, - replacementModeFromWrapper(replacementMode), - ); - }); + product: productDetails.productId, + accountId: accountId, + obfuscatedProfileId: profileId, + oldProduct: dummyOldPurchase.products.first, + replacementMode: replacementMode, + purchaseToken: dummyOldPurchase.purchaseToken, + ), + equals(expectedBillingResult), + ); + final VerificationResult result = verify( + mockApi.launchBillingFlow(captureAny), + ); + final PlatformBillingFlowParams params = + result.captured.single as PlatformBillingFlowParams; + expect(params.product, equals(productDetails.productId)); + expect(params.accountId, equals(accountId)); + expect(params.oldProduct, equals(dummyOldPurchase.products.first)); + expect(params.obfuscatedProfileId, equals(profileId)); + expect(params.purchaseToken, equals(dummyOldPurchase.purchaseToken)); + expect( + params.replacementMode, + replacementModeFromWrapper(replacementMode), + ); + }, + ); test('handles null accountId', () async { const String debugMessage = 'dummy message'; const BillingResponse responseCode = BillingResponse.ok; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: responseCode, debugMessage: debugMessage); - when(mockApi.launchBillingFlow(any)).thenAnswer( - (_) async => convertToPigeonResult(expectedBillingResult)); + responseCode: responseCode, + debugMessage: debugMessage, + ); + when( + mockApi.launchBillingFlow(any), + ).thenAnswer((_) async => convertToPigeonResult(expectedBillingResult)); const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; expect( - await billingClient.launchBillingFlow( - product: productDetails.productId), - equals(expectedBillingResult)); - final VerificationResult result = - verify(mockApi.launchBillingFlow(captureAny)); + await billingClient.launchBillingFlow( + product: productDetails.productId, + ), + equals(expectedBillingResult), + ); + final VerificationResult result = verify( + mockApi.launchBillingFlow(captureAny), + ); final PlatformBillingFlowParams params = result.captured.single as PlatformBillingFlowParams; expect(params.product, equals(productDetails.productId)); @@ -402,24 +476,31 @@ void main() { test('serializes and deserializes data', () async { const BillingResponse expectedCode = BillingResponse.ok; final List expectedList = [ - dummyPurchase + dummyPurchase, ]; const String debugMessage = 'dummy message'; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: expectedCode, debugMessage: debugMessage); - when(mockApi.queryPurchasesAsync(any)) - .thenAnswer((_) async => PlatformPurchasesResponse( - billingResult: PlatformBillingResult( - responseCode: PlatformBillingResponse.ok, - debugMessage: debugMessage), - purchases: expectedList - .map((PurchaseWrapper purchase) => - convertToPigeonPurchase(purchase)) - .toList(), - )); - - final PurchasesResultWrapper response = - await billingClient.queryPurchases(ProductType.inapp); + responseCode: expectedCode, + debugMessage: debugMessage, + ); + when(mockApi.queryPurchasesAsync(any)).thenAnswer( + (_) async => PlatformPurchasesResponse( + billingResult: PlatformBillingResult( + responseCode: PlatformBillingResponse.ok, + debugMessage: debugMessage, + ), + purchases: + expectedList + .map( + (PurchaseWrapper purchase) => + convertToPigeonPurchase(purchase), + ) + .toList(), + ), + ); + + final PurchasesResultWrapper response = await billingClient + .queryPurchases(ProductType.inapp); expect(response.billingResult, equals(expectedBillingResult)); expect(response.responseCode, equals(expectedCode)); @@ -430,17 +511,21 @@ void main() { const BillingResponse expectedCode = BillingResponse.userCanceled; const String debugMessage = 'dummy message'; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: expectedCode, debugMessage: debugMessage); - when(mockApi.queryPurchasesAsync(any)) - .thenAnswer((_) async => PlatformPurchasesResponse( - billingResult: PlatformBillingResult( - responseCode: PlatformBillingResponse.userCanceled, - debugMessage: debugMessage), - purchases: [], - )); - - final PurchasesResultWrapper response = - await billingClient.queryPurchases(ProductType.inapp); + responseCode: expectedCode, + debugMessage: debugMessage, + ); + when(mockApi.queryPurchasesAsync(any)).thenAnswer( + (_) async => PlatformPurchasesResponse( + billingResult: PlatformBillingResult( + responseCode: PlatformBillingResponse.userCanceled, + debugMessage: debugMessage, + ), + purchases: [], + ), + ); + + final PurchasesResultWrapper response = await billingClient + .queryPurchases(ProductType.inapp); expect(response.billingResult, equals(expectedBillingResult)); // The top-level response code is hard-coded to "ok", as the underlying @@ -455,17 +540,21 @@ void main() { const BillingResponse expectedCode = BillingResponse.userCanceled; const String debugMessage = 'dummy message'; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: expectedCode, debugMessage: debugMessage); - when(mockApi.queryPurchaseHistoryAsync(any)) - .thenAnswer((_) async => PlatformPurchaseHistoryResponse( - billingResult: PlatformBillingResult( - responseCode: PlatformBillingResponse.userCanceled, - debugMessage: debugMessage), - purchases: [], - )); - - final PurchasesHistoryResult response = - await billingClient.queryPurchaseHistory(ProductType.inapp); + responseCode: expectedCode, + debugMessage: debugMessage, + ); + when(mockApi.queryPurchaseHistoryAsync(any)).thenAnswer( + (_) async => PlatformPurchaseHistoryResponse( + billingResult: PlatformBillingResult( + responseCode: PlatformBillingResponse.userCanceled, + debugMessage: debugMessage, + ), + purchases: [], + ), + ); + + final PurchasesHistoryResult response = await billingClient + .queryPurchaseHistory(ProductType.inapp); expect(response.billingResult, equals(expectedBillingResult)); expect(response.purchaseHistoryRecordList, isEmpty); @@ -478,12 +567,15 @@ void main() { const BillingResponse expectedCode = BillingResponse.ok; const String debugMessage = 'dummy message'; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: expectedCode, debugMessage: debugMessage); - when(mockApi.consumeAsync(token)).thenAnswer( - (_) async => convertToPigeonResult(expectedBillingResult)); + responseCode: expectedCode, + debugMessage: debugMessage, + ); + when( + mockApi.consumeAsync(token), + ).thenAnswer((_) async => convertToPigeonResult(expectedBillingResult)); - final BillingResultWrapper billingResult = - await billingClient.consumeAsync(token); + final BillingResultWrapper billingResult = await billingClient + .consumeAsync(token); expect(billingResult, equals(expectedBillingResult)); }); @@ -495,12 +587,15 @@ void main() { const BillingResponse expectedCode = BillingResponse.ok; const String debugMessage = 'dummy message'; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: expectedCode, debugMessage: debugMessage); - when(mockApi.acknowledgePurchase(token)).thenAnswer( - (_) async => convertToPigeonResult(expectedBillingResult)); + responseCode: expectedCode, + debugMessage: debugMessage, + ); + when( + mockApi.acknowledgePurchase(token), + ).thenAnswer((_) async => convertToPigeonResult(expectedBillingResult)); - final BillingResultWrapper billingResult = - await billingClient.acknowledgePurchase(token); + final BillingResultWrapper billingResult = await billingClient + .acknowledgePurchase(token); expect(billingResult, equals(expectedBillingResult)); }); @@ -508,20 +603,22 @@ void main() { group('isFeatureSupported', () { test('isFeatureSupported returns false', () async { - when(mockApi - .isFeatureSupported(PlatformBillingClientFeature.subscriptions)) - .thenAnswer((_) async => false); - final bool isSupported = await billingClient - .isFeatureSupported(BillingClientFeature.subscriptions); + when( + mockApi.isFeatureSupported(PlatformBillingClientFeature.subscriptions), + ).thenAnswer((_) async => false); + final bool isSupported = await billingClient.isFeatureSupported( + BillingClientFeature.subscriptions, + ); expect(isSupported, isFalse); }); test('isFeatureSupported returns true', () async { - when(mockApi - .isFeatureSupported(PlatformBillingClientFeature.subscriptions)) - .thenAnswer((_) async => true); - final bool isSupported = await billingClient - .isFeatureSupported(BillingClientFeature.subscriptions); + when( + mockApi.isFeatureSupported(PlatformBillingClientFeature.subscriptions), + ).thenAnswer((_) async => true); + final bool isSupported = await billingClient.isFeatureSupported( + BillingClientFeature.subscriptions, + ); expect(isSupported, isTrue); }); }); @@ -529,11 +626,13 @@ void main() { group('billingConfig', () { test('billingConfig returns object', () async { const BillingConfigWrapper expected = BillingConfigWrapper( - countryCode: 'US', - responseCode: BillingResponse.ok, - debugMessage: ''); - when(mockApi.getBillingConfigAsync()) - .thenAnswer((_) async => platformBillingConfigFromWrapper(expected)); + countryCode: 'US', + responseCode: BillingResponse.ok, + debugMessage: '', + ); + when( + mockApi.getBillingConfigAsync(), + ).thenAnswer((_) async => platformBillingConfigFromWrapper(expected)); final BillingConfigWrapper result = await billingClient.getBillingConfig(); expect(result.countryCode, 'US'); @@ -544,11 +643,15 @@ void main() { group('isAlternativeBillingOnlyAvailable', () { test('returns object', () async { const BillingResultWrapper expected = BillingResultWrapper( - responseCode: BillingResponse.ok, debugMessage: 'message'); + responseCode: BillingResponse.ok, + debugMessage: 'message', + ); when(mockApi.isAlternativeBillingOnlyAvailableAsync()).thenAnswer( - (_) async => PlatformBillingResult( - responseCode: PlatformBillingResponse.ok, - debugMessage: expected.debugMessage!)); + (_) async => PlatformBillingResult( + responseCode: PlatformBillingResponse.ok, + debugMessage: expected.debugMessage!, + ), + ); final BillingResultWrapper result = await billingClient.isAlternativeBillingOnlyAvailable(); expect(result, expected); @@ -559,13 +662,16 @@ void main() { test('returns object', () async { const AlternativeBillingOnlyReportingDetailsWrapper expected = AlternativeBillingOnlyReportingDetailsWrapper( - responseCode: BillingResponse.ok, - debugMessage: 'debug', - externalTransactionToken: 'abc123youandme'); - when(mockApi.createAlternativeBillingOnlyReportingDetailsAsync()) - .thenAnswer((_) async => - platformAlternativeBillingOnlyReportingDetailsFromWrapper( - expected)); + responseCode: BillingResponse.ok, + debugMessage: 'debug', + externalTransactionToken: 'abc123youandme', + ); + when( + mockApi.createAlternativeBillingOnlyReportingDetailsAsync(), + ).thenAnswer( + (_) async => + platformAlternativeBillingOnlyReportingDetailsFromWrapper(expected), + ); final AlternativeBillingOnlyReportingDetailsWrapper result = await billingClient.createAlternativeBillingOnlyReportingDetails(); expect(result, equals(expected)); @@ -575,11 +681,15 @@ void main() { group('showAlternativeBillingOnlyInformationDialog', () { test('returns object', () async { const BillingResultWrapper expected = BillingResultWrapper( - responseCode: BillingResponse.ok, debugMessage: 'message'); + responseCode: BillingResponse.ok, + debugMessage: 'message', + ); when(mockApi.showAlternativeBillingOnlyInformationDialog()).thenAnswer( - (_) async => PlatformBillingResult( - responseCode: PlatformBillingResponse.ok, - debugMessage: expected.debugMessage!)); + (_) async => PlatformBillingResult( + responseCode: PlatformBillingResponse.ok, + debugMessage: expected.debugMessage!, + ), + ); final BillingResultWrapper result = await billingClient.showAlternativeBillingOnlyInformationDialog(); expect(result, expected); @@ -588,22 +698,26 @@ void main() { } PlatformBillingConfigResponse platformBillingConfigFromWrapper( - BillingConfigWrapper original) { + BillingConfigWrapper original, +) { return PlatformBillingConfigResponse( - billingResult: PlatformBillingResult( - responseCode: billingResponseFromWrapper(original.responseCode), - debugMessage: original.debugMessage!, - ), - countryCode: original.countryCode); + billingResult: PlatformBillingResult( + responseCode: billingResponseFromWrapper(original.responseCode), + debugMessage: original.debugMessage!, + ), + countryCode: original.countryCode, + ); } PlatformAlternativeBillingOnlyReportingDetailsResponse - platformAlternativeBillingOnlyReportingDetailsFromWrapper( - AlternativeBillingOnlyReportingDetailsWrapper original) { +platformAlternativeBillingOnlyReportingDetailsFromWrapper( + AlternativeBillingOnlyReportingDetailsWrapper original, +) { return PlatformAlternativeBillingOnlyReportingDetailsResponse( - billingResult: PlatformBillingResult( - responseCode: billingResponseFromWrapper(original.responseCode), - debugMessage: original.debugMessage!, - ), - externalTransactionToken: original.externalTransactionToken); + billingResult: PlatformBillingResult( + responseCode: billingResponseFromWrapper(original.responseCode), + debugMessage: original.debugMessage!, + ), + externalTransactionToken: original.externalTransactionToken, + ); } diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.mocks.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.mocks.dart index a5086ce40a6..80a0fa790fa 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.mocks.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.mocks.dart @@ -24,13 +24,8 @@ import 'package:mockito/src/dummies.dart' as _i3; class _FakePlatformBillingResult_0 extends _i1.SmartFake implements _i2.PlatformBillingResult { - _FakePlatformBillingResult_0( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakePlatformBillingResult_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakePlatformBillingConfigResponse_1 extends _i1.SmartFake @@ -38,21 +33,13 @@ class _FakePlatformBillingConfigResponse_1 extends _i1.SmartFake _FakePlatformBillingConfigResponse_1( Object parent, Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + ) : super(parent, parentInvocation); } class _FakePlatformPurchasesResponse_2 extends _i1.SmartFake implements _i2.PlatformPurchasesResponse { - _FakePlatformPurchasesResponse_2( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + _FakePlatformPurchasesResponse_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } class _FakePlatformPurchaseHistoryResponse_3 extends _i1.SmartFake @@ -60,10 +47,7 @@ class _FakePlatformPurchaseHistoryResponse_3 extends _i1.SmartFake _FakePlatformPurchaseHistoryResponse_3( Object parent, Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + ) : super(parent, parentInvocation); } class _FakePlatformProductDetailsResponse_4 extends _i1.SmartFake @@ -71,10 +55,7 @@ class _FakePlatformProductDetailsResponse_4 extends _i1.SmartFake _FakePlatformProductDetailsResponse_4( Object parent, Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + ) : super(parent, parentInvocation); } class _FakePlatformAlternativeBillingOnlyReportingDetailsResponse_5 @@ -83,10 +64,7 @@ class _FakePlatformAlternativeBillingOnlyReportingDetailsResponse_5 _FakePlatformAlternativeBillingOnlyReportingDetailsResponse_5( Object parent, Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); + ) : super(parent, parentInvocation); } /// A class which mocks [InAppPurchaseApi]. @@ -94,27 +72,28 @@ class _FakePlatformAlternativeBillingOnlyReportingDetailsResponse_5 /// See the documentation for Mockito's code generation for more information. class MockInAppPurchaseApi extends _i1.Mock implements _i2.InAppPurchaseApi { @override - String get pigeonVar_messageChannelSuffix => (super.noSuchMethod( - Invocation.getter(#pigeonVar_messageChannelSuffix), - returnValue: _i3.dummyValue( - this, - Invocation.getter(#pigeonVar_messageChannelSuffix), - ), - returnValueForMissingStub: _i3.dummyValue( - this, - Invocation.getter(#pigeonVar_messageChannelSuffix), - ), - ) as String); + String get pigeonVar_messageChannelSuffix => + (super.noSuchMethod( + Invocation.getter(#pigeonVar_messageChannelSuffix), + returnValue: _i3.dummyValue( + this, + Invocation.getter(#pigeonVar_messageChannelSuffix), + ), + returnValueForMissingStub: _i3.dummyValue( + this, + Invocation.getter(#pigeonVar_messageChannelSuffix), + ), + ) + as String); @override - _i4.Future isReady() => (super.noSuchMethod( - Invocation.method( - #isReady, - [], - ), - returnValue: _i4.Future.value(false), - returnValueForMissingStub: _i4.Future.value(false), - ) as _i4.Future); + _i4.Future isReady() => + (super.noSuchMethod( + Invocation.method(#isReady, []), + returnValue: _i4.Future.value(false), + returnValueForMissingStub: _i4.Future.value(false), + ) + as _i4.Future); @override _i4.Future<_i2.PlatformBillingResult> startConnection( @@ -123,326 +102,290 @@ class MockInAppPurchaseApi extends _i1.Mock implements _i2.InAppPurchaseApi { _i2.PlatformPendingPurchasesParams? pendingPurchasesParams, ) => (super.noSuchMethod( - Invocation.method( - #startConnection, - [ - callbackHandle, - billingMode, - pendingPurchasesParams, - ], - ), - returnValue: _i4.Future<_i2.PlatformBillingResult>.value( - _FakePlatformBillingResult_0( - this, - Invocation.method( - #startConnection, - [ + Invocation.method(#startConnection, [ callbackHandle, billingMode, pendingPurchasesParams, - ], - ), - )), - returnValueForMissingStub: _i4.Future<_i2.PlatformBillingResult>.value( - _FakePlatformBillingResult_0( - this, - Invocation.method( - #startConnection, - [ - callbackHandle, - billingMode, - pendingPurchasesParams, - ], - ), - )), - ) as _i4.Future<_i2.PlatformBillingResult>); + ]), + returnValue: _i4.Future<_i2.PlatformBillingResult>.value( + _FakePlatformBillingResult_0( + this, + Invocation.method(#startConnection, [ + callbackHandle, + billingMode, + pendingPurchasesParams, + ]), + ), + ), + returnValueForMissingStub: + _i4.Future<_i2.PlatformBillingResult>.value( + _FakePlatformBillingResult_0( + this, + Invocation.method(#startConnection, [ + callbackHandle, + billingMode, + pendingPurchasesParams, + ]), + ), + ), + ) + as _i4.Future<_i2.PlatformBillingResult>); @override - _i4.Future endConnection() => (super.noSuchMethod( - Invocation.method( - #endConnection, - [], - ), - returnValue: _i4.Future.value(), - returnValueForMissingStub: _i4.Future.value(), - ) as _i4.Future); + _i4.Future endConnection() => + (super.noSuchMethod( + Invocation.method(#endConnection, []), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) + as _i4.Future); @override _i4.Future<_i2.PlatformBillingConfigResponse> getBillingConfigAsync() => (super.noSuchMethod( - Invocation.method( - #getBillingConfigAsync, - [], - ), - returnValue: _i4.Future<_i2.PlatformBillingConfigResponse>.value( - _FakePlatformBillingConfigResponse_1( - this, - Invocation.method( - #getBillingConfigAsync, - [], - ), - )), - returnValueForMissingStub: - _i4.Future<_i2.PlatformBillingConfigResponse>.value( - _FakePlatformBillingConfigResponse_1( - this, - Invocation.method( - #getBillingConfigAsync, - [], - ), - )), - ) as _i4.Future<_i2.PlatformBillingConfigResponse>); + Invocation.method(#getBillingConfigAsync, []), + returnValue: _i4.Future<_i2.PlatformBillingConfigResponse>.value( + _FakePlatformBillingConfigResponse_1( + this, + Invocation.method(#getBillingConfigAsync, []), + ), + ), + returnValueForMissingStub: + _i4.Future<_i2.PlatformBillingConfigResponse>.value( + _FakePlatformBillingConfigResponse_1( + this, + Invocation.method(#getBillingConfigAsync, []), + ), + ), + ) + as _i4.Future<_i2.PlatformBillingConfigResponse>); @override _i4.Future<_i2.PlatformBillingResult> launchBillingFlow( - _i2.PlatformBillingFlowParams? params) => + _i2.PlatformBillingFlowParams? params, + ) => (super.noSuchMethod( - Invocation.method( - #launchBillingFlow, - [params], - ), - returnValue: _i4.Future<_i2.PlatformBillingResult>.value( - _FakePlatformBillingResult_0( - this, - Invocation.method( - #launchBillingFlow, - [params], - ), - )), - returnValueForMissingStub: _i4.Future<_i2.PlatformBillingResult>.value( - _FakePlatformBillingResult_0( - this, - Invocation.method( - #launchBillingFlow, - [params], - ), - )), - ) as _i4.Future<_i2.PlatformBillingResult>); + Invocation.method(#launchBillingFlow, [params]), + returnValue: _i4.Future<_i2.PlatformBillingResult>.value( + _FakePlatformBillingResult_0( + this, + Invocation.method(#launchBillingFlow, [params]), + ), + ), + returnValueForMissingStub: + _i4.Future<_i2.PlatformBillingResult>.value( + _FakePlatformBillingResult_0( + this, + Invocation.method(#launchBillingFlow, [params]), + ), + ), + ) + as _i4.Future<_i2.PlatformBillingResult>); @override _i4.Future<_i2.PlatformBillingResult> acknowledgePurchase( - String? purchaseToken) => + String? purchaseToken, + ) => (super.noSuchMethod( - Invocation.method( - #acknowledgePurchase, - [purchaseToken], - ), - returnValue: _i4.Future<_i2.PlatformBillingResult>.value( - _FakePlatformBillingResult_0( - this, - Invocation.method( - #acknowledgePurchase, - [purchaseToken], - ), - )), - returnValueForMissingStub: _i4.Future<_i2.PlatformBillingResult>.value( - _FakePlatformBillingResult_0( - this, - Invocation.method( - #acknowledgePurchase, - [purchaseToken], - ), - )), - ) as _i4.Future<_i2.PlatformBillingResult>); + Invocation.method(#acknowledgePurchase, [purchaseToken]), + returnValue: _i4.Future<_i2.PlatformBillingResult>.value( + _FakePlatformBillingResult_0( + this, + Invocation.method(#acknowledgePurchase, [purchaseToken]), + ), + ), + returnValueForMissingStub: + _i4.Future<_i2.PlatformBillingResult>.value( + _FakePlatformBillingResult_0( + this, + Invocation.method(#acknowledgePurchase, [purchaseToken]), + ), + ), + ) + as _i4.Future<_i2.PlatformBillingResult>); @override _i4.Future<_i2.PlatformBillingResult> consumeAsync(String? purchaseToken) => (super.noSuchMethod( - Invocation.method( - #consumeAsync, - [purchaseToken], - ), - returnValue: _i4.Future<_i2.PlatformBillingResult>.value( - _FakePlatformBillingResult_0( - this, - Invocation.method( - #consumeAsync, - [purchaseToken], - ), - )), - returnValueForMissingStub: _i4.Future<_i2.PlatformBillingResult>.value( - _FakePlatformBillingResult_0( - this, - Invocation.method( - #consumeAsync, - [purchaseToken], - ), - )), - ) as _i4.Future<_i2.PlatformBillingResult>); + Invocation.method(#consumeAsync, [purchaseToken]), + returnValue: _i4.Future<_i2.PlatformBillingResult>.value( + _FakePlatformBillingResult_0( + this, + Invocation.method(#consumeAsync, [purchaseToken]), + ), + ), + returnValueForMissingStub: + _i4.Future<_i2.PlatformBillingResult>.value( + _FakePlatformBillingResult_0( + this, + Invocation.method(#consumeAsync, [purchaseToken]), + ), + ), + ) + as _i4.Future<_i2.PlatformBillingResult>); @override _i4.Future<_i2.PlatformPurchasesResponse> queryPurchasesAsync( - _i2.PlatformProductType? productType) => + _i2.PlatformProductType? productType, + ) => (super.noSuchMethod( - Invocation.method( - #queryPurchasesAsync, - [productType], - ), - returnValue: _i4.Future<_i2.PlatformPurchasesResponse>.value( - _FakePlatformPurchasesResponse_2( - this, - Invocation.method( - #queryPurchasesAsync, - [productType], - ), - )), - returnValueForMissingStub: - _i4.Future<_i2.PlatformPurchasesResponse>.value( - _FakePlatformPurchasesResponse_2( - this, - Invocation.method( - #queryPurchasesAsync, - [productType], - ), - )), - ) as _i4.Future<_i2.PlatformPurchasesResponse>); + Invocation.method(#queryPurchasesAsync, [productType]), + returnValue: _i4.Future<_i2.PlatformPurchasesResponse>.value( + _FakePlatformPurchasesResponse_2( + this, + Invocation.method(#queryPurchasesAsync, [productType]), + ), + ), + returnValueForMissingStub: + _i4.Future<_i2.PlatformPurchasesResponse>.value( + _FakePlatformPurchasesResponse_2( + this, + Invocation.method(#queryPurchasesAsync, [productType]), + ), + ), + ) + as _i4.Future<_i2.PlatformPurchasesResponse>); @override _i4.Future<_i2.PlatformPurchaseHistoryResponse> queryPurchaseHistoryAsync( - _i2.PlatformProductType? productType) => + _i2.PlatformProductType? productType, + ) => (super.noSuchMethod( - Invocation.method( - #queryPurchaseHistoryAsync, - [productType], - ), - returnValue: _i4.Future<_i2.PlatformPurchaseHistoryResponse>.value( - _FakePlatformPurchaseHistoryResponse_3( - this, - Invocation.method( - #queryPurchaseHistoryAsync, - [productType], - ), - )), - returnValueForMissingStub: - _i4.Future<_i2.PlatformPurchaseHistoryResponse>.value( - _FakePlatformPurchaseHistoryResponse_3( - this, - Invocation.method( - #queryPurchaseHistoryAsync, - [productType], - ), - )), - ) as _i4.Future<_i2.PlatformPurchaseHistoryResponse>); + Invocation.method(#queryPurchaseHistoryAsync, [productType]), + returnValue: _i4.Future<_i2.PlatformPurchaseHistoryResponse>.value( + _FakePlatformPurchaseHistoryResponse_3( + this, + Invocation.method(#queryPurchaseHistoryAsync, [productType]), + ), + ), + returnValueForMissingStub: + _i4.Future<_i2.PlatformPurchaseHistoryResponse>.value( + _FakePlatformPurchaseHistoryResponse_3( + this, + Invocation.method(#queryPurchaseHistoryAsync, [ + productType, + ]), + ), + ), + ) + as _i4.Future<_i2.PlatformPurchaseHistoryResponse>); @override _i4.Future<_i2.PlatformProductDetailsResponse> queryProductDetailsAsync( - List<_i2.PlatformQueryProduct>? products) => + List<_i2.PlatformQueryProduct>? products, + ) => (super.noSuchMethod( - Invocation.method( - #queryProductDetailsAsync, - [products], - ), - returnValue: _i4.Future<_i2.PlatformProductDetailsResponse>.value( - _FakePlatformProductDetailsResponse_4( - this, - Invocation.method( - #queryProductDetailsAsync, - [products], - ), - )), - returnValueForMissingStub: - _i4.Future<_i2.PlatformProductDetailsResponse>.value( - _FakePlatformProductDetailsResponse_4( - this, - Invocation.method( - #queryProductDetailsAsync, - [products], - ), - )), - ) as _i4.Future<_i2.PlatformProductDetailsResponse>); + Invocation.method(#queryProductDetailsAsync, [products]), + returnValue: _i4.Future<_i2.PlatformProductDetailsResponse>.value( + _FakePlatformProductDetailsResponse_4( + this, + Invocation.method(#queryProductDetailsAsync, [products]), + ), + ), + returnValueForMissingStub: + _i4.Future<_i2.PlatformProductDetailsResponse>.value( + _FakePlatformProductDetailsResponse_4( + this, + Invocation.method(#queryProductDetailsAsync, [products]), + ), + ), + ) + as _i4.Future<_i2.PlatformProductDetailsResponse>); @override _i4.Future isFeatureSupported( - _i2.PlatformBillingClientFeature? feature) => + _i2.PlatformBillingClientFeature? feature, + ) => (super.noSuchMethod( - Invocation.method( - #isFeatureSupported, - [feature], - ), - returnValue: _i4.Future.value(false), - returnValueForMissingStub: _i4.Future.value(false), - ) as _i4.Future); + Invocation.method(#isFeatureSupported, [feature]), + returnValue: _i4.Future.value(false), + returnValueForMissingStub: _i4.Future.value(false), + ) + as _i4.Future); @override _i4.Future<_i2.PlatformBillingResult> - isAlternativeBillingOnlyAvailableAsync() => (super.noSuchMethod( - Invocation.method( - #isAlternativeBillingOnlyAvailableAsync, - [], - ), + isAlternativeBillingOnlyAvailableAsync() => + (super.noSuchMethod( + Invocation.method(#isAlternativeBillingOnlyAvailableAsync, []), returnValue: _i4.Future<_i2.PlatformBillingResult>.value( - _FakePlatformBillingResult_0( - this, - Invocation.method( - #isAlternativeBillingOnlyAvailableAsync, - [], + _FakePlatformBillingResult_0( + this, + Invocation.method(#isAlternativeBillingOnlyAvailableAsync, []), ), - )), + ), returnValueForMissingStub: _i4.Future<_i2.PlatformBillingResult>.value( - _FakePlatformBillingResult_0( - this, - Invocation.method( - #isAlternativeBillingOnlyAvailableAsync, - [], - ), - )), - ) as _i4.Future<_i2.PlatformBillingResult>); + _FakePlatformBillingResult_0( + this, + Invocation.method( + #isAlternativeBillingOnlyAvailableAsync, + [], + ), + ), + ), + ) + as _i4.Future<_i2.PlatformBillingResult>); @override _i4.Future<_i2.PlatformBillingResult> - showAlternativeBillingOnlyInformationDialog() => (super.noSuchMethod( - Invocation.method( - #showAlternativeBillingOnlyInformationDialog, - [], - ), + showAlternativeBillingOnlyInformationDialog() => + (super.noSuchMethod( + Invocation.method(#showAlternativeBillingOnlyInformationDialog, []), returnValue: _i4.Future<_i2.PlatformBillingResult>.value( - _FakePlatformBillingResult_0( - this, - Invocation.method( - #showAlternativeBillingOnlyInformationDialog, - [], + _FakePlatformBillingResult_0( + this, + Invocation.method( + #showAlternativeBillingOnlyInformationDialog, + [], + ), ), - )), + ), returnValueForMissingStub: _i4.Future<_i2.PlatformBillingResult>.value( - _FakePlatformBillingResult_0( - this, - Invocation.method( - #showAlternativeBillingOnlyInformationDialog, - [], - ), - )), - ) as _i4.Future<_i2.PlatformBillingResult>); + _FakePlatformBillingResult_0( + this, + Invocation.method( + #showAlternativeBillingOnlyInformationDialog, + [], + ), + ), + ), + ) + as _i4.Future<_i2.PlatformBillingResult>); @override _i4.Future<_i2.PlatformAlternativeBillingOnlyReportingDetailsResponse> - createAlternativeBillingOnlyReportingDetailsAsync() => - (super.noSuchMethod( + createAlternativeBillingOnlyReportingDetailsAsync() => + (super.noSuchMethod( Invocation.method( #createAlternativeBillingOnlyReportingDetailsAsync, [], ), returnValue: _i4.Future< - _i2 - .PlatformAlternativeBillingOnlyReportingDetailsResponse>.value( - _FakePlatformAlternativeBillingOnlyReportingDetailsResponse_5( - this, - Invocation.method( - #createAlternativeBillingOnlyReportingDetailsAsync, - [], + _i2.PlatformAlternativeBillingOnlyReportingDetailsResponse + >.value( + _FakePlatformAlternativeBillingOnlyReportingDetailsResponse_5( + this, + Invocation.method( + #createAlternativeBillingOnlyReportingDetailsAsync, + [], + ), ), - )), + ), returnValueForMissingStub: _i4.Future< - _i2 - .PlatformAlternativeBillingOnlyReportingDetailsResponse>.value( - _FakePlatformAlternativeBillingOnlyReportingDetailsResponse_5( - this, - Invocation.method( - #createAlternativeBillingOnlyReportingDetailsAsync, - [], + _i2.PlatformAlternativeBillingOnlyReportingDetailsResponse + >.value( + _FakePlatformAlternativeBillingOnlyReportingDetailsResponse_5( + this, + Invocation.method( + #createAlternativeBillingOnlyReportingDetailsAsync, + [], + ), ), - )), - ) as _i4.Future< - _i2.PlatformAlternativeBillingOnlyReportingDetailsResponse>); + ), + ) + as _i4.Future< + _i2.PlatformAlternativeBillingOnlyReportingDetailsResponse + >); } diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/product_details_wrapper_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/product_details_wrapper_test.dart index 877a0d1259e..3c237c808b2 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/product_details_wrapper_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/product_details_wrapper_test.dart @@ -25,13 +25,15 @@ void main() { const ProductDetailsWrapper wrapper = dummyOneTimeProductDetails; final GooglePlayProductDetails product = GooglePlayProductDetails.fromProductDetails( - dummyOneTimeProductDetails) - .first; + dummyOneTimeProductDetails, + ).first; expect(product.title, wrapper.title); expect(product.description, wrapper.description); expect(product.id, wrapper.productId); expect( - product.price, wrapper.oneTimePurchaseOfferDetails?.formattedPrice); + product.price, + wrapper.oneTimePurchaseOfferDetails?.formattedPrice, + ); expect(product.productDetails, wrapper); }); }); @@ -40,87 +42,89 @@ void main() { test('operator == of ProductDetailsWrapper works fine', () { const ProductDetailsWrapper firstProductDetailsInstance = ProductDetailsWrapper( - description: 'description', - title: 'title', - productType: ProductType.inapp, - name: 'name', - productId: 'productId', - oneTimePurchaseOfferDetails: OneTimePurchaseOfferDetailsWrapper( - formattedPrice: 'formattedPrice', - priceAmountMicros: 10, - priceCurrencyCode: 'priceCurrencyCode', - ), - subscriptionOfferDetails: [ - SubscriptionOfferDetailsWrapper( - basePlanId: 'basePlanId', - offerTags: ['offerTags'], - offerIdToken: 'offerToken', - pricingPhases: [ - PricingPhaseWrapper( - billingCycleCount: 4, - billingPeriod: 'billingPeriod', - formattedPrice: 'formattedPrice', - priceAmountMicros: 10, - priceCurrencyCode: 'priceCurrencyCode', - recurrenceMode: RecurrenceMode.finiteRecurring, + description: 'description', + title: 'title', + productType: ProductType.inapp, + name: 'name', + productId: 'productId', + oneTimePurchaseOfferDetails: OneTimePurchaseOfferDetailsWrapper( + formattedPrice: 'formattedPrice', + priceAmountMicros: 10, + priceCurrencyCode: 'priceCurrencyCode', + ), + subscriptionOfferDetails: [ + SubscriptionOfferDetailsWrapper( + basePlanId: 'basePlanId', + offerTags: ['offerTags'], + offerIdToken: 'offerToken', + pricingPhases: [ + PricingPhaseWrapper( + billingCycleCount: 4, + billingPeriod: 'billingPeriod', + formattedPrice: 'formattedPrice', + priceAmountMicros: 10, + priceCurrencyCode: 'priceCurrencyCode', + recurrenceMode: RecurrenceMode.finiteRecurring, + ), + ], + installmentPlanDetails: InstallmentPlanDetailsWrapper( + commitmentPaymentsCount: 1, + subsequentCommitmentPaymentsCount: 2, + ), ), ], - installmentPlanDetails: InstallmentPlanDetailsWrapper( - commitmentPaymentsCount: 1, - subsequentCommitmentPaymentsCount: 2, - ), - ), - ], - ); + ); const ProductDetailsWrapper secondProductDetailsInstance = ProductDetailsWrapper( - description: 'description', - title: 'title', - productType: ProductType.inapp, - name: 'name', - productId: 'productId', - oneTimePurchaseOfferDetails: OneTimePurchaseOfferDetailsWrapper( - formattedPrice: 'formattedPrice', - priceAmountMicros: 10, - priceCurrencyCode: 'priceCurrencyCode', - ), - subscriptionOfferDetails: [ - SubscriptionOfferDetailsWrapper( - basePlanId: 'basePlanId', - offerTags: ['offerTags'], - offerIdToken: 'offerToken', - pricingPhases: [ - PricingPhaseWrapper( - billingCycleCount: 4, - billingPeriod: 'billingPeriod', - formattedPrice: 'formattedPrice', - priceAmountMicros: 10, - priceCurrencyCode: 'priceCurrencyCode', - recurrenceMode: RecurrenceMode.finiteRecurring, + description: 'description', + title: 'title', + productType: ProductType.inapp, + name: 'name', + productId: 'productId', + oneTimePurchaseOfferDetails: OneTimePurchaseOfferDetailsWrapper( + formattedPrice: 'formattedPrice', + priceAmountMicros: 10, + priceCurrencyCode: 'priceCurrencyCode', + ), + subscriptionOfferDetails: [ + SubscriptionOfferDetailsWrapper( + basePlanId: 'basePlanId', + offerTags: ['offerTags'], + offerIdToken: 'offerToken', + pricingPhases: [ + PricingPhaseWrapper( + billingCycleCount: 4, + billingPeriod: 'billingPeriod', + formattedPrice: 'formattedPrice', + priceAmountMicros: 10, + priceCurrencyCode: 'priceCurrencyCode', + recurrenceMode: RecurrenceMode.finiteRecurring, + ), + ], + installmentPlanDetails: InstallmentPlanDetailsWrapper( + commitmentPaymentsCount: 1, + subsequentCommitmentPaymentsCount: 2, + ), ), ], - installmentPlanDetails: InstallmentPlanDetailsWrapper( - commitmentPaymentsCount: 1, - subsequentCommitmentPaymentsCount: 2, - ), - ), - ], - ); + ); expect( - firstProductDetailsInstance == secondProductDetailsInstance, isTrue); + firstProductDetailsInstance == secondProductDetailsInstance, + isTrue, + ); }); test('operator == of BillingResultWrapper works fine', () { const BillingResultWrapper firstBillingResultInstance = BillingResultWrapper( - responseCode: BillingResponse.ok, - debugMessage: 'debugMessage', - ); + responseCode: BillingResponse.ok, + debugMessage: 'debugMessage', + ); const BillingResultWrapper secondBillingResultInstance = BillingResultWrapper( - responseCode: BillingResponse.ok, - debugMessage: 'debugMessage', - ); + responseCode: BillingResponse.ok, + debugMessage: 'debugMessage', + ); expect(firstBillingResultInstance == secondBillingResultInstance, isTrue); }); }); diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart index 71449d7e378..24723277c2c 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart @@ -58,49 +58,67 @@ void main() { expect(details[0].purchaseID, dummyMultipleProductsPurchase.orderId); expect(details[0].productID, dummyMultipleProductsPurchase.products[0]); - expect(details[0].transactionDate, - dummyMultipleProductsPurchase.purchaseTime.toString()); + expect( + details[0].transactionDate, + dummyMultipleProductsPurchase.purchaseTime.toString(), + ); expect(details[0].verificationData, isNotNull); expect(details[0].verificationData.source, kIAPSource); - expect(details[0].verificationData.localVerificationData, - dummyMultipleProductsPurchase.originalJson); - expect(details[0].verificationData.serverVerificationData, - dummyMultipleProductsPurchase.purchaseToken); + expect( + details[0].verificationData.localVerificationData, + dummyMultipleProductsPurchase.originalJson, + ); + expect( + details[0].verificationData.serverVerificationData, + dummyMultipleProductsPurchase.purchaseToken, + ); expect(details[0].billingClientPurchase, dummyMultipleProductsPurchase); expect(details[0].pendingCompletePurchase, false); expect(details[1].purchaseID, dummyMultipleProductsPurchase.orderId); expect(details[1].productID, dummyMultipleProductsPurchase.products[1]); - expect(details[1].transactionDate, - dummyMultipleProductsPurchase.purchaseTime.toString()); + expect( + details[1].transactionDate, + dummyMultipleProductsPurchase.purchaseTime.toString(), + ); expect(details[1].verificationData, isNotNull); expect(details[1].verificationData.source, kIAPSource); - expect(details[1].verificationData.localVerificationData, - dummyMultipleProductsPurchase.originalJson); - expect(details[1].verificationData.serverVerificationData, - dummyMultipleProductsPurchase.purchaseToken); + expect( + details[1].verificationData.localVerificationData, + dummyMultipleProductsPurchase.originalJson, + ); + expect( + details[1].verificationData.serverVerificationData, + dummyMultipleProductsPurchase.purchaseToken, + ); expect(details[1].billingClientPurchase, dummyMultipleProductsPurchase); expect(details[1].pendingCompletePurchase, false); }); test( - 'fromPurchase() should return set pendingCompletePurchase to true for unacknowledged purchase', - () { - final GooglePlayPurchaseDetails details = - GooglePlayPurchaseDetails.fromPurchase(dummyUnacknowledgedPurchase) - .first; + 'fromPurchase() should return set pendingCompletePurchase to true for unacknowledged purchase', + () { + final GooglePlayPurchaseDetails details = + GooglePlayPurchaseDetails.fromPurchase( + dummyUnacknowledgedPurchase, + ).first; - expect(details.purchaseID, dummyPurchase.orderId); - expect(details.productID, dummyPurchase.products.first); - expect(details.transactionDate, dummyPurchase.purchaseTime.toString()); - expect(details.verificationData, isNotNull); - expect(details.verificationData.source, kIAPSource); - expect(details.verificationData.localVerificationData, - dummyPurchase.originalJson); - expect(details.verificationData.serverVerificationData, - dummyPurchase.purchaseToken); - expect(details.billingClientPurchase, dummyUnacknowledgedPurchase); - expect(details.pendingCompletePurchase, true); - }); + expect(details.purchaseID, dummyPurchase.orderId); + expect(details.productID, dummyPurchase.products.first); + expect(details.transactionDate, dummyPurchase.purchaseTime.toString()); + expect(details.verificationData, isNotNull); + expect(details.verificationData.source, kIAPSource); + expect( + details.verificationData.localVerificationData, + dummyPurchase.originalJson, + ); + expect( + details.verificationData.serverVerificationData, + dummyPurchase.purchaseToken, + ); + expect(details.billingClientPurchase, dummyUnacknowledgedPurchase); + expect(details.pendingCompletePurchase, true); + }, + ); }); } diff --git a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart index 38c2deaf692..dc4a76f9ef2 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart @@ -27,14 +27,20 @@ void main() { setUp(() { widgets.WidgetsFlutterBinding.ensureInitialized(); mockApi = MockInAppPurchaseApi(); - when(mockApi.startConnection(any, any, any)).thenAnswer((_) async => - PlatformBillingResult( - responseCode: PlatformBillingResponse.ok, debugMessage: '')); + when(mockApi.startConnection(any, any, any)).thenAnswer( + (_) async => PlatformBillingResult( + responseCode: PlatformBillingResponse.ok, + debugMessage: '', + ), + ); manager = BillingClientManager( - billingClientFactory: (PurchasesUpdatedListener listener, - UserSelectedAlternativeBillingListener? - alternativeBillingListener) => - BillingClient(listener, alternativeBillingListener, api: mockApi)); + billingClientFactory: + ( + PurchasesUpdatedListener listener, + UserSelectedAlternativeBillingListener? alternativeBillingListener, + ) => + BillingClient(listener, alternativeBillingListener, api: mockApi), + ); iapAndroidPlatformAddition = InAppPurchaseAndroidPlatformAddition(manager); }); @@ -43,12 +49,16 @@ void main() { const BillingResponse expectedCode = BillingResponse.ok; const String debugMessage = 'dummy message'; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: expectedCode, debugMessage: debugMessage); - when(mockApi.consumeAsync(any)).thenAnswer( - (_) async => convertToPigeonResult(expectedBillingResult)); + responseCode: expectedCode, + debugMessage: debugMessage, + ); + when( + mockApi.consumeAsync(any), + ).thenAnswer((_) async => convertToPigeonResult(expectedBillingResult)); final BillingResultWrapper billingResultWrapper = await iapAndroidPlatformAddition.consumePurchase( - GooglePlayPurchaseDetails.fromPurchase(dummyPurchase).first); + GooglePlayPurchaseDetails.fromPurchase(dummyPurchase).first, + ); expect(billingResultWrapper, equals(expectedBillingResult)); }); @@ -58,12 +68,14 @@ void main() { test('getCountryCode success', () async { const String expectedCountryCode = 'US'; const BillingConfigWrapper expected = BillingConfigWrapper( - countryCode: expectedCountryCode, - responseCode: BillingResponse.ok, - debugMessage: 'dummy message'); + countryCode: expectedCountryCode, + responseCode: BillingResponse.ok, + debugMessage: 'dummy message', + ); - when(mockApi.getBillingConfigAsync()) - .thenAnswer((_) async => platformBillingConfigFromWrapper(expected)); + when( + mockApi.getBillingConfigAsync(), + ).thenAnswer((_) async => platformBillingConfigFromWrapper(expected)); final String countryCode = await iapAndroidPlatformAddition.getCountryCode(); @@ -74,29 +86,35 @@ void main() { group('setBillingChoice', () { test('setAlternativeBillingOnlyState', () async { clearInteractions(mockApi); - await iapAndroidPlatformAddition - .setBillingChoice(BillingChoiceMode.alternativeBillingOnly); + await iapAndroidPlatformAddition.setBillingChoice( + BillingChoiceMode.alternativeBillingOnly, + ); // Fake the disconnect that we would expect from a endConnectionCall. manager.client.hostCallbackHandler.onBillingServiceDisconnected(0); // Verify that after connection ended reconnect was called. - final VerificationResult result = - verify(mockApi.startConnection(any, captureAny, any)); + final VerificationResult result = verify( + mockApi.startConnection(any, captureAny, any), + ); expect(result.callCount, equals(2)); - expect(result.captured.last, - PlatformBillingChoiceMode.alternativeBillingOnly); + expect( + result.captured.last, + PlatformBillingChoiceMode.alternativeBillingOnly, + ); }); test('setPlayBillingState', () async { clearInteractions(mockApi); - await iapAndroidPlatformAddition - .setBillingChoice(BillingChoiceMode.playBillingOnly); + await iapAndroidPlatformAddition.setBillingChoice( + BillingChoiceMode.playBillingOnly, + ); // Fake the disconnect that we would expect from a endConnectionCall. manager.client.hostCallbackHandler.onBillingServiceDisconnected(0); // Verify that after connection ended reconnect was called. - final VerificationResult result = - verify(mockApi.startConnection(any, captureAny, any)); + final VerificationResult result = verify( + mockApi.startConnection(any, captureAny, any), + ); expect(result.callCount, equals(2)); expect(result.captured.last, PlatformBillingChoiceMode.playBillingOnly); }); @@ -105,11 +123,15 @@ void main() { group('isAlternativeBillingOnlyAvailable', () { test('isAlternativeBillingOnlyAvailable success', () async { const BillingResultWrapper expected = BillingResultWrapper( - responseCode: BillingResponse.ok, debugMessage: 'dummy message'); + responseCode: BillingResponse.ok, + debugMessage: 'dummy message', + ); when(mockApi.isAlternativeBillingOnlyAvailableAsync()).thenAnswer( - (_) async => PlatformBillingResult( - responseCode: PlatformBillingResponse.ok, - debugMessage: expected.debugMessage!)); + (_) async => PlatformBillingResult( + responseCode: PlatformBillingResponse.ok, + debugMessage: expected.debugMessage!, + ), + ); final BillingResultWrapper result = await iapAndroidPlatformAddition.isAlternativeBillingOnlyAvailable(); @@ -121,12 +143,16 @@ void main() { group('showAlternativeBillingOnlyInformationDialog', () { test('showAlternativeBillingOnlyInformationDialog success', () async { const BillingResultWrapper expected = BillingResultWrapper( - responseCode: BillingResponse.ok, debugMessage: 'dummy message'); + responseCode: BillingResponse.ok, + debugMessage: 'dummy message', + ); - when(mockApi.isAlternativeBillingOnlyAvailableAsync()) - .thenAnswer((_) async => convertToPigeonResult(expected)); - when(mockApi.showAlternativeBillingOnlyInformationDialog()) - .thenAnswer((_) async => convertToPigeonResult(expected)); + when( + mockApi.isAlternativeBillingOnlyAvailableAsync(), + ).thenAnswer((_) async => convertToPigeonResult(expected)); + when( + mockApi.showAlternativeBillingOnlyInformationDialog(), + ).thenAnswer((_) async => convertToPigeonResult(expected)); final BillingResultWrapper result = await iapAndroidPlatformAddition.isAlternativeBillingOnlyAvailable(); @@ -140,14 +166,17 @@ void main() { const String debugMessage = 'dummy message'; const PlatformBillingResponse responseCode = PlatformBillingResponse.ok; - when(mockApi.queryPurchasesAsync(any)) - .thenAnswer((_) async => PlatformPurchasesResponse( - billingResult: PlatformBillingResult( - responseCode: responseCode, debugMessage: debugMessage), - purchases: [ - convertToPigeonPurchase(dummyPurchase), - ], - )); + when(mockApi.queryPurchasesAsync(any)).thenAnswer( + (_) async => PlatformPurchasesResponse( + billingResult: PlatformBillingResult( + responseCode: responseCode, + debugMessage: debugMessage, + ), + purchases: [ + convertToPigeonPurchase(dummyPurchase), + ], + ), + ); // Since queryPastPurchases makes 2 platform method calls (one for each ProductType), the result will contain 2 dummyWrapper instead // of 1. @@ -171,26 +200,27 @@ void main() { expect(response.error, isNotNull); expect(response.error!.code, 'error_code'); expect(response.error!.message, 'error_message'); - expect( - response.error!.details, {'info': 'error_info'}); + expect(response.error!.details, { + 'info': 'error_info', + }); }); }); }); group('isFeatureSupported', () { test('isFeatureSupported returns false', () async { - when(mockApi - .isFeatureSupported(PlatformBillingClientFeature.subscriptions)) - .thenAnswer((_) async => false); + when( + mockApi.isFeatureSupported(PlatformBillingClientFeature.subscriptions), + ).thenAnswer((_) async => false); final bool isSupported = await iapAndroidPlatformAddition .isFeatureSupported(BillingClientFeature.subscriptions); expect(isSupported, isFalse); }); test('isFeatureSupported returns true', () async { - when(mockApi - .isFeatureSupported(PlatformBillingClientFeature.subscriptions)) - .thenAnswer((_) async => true); + when( + mockApi.isFeatureSupported(PlatformBillingClientFeature.subscriptions), + ).thenAnswer((_) async => true); final bool isSupported = await iapAndroidPlatformAddition .isFeatureSupported(BillingClientFeature.subscriptions); expect(isSupported, isTrue); @@ -206,18 +236,22 @@ void main() { externalTransactionToken: 'TransactionToken', products: [ UserChoiceDetailsProductWrapper( - id: 'id1', - offerToken: 'offerToken1', - productType: ProductType.inapp), + id: 'id1', + offerToken: 'offerToken1', + productType: ProductType.inapp, + ), UserChoiceDetailsProductWrapper( - id: 'id2', - offerToken: 'offerToken2', - productType: ProductType.inapp), + id: 'id2', + offerToken: 'offerToken2', + productType: ProductType.inapp, + ), ], ); manager.onUserChoiceAlternativeBilling(expected); expect( - await futureDetails, Translator.convertToUserChoiceDetails(expected)); + await futureDetails, + Translator.convertToUserChoiceDetails(expected), + ); }); }); } diff --git a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart index f3b741eef3f..6e13549dbe0 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart @@ -22,30 +22,30 @@ import 'test_conversion_utils.dart'; const ProductDetailsWrapper dummySubscriptionProductDetails = ProductDetailsWrapper( - description: 'description', - name: 'name', - productId: 'productId', - productType: ProductType.subs, - title: 'title', - subscriptionOfferDetails: [ - SubscriptionOfferDetailsWrapper( - basePlanId: 'basePlanId', - offerTags: ['offerTags'], - offerId: 'offerId', - offerIdToken: 'offerToken', - pricingPhases: [ - PricingPhaseWrapper( - billingCycleCount: 4, - billingPeriod: 'billingPeriod', - formattedPrice: r'$100', - priceAmountMicros: 100000000, - priceCurrencyCode: 'USD', - recurrenceMode: RecurrenceMode.finiteRecurring, + description: 'description', + name: 'name', + productId: 'productId', + productType: ProductType.subs, + title: 'title', + subscriptionOfferDetails: [ + SubscriptionOfferDetailsWrapper( + basePlanId: 'basePlanId', + offerTags: ['offerTags'], + offerId: 'offerId', + offerIdToken: 'offerToken', + pricingPhases: [ + PricingPhaseWrapper( + billingCycleCount: 4, + billingPeriod: 'billingPeriod', + formattedPrice: r'$100', + priceAmountMicros: 100000000, + priceCurrencyCode: 'USD', + recurrenceMode: RecurrenceMode.finiteRecurring, + ), + ], ), ], - ), - ], -); + ); void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -57,16 +57,26 @@ void main() { widgets.WidgetsFlutterBinding.ensureInitialized(); mockApi = MockInAppPurchaseApi(); - when(mockApi.startConnection(any, any, any)).thenAnswer((_) async => - PlatformBillingResult( - responseCode: PlatformBillingResponse.ok, debugMessage: '')); + when(mockApi.startConnection(any, any, any)).thenAnswer( + (_) async => PlatformBillingResult( + responseCode: PlatformBillingResponse.ok, + debugMessage: '', + ), + ); iapAndroidPlatform = InAppPurchaseAndroidPlatform( - manager: BillingClientManager( - billingClientFactory: (PurchasesUpdatedListener listener, - UserSelectedAlternativeBillingListener? - alternativeBillingListener) => - BillingClient(listener, alternativeBillingListener, - api: mockApi))); + manager: BillingClientManager( + billingClientFactory: + ( + PurchasesUpdatedListener listener, + UserSelectedAlternativeBillingListener? + alternativeBillingListener, + ) => BillingClient( + listener, + alternativeBillingListener, + api: mockApi, + ), + ), + ); InAppPurchasePlatform.instance = iapAndroidPlatform; }); @@ -83,32 +93,38 @@ void main() { }); test( - 're-connects when operation returns BillingResponse.clientDisconnected', - () async { - when(mockApi.acknowledgePurchase(any)).thenAnswer( - (_) async => PlatformBillingResult( - responseCode: PlatformBillingResponse.serviceDisconnected, - debugMessage: 'disconnected'), - ); - when(mockApi.startConnection(any, any, any)).thenAnswer((_) async { - // Change the acknowledgePurchase response to success for the next call. + 're-connects when operation returns BillingResponse.clientDisconnected', + () async { when(mockApi.acknowledgePurchase(any)).thenAnswer( (_) async => PlatformBillingResult( - responseCode: PlatformBillingResponse.ok, - debugMessage: 'disconnected'), + responseCode: PlatformBillingResponse.serviceDisconnected, + debugMessage: 'disconnected', + ), ); - return PlatformBillingResult( - responseCode: PlatformBillingResponse.ok, debugMessage: ''); - }); - final PurchaseDetails purchase = - GooglePlayPurchaseDetails.fromPurchase(dummyUnacknowledgedPurchase) - .first; - final BillingResultWrapper result = - await iapAndroidPlatform.completePurchase(purchase); - verify(mockApi.acknowledgePurchase(any)).called(2); - verify(mockApi.startConnection(any, any, any)).called(2); - expect(result.responseCode, equals(BillingResponse.ok)); - }); + when(mockApi.startConnection(any, any, any)).thenAnswer((_) async { + // Change the acknowledgePurchase response to success for the next call. + when(mockApi.acknowledgePurchase(any)).thenAnswer( + (_) async => PlatformBillingResult( + responseCode: PlatformBillingResponse.ok, + debugMessage: 'disconnected', + ), + ); + return PlatformBillingResult( + responseCode: PlatformBillingResponse.ok, + debugMessage: '', + ); + }); + final PurchaseDetails purchase = + GooglePlayPurchaseDetails.fromPurchase( + dummyUnacknowledgedPurchase, + ).first; + final BillingResultWrapper result = await iapAndroidPlatform + .completePurchase(purchase); + verify(mockApi.acknowledgePurchase(any)).called(2); + verify(mockApi.startConnection(any, any, any)).called(2); + expect(result.responseCode, equals(BillingResponse.ok)); + }, + ); }); group('isAvailable', () { @@ -127,84 +143,100 @@ void main() { test('handles empty productDetails', () async { const String debugMessage = 'dummy message'; const PlatformBillingResponse responseCode = PlatformBillingResponse.ok; - when(mockApi.queryProductDetailsAsync(any)) - .thenAnswer((_) async => PlatformProductDetailsResponse( - billingResult: PlatformBillingResult( - responseCode: responseCode, debugMessage: debugMessage), - productDetails: [], - )); - - final ProductDetailsResponse response = - await iapAndroidPlatform.queryProductDetails({''}); + when(mockApi.queryProductDetailsAsync(any)).thenAnswer( + (_) async => PlatformProductDetailsResponse( + billingResult: PlatformBillingResult( + responseCode: responseCode, + debugMessage: debugMessage, + ), + productDetails: [], + ), + ); + + final ProductDetailsResponse response = await iapAndroidPlatform + .queryProductDetails({''}); expect(response.productDetails, isEmpty); }); test('should get correct product details', () async { const String debugMessage = 'dummy message'; const PlatformBillingResponse responseCode = PlatformBillingResponse.ok; - when(mockApi.queryProductDetailsAsync(any)) - .thenAnswer((_) async => PlatformProductDetailsResponse( - billingResult: PlatformBillingResult( - responseCode: responseCode, debugMessage: debugMessage), - productDetails: [ - convertToPigeonProductDetails(dummyOneTimeProductDetails) - ], - )); + when(mockApi.queryProductDetailsAsync(any)).thenAnswer( + (_) async => PlatformProductDetailsResponse( + billingResult: PlatformBillingResult( + responseCode: responseCode, + debugMessage: debugMessage, + ), + productDetails: [ + convertToPigeonProductDetails(dummyOneTimeProductDetails), + ], + ), + ); // Since queryProductDetails makes 2 platform method calls (one for each ProductType), the result will contain 2 dummyWrapper instead // of 1. - final ProductDetailsResponse response = - await iapAndroidPlatform.queryProductDetails({'valid'}); - expect(response.productDetails.first.title, - dummyOneTimeProductDetails.title); - expect(response.productDetails.first.description, - dummyOneTimeProductDetails.description); + final ProductDetailsResponse response = await iapAndroidPlatform + .queryProductDetails({'valid'}); + expect( + response.productDetails.first.title, + dummyOneTimeProductDetails.title, + ); + expect( + response.productDetails.first.description, + dummyOneTimeProductDetails.description, + ); expect( - response.productDetails.first.price, - dummyOneTimeProductDetails - .oneTimePurchaseOfferDetails?.formattedPrice); + response.productDetails.first.price, + dummyOneTimeProductDetails.oneTimePurchaseOfferDetails?.formattedPrice, + ); expect(response.productDetails.first.currencySymbol, r'$'); }); test('should get the correct notFoundIDs', () async { const String debugMessage = 'dummy message'; const PlatformBillingResponse responseCode = PlatformBillingResponse.ok; - when(mockApi.queryProductDetailsAsync(any)) - .thenAnswer((_) async => PlatformProductDetailsResponse( - billingResult: PlatformBillingResult( - responseCode: responseCode, debugMessage: debugMessage), - productDetails: [ - convertToPigeonProductDetails(dummyOneTimeProductDetails) - ], - )); + when(mockApi.queryProductDetailsAsync(any)).thenAnswer( + (_) async => PlatformProductDetailsResponse( + billingResult: PlatformBillingResult( + responseCode: responseCode, + debugMessage: debugMessage, + ), + productDetails: [ + convertToPigeonProductDetails(dummyOneTimeProductDetails), + ], + ), + ); // Since queryProductDetails makes 2 platform method calls (one for each ProductType), the result will contain 2 dummyWrapper instead // of 1. - final ProductDetailsResponse response = - await iapAndroidPlatform.queryProductDetails({'invalid'}); + final ProductDetailsResponse response = await iapAndroidPlatform + .queryProductDetails({'invalid'}); expect(response.notFoundIDs.first, 'invalid'); }); test( - 'should have error stored in the response when platform exception is thrown', - () async { - when(mockApi.queryProductDetailsAsync(any)).thenAnswer((_) async { - throw PlatformException( - code: 'error_code', - message: 'error_message', - details: {'info': 'error_info'}, - ); - }); - // Since queryProductDetails makes 2 platform method calls (one for each ProductType), the result will contain 2 dummyWrapper instead - // of 1. - final ProductDetailsResponse response = - await iapAndroidPlatform.queryProductDetails({'invalid'}); - expect(response.notFoundIDs, ['invalid']); - expect(response.productDetails, isEmpty); - expect(response.error, isNotNull); - expect(response.error!.source, kIAPSource); - expect(response.error!.code, 'error_code'); - expect(response.error!.message, 'error_message'); - expect(response.error!.details, {'info': 'error_info'}); - }); + 'should have error stored in the response when platform exception is thrown', + () async { + when(mockApi.queryProductDetailsAsync(any)).thenAnswer((_) async { + throw PlatformException( + code: 'error_code', + message: 'error_message', + details: {'info': 'error_info'}, + ); + }); + // Since queryProductDetails makes 2 platform method calls (one for each ProductType), the result will contain 2 dummyWrapper instead + // of 1. + final ProductDetailsResponse response = await iapAndroidPlatform + .queryProductDetails({'invalid'}); + expect(response.notFoundIDs, ['invalid']); + expect(response.productDetails, isEmpty); + expect(response.error, isNotNull); + expect(response.error!.source, kIAPSource); + expect(response.error!.code, 'error_code'); + expect(response.error!.message, 'error_message'); + expect(response.error!.details, { + 'info': 'error_info', + }); + }, + ); }); group('restorePurchases', () { @@ -222,10 +254,16 @@ void main() { throwsA( isA() .having((PlatformException e) => e.code, 'code', 'error_code') - .having((PlatformException e) => e.message, 'message', - 'error_message') - .having((PlatformException e) => e.details, 'details', - {'info': 'error_info'}), + .having( + (PlatformException e) => e.message, + 'message', + 'error_message', + ) + .having( + (PlatformException e) => e.details, + 'details', + {'info': 'error_info'}, + ), ), ); }); @@ -247,14 +285,15 @@ void main() { const String debugMessage = 'dummy message'; const PlatformBillingResponse responseCode = PlatformBillingResponse.ok; - when(mockApi.queryPurchasesAsync(any)) - .thenAnswer((_) async => PlatformPurchasesResponse( - billingResult: PlatformBillingResult( - responseCode: responseCode, debugMessage: debugMessage), - purchases: [ - convertToPigeonPurchase(dummyPurchase), - ], - )); + when(mockApi.queryPurchasesAsync(any)).thenAnswer( + (_) async => PlatformPurchasesResponse( + billingResult: PlatformBillingResult( + responseCode: responseCode, + debugMessage: debugMessage, + ), + purchases: [convertToPigeonPurchase(dummyPurchase)], + ), + ); // Since queryPastPurchases makes 2 platform method calls (one for each // ProductType), the result will contain 2 dummyPurchase instances instead @@ -269,10 +308,14 @@ void main() { expect(purchase.productID, dummyPurchase.products.first); expect(purchase.purchaseID, dummyPurchase.orderId); - expect(purchase.verificationData.localVerificationData, - dummyPurchase.originalJson); - expect(purchase.verificationData.serverVerificationData, - dummyPurchase.purchaseToken); + expect( + purchase.verificationData.localVerificationData, + dummyPurchase.originalJson, + ); + expect( + purchase.verificationData.serverVerificationData, + dummyPurchase.purchaseToken, + ); expect(purchase.verificationData.source, kIAPSource); expect(purchase.transactionDate, dummyPurchase.purchaseTime.toString()); expect(purchase.billingClientPurchase, dummyPurchase); @@ -282,66 +325,75 @@ void main() { }); group('make payment', () { - test('buy non consumable subscribe offer, serializes and deserializes data', - () async { - const ProductDetailsWrapper productDetails = - dummySubscriptionProductDetails; - const String accountId = 'hashedAccountId'; - const String debugMessage = 'dummy message'; - const BillingResponse sentCode = BillingResponse.ok; - const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: sentCode, debugMessage: debugMessage); - - when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { - // Mock java update purchase callback. - iapAndroidPlatform.billingClientManager.client.hostCallbackHandler - .onPurchasesUpdated(PlatformPurchasesResponse( - billingResult: convertToPigeonResult(expectedBillingResult), - purchases: [ - PlatformPurchase( - orderId: 'orderID1', - products: [productDetails.productId], - isAutoRenewing: false, - packageName: 'package', - purchaseTime: 1231231231, - purchaseToken: 'token', - signature: 'sign', - originalJson: 'json', - developerPayload: 'dummy payload', - isAcknowledged: true, - purchaseState: PlatformPurchaseState.purchased, - quantity: 1, - ) - ], - )); + test( + 'buy non consumable subscribe offer, serializes and deserializes data', + () async { + const ProductDetailsWrapper productDetails = + dummySubscriptionProductDetails; + const String accountId = 'hashedAccountId'; + const String debugMessage = 'dummy message'; + const BillingResponse sentCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( + responseCode: sentCode, + debugMessage: debugMessage, + ); - return convertToPigeonResult(expectedBillingResult); - }); - final Completer completer = Completer(); - PurchaseDetails purchaseDetails; - final Stream> purchaseStream = - iapAndroidPlatform.purchaseStream; - late StreamSubscription> subscription; - subscription = purchaseStream.listen((List details) { - purchaseDetails = details.first; - completer.complete(purchaseDetails); - subscription.cancel(); - }, onDone: () {}); - final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( + when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { + // Mock java update purchase callback. + iapAndroidPlatform.billingClientManager.client.hostCallbackHandler + .onPurchasesUpdated( + PlatformPurchasesResponse( + billingResult: convertToPigeonResult(expectedBillingResult), + purchases: [ + PlatformPurchase( + orderId: 'orderID1', + products: [productDetails.productId], + isAutoRenewing: false, + packageName: 'package', + purchaseTime: 1231231231, + purchaseToken: 'token', + signature: 'sign', + originalJson: 'json', + developerPayload: 'dummy payload', + isAcknowledged: true, + purchaseState: PlatformPurchaseState.purchased, + quantity: 1, + ), + ], + ), + ); + + return convertToPigeonResult(expectedBillingResult); + }); + final Completer completer = + Completer(); + PurchaseDetails purchaseDetails; + final Stream> purchaseStream = + iapAndroidPlatform.purchaseStream; + late StreamSubscription> subscription; + subscription = purchaseStream.listen((List details) { + purchaseDetails = details.first; + completer.complete(purchaseDetails); + subscription.cancel(); + }, onDone: () {}); + final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( offerToken: productDetails.subscriptionOfferDetails?.first.offerIdToken, productDetails: GooglePlayProductDetails.fromProductDetails(productDetails).first, - applicationUserName: accountId); - final bool launchResult = await iapAndroidPlatform.buyNonConsumable( - purchaseParam: purchaseParam); + applicationUserName: accountId, + ); + final bool launchResult = await iapAndroidPlatform.buyNonConsumable( + purchaseParam: purchaseParam, + ); - final PurchaseDetails result = await completer.future; - expect(launchResult, isTrue); - expect(result.purchaseID, 'orderID1'); - expect(result.status, PurchaseStatus.purchased); - expect(result.productID, productDetails.productId); - }); + final PurchaseDetails result = await completer.future; + expect(launchResult, isTrue); + expect(result.purchaseID, 'orderID1'); + expect(result.status, PurchaseStatus.purchased); + expect(result.productID, productDetails.productId); + }, + ); test('buy non consumable, serializes and deserializes data', () async { const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; @@ -349,30 +401,34 @@ void main() { const String debugMessage = 'dummy message'; const BillingResponse sentCode = BillingResponse.ok; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: sentCode, debugMessage: debugMessage); + responseCode: sentCode, + debugMessage: debugMessage, + ); when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { // Mock java update purchase callback. iapAndroidPlatform.billingClientManager.client.hostCallbackHandler - .onPurchasesUpdated(PlatformPurchasesResponse( - billingResult: convertToPigeonResult(expectedBillingResult), - purchases: [ - PlatformPurchase( - orderId: 'orderID1', - products: [productDetails.productId], - isAutoRenewing: false, - packageName: 'package', - purchaseTime: 1231231231, - purchaseToken: 'token', - signature: 'sign', - originalJson: 'json', - developerPayload: 'dummy payload', - isAcknowledged: true, - purchaseState: PlatformPurchaseState.purchased, - quantity: 1, - ) - ], - )); + .onPurchasesUpdated( + PlatformPurchasesResponse( + billingResult: convertToPigeonResult(expectedBillingResult), + purchases: [ + PlatformPurchase( + orderId: 'orderID1', + products: [productDetails.productId], + isAutoRenewing: false, + packageName: 'package', + purchaseTime: 1231231231, + purchaseToken: 'token', + signature: 'sign', + originalJson: 'json', + developerPayload: 'dummy payload', + isAcknowledged: true, + purchaseState: PlatformPurchaseState.purchased, + quantity: 1, + ), + ], + ), + ); return convertToPigeonResult(expectedBillingResult); }); @@ -387,11 +443,13 @@ void main() { subscription.cancel(); }, onDone: () {}); final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( - productDetails: - GooglePlayProductDetails.fromProductDetails(productDetails).first, - applicationUserName: accountId); + productDetails: + GooglePlayProductDetails.fromProductDetails(productDetails).first, + applicationUserName: accountId, + ); final bool launchResult = await iapAndroidPlatform.buyNonConsumable( - purchaseParam: purchaseParam); + purchaseParam: purchaseParam, + ); final PurchaseDetails result = await completer.future; expect(launchResult, isTrue); @@ -406,15 +464,19 @@ void main() { const String debugMessage = 'dummy message'; const BillingResponse sentCode = BillingResponse.error; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: sentCode, debugMessage: debugMessage); + responseCode: sentCode, + debugMessage: debugMessage, + ); when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { // Mock java update purchase callback. iapAndroidPlatform.billingClientManager.client.hostCallbackHandler - .onPurchasesUpdated(PlatformPurchasesResponse( - billingResult: convertToPigeonResult(expectedBillingResult), - purchases: [], - )); + .onPurchasesUpdated( + PlatformPurchasesResponse( + billingResult: convertToPigeonResult(expectedBillingResult), + purchases: [], + ), + ); return convertToPigeonResult(expectedBillingResult); }); @@ -429,9 +491,10 @@ void main() { subscription.cancel(); }, onDone: () {}); final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( - productDetails: - GooglePlayProductDetails.fromProductDetails(productDetails).first, - applicationUserName: accountId); + productDetails: + GooglePlayProductDetails.fromProductDetails(productDetails).first, + applicationUserName: accountId, + ); await iapAndroidPlatform.buyNonConsumable(purchaseParam: purchaseParam); final PurchaseDetails result = await completer.future; @@ -441,118 +504,149 @@ void main() { expect(result.purchaseID, isEmpty); }); - test('buy consumable with auto consume, serializes and deserializes data', - () async { - const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; - const String accountId = 'hashedAccountId'; - const String debugMessage = 'dummy message'; - const BillingResponse sentCode = BillingResponse.ok; - const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: sentCode, debugMessage: debugMessage); - - when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { - // Mock java update purchase callback. - iapAndroidPlatform.billingClientManager.client.hostCallbackHandler - .onPurchasesUpdated(PlatformPurchasesResponse( - billingResult: convertToPigeonResult(expectedBillingResult), - purchases: [ - PlatformPurchase( - orderId: 'orderID1', - products: [productDetails.productId], - isAutoRenewing: false, - packageName: 'package', - purchaseTime: 1231231231, - purchaseToken: 'token', - signature: 'sign', - originalJson: 'json', - developerPayload: 'dummy payload', - isAcknowledged: true, - purchaseState: PlatformPurchaseState.purchased, - quantity: 1, - ) - ], - )); - - return convertToPigeonResult(expectedBillingResult); - }); - final Completer consumeCompleter = Completer(); - // adding call back for consume purchase - const BillingResponse expectedCode = BillingResponse.ok; - const BillingResultWrapper expectedBillingResultForConsume = - BillingResultWrapper( - responseCode: expectedCode, debugMessage: debugMessage); - when(mockApi.consumeAsync(any)).thenAnswer((Invocation invocation) async { - final String purchaseToken = - invocation.positionalArguments.first as String; - consumeCompleter.complete(purchaseToken); - return convertToPigeonResult(expectedBillingResultForConsume); - }); + test( + 'buy consumable with auto consume, serializes and deserializes data', + () async { + const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; + const String accountId = 'hashedAccountId'; + const String debugMessage = 'dummy message'; + const BillingResponse sentCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( + responseCode: sentCode, + debugMessage: debugMessage, + ); - final Completer completer = Completer(); - PurchaseDetails purchaseDetails; - final Stream> purchaseStream = - iapAndroidPlatform.purchaseStream; - late StreamSubscription> subscription; - subscription = purchaseStream.listen((List details) { - purchaseDetails = details.first; - completer.complete(purchaseDetails); - subscription.cancel(); - }, onDone: () {}); - final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( + when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { + // Mock java update purchase callback. + iapAndroidPlatform.billingClientManager.client.hostCallbackHandler + .onPurchasesUpdated( + PlatformPurchasesResponse( + billingResult: convertToPigeonResult(expectedBillingResult), + purchases: [ + PlatformPurchase( + orderId: 'orderID1', + products: [productDetails.productId], + isAutoRenewing: false, + packageName: 'package', + purchaseTime: 1231231231, + purchaseToken: 'token', + signature: 'sign', + originalJson: 'json', + developerPayload: 'dummy payload', + isAcknowledged: true, + purchaseState: PlatformPurchaseState.purchased, + quantity: 1, + ), + ], + ), + ); + + return convertToPigeonResult(expectedBillingResult); + }); + final Completer consumeCompleter = Completer(); + // adding call back for consume purchase + const BillingResponse expectedCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResultForConsume = + BillingResultWrapper( + responseCode: expectedCode, + debugMessage: debugMessage, + ); + when(mockApi.consumeAsync(any)).thenAnswer(( + Invocation invocation, + ) async { + final String purchaseToken = + invocation.positionalArguments.first as String; + consumeCompleter.complete(purchaseToken); + return convertToPigeonResult(expectedBillingResultForConsume); + }); + + final Completer completer = + Completer(); + PurchaseDetails purchaseDetails; + final Stream> purchaseStream = + iapAndroidPlatform.purchaseStream; + late StreamSubscription> subscription; + subscription = purchaseStream.listen((List details) { + purchaseDetails = details.first; + completer.complete(purchaseDetails); + subscription.cancel(); + }, onDone: () {}); + final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( productDetails: GooglePlayProductDetails.fromProductDetails(productDetails).first, - applicationUserName: accountId); - final bool launchResult = - await iapAndroidPlatform.buyConsumable(purchaseParam: purchaseParam); + applicationUserName: accountId, + ); + final bool launchResult = await iapAndroidPlatform.buyConsumable( + purchaseParam: purchaseParam, + ); - // Verify that the result has succeeded - final GooglePlayPurchaseDetails result = - await completer.future as GooglePlayPurchaseDetails; - expect(launchResult, isTrue); - expect(result.billingClientPurchase, isNotNull); - expect(result.billingClientPurchase.purchaseToken, - await consumeCompleter.future); - expect(result.status, PurchaseStatus.purchased); - expect(result.error, isNull); - }); + // Verify that the result has succeeded + final GooglePlayPurchaseDetails result = + await completer.future as GooglePlayPurchaseDetails; + expect(launchResult, isTrue); + expect(result.billingClientPurchase, isNotNull); + expect( + result.billingClientPurchase.purchaseToken, + await consumeCompleter.future, + ); + expect(result.status, PurchaseStatus.purchased); + expect(result.error, isNull); + }, + ); - test('buyNonConsumable propagates failures to launch the billing flow', - () async { - const String debugMessage = 'dummy message'; - const BillingResponse sentCode = BillingResponse.error; - const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: sentCode, debugMessage: debugMessage); - when(mockApi.launchBillingFlow(any)).thenAnswer( - (_) async => convertToPigeonResult(expectedBillingResult)); + test( + 'buyNonConsumable propagates failures to launch the billing flow', + () async { + const String debugMessage = 'dummy message'; + const BillingResponse sentCode = BillingResponse.error; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( + responseCode: sentCode, + debugMessage: debugMessage, + ); + when( + mockApi.launchBillingFlow(any), + ).thenAnswer((_) async => convertToPigeonResult(expectedBillingResult)); - final bool result = await iapAndroidPlatform.buyNonConsumable( + final bool result = await iapAndroidPlatform.buyNonConsumable( purchaseParam: GooglePlayPurchaseParam( - productDetails: GooglePlayProductDetails.fromProductDetails( - dummyOneTimeProductDetails) - .first)); + productDetails: + GooglePlayProductDetails.fromProductDetails( + dummyOneTimeProductDetails, + ).first, + ), + ); - // Verify that the failure has been converted and returned - expect(result, isFalse); - }); + // Verify that the failure has been converted and returned + expect(result, isFalse); + }, + ); - test('buyConsumable propagates failures to launch the billing flow', - () async { - const String debugMessage = 'dummy message'; - const BillingResponse sentCode = BillingResponse.developerError; - const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: sentCode, debugMessage: debugMessage); - when(mockApi.launchBillingFlow(any)).thenAnswer( - (_) async => convertToPigeonResult(expectedBillingResult)); + test( + 'buyConsumable propagates failures to launch the billing flow', + () async { + const String debugMessage = 'dummy message'; + const BillingResponse sentCode = BillingResponse.developerError; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( + responseCode: sentCode, + debugMessage: debugMessage, + ); + when( + mockApi.launchBillingFlow(any), + ).thenAnswer((_) async => convertToPigeonResult(expectedBillingResult)); - final bool result = await iapAndroidPlatform.buyConsumable( + final bool result = await iapAndroidPlatform.buyConsumable( purchaseParam: GooglePlayPurchaseParam( - productDetails: GooglePlayProductDetails.fromProductDetails( - dummyOneTimeProductDetails) - .first)); + productDetails: + GooglePlayProductDetails.fromProductDetails( + dummyOneTimeProductDetails, + ).first, + ), + ); - // Verify that the failure has been converted and returned - expect(result, isFalse); - }); + // Verify that the failure has been converted and returned + expect(result, isFalse); + }, + ); test('adds consumption failures to PurchaseDetails objects', () async { const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; @@ -560,29 +654,33 @@ void main() { const String debugMessage = 'dummy message'; const BillingResponse sentCode = BillingResponse.ok; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: sentCode, debugMessage: debugMessage); + responseCode: sentCode, + debugMessage: debugMessage, + ); when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { // Mock java update purchase callback. iapAndroidPlatform.billingClientManager.client.hostCallbackHandler - .onPurchasesUpdated(PlatformPurchasesResponse( - billingResult: convertToPigeonResult(expectedBillingResult), - purchases: [ - PlatformPurchase( - orderId: 'orderID1', - products: [productDetails.productId], - isAutoRenewing: false, - packageName: 'package', - purchaseTime: 1231231231, - purchaseToken: 'token', - signature: 'sign', - originalJson: 'json', - developerPayload: 'dummy payload', - isAcknowledged: true, - purchaseState: PlatformPurchaseState.purchased, - quantity: 1, - ) - ], - )); + .onPurchasesUpdated( + PlatformPurchasesResponse( + billingResult: convertToPigeonResult(expectedBillingResult), + purchases: [ + PlatformPurchase( + orderId: 'orderID1', + products: [productDetails.productId], + isAutoRenewing: false, + packageName: 'package', + purchaseTime: 1231231231, + purchaseToken: 'token', + signature: 'sign', + originalJson: 'json', + developerPayload: 'dummy payload', + isAcknowledged: true, + purchaseState: PlatformPurchaseState.purchased, + quantity: 1, + ), + ], + ), + ); return convertToPigeonResult(expectedBillingResult); }); @@ -591,7 +689,9 @@ void main() { const BillingResponse expectedCode = BillingResponse.error; const BillingResultWrapper expectedBillingResultForConsume = BillingResultWrapper( - responseCode: expectedCode, debugMessage: debugMessage); + responseCode: expectedCode, + debugMessage: debugMessage, + ); when(mockApi.consumeAsync(any)).thenAnswer((Invocation invocation) async { final String purchaseToken = invocation.positionalArguments.first as String; @@ -610,200 +710,234 @@ void main() { subscription.cancel(); }, onDone: () {}); final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( - productDetails: - GooglePlayProductDetails.fromProductDetails(productDetails).first, - applicationUserName: accountId); + productDetails: + GooglePlayProductDetails.fromProductDetails(productDetails).first, + applicationUserName: accountId, + ); await iapAndroidPlatform.buyConsumable(purchaseParam: purchaseParam); // Verify that the result has an error for the failed consumption final GooglePlayPurchaseDetails result = await completer.future as GooglePlayPurchaseDetails; expect(result.billingClientPurchase, isNotNull); - expect(result.billingClientPurchase.purchaseToken, - await consumeCompleter.future); + expect( + result.billingClientPurchase.purchaseToken, + await consumeCompleter.future, + ); expect(result.status, PurchaseStatus.error); expect(result.error, isNotNull); expect(result.error!.code, kConsumptionFailedErrorCode); }); test( - 'buy consumable without auto consume, consume api should not receive calls', - () async { - const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; - const String accountId = 'hashedAccountId'; - const String debugMessage = 'dummy message'; - const BillingResponse sentCode = BillingResponse.developerError; - const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: sentCode, debugMessage: debugMessage); - - when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { - // Mock java update purchase callback. - iapAndroidPlatform.billingClientManager.client.hostCallbackHandler - .onPurchasesUpdated(PlatformPurchasesResponse( - billingResult: convertToPigeonResult(expectedBillingResult), - purchases: [ - PlatformPurchase( - orderId: 'orderID1', - products: [productDetails.productId], - isAutoRenewing: false, - packageName: 'package', - purchaseTime: 1231231231, - purchaseToken: 'token', - signature: 'sign', - originalJson: 'json', - developerPayload: 'dummy payload', - isAcknowledged: true, - purchaseState: PlatformPurchaseState.purchased, - quantity: 1, - ) - ], - )); - - return convertToPigeonResult(expectedBillingResult); - }); - final Completer consumeCompleter = Completer(); - // adding call back for consume purchase - const BillingResponse expectedCode = BillingResponse.ok; - const BillingResultWrapper expectedBillingResultForConsume = - BillingResultWrapper( - responseCode: expectedCode, debugMessage: debugMessage); - when(mockApi.consumeAsync(any)).thenAnswer((Invocation invocation) async { - final String purchaseToken = - invocation.positionalArguments.first as String; - consumeCompleter.complete(purchaseToken); - return convertToPigeonResult(expectedBillingResultForConsume); - }); + 'buy consumable without auto consume, consume api should not receive calls', + () async { + const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; + const String accountId = 'hashedAccountId'; + const String debugMessage = 'dummy message'; + const BillingResponse sentCode = BillingResponse.developerError; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( + responseCode: sentCode, + debugMessage: debugMessage, + ); - final Stream> purchaseStream = - iapAndroidPlatform.purchaseStream; - late StreamSubscription> subscription; - subscription = purchaseStream.listen((_) { - consumeCompleter.complete(null); - subscription.cancel(); - }, onDone: () {}); - final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( + when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { + // Mock java update purchase callback. + iapAndroidPlatform.billingClientManager.client.hostCallbackHandler + .onPurchasesUpdated( + PlatformPurchasesResponse( + billingResult: convertToPigeonResult(expectedBillingResult), + purchases: [ + PlatformPurchase( + orderId: 'orderID1', + products: [productDetails.productId], + isAutoRenewing: false, + packageName: 'package', + purchaseTime: 1231231231, + purchaseToken: 'token', + signature: 'sign', + originalJson: 'json', + developerPayload: 'dummy payload', + isAcknowledged: true, + purchaseState: PlatformPurchaseState.purchased, + quantity: 1, + ), + ], + ), + ); + + return convertToPigeonResult(expectedBillingResult); + }); + final Completer consumeCompleter = Completer(); + // adding call back for consume purchase + const BillingResponse expectedCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResultForConsume = + BillingResultWrapper( + responseCode: expectedCode, + debugMessage: debugMessage, + ); + when(mockApi.consumeAsync(any)).thenAnswer(( + Invocation invocation, + ) async { + final String purchaseToken = + invocation.positionalArguments.first as String; + consumeCompleter.complete(purchaseToken); + return convertToPigeonResult(expectedBillingResultForConsume); + }); + + final Stream> purchaseStream = + iapAndroidPlatform.purchaseStream; + late StreamSubscription> subscription; + subscription = purchaseStream.listen((_) { + consumeCompleter.complete(null); + subscription.cancel(); + }, onDone: () {}); + final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( productDetails: GooglePlayProductDetails.fromProductDetails(productDetails).first, - applicationUserName: accountId); - await iapAndroidPlatform.buyConsumable( - purchaseParam: purchaseParam, autoConsume: false); - expect(null, await consumeCompleter.future); - }); + applicationUserName: accountId, + ); + await iapAndroidPlatform.buyConsumable( + purchaseParam: purchaseParam, + autoConsume: false, + ); + expect(null, await consumeCompleter.future); + }, + ); test( - 'should get canceled purchase status when response code is BillingResponse.userCanceled', - () async { - const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; - const String accountId = 'hashedAccountId'; - const String debugMessage = 'dummy message'; - const BillingResponse sentCode = BillingResponse.userCanceled; - const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: sentCode, debugMessage: debugMessage); - when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { - // Mock java update purchase callback. - iapAndroidPlatform.billingClientManager.client.hostCallbackHandler - .onPurchasesUpdated(PlatformPurchasesResponse( - billingResult: convertToPigeonResult(expectedBillingResult), - purchases: [ - PlatformPurchase( - orderId: 'orderID1', - products: [productDetails.productId], - isAutoRenewing: false, - packageName: 'package', - purchaseTime: 1231231231, - purchaseToken: 'token', - signature: 'sign', - originalJson: 'json', - developerPayload: 'dummy payload', - isAcknowledged: true, - purchaseState: PlatformPurchaseState.purchased, - quantity: 1, - ) - ], - )); - - return convertToPigeonResult(expectedBillingResult); - }); - final Completer consumeCompleter = Completer(); - // adding call back for consume purchase - const BillingResponse expectedCode = BillingResponse.userCanceled; - const BillingResultWrapper expectedBillingResultForConsume = - BillingResultWrapper( - responseCode: expectedCode, debugMessage: debugMessage); - when(mockApi.consumeAsync(any)).thenAnswer((Invocation invocation) async { - final String purchaseToken = - invocation.positionalArguments.first as String; - consumeCompleter.complete(purchaseToken); - return convertToPigeonResult(expectedBillingResultForConsume); - }); - - final Completer completer = Completer(); - PurchaseDetails purchaseDetails; - final Stream> purchaseStream = - iapAndroidPlatform.purchaseStream; - late StreamSubscription> subscription; - subscription = purchaseStream.listen((List details) { - purchaseDetails = details.first; - completer.complete(purchaseDetails); - subscription.cancel(); - }, onDone: () {}); - final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( + 'should get canceled purchase status when response code is BillingResponse.userCanceled', + () async { + const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; + const String accountId = 'hashedAccountId'; + const String debugMessage = 'dummy message'; + const BillingResponse sentCode = BillingResponse.userCanceled; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( + responseCode: sentCode, + debugMessage: debugMessage, + ); + when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { + // Mock java update purchase callback. + iapAndroidPlatform.billingClientManager.client.hostCallbackHandler + .onPurchasesUpdated( + PlatformPurchasesResponse( + billingResult: convertToPigeonResult(expectedBillingResult), + purchases: [ + PlatformPurchase( + orderId: 'orderID1', + products: [productDetails.productId], + isAutoRenewing: false, + packageName: 'package', + purchaseTime: 1231231231, + purchaseToken: 'token', + signature: 'sign', + originalJson: 'json', + developerPayload: 'dummy payload', + isAcknowledged: true, + purchaseState: PlatformPurchaseState.purchased, + quantity: 1, + ), + ], + ), + ); + + return convertToPigeonResult(expectedBillingResult); + }); + final Completer consumeCompleter = Completer(); + // adding call back for consume purchase + const BillingResponse expectedCode = BillingResponse.userCanceled; + const BillingResultWrapper expectedBillingResultForConsume = + BillingResultWrapper( + responseCode: expectedCode, + debugMessage: debugMessage, + ); + when(mockApi.consumeAsync(any)).thenAnswer(( + Invocation invocation, + ) async { + final String purchaseToken = + invocation.positionalArguments.first as String; + consumeCompleter.complete(purchaseToken); + return convertToPigeonResult(expectedBillingResultForConsume); + }); + + final Completer completer = + Completer(); + PurchaseDetails purchaseDetails; + final Stream> purchaseStream = + iapAndroidPlatform.purchaseStream; + late StreamSubscription> subscription; + subscription = purchaseStream.listen((List details) { + purchaseDetails = details.first; + completer.complete(purchaseDetails); + subscription.cancel(); + }, onDone: () {}); + final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( productDetails: GooglePlayProductDetails.fromProductDetails(productDetails).first, - applicationUserName: accountId); - await iapAndroidPlatform.buyConsumable(purchaseParam: purchaseParam); + applicationUserName: accountId, + ); + await iapAndroidPlatform.buyConsumable(purchaseParam: purchaseParam); - // Verify that the result has an error for the failed consumption - final GooglePlayPurchaseDetails result = - await completer.future as GooglePlayPurchaseDetails; - expect(result.status, PurchaseStatus.canceled); - }); + // Verify that the result has an error for the failed consumption + final GooglePlayPurchaseDetails result = + await completer.future as GooglePlayPurchaseDetails; + expect(result.status, PurchaseStatus.canceled); + }, + ); test( - 'should get purchased purchase status when upgrading subscription by deferred proration mode', - () async { - const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; - const String accountId = 'hashedAccountId'; - const String debugMessage = 'dummy message'; - const BillingResponse sentCode = BillingResponse.ok; - const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: sentCode, debugMessage: debugMessage); - when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { - // Mock java update purchase callback. - iapAndroidPlatform.billingClientManager.client.hostCallbackHandler - .onPurchasesUpdated(PlatformPurchasesResponse( - billingResult: convertToPigeonResult(expectedBillingResult), - purchases: [], - )); - - return convertToPigeonResult(expectedBillingResult); - }); - - final Completer completer = Completer(); - PurchaseDetails purchaseDetails; - final Stream> purchaseStream = - iapAndroidPlatform.purchaseStream; - late StreamSubscription> subscription; - subscription = purchaseStream.listen((List details) { - purchaseDetails = details.first; - completer.complete(purchaseDetails); - subscription.cancel(); - }, onDone: () {}); - final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( + 'should get purchased purchase status when upgrading subscription by deferred proration mode', + () async { + const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; + const String accountId = 'hashedAccountId'; + const String debugMessage = 'dummy message'; + const BillingResponse sentCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( + responseCode: sentCode, + debugMessage: debugMessage, + ); + when(mockApi.launchBillingFlow(any)).thenAnswer((_) async { + // Mock java update purchase callback. + iapAndroidPlatform.billingClientManager.client.hostCallbackHandler + .onPurchasesUpdated( + PlatformPurchasesResponse( + billingResult: convertToPigeonResult(expectedBillingResult), + purchases: [], + ), + ); + + return convertToPigeonResult(expectedBillingResult); + }); + + final Completer completer = + Completer(); + PurchaseDetails purchaseDetails; + final Stream> purchaseStream = + iapAndroidPlatform.purchaseStream; + late StreamSubscription> subscription; + subscription = purchaseStream.listen((List details) { + purchaseDetails = details.first; + completer.complete(purchaseDetails); + subscription.cancel(); + }, onDone: () {}); + final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( productDetails: GooglePlayProductDetails.fromProductDetails(productDetails).first, applicationUserName: accountId, changeSubscriptionParam: ChangeSubscriptionParam( - oldPurchaseDetails: GooglePlayPurchaseDetails.fromPurchase( - dummyUnacknowledgedPurchase) - .first, + oldPurchaseDetails: + GooglePlayPurchaseDetails.fromPurchase( + dummyUnacknowledgedPurchase, + ).first, replacementMode: ReplacementMode.deferred, - )); - await iapAndroidPlatform.buyNonConsumable(purchaseParam: purchaseParam); + ), + ); + await iapAndroidPlatform.buyNonConsumable(purchaseParam: purchaseParam); - final PurchaseDetails result = await completer.future; - expect(result.status, PurchaseStatus.purchased); - }); + final PurchaseDetails result = await completer.future; + expect(result.status, PurchaseStatus.purchased); + }, + ); }); group('complete purchase', () { @@ -811,12 +945,16 @@ void main() { const BillingResponse expectedCode = BillingResponse.ok; const String debugMessage = 'dummy message'; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( - responseCode: expectedCode, debugMessage: debugMessage); - when(mockApi.acknowledgePurchase(any)).thenAnswer( - (_) async => convertToPigeonResult(expectedBillingResult)); + responseCode: expectedCode, + debugMessage: debugMessage, + ); + when( + mockApi.acknowledgePurchase(any), + ).thenAnswer((_) async => convertToPigeonResult(expectedBillingResult)); final PurchaseDetails purchaseDetails = - GooglePlayPurchaseDetails.fromPurchase(dummyUnacknowledgedPurchase) - .first; + GooglePlayPurchaseDetails.fromPurchase( + dummyUnacknowledgedPurchase, + ).first; final Completer completer = Completer(); purchaseDetails.status = PurchaseStatus.purchased; @@ -834,18 +972,22 @@ void main() { test('getCountryCode success', () async { const String expectedCountryCode = 'US'; const BillingConfigWrapper expected = BillingConfigWrapper( - countryCode: expectedCountryCode, - responseCode: BillingResponse.ok, - debugMessage: 'dummy message'); + countryCode: expectedCountryCode, + responseCode: BillingResponse.ok, + debugMessage: 'dummy message', + ); - when(mockApi.getBillingConfigAsync()) - .thenAnswer((_) async => platformBillingConfigFromWrapper(expected)); + when( + mockApi.getBillingConfigAsync(), + ).thenAnswer((_) async => platformBillingConfigFromWrapper(expected)); final String countryCode = await iapAndroidPlatform.countryCode(); expect(countryCode, equals(expectedCountryCode)); // Ensure deprecated code keeps working until removed. - expect(await iapAndroidPlatform.getCountryCode(), - equals(expectedCountryCode)); + expect( + await iapAndroidPlatform.getCountryCode(), + equals(expectedCountryCode), + ); }); }); } diff --git a/packages/in_app_purchase/in_app_purchase_android/test/test_conversion_utils.dart b/packages/in_app_purchase/in_app_purchase_android/test/test_conversion_utils.dart index 9c0bfae2aa7..6d277ac8dc9 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/test_conversion_utils.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/test_conversion_utils.dart @@ -21,80 +21,92 @@ PlatformBillingResult convertToPigeonResult(BillingResultWrapper targetResult) { /// Creates a [PlatformPurchase] from the corresponding [PurchaseWrapper]. PlatformPurchase convertToPigeonPurchase(PurchaseWrapper purchase) { return PlatformPurchase( - orderId: purchase.orderId, - packageName: purchase.packageName, - purchaseTime: purchase.purchaseTime, - purchaseToken: purchase.purchaseToken, - signature: purchase.signature, - products: purchase.products, - isAutoRenewing: purchase.isAutoRenewing, - originalJson: purchase.originalJson, - developerPayload: purchase.developerPayload ?? '', - isAcknowledged: purchase.isAcknowledged, - purchaseState: _convertToPigeonPurchaseState(purchase.purchaseState), - // For some reason quantity is not in PurchaseWrapper. - quantity: 99, - accountIdentifiers: purchase.obfuscatedAccountId != null || - purchase.obfuscatedProfileId != null - ? PlatformAccountIdentifiers( + orderId: purchase.orderId, + packageName: purchase.packageName, + purchaseTime: purchase.purchaseTime, + purchaseToken: purchase.purchaseToken, + signature: purchase.signature, + products: purchase.products, + isAutoRenewing: purchase.isAutoRenewing, + originalJson: purchase.originalJson, + developerPayload: purchase.developerPayload ?? '', + isAcknowledged: purchase.isAcknowledged, + purchaseState: _convertToPigeonPurchaseState(purchase.purchaseState), + // For some reason quantity is not in PurchaseWrapper. + quantity: 99, + accountIdentifiers: + purchase.obfuscatedAccountId != null || + purchase.obfuscatedProfileId != null + ? PlatformAccountIdentifiers( obfuscatedAccountId: purchase.obfuscatedAccountId, obfuscatedProfileId: purchase.obfuscatedProfileId, ) - : null); + : null, + ); } /// Creates a [PlatformProductDetails] from the corresponding [ProductDetailsWrapper]. PlatformProductDetails convertToPigeonProductDetails( - ProductDetailsWrapper details) { + ProductDetailsWrapper details, +) { return PlatformProductDetails( - description: details.description, - name: details.name, - productId: details.productId, - productType: platformProductTypeFromWrapper(details.productType), - title: details.title, - oneTimePurchaseOfferDetails: _convertToPigeonOneTimePurchaseOfferDetails( - details.oneTimePurchaseOfferDetails), - subscriptionOfferDetails: details.subscriptionOfferDetails - ?.map(convertToPigeonSubscriptionOfferDetails) - .toList()); + description: details.description, + name: details.name, + productId: details.productId, + productType: platformProductTypeFromWrapper(details.productType), + title: details.title, + oneTimePurchaseOfferDetails: _convertToPigeonOneTimePurchaseOfferDetails( + details.oneTimePurchaseOfferDetails, + ), + subscriptionOfferDetails: + details.subscriptionOfferDetails + ?.map(convertToPigeonSubscriptionOfferDetails) + .toList(), + ); } PlatformSubscriptionOfferDetails convertToPigeonSubscriptionOfferDetails( - SubscriptionOfferDetailsWrapper details) { + SubscriptionOfferDetailsWrapper details, +) { return PlatformSubscriptionOfferDetails( - basePlanId: details.basePlanId, - offerId: details.offerId, - offerToken: details.offerIdToken, - offerTags: details.offerTags, - pricingPhases: - details.pricingPhases.map(convertToPigeonPricingPhase).toList()); + basePlanId: details.basePlanId, + offerId: details.offerId, + offerToken: details.offerIdToken, + offerTags: details.offerTags, + pricingPhases: + details.pricingPhases.map(convertToPigeonPricingPhase).toList(), + ); } PlatformPricingPhase convertToPigeonPricingPhase(PricingPhaseWrapper phase) { return PlatformPricingPhase( - billingCycleCount: phase.billingCycleCount, - recurrenceMode: _convertToPigeonRecurrenceMode(phase.recurrenceMode), - priceAmountMicros: phase.priceAmountMicros, - billingPeriod: phase.billingPeriod, - formattedPrice: phase.formattedPrice, - priceCurrencyCode: phase.priceCurrencyCode); + billingCycleCount: phase.billingCycleCount, + recurrenceMode: _convertToPigeonRecurrenceMode(phase.recurrenceMode), + priceAmountMicros: phase.priceAmountMicros, + billingPeriod: phase.billingPeriod, + formattedPrice: phase.formattedPrice, + priceCurrencyCode: phase.priceCurrencyCode, + ); } PlatformOneTimePurchaseOfferDetails? - _convertToPigeonOneTimePurchaseOfferDetails( - OneTimePurchaseOfferDetailsWrapper? offer) { +_convertToPigeonOneTimePurchaseOfferDetails( + OneTimePurchaseOfferDetailsWrapper? offer, +) { if (offer == null) { return null; } return PlatformOneTimePurchaseOfferDetails( - priceAmountMicros: offer.priceAmountMicros, - formattedPrice: offer.formattedPrice, - priceCurrencyCode: offer.priceCurrencyCode); + priceAmountMicros: offer.priceAmountMicros, + formattedPrice: offer.formattedPrice, + priceCurrencyCode: offer.priceCurrencyCode, + ); } /// Creates a [PlatformPurchaseState] from the Dart wrapper equivalent. PlatformPurchaseState _convertToPigeonPurchaseState( - PurchaseStateWrapper state) { + PurchaseStateWrapper state, +) { return switch (state) { PurchaseStateWrapper.unspecified_state => PlatformPurchaseState.unspecified, PurchaseStateWrapper.purchased => PlatformPurchaseState.purchased, diff --git a/packages/in_app_purchase/in_app_purchase_android/test/types/translator_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/types/translator_test.dart index 7e19c4b4157..e135c860c67 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/types/translator_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/types/translator_test.dart @@ -10,62 +10,79 @@ import 'package:test/test.dart'; void main() { group('Translator ', () { test('convertToPlayProductType', () { - expect(Translator.convertToPlayProductType(ProductType.inapp), - GooglePlayProductType.inapp); - expect(Translator.convertToPlayProductType(ProductType.subs), - GooglePlayProductType.subs); + expect( + Translator.convertToPlayProductType(ProductType.inapp), + GooglePlayProductType.inapp, + ); + expect( + Translator.convertToPlayProductType(ProductType.subs), + GooglePlayProductType.subs, + ); expect(GooglePlayProductType.values.length, ProductType.values.length); }); test('convertToUserChoiceDetailsProduct', () { const GooglePlayUserChoiceDetailsProduct expected = GooglePlayUserChoiceDetailsProduct( - id: 'id', - offerToken: 'offerToken', - productType: GooglePlayProductType.inapp); + id: 'id', + offerToken: 'offerToken', + productType: GooglePlayProductType.inapp, + ); expect( - Translator.convertToUserChoiceDetailsProduct( - UserChoiceDetailsProductWrapper( - id: expected.id, - offerToken: expected.offerToken, - productType: ProductType.inapp)), - expected); + Translator.convertToUserChoiceDetailsProduct( + UserChoiceDetailsProductWrapper( + id: expected.id, + offerToken: expected.offerToken, + productType: ProductType.inapp, + ), + ), + expected, + ); }); test('convertToUserChoiceDetailsProduct', () { const GooglePlayUserChoiceDetailsProduct expectedProduct1 = GooglePlayUserChoiceDetailsProduct( - id: 'id1', - offerToken: 'offerToken1', - productType: GooglePlayProductType.inapp); + id: 'id1', + offerToken: 'offerToken1', + productType: GooglePlayProductType.inapp, + ); const GooglePlayUserChoiceDetailsProduct expectedProduct2 = GooglePlayUserChoiceDetailsProduct( - id: 'id2', - offerToken: 'offerToken2', - productType: GooglePlayProductType.subs); + id: 'id2', + offerToken: 'offerToken2', + productType: GooglePlayProductType.subs, + ); const GooglePlayUserChoiceDetails expected = GooglePlayUserChoiceDetails( - originalExternalTransactionId: 'originalExternalTransactionId', - externalTransactionToken: 'externalTransactionToken', - products: [ - expectedProduct1, - expectedProduct2 - ]); + originalExternalTransactionId: 'originalExternalTransactionId', + externalTransactionToken: 'externalTransactionToken', + products: [ + expectedProduct1, + expectedProduct2, + ], + ); expect( - Translator.convertToUserChoiceDetails(UserChoiceDetailsWrapper( - originalExternalTransactionId: - expected.originalExternalTransactionId, - externalTransactionToken: expected.externalTransactionToken, - products: [ - UserChoiceDetailsProductWrapper( - id: expectedProduct1.id, - offerToken: expectedProduct1.offerToken, - productType: ProductType.inapp), - UserChoiceDetailsProductWrapper( - id: expectedProduct2.id, - offerToken: expectedProduct2.offerToken, - productType: ProductType.subs), - ])), - expected); + Translator.convertToUserChoiceDetails( + UserChoiceDetailsWrapper( + originalExternalTransactionId: + expected.originalExternalTransactionId, + externalTransactionToken: expected.externalTransactionToken, + products: [ + UserChoiceDetailsProductWrapper( + id: expectedProduct1.id, + offerToken: expectedProduct1.offerToken, + productType: ProductType.inapp, + ), + UserChoiceDetailsProductWrapper( + id: expectedProduct2.id, + offerToken: expectedProduct2.offerToken, + productType: ProductType.subs, + ), + ], + ), + ), + expected, + ); }); }); } diff --git a/packages/in_app_purchase/in_app_purchase_platform_interface/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_platform_interface/CHANGELOG.md index a1359fae526..46a7364e6c5 100644 --- a/packages/in_app_purchase/in_app_purchase_platform_interface/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.27/Dart 3.6. +* Updates minimum supported SDK version to Flutter 3.29/Dart 3.7. ## 1.4.0 diff --git a/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/errors/in_app_purchase_error.dart b/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/errors/in_app_purchase_error.dart index 166646d35b2..870afb01e54 100644 --- a/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/errors/in_app_purchase_error.dart +++ b/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/errors/in_app_purchase_error.dart @@ -11,11 +11,12 @@ /// * [PurchaseDetails] for error happened in purchase. class IAPError { /// Creates a new IAP error object with the given error details. - IAPError( - {required this.source, - required this.code, - required this.message, - this.details}); + IAPError({ + required this.source, + required this.code, + required this.message, + this.details, + }); /// Which source is the error on. final String source; diff --git a/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/in_app_purchase_platform.dart b/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/in_app_purchase_platform.dart index 7fd34538025..6f5db0e4073 100644 --- a/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/in_app_purchase_platform.dart +++ b/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/in_app_purchase_platform.dart @@ -72,7 +72,8 @@ abstract class InAppPurchasePlatform extends PlatformInterface { /// Console](https://play.google.com/) for Android. Future queryProductDetails(Set identifiers) => throw UnimplementedError( - 'queryProductDetails() had not been implemented.'); + 'queryProductDetails() had not been implemented.', + ); /// Buy a non consumable product or subscription. /// @@ -149,8 +150,7 @@ abstract class InAppPurchasePlatform extends PlatformInterface { Future buyConsumable({ required PurchaseParam purchaseParam, bool autoConsume = true, - }) => - throw UnimplementedError('buyConsumable() has not been implemented.'); + }) => throw UnimplementedError('buyConsumable() has not been implemented.'); /// Mark that purchased content has been delivered to the user. /// diff --git a/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/types/product_details_response.dart b/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/types/product_details_response.dart index 3a9d7c3c976..97c5a096ac0 100644 --- a/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/types/product_details_response.dart +++ b/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/types/product_details_response.dart @@ -10,8 +10,11 @@ import 'product_details.dart'; /// A list of [ProductDetails] can be obtained from the this response. class ProductDetailsResponse { /// Creates a new [ProductDetailsResponse] with the provided response details. - ProductDetailsResponse( - {required this.productDetails, required this.notFoundIDs, this.error}); + ProductDetailsResponse({ + required this.productDetails, + required this.notFoundIDs, + this.error, + }); /// Each [ProductDetails] uniquely matches one valid identifier in [identifiers] of [InAppPurchasePlatform.queryProductDetails]. final List productDetails; diff --git a/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/types/purchase_param.dart b/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/types/purchase_param.dart index df75159c152..0f884fc2661 100644 --- a/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/types/purchase_param.dart +++ b/packages/in_app_purchase/in_app_purchase_platform_interface/lib/src/types/purchase_param.dart @@ -7,10 +7,7 @@ import 'product_details.dart'; /// The parameter object for generating a purchase. class PurchaseParam { /// Creates a new purchase parameter object with the given data. - PurchaseParam({ - required this.productDetails, - this.applicationUserName, - }); + PurchaseParam({required this.productDetails, this.applicationUserName}); /// The product to create payment for. /// diff --git a/packages/in_app_purchase/in_app_purchase_platform_interface/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_platform_interface/pubspec.yaml index a34a7fb7f70..45e698063d9 100644 --- a/packages/in_app_purchase/in_app_purchase_platform_interface/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.4.0 environment: - sdk: ^3.6.0 - flutter: ">=3.27.0" + sdk: ^3.7.0 + flutter: ">=3.29.0" dependencies: flutter: diff --git a/packages/in_app_purchase/in_app_purchase_platform_interface/test/in_app_purchase_platform_test.dart b/packages/in_app_purchase/in_app_purchase_platform_interface/test/in_app_purchase_platform_test.dart index 5ae13ade1bb..1484885a9aa 100644 --- a/packages/in_app_purchase/in_app_purchase_platform_interface/test/in_app_purchase_platform_test.dart +++ b/packages/in_app_purchase/in_app_purchase_platform_interface/test/in_app_purchase_platform_test.dart @@ -33,104 +33,112 @@ void main() { }); test( - 'Default implementation of purchaseStream should throw unimplemented error', - () { - final ExtendsInAppPurchasePlatform inAppPurchasePlatform = - ExtendsInAppPurchasePlatform(); - - expect( - () => inAppPurchasePlatform.purchaseStream, - throwsUnimplementedError, - ); - }); + 'Default implementation of purchaseStream should throw unimplemented error', + () { + final ExtendsInAppPurchasePlatform inAppPurchasePlatform = + ExtendsInAppPurchasePlatform(); + + expect( + () => inAppPurchasePlatform.purchaseStream, + throwsUnimplementedError, + ); + }, + ); test( - 'Default implementation of isAvailable should throw unimplemented error', - () { - final ExtendsInAppPurchasePlatform inAppPurchasePlatform = - ExtendsInAppPurchasePlatform(); - - expect( - () => inAppPurchasePlatform.isAvailable(), - throwsUnimplementedError, - ); - }); + 'Default implementation of isAvailable should throw unimplemented error', + () { + final ExtendsInAppPurchasePlatform inAppPurchasePlatform = + ExtendsInAppPurchasePlatform(); + + expect( + () => inAppPurchasePlatform.isAvailable(), + throwsUnimplementedError, + ); + }, + ); test( - 'Default implementation of queryProductDetails should throw unimplemented error', - () { - final ExtendsInAppPurchasePlatform inAppPurchasePlatform = - ExtendsInAppPurchasePlatform(); - - expect( - () => inAppPurchasePlatform.queryProductDetails({''}), - throwsUnimplementedError, - ); - }); + 'Default implementation of queryProductDetails should throw unimplemented error', + () { + final ExtendsInAppPurchasePlatform inAppPurchasePlatform = + ExtendsInAppPurchasePlatform(); + + expect( + () => inAppPurchasePlatform.queryProductDetails({''}), + throwsUnimplementedError, + ); + }, + ); test( - 'Default implementation of buyNonConsumable should throw unimplemented error', - () { - final ExtendsInAppPurchasePlatform inAppPurchasePlatform = - ExtendsInAppPurchasePlatform(); - - expect( - () => inAppPurchasePlatform.buyNonConsumable( - purchaseParam: MockPurchaseParam(), - ), - throwsUnimplementedError, - ); - }); + 'Default implementation of buyNonConsumable should throw unimplemented error', + () { + final ExtendsInAppPurchasePlatform inAppPurchasePlatform = + ExtendsInAppPurchasePlatform(); + + expect( + () => inAppPurchasePlatform.buyNonConsumable( + purchaseParam: MockPurchaseParam(), + ), + throwsUnimplementedError, + ); + }, + ); test( - 'Default implementation of buyConsumable should throw unimplemented error', - () { - final ExtendsInAppPurchasePlatform inAppPurchasePlatform = - ExtendsInAppPurchasePlatform(); - - expect( - () => inAppPurchasePlatform.buyConsumable( - purchaseParam: MockPurchaseParam(), - ), - throwsUnimplementedError, - ); - }); + 'Default implementation of buyConsumable should throw unimplemented error', + () { + final ExtendsInAppPurchasePlatform inAppPurchasePlatform = + ExtendsInAppPurchasePlatform(); + + expect( + () => inAppPurchasePlatform.buyConsumable( + purchaseParam: MockPurchaseParam(), + ), + throwsUnimplementedError, + ); + }, + ); test( - 'Default implementation of completePurchase should throw unimplemented error', - () { - final ExtendsInAppPurchasePlatform inAppPurchasePlatform = - ExtendsInAppPurchasePlatform(); - - expect( - () => inAppPurchasePlatform.completePurchase(MockPurchaseDetails()), - throwsUnimplementedError, - ); - }); + 'Default implementation of completePurchase should throw unimplemented error', + () { + final ExtendsInAppPurchasePlatform inAppPurchasePlatform = + ExtendsInAppPurchasePlatform(); + + expect( + () => inAppPurchasePlatform.completePurchase(MockPurchaseDetails()), + throwsUnimplementedError, + ); + }, + ); test( - 'Default implementation of restorePurchases should throw unimplemented error', - () { - final ExtendsInAppPurchasePlatform inAppPurchasePlatform = - ExtendsInAppPurchasePlatform(); - - expect( - () => inAppPurchasePlatform.restorePurchases(), - throwsUnimplementedError, - ); - }); + 'Default implementation of restorePurchases should throw unimplemented error', + () { + final ExtendsInAppPurchasePlatform inAppPurchasePlatform = + ExtendsInAppPurchasePlatform(); + + expect( + () => inAppPurchasePlatform.restorePurchases(), + throwsUnimplementedError, + ); + }, + ); test( - 'Default implementation of countryCode should throw unimplemented error', - () { - final ExtendsInAppPurchasePlatform inAppPurchasePlatform = - ExtendsInAppPurchasePlatform(); - - expect( - () => inAppPurchasePlatform.countryCode(), - throwsUnimplementedError, - ); - }); + 'Default implementation of countryCode should throw unimplemented error', + () { + final ExtendsInAppPurchasePlatform inAppPurchasePlatform = + ExtendsInAppPurchasePlatform(); + + expect( + () => inAppPurchasePlatform.countryCode(), + throwsUnimplementedError, + ); + }, + ); }); group('$InAppPurchasePlatformAddition', () { @@ -154,9 +162,11 @@ void main() { test('Can not be a `InAppPurchasePlatform`', () { expect( - () => InAppPurchasePlatformAddition.instance = - ExtendsInAppPurchasePlatformAdditionIsPlatformInterface(), - throwsAssertionError); + () => + InAppPurchasePlatformAddition.instance = + ExtendsInAppPurchasePlatformAdditionIsPlatformInterface(), + throwsAssertionError, + ); }); test('Provider can provide', () { @@ -187,8 +197,7 @@ class MockInAppPurchasePlatform extends Mock with // ignore: prefer_mixin MockPlatformInterfaceMixin - implements - InAppPurchasePlatform {} + implements InAppPurchasePlatform {} class ExtendsInAppPurchasePlatform extends InAppPurchasePlatform {} diff --git a/packages/in_app_purchase/in_app_purchase_platform_interface/test/src/errors/in_app_purchase_error_test.dart b/packages/in_app_purchase/in_app_purchase_platform_interface/test/src/errors/in_app_purchase_error_test.dart index ed63f495b4c..c17f70597bb 100644 --- a/packages/in_app_purchase/in_app_purchase_platform_interface/test/src/errors/in_app_purchase_error_test.dart +++ b/packages/in_app_purchase/in_app_purchase_platform_interface/test/src/errors/in_app_purchase_error_test.dart @@ -13,8 +13,10 @@ void main() { source: 'dummy_source', ); - expect(exceptionNoDetails.toString(), - 'IAPError(code: error_code, source: dummy_source, message: dummy_message, details: null)'); + expect( + exceptionNoDetails.toString(), + 'IAPError(code: error_code, source: dummy_source, message: dummy_message, details: null)', + ); final IAPError exceptionWithDetails = IAPError( code: 'error_code', @@ -23,7 +25,9 @@ void main() { details: 'dummy_details', ); - expect(exceptionWithDetails.toString(), - 'IAPError(code: error_code, source: dummy_source, message: dummy_message, details: dummy_details)'); + expect( + exceptionWithDetails.toString(), + 'IAPError(code: error_code, source: dummy_source, message: dummy_message, details: dummy_details)', + ); }); } diff --git a/packages/in_app_purchase/in_app_purchase_platform_interface/test/src/errors/in_app_purchase_exception_test.dart b/packages/in_app_purchase/in_app_purchase_platform_interface/test/src/errors/in_app_purchase_exception_test.dart index ff9468ec2d8..45d7857269f 100644 --- a/packages/in_app_purchase/in_app_purchase_platform_interface/test/src/errors/in_app_purchase_exception_test.dart +++ b/packages/in_app_purchase/in_app_purchase_platform_interface/test/src/errors/in_app_purchase_exception_test.dart @@ -17,7 +17,9 @@ void main() { final String actual = exception.toString(); // Assert - expect(actual, - 'InAppPurchaseException(error_code, dummy message, dummy_source)'); + expect( + actual, + 'InAppPurchaseException(error_code, dummy message, dummy_source)', + ); }); } diff --git a/packages/in_app_purchase/in_app_purchase_platform_interface/test/src/types/product_details_test.dart b/packages/in_app_purchase/in_app_purchase_platform_interface/test/src/types/product_details_test.dart index 486f38fa850..96ac3934527 100644 --- a/packages/in_app_purchase/in_app_purchase_platform_interface/test/src/types/product_details_test.dart +++ b/packages/in_app_purchase/in_app_purchase_platform_interface/test/src/types/product_details_test.dart @@ -8,24 +8,26 @@ import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_inte void main() { group('Constructor Tests', () { test( - 'fromSkProduct should correctly parse data from a SKProductWrapper instance.', - () { - final ProductDetails productDetails = ProductDetails( + 'fromSkProduct should correctly parse data from a SKProductWrapper instance.', + () { + final ProductDetails productDetails = ProductDetails( id: 'id', title: 'title', description: 'description', price: '13.37', currencyCode: 'USD', currencySymbol: r'$', - rawPrice: 13.37); + rawPrice: 13.37, + ); - expect(productDetails.id, 'id'); - expect(productDetails.title, 'title'); - expect(productDetails.description, 'description'); - expect(productDetails.rawPrice, 13.37); - expect(productDetails.currencyCode, 'USD'); - expect(productDetails.currencySymbol, r'$'); - }); + expect(productDetails.id, 'id'); + expect(productDetails.title, 'title'); + expect(productDetails.description, 'description'); + expect(productDetails.rawPrice, 13.37); + expect(productDetails.currencyCode, 'USD'); + expect(productDetails.currencySymbol, r'$'); + }, + ); }); group('PurchaseStatus Tests', () { 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 09fb7d5ed81..87b7fa01ff2 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 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.29/Dart 3.7. + ## 0.4.4 * Added support for specifying quantity in `SK2ProductPurchaseOptions` (consumable purchases on iOS). diff --git a/packages/in_app_purchase/in_app_purchase_storekit/example/integration_test/in_app_purchase_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/example/integration_test/in_app_purchase_test.dart index 32ea11314ee..18b20979de6 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/example/integration_test/in_app_purchase_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/example/integration_test/in_app_purchase_test.dart @@ -10,8 +10,9 @@ import 'package:integration_test/integration_test.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - testWidgets('Can create InAppPurchaseStoreKit instance', - (WidgetTester tester) async { + testWidgets('Can create InAppPurchaseStoreKit instance', ( + WidgetTester tester, + ) async { InAppPurchaseStoreKitPlatform.registerPlatform(); final InAppPurchasePlatform androidPlatform = InAppPurchasePlatform.instance; diff --git a/packages/in_app_purchase/in_app_purchase_storekit/example/lib/example_payment_queue_delegate.dart b/packages/in_app_purchase/in_app_purchase_storekit/example/lib/example_payment_queue_delegate.dart index ba04ab12f37..edcb7e42974 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/example/lib/example_payment_queue_delegate.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/example/lib/example_payment_queue_delegate.dart @@ -12,7 +12,9 @@ import 'package:in_app_purchase_storekit/store_kit_wrappers.dart'; class ExamplePaymentQueueDelegate implements SKPaymentQueueDelegateWrapper { @override bool shouldContinueTransaction( - SKPaymentTransactionWrapper transaction, SKStorefrontWrapper storefront) { + SKPaymentTransactionWrapper transaction, + SKStorefrontWrapper storefront, + ) { return true; } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/example/lib/main.dart b/packages/in_app_purchase/in_app_purchase_storekit/example/lib/main.dart index 32f7176502d..c2b8c98bd36 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/example/lib/main.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/example/lib/main.dart @@ -57,14 +57,17 @@ class _MyAppState extends State<_MyApp> { void initState() { final Stream> purchaseUpdated = _iapStoreKitPlatform.purchaseStream; - _subscription = - purchaseUpdated.listen((List purchaseDetailsList) { - _listenToPurchaseUpdated(purchaseDetailsList); - }, onDone: () { - _subscription.cancel(); - }, onError: (Object error) { - // handle error here. - }); + _subscription = purchaseUpdated.listen( + (List purchaseDetailsList) { + _listenToPurchaseUpdated(purchaseDetailsList); + }, + onDone: () { + _subscription.cancel(); + }, + onError: (Object error) { + // handle error here. + }, + ); // Register the example payment queue delegate _iapStoreKitPlatformAddition.setDelegate(ExamplePaymentQueueDelegate()); @@ -150,9 +153,7 @@ class _MyAppState extends State<_MyApp> { ), ); } else { - stack.add(Center( - child: Text(_queryProductError!), - )); + stack.add(Center(child: Text(_queryProductError!))); } if (_purchasePending) { stack.add( @@ -162,9 +163,7 @@ class _MyAppState extends State<_MyApp> { opacity: 0.3, child: ModalBarrier(dismissible: false, color: Colors.grey), ), - Center( - child: CircularProgressIndicator(), - ), + Center(child: CircularProgressIndicator()), ], ), ); @@ -172,12 +171,8 @@ class _MyAppState extends State<_MyApp> { return MaterialApp( home: Scaffold( - appBar: AppBar( - title: const Text('IAP Example'), - ), - body: Stack( - children: stack, - ), + appBar: AppBar(title: const Text('IAP Example')), + body: Stack(children: stack), ), ); } @@ -187,12 +182,14 @@ class _MyAppState extends State<_MyApp> { return const Card(child: ListTile(title: Text('Trying to connect...'))); } final Widget storeHeader = ListTile( - leading: Icon(_isAvailable ? Icons.check : Icons.block, - color: _isAvailable - ? Colors.green - : ThemeData.light().colorScheme.error), - title: - Text('The store is ${_isAvailable ? 'available' : 'unavailable'}.'), + leading: Icon( + _isAvailable ? Icons.check : Icons.block, + color: + _isAvailable ? Colors.green : ThemeData.light().colorScheme.error, + ), + title: Text( + 'The store is ${_isAvailable ? 'available' : 'unavailable'}.', + ), ); final List children = [storeHeader]; @@ -200,10 +197,13 @@ class _MyAppState extends State<_MyApp> { children.addAll([ const Divider(), ListTile( - title: Text('Not connected', - style: TextStyle(color: ThemeData.light().colorScheme.error)), + title: Text( + 'Not connected', + style: TextStyle(color: ThemeData.light().colorScheme.error), + ), subtitle: const Text( - 'Unable to connect to the payments processor. Has this app been configured correctly? See the example README for instructions.'), + 'Unable to connect to the payments processor. Has this app been configured correctly? See the example README for instructions.', + ), ), ]); } @@ -213,9 +213,11 @@ class _MyAppState extends State<_MyApp> { Widget _buildProductList() { if (_loading) { return const Card( - child: ListTile( - leading: CircularProgressIndicator(), - title: Text('Fetching products...'))); + child: ListTile( + leading: CircularProgressIndicator(), + title: Text('Fetching products...'), + ), + ); } if (!_isAvailable) { return const Card(); @@ -223,28 +225,28 @@ class _MyAppState extends State<_MyApp> { const ListTile productHeader = ListTile( title: Text( 'Products for Sale', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), ); const ListTile promoHeader = ListTile( title: Text( 'Products in promo', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), ); final List productList = []; if (_notFoundIds.isNotEmpty) { - productList.add(ListTile( - title: Text('[${_notFoundIds.join(", ")}] not found', - style: TextStyle(color: ThemeData.light().colorScheme.error)), + productList.add( + ListTile( + title: Text( + '[${_notFoundIds.join(", ")}] not found', + style: TextStyle(color: ThemeData.light().colorScheme.error), + ), subtitle: const Text( - 'This app needs special configuration to run. Please see example/README.md for instructions.'))); + 'This app needs special configuration to run. Please see example/README.md for instructions.', + ), + ), + ); } // This loading previous purchases code is just a demo. Please do not use this as it is. @@ -252,29 +254,31 @@ class _MyAppState extends State<_MyApp> { // We recommend that you use your own server to verify the purchase data. final Map purchases = Map.fromEntries( - _purchases.map((PurchaseDetails purchase) { - if (purchase.pendingCompletePurchase) { - _iapStoreKitPlatform.completePurchase(purchase); - } - return MapEntry(purchase.productID, purchase); - })); - productList.addAll(_products.map( - (ProductDetails productDetails) { + _purchases.map((PurchaseDetails purchase) { + if (purchase.pendingCompletePurchase) { + _iapStoreKitPlatform.completePurchase(purchase); + } + return MapEntry( + purchase.productID, + purchase, + ); + }), + ); + productList.addAll( + _products.map((ProductDetails productDetails) { final PurchaseDetails? previousPurchase = purchases[productDetails.id]; return ListTile( - title: Text( - productDetails.title, - ), - subtitle: Text( - productDetails.description, - ), - trailing: previousPurchase != null - ? IconButton( + title: Text(productDetails.title), + subtitle: Text(productDetails.description), + trailing: + previousPurchase != null + ? IconButton( onPressed: () { _iapStoreKitPlatformAddition.showPriceConsentIfNeeded(); }, - icon: const Icon(Icons.upgrade)) - : TextButton( + icon: const Icon(Icons.upgrade), + ) + : TextButton( style: TextButton.styleFrom( backgroundColor: Colors.green[800], foregroundColor: Colors.white, @@ -285,26 +289,25 @@ class _MyAppState extends State<_MyApp> { ); if (productDetails.id == _kConsumableId) { _iapStoreKitPlatform.buyConsumable( - purchaseParam: purchaseParam); + purchaseParam: purchaseParam, + ); } else { _iapStoreKitPlatform.buyNonConsumable( - purchaseParam: purchaseParam); + purchaseParam: purchaseParam, + ); } }, child: Text(productDetails.price), - )); - }, - )); + ), + ); + }), + ); return Column( children: [ Card( child: Column( - children: [ - productHeader, - const Divider(), - ...productList, - ], + children: [productHeader, const Divider(), ...productList], ), ), Card( @@ -314,14 +317,14 @@ class _MyAppState extends State<_MyApp> { const Divider(), FutureBuilder>( future: _buildPromoList(), - builder: (BuildContext context, - AsyncSnapshot> snapshot) { + builder: ( + BuildContext context, + AsyncSnapshot> snapshot, + ) { final List? data = snapshot.data; if (data != null) { - return Column( - children: data, - ); + return Column(children: data); } return const SizedBox.shrink(); @@ -345,11 +348,8 @@ class _MyAppState extends State<_MyApp> { for (final SK2SubscriptionOffer offer in offers) { if (offer.type == SK2SubscriptionOfferType.winBack) { - final bool eligible = - await _iapStoreKitPlatform.isWinBackOfferEligible( - detail.id, - offer.id ?? '', - ); + final bool eligible = await _iapStoreKitPlatform + .isWinBackOfferEligible(detail.id, offer.id ?? ''); if (!eligible) { continue; @@ -368,12 +368,8 @@ class _MyAppState extends State<_MyApp> { SK2SubscriptionOffer offer, ) { return ListTile( - title: Text( - '${productDetails.title} [${offer.type.name}]', - ), - subtitle: Text( - productDetails.description, - ), + title: Text('${productDetails.title} [${offer.type.name}]'), + subtitle: Text(productDetails.description), trailing: TextButton( style: TextButton.styleFrom( backgroundColor: Colors.green[800], @@ -401,39 +397,42 @@ class _MyAppState extends State<_MyApp> { Card _buildConsumableBox() { if (_loading) { return const Card( - child: ListTile( - leading: CircularProgressIndicator(), - title: Text('Fetching consumables...'))); + child: ListTile( + leading: CircularProgressIndicator(), + title: Text('Fetching consumables...'), + ), + ); } if (!_isAvailable || _notFoundIds.contains(_kConsumableId)) { return const Card(); } - const ListTile consumableHeader = - ListTile(title: Text('Purchased consumables')); - final List tokens = _consumables.map((String id) { - return GridTile( - child: IconButton( - icon: const Icon( - Icons.stars, - size: 42.0, - color: Colors.orange, - ), - splashColor: Colors.yellowAccent, - onPressed: () => consume(id), - ), - ); - }).toList(); + const ListTile consumableHeader = ListTile( + title: Text('Purchased consumables'), + ); + final List tokens = + _consumables.map((String id) { + return GridTile( + child: IconButton( + icon: const Icon(Icons.stars, size: 42.0, color: Colors.orange), + splashColor: Colors.yellowAccent, + onPressed: () => consume(id), + ), + ); + }).toList(); return Card( - child: Column(children: [ - consumableHeader, - const Divider(), - GridView.count( - crossAxisCount: 5, - shrinkWrap: true, - padding: const EdgeInsets.all(16.0), - children: tokens, - ) - ])); + child: Column( + children: [ + consumableHeader, + const Divider(), + GridView.count( + crossAxisCount: 5, + shrinkWrap: true, + padding: const EdgeInsets.all(16.0), + children: tokens, + ), + ], + ), + ); } Widget _buildRestoreButton() { @@ -511,7 +510,8 @@ class _MyAppState extends State<_MyApp> { } Future _handleReportedPurchaseState( - PurchaseDetails purchaseDetails) async { + PurchaseDetails purchaseDetails, + ) async { if (purchaseDetails.status == PurchaseStatus.pending) { showPendingUI(); } else { diff --git a/packages/in_app_purchase/in_app_purchase_storekit/example/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_storekit/example/pubspec.yaml index 099b0d0a51e..f5bb54338ab 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/example/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_storekit/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the in_app_purchase_storekit plugin. publish_to: none environment: - sdk: ^3.6.0 - flutter: ">=3.27.0" + sdk: ^3.7.0 + flutter: ">=3.29.0" dependencies: flutter: diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/channel.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/channel.dart index d045dab448e..a60b83c5f20 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/channel.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/channel.dart @@ -5,10 +5,12 @@ import 'package:flutter/services.dart'; /// Method channel for the plugin's platform<-->Dart calls. -const MethodChannel channel = - MethodChannel('plugins.flutter.io/in_app_purchase'); +const MethodChannel channel = MethodChannel( + 'plugins.flutter.io/in_app_purchase', +); /// Method channel used to deliver the payment queue delegate system calls to /// Dart. -const MethodChannel paymentQueueDelegateChannel = - MethodChannel('plugins.flutter.io/in_app_purchase_payment_queue_delegate'); +const MethodChannel paymentQueueDelegateChannel = MethodChannel( + 'plugins.flutter.io/in_app_purchase_payment_queue_delegate', +); diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/in_app_purchase_storekit_platform.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/in_app_purchase_storekit_platform.dart index 9b785b795f9..643824bd9c3 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/in_app_purchase_storekit_platform.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/in_app_purchase_storekit_platform.dart @@ -41,9 +41,10 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform { static late SK2TransactionObserverWrapper _sk2transactionObserver; @override - Stream> get purchaseStream => _useStoreKit2 - ? _sk2transactionObserver.transactionsCreatedController.stream - : _sk1transactionObserver.purchaseUpdatedController.stream; + Stream> get purchaseStream => + _useStoreKit2 + ? _sk2transactionObserver.transactionsCreatedController.stream + : _sk1transactionObserver.purchaseUpdatedController.stream; /// Callback handler for transaction status changes. @visibleForTesting @@ -70,17 +71,18 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform { if (_useStoreKit2) { final StreamController> updateController2 = StreamController>.broadcast( - onListen: () => SK2Transaction.startListeningToTransactions(), - onCancel: () => SK2Transaction.stopListeningToTransactions(), - ); + onListen: () => SK2Transaction.startListeningToTransactions(), + onCancel: () => SK2Transaction.stopListeningToTransactions(), + ); _sk2transactionObserver = SK2TransactionObserverWrapper( - transactionsCreatedController: updateController2); + transactionsCreatedController: updateController2, + ); InAppPurchase2CallbackAPI.setUp(_sk2transactionObserver); } else { // Create a purchaseUpdatedController and notify the native side when to // start of stop sending updates. - final StreamController> updateController = - StreamController>.broadcast( + final StreamController> + updateController = StreamController>.broadcast( onListen: () => _skPaymentQueueWrapper.startObservingTransactionQueue(), onCancel: () => _skPaymentQueueWrapper.stopObservingTransactionQueue(), ); @@ -168,9 +170,10 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform { ); } else { options = SK2ProductPurchaseOptions( - quantity: purchaseParam is AppStorePurchaseParam - ? purchaseParam.quantity - : 1, + quantity: + purchaseParam is AppStorePurchaseParam + ? purchaseParam.quantity + : 1, appAccountToken: purchaseParam.applicationUserName, ); } @@ -182,16 +185,21 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform { return true; } - await _skPaymentQueueWrapper.addPayment(SKPaymentWrapper( + await _skPaymentQueueWrapper.addPayment( + SKPaymentWrapper( productIdentifier: purchaseParam.productDetails.id, quantity: purchaseParam is AppStorePurchaseParam ? purchaseParam.quantity : 1, applicationUsername: purchaseParam.applicationUserName, - simulatesAskToBuyInSandbox: purchaseParam is AppStorePurchaseParam && + simulatesAskToBuyInSandbox: + purchaseParam is AppStorePurchaseParam && purchaseParam.simulatesAskToBuyInSandbox, - paymentDiscount: purchaseParam is AppStorePurchaseParam - ? purchaseParam.discount - : null)); + paymentDiscount: + purchaseParam is AppStorePurchaseParam + ? purchaseParam.discount + : null, + ), + ); return true; // There's no error feedback from iOS here to return. } @@ -215,8 +223,10 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform { } @override - Future buyConsumable( - {required PurchaseParam purchaseParam, bool autoConsume = true}) { + Future buyConsumable({ + required PurchaseParam purchaseParam, + bool autoConsume = true, + }) { assert(autoConsume, 'On iOS, we should always auto consume'); return buyNonConsumable(purchaseParam: purchaseParam); } @@ -244,10 +254,12 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform { } return _sk1transactionObserver .restoreTransactions( - queue: _skPaymentQueueWrapper, - applicationUserName: applicationUserName) + queue: _skPaymentQueueWrapper, + applicationUserName: applicationUserName, + ) .whenComplete( - () => _sk1transactionObserver.cleanUpRestoredTransactions()); + () => _sk1transactionObserver.cleanUpRestoredTransactions(), + ); } /// Query the product detail list. @@ -257,7 +269,8 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform { /// to get the [SKProductResponseWrapper]. @override Future queryProductDetails( - Set identifiers) async { + Set identifiers, + ) async { if (_useStoreKit2) { List products = []; Set invalidProductIdentifiers; @@ -267,26 +280,32 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform { // Storekit 2 no longer automatically returns a list of invalid identifiers, // so get the difference between given identifiers and returned products invalidProductIdentifiers = identifiers.difference( - products.map((SK2Product product) => product.id).toSet()); + products.map((SK2Product product) => product.id).toSet(), + ); } on PlatformException catch (e) { exception = e; invalidProductIdentifiers = identifiers; } List productDetails; - productDetails = products - .map((SK2Product productWrapper) => - AppStoreProduct2Details.fromSK2Product(productWrapper)) - .toList(); + productDetails = + products + .map( + (SK2Product productWrapper) => + AppStoreProduct2Details.fromSK2Product(productWrapper), + ) + .toList(); final ProductDetailsResponse response = ProductDetailsResponse( productDetails: productDetails, notFoundIDs: invalidProductIdentifiers.toList(), - error: exception == null - ? null - : IAPError( - source: kIAPSource, - code: exception.code, - message: exception.message ?? '', - details: exception.details), + error: + exception == null + ? null + : IAPError( + source: kIAPSource, + code: exception.code, + message: exception.message ?? '', + details: exception.details, + ), ); return response; } @@ -298,30 +317,36 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform { } on PlatformException catch (e) { exception = e; response = SkProductResponseWrapper( - products: const [], - invalidProductIdentifiers: identifiers.toList()); + products: const [], + invalidProductIdentifiers: identifiers.toList(), + ); } List productDetails = []; - productDetails = response.products - .map((SKProductWrapper productWrapper) => - AppStoreProductDetails.fromSKProduct(productWrapper)) - .toList(); + productDetails = + response.products + .map( + (SKProductWrapper productWrapper) => + AppStoreProductDetails.fromSKProduct(productWrapper), + ) + .toList(); List invalidIdentifiers = response.invalidProductIdentifiers; if (productDetails.isEmpty) { invalidIdentifiers = identifiers.toList(); } final ProductDetailsResponse productDetailsResponse = ProductDetailsResponse( - productDetails: productDetails, - notFoundIDs: invalidIdentifiers, - error: exception == null - ? null - : IAPError( - source: kIAPSource, - code: exception.code, - message: exception.message ?? '', - details: exception.details), - ); + productDetails: productDetails, + notFoundIDs: invalidIdentifiers, + error: + exception == null + ? null + : IAPError( + source: kIAPSource, + code: exception.code, + message: exception.message ?? '', + details: exception.details, + ), + ); return productDetailsResponse; } @@ -365,9 +390,7 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform { /// - `storekit2_failed_to_fetch_product` /// - `storekit2_not_subscription` /// - `storekit2_eligibility_check_failed` - Future isIntroductoryOfferEligible( - String productId, - ) async { + Future isIntroductoryOfferEligible(String productId) async { if (!_useStoreKit2) { throw PlatformException( code: 'storekit2_not_enabled', @@ -393,10 +416,7 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform { /// - `storekit2_failed_to_fetch_product` /// - `storekit2_not_subscription` /// - `storekit2_eligibility_check_failed` - Future isWinBackOfferEligible( - String productId, - String offerId, - ) async { + Future isWinBackOfferEligible(String productId, String offerId) async { if (!_useStoreKit2) { throw PlatformException( code: 'storekit2_not_enabled', @@ -444,14 +464,16 @@ class _TransactionObserver implements SKTransactionObserverWrapper { } @override - void updatedTransactions( - {required List transactions}) { + void updatedTransactions({ + required List transactions, + }) { _handleTransationUpdates(transactions); } @override - void removedTransactions( - {required List transactions}) {} + void removedTransactions({ + required List transactions, + }) {} /// Triggered when there is an error while restoring transactions. @override @@ -476,8 +498,10 @@ class _TransactionObserver implements SKTransactionObserverWrapper { } @override - bool shouldAddStorePayment( - {required SKPaymentWrapper payment, required SKProductWrapper product}) { + bool shouldAddStorePayment({ + required SKPaymentWrapper payment, + required SKProductWrapper product, + }) { // In this unified API, we always return true to keep it consistent with the behavior on Google Play. return true; } @@ -492,20 +516,29 @@ class _TransactionObserver implements SKTransactionObserverWrapper { } Future _handleTransationUpdates( - List transactions) async { + List transactions, + ) async { if (_transactionRestoreState == _TransactionRestoreState.waitingForTransactions && - transactions.any((SKPaymentTransactionWrapper transaction) => - transaction.transactionState == - SKPaymentTransactionStateWrapper.restored)) { + transactions.any( + (SKPaymentTransactionWrapper transaction) => + transaction.transactionState == + SKPaymentTransactionStateWrapper.restored, + )) { _transactionRestoreState = _TransactionRestoreState.receivedTransaction; } final String receiptData = await getReceiptData(); - final List purchases = transactions - .map((SKPaymentTransactionWrapper transaction) => - AppStorePurchaseDetails.fromSKTransaction(transaction, receiptData)) - .toList(); + final List purchases = + transactions + .map( + (SKPaymentTransactionWrapper transaction) => + AppStorePurchaseDetails.fromSKTransaction( + transaction, + receiptData, + ), + ) + .toList(); purchaseUpdatedController.add(purchases); } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/in_app_purchase_storekit_platform_addition.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/in_app_purchase_storekit_platform_addition.dart index 447f41f0a18..d1237c7973a 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/in_app_purchase_storekit_platform_addition.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/in_app_purchase_storekit_platform_addition.dart @@ -34,14 +34,16 @@ class InAppPurchaseStoreKitPlatformAddition try { final String receipt = await SKReceiptManager.retrieveReceiptData(); return PurchaseVerificationData( - localVerificationData: receipt, - serverVerificationData: receipt, - source: kIAPSource); + localVerificationData: receipt, + serverVerificationData: receipt, + source: kIAPSource, + ); } catch (e) { // ignore: avoid_print print( - 'Something is wrong while fetching the receipt, this normally happens when the app is ' - 'running on a simulator: $e'); + 'Something is wrong while fetching the receipt, this normally happens when the app is ' + 'running on a simulator: $e', + ); return null; } } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/messages.g.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/messages.g.dart index bd675a296cb..7b01b7993ab 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/messages.g.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/messages.g.dart @@ -18,8 +18,11 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse( - {Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({ + Object? result, + PlatformException? error, + bool empty = false, +}) { if (empty) { return []; } @@ -88,12 +91,7 @@ enum SKProductDiscountPaymentModeMessage { unspecified, } -enum SKSubscriptionPeriodUnitMessage { - day, - week, - month, - year, -} +enum SKSubscriptionPeriodUnitMessage { day, week, month, year } class SKPaymentTransactionMessage { SKPaymentTransactionMessage({ @@ -188,11 +186,7 @@ class SKPaymentMessage { } class SKErrorMessage { - SKErrorMessage({ - required this.code, - required this.domain, - this.userInfo, - }); + SKErrorMessage({required this.code, required this.domain, this.userInfo}); int code; @@ -201,11 +195,7 @@ class SKErrorMessage { Map? userInfo; Object encode() { - return [ - code, - domain, - userInfo, - ]; + return [code, domain, userInfo]; } static SKErrorMessage decode(Object result) { @@ -238,13 +228,7 @@ class SKPaymentDiscountMessage { int timestamp; Object encode() { - return [ - identifier, - keyIdentifier, - nonce, - signature, - timestamp, - ]; + return [identifier, keyIdentifier, nonce, signature, timestamp]; } static SKPaymentDiscountMessage decode(Object result) { @@ -260,20 +244,14 @@ class SKPaymentDiscountMessage { } class SKStorefrontMessage { - SKStorefrontMessage({ - required this.countryCode, - required this.identifier, - }); + SKStorefrontMessage({required this.countryCode, required this.identifier}); String countryCode; String identifier; Object encode() { - return [ - countryCode, - identifier, - ]; + return [countryCode, identifier]; } static SKStorefrontMessage decode(Object result) { @@ -286,20 +264,14 @@ class SKStorefrontMessage { } class SKProductsResponseMessage { - SKProductsResponseMessage({ - this.products, - this.invalidProductIdentifiers, - }); + SKProductsResponseMessage({this.products, this.invalidProductIdentifiers}); List? products; List? invalidProductIdentifiers; Object encode() { - return [ - products, - invalidProductIdentifiers, - ]; + return [products, invalidProductIdentifiers]; } static SKProductsResponseMessage decode(Object result) { @@ -390,11 +362,7 @@ class SKPriceLocaleMessage { String countryCode; Object encode() { - return [ - currencySymbol, - currencyCode, - countryCode, - ]; + return [currencySymbol, currencyCode, countryCode]; } static SKPriceLocaleMessage decode(Object result) { @@ -469,10 +437,7 @@ class SKProductSubscriptionPeriodMessage { SKSubscriptionPeriodUnitMessage unit; Object encode() { - return [ - numberOfUnits, - unit, - ]; + return [numberOfUnits, unit]; } static SKProductSubscriptionPeriodMessage decode(Object result) { @@ -591,11 +556,12 @@ class InAppPurchaseAPI { /// Constructor for [InAppPurchaseAPI]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - InAppPurchaseAPI( - {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = - messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + InAppPurchaseAPI({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -608,10 +574,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.canMakePayments$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -637,10 +603,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.transactions$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -667,10 +633,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.storefront$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -696,10 +662,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.addPayment$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send([paymentMap]) as List?; if (pigeonVar_replyList == null) { @@ -716,17 +682,19 @@ class InAppPurchaseAPI { } Future startProductRequest( - List productIdentifiers) async { + List productIdentifiers, + ) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.startProductRequest$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([productIdentifiers]) as List?; + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send([productIdentifiers]) + as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -750,10 +718,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.finishTransaction$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send([finishMap]) as List?; if (pigeonVar_replyList == null) { @@ -774,12 +742,13 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.restoreTransactions$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([applicationUserName]) as List?; + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send([applicationUserName]) + as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -798,10 +767,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.presentCodeRedemptionSheet$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -822,10 +791,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.retrieveReceiptData$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -846,12 +815,13 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.refreshReceipt$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([receiptProperties]) as List?; + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send([receiptProperties]) + as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -870,10 +840,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.startObservingPaymentQueue$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -894,10 +864,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.stopObservingPaymentQueue$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -918,10 +888,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.registerPaymentQueueDelegate$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -942,10 +912,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.removePaymentQueueDelegate$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -966,10 +936,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.showPriceConsentIfNeeded$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { @@ -990,10 +960,10 @@ class InAppPurchaseAPI { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.supportsStoreKit2$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final List? pigeonVar_replyList = await pigeonVar_channel.send(null) as List?; if (pigeonVar_replyList == null) { diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/sk2_pigeon.g.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/sk2_pigeon.g.dart index fa19079811f..e875f059905 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/sk2_pigeon.g.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/sk2_pigeon.g.dart @@ -18,8 +18,11 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse( - {Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({ + Object? result, + PlatformException? error, + bool empty = false, +}) { if (empty) { return []; } @@ -32,14 +35,17 @@ List wrapResponse( bool _deepEquals(Object? a, Object? b) { if (a is List && b is List) { return a.length == b.length && - a.indexed - .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); + a.indexed.every( + ((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]), + ); } if (a is Map && b is Map) { return a.length == b.length && - a.entries.every((MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key])); + a.entries.every( + (MapEntry entry) => + (b as Map).containsKey(entry.key) && + _deepEquals(entry.value, b[entry.key]), + ); } return a == b; } @@ -58,11 +64,7 @@ enum SK2ProductTypeMessage { autoRenewable, } -enum SK2SubscriptionOfferTypeMessage { - introductory, - promotional, - winBack, -} +enum SK2SubscriptionOfferTypeMessage { introductory, promotional, winBack } enum SK2SubscriptionOfferPaymentModeMessage { payAsYouGo, @@ -70,18 +72,9 @@ enum SK2SubscriptionOfferPaymentModeMessage { freeTrial, } -enum SK2SubscriptionPeriodUnitMessage { - day, - week, - month, - year, -} +enum SK2SubscriptionPeriodUnitMessage { day, week, month, year } -enum SK2ProductPurchaseResultMessage { - success, - userCancelled, - pending, -} +enum SK2ProductPurchaseResultMessage { success, userCancelled, pending } class SK2SubscriptionOfferMessage { SK2SubscriptionOfferMessage({ @@ -106,14 +99,7 @@ class SK2SubscriptionOfferMessage { SK2SubscriptionOfferPaymentModeMessage paymentMode; List _toList() { - return [ - id, - price, - type, - period, - periodCount, - paymentMode, - ]; + return [id, price, type, period, periodCount, paymentMode]; } Object encode() { @@ -151,10 +137,7 @@ class SK2SubscriptionOfferMessage { } class SK2SubscriptionPeriodMessage { - SK2SubscriptionPeriodMessage({ - required this.value, - required this.unit, - }); + SK2SubscriptionPeriodMessage({required this.value, required this.unit}); /// The number of units that the period represents. int value; @@ -163,10 +146,7 @@ class SK2SubscriptionPeriodMessage { SK2SubscriptionPeriodUnitMessage unit; List _toList() { - return [ - value, - unit, - ]; + return [value, unit]; } Object encode() { @@ -352,10 +332,7 @@ class SK2PriceLocaleMessage { String currencySymbol; List _toList() { - return [ - currencyCode, - currencySymbol, - ]; + return [currencyCode, currencySymbol]; } Object encode() { @@ -406,12 +383,7 @@ class SK2SubscriptionOfferSignatureMessage { String signature; List _toList() { - return [ - keyID, - nonce, - timestamp, - signature, - ]; + return [keyID, nonce, timestamp, signature]; } Object encode() { @@ -457,10 +429,7 @@ class SK2SubscriptionOfferPurchaseMessage { SK2SubscriptionOfferSignatureMessage promotionalOfferSignature; List _toList() { - return [ - promotionalOfferId, - promotionalOfferSignature, - ]; + return [promotionalOfferId, promotionalOfferSignature]; } Object encode() { @@ -643,11 +612,7 @@ class SK2TransactionMessage { } class SK2ErrorMessage { - SK2ErrorMessage({ - required this.code, - required this.domain, - this.userInfo, - }); + SK2ErrorMessage({required this.code, required this.domain, this.userInfo}); int code; @@ -656,11 +621,7 @@ class SK2ErrorMessage { Map? userInfo; List _toList() { - return [ - code, - domain, - userInfo, - ]; + return [code, domain, userInfo]; } Object encode() { @@ -806,11 +767,12 @@ class InAppPurchase2API { /// Constructor for [InAppPurchase2API]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - InAppPurchase2API( - {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = - messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + InAppPurchase2API({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -822,10 +784,10 @@ class InAppPurchase2API { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.canMakePayments$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; @@ -852,12 +814,13 @@ class InAppPurchase2API { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.products$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [identifiers], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([identifiers]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -879,18 +842,21 @@ class InAppPurchase2API { } } - Future purchase(String id, - {SK2ProductPurchaseOptionsMessage? options}) async { + Future purchase( + String id, { + SK2ProductPurchaseOptionsMessage? options, + }) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.purchase$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [id, options], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([id, options]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -916,12 +882,13 @@ class InAppPurchase2API { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isWinBackOfferEligible$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [productId, offerId], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([productId, offerId]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -947,12 +914,13 @@ class InAppPurchase2API { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isIntroductoryOfferEligible$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [productId], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([productId]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -978,10 +946,10 @@ class InAppPurchase2API { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.transactions$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; @@ -1009,12 +977,13 @@ class InAppPurchase2API { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.finish$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [id], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([id]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -1035,10 +1004,10 @@ class InAppPurchase2API { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.startListeningToTransactions$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; @@ -1060,10 +1029,10 @@ class InAppPurchase2API { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.stopListeningToTransactions$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; @@ -1085,10 +1054,10 @@ class InAppPurchase2API { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.restorePurchases$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; @@ -1110,10 +1079,10 @@ class InAppPurchase2API { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.countryCode$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; @@ -1140,10 +1109,10 @@ class InAppPurchase2API { 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.sync$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; @@ -1174,23 +1143,27 @@ abstract class InAppPurchase2CallbackAPI { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2CallbackAPI.onTransactionsUpdated$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2CallbackAPI.onTransactionsUpdated$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2CallbackAPI.onTransactionsUpdated was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2CallbackAPI.onTransactionsUpdated was null.', + ); final List args = (message as List?)!; final List? arg_newTransactions = (args[0] as List?)?.cast(); - assert(arg_newTransactions != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2CallbackAPI.onTransactionsUpdated was null, expected non-null List.'); + assert( + arg_newTransactions != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2CallbackAPI.onTransactionsUpdated was null, expected non-null List.', + ); try { api.onTransactionsUpdated(arg_newTransactions!); return wrapResponse(empty: true); @@ -1198,7 +1171,8 @@ abstract class InAppPurchase2CallbackAPI { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_product_wrapper.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_product_wrapper.dart index 7170c3e50b6..9222a2b0e8d 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_product_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_product_wrapper.dart @@ -22,7 +22,7 @@ enum SK2ProductType { nonRenewable, /// An auto-renewable subscription. - autoRenewable; + autoRenewable, } extension on SK2ProductTypeMessage { @@ -119,12 +119,13 @@ class SK2SubscriptionOffer { extension on SK2SubscriptionOfferMessage { SK2SubscriptionOffer convertFromPigeon() { return SK2SubscriptionOffer( - id: id, - price: price, - type: type.convertFromPigeon(), - period: period.convertFromPigeon(), - periodCount: periodCount, - paymentMode: paymentMode.convertFromPigeon()); + id: id, + price: price, + type: type.convertFromPigeon(), + period: period.convertFromPigeon(), + periodCount: periodCount, + paymentMode: paymentMode.convertFromPigeon(), + ); } } @@ -154,9 +155,13 @@ extension on SK2SubscriptionInfoMessage { SK2SubscriptionInfo convertFromPigeon() { return SK2SubscriptionInfo( subscriptionGroupID: subscriptionGroupID, - promotionalOffers: promotionalOffers - .map((SK2SubscriptionOfferMessage offer) => offer.convertFromPigeon()) - .toList(), + promotionalOffers: + promotionalOffers + .map( + (SK2SubscriptionOfferMessage offer) => + offer.convertFromPigeon(), + ) + .toList(), subscriptionPeriod: subscriptionPeriod.convertFromPigeon(), ); } @@ -196,7 +201,7 @@ enum SK2SubscriptionPeriodUnit { month, /// A subscription period unit of a year. - year + year, } extension on SK2SubscriptionPeriodUnitMessage { @@ -224,7 +229,7 @@ enum SK2SubscriptionOfferPaymentMode { payUpFront, /// A payment mode of a product discount that indicates a free trial offer. - freeTrial; + freeTrial, } extension on SK2SubscriptionOfferPaymentModeMessage { @@ -255,14 +260,18 @@ class SK2PriceLocale { /// Convert this instance of [SK2PriceLocale] to [SK2PriceLocaleMessage] SK2PriceLocaleMessage convertToPigeon() { return SK2PriceLocaleMessage( - currencyCode: currencyCode, currencySymbol: currencySymbol); + currencyCode: currencyCode, + currencySymbol: currencySymbol, + ); } } extension on SK2PriceLocaleMessage { SK2PriceLocale convertFromPigeon() { return SK2PriceLocale( - currencyCode: currencyCode, currencySymbol: currencySymbol); + currencyCode: currencyCode, + currencySymbol: currencySymbol, + ); } } @@ -276,7 +285,7 @@ enum SK2ProductPurchaseResult { userCancelled, /// The purchase is pending, and requires action from the customer. - pending + pending, } /// Wrapper around [PurchaseOption] @@ -371,8 +380,9 @@ class SK2Product { /// If any of the identifiers are invalid or can't be found, they are excluded /// from the returned list. static Future> products(List identifiers) async { - final List productsMsg = - await _hostApi.products(identifiers); + final List productsMsg = await _hostApi.products( + identifiers, + ); if (productsMsg.isEmpty && identifiers.isNotEmpty) { throw PlatformException( code: 'storekit_no_response', @@ -389,8 +399,10 @@ class SK2Product { /// Wrapper for StoreKit's [Product.purchase] /// https://developer.apple.com/documentation/storekit/product/3791971-purchase /// Initiates a purchase for the product with the App Store and displays the confirmation sheet. - static Future purchase(String id, - {SK2ProductPurchaseOptions? options}) async { + static Future purchase( + String id, { + SK2ProductPurchaseOptions? options, + }) async { SK2ProductPurchaseResultMessage result; if (options != null) { result = await _hostApi.purchase(id, options: options.convertToPigeon()); @@ -402,12 +414,8 @@ class SK2Product { /// Checks if the user is eligible for an introductory offer. /// The product must be an auto-renewable subscription. - static Future isIntroductoryOfferEligible( - String productId, - ) async { - final bool result = await _hostApi.isIntroductoryOfferEligible( - productId, - ); + static Future isIntroductoryOfferEligible(String productId) async { + final bool result = await _hostApi.isIntroductoryOfferEligible(productId); return result; } @@ -428,26 +436,28 @@ class SK2Product { /// Converts this instance of [SK2Product] to it's pigeon representation [SK2ProductMessage] SK2ProductMessage convertToPigeon() { return SK2ProductMessage( - id: id, - displayName: displayName, - description: description, - price: price, - displayPrice: displayPrice, - type: type.convertToPigeon(), - priceLocale: priceLocale.convertToPigeon()); + id: id, + displayName: displayName, + description: description, + price: price, + displayPrice: displayPrice, + type: type.convertToPigeon(), + priceLocale: priceLocale.convertToPigeon(), + ); } } extension on SK2ProductMessage { SK2Product convertFromPigeon() { return SK2Product( - id: id, - displayName: displayName, - displayPrice: displayPrice, - price: price, - description: description, - type: type.convertFromPigeon(), - subscription: subscription?.convertFromPigeon(), - priceLocale: priceLocale.convertFromPigeon()); + id: id, + displayName: displayName, + displayPrice: displayPrice, + price: price, + description: description, + type: type.convertFromPigeon(), + subscription: subscription?.convertFromPigeon(), + priceLocale: priceLocale.convertFromPigeon(), + ); } } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart index fe44700815e..cbbd615fd88 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart @@ -17,18 +17,19 @@ InAppPurchase2API _hostApi = InAppPurchase2API(); /// SKPayment and SKTransaction in StoreKit1 class SK2Transaction { /// Creates a new instance of [SK2Transaction] - SK2Transaction( - {required this.id, - required this.originalId, - required this.productId, - required this.purchaseDate, - this.expirationDate, - this.quantity = 1, - required this.appAccountToken, - this.subscriptionGroupID, - this.price, - this.error, - this.jsonRepresentation}); + SK2Transaction({ + required this.id, + required this.originalId, + required this.productId, + required this.purchaseDate, + this.expirationDate, + this.quantity = 1, + required this.appAccountToken, + this.subscriptionGroupID, + this.price, + this.error, + this.jsonRepresentation, + }); /// The unique identifier for the transaction. final String id; @@ -104,13 +105,14 @@ class SK2Transaction { extension on SK2TransactionMessage { SK2Transaction convertFromPigeon() { return SK2Transaction( - id: id.toString(), - originalId: originalId.toString(), - productId: productId, - purchaseDate: purchaseDate, - expirationDate: expirationDate, - appAccountToken: appAccountToken, - jsonRepresentation: jsonRepresentation); + id: id.toString(), + originalId: originalId.toString(), + productId: productId, + purchaseDate: purchaseDate, + expirationDate: expirationDate, + appAccountToken: appAccountToken, + jsonRepresentation: jsonRepresentation, + ); } PurchaseDetails convertToDetails() { @@ -121,10 +123,11 @@ extension on SK2TransactionMessage { // receipt isn’t necessary with SK2 as a Transaction can only be returned // from validated purchases. verificationData: PurchaseVerificationData( - localVerificationData: jsonRepresentation ?? '', - // receiptData is the JWS representation of the transaction - serverVerificationData: receiptData ?? '', - source: kIAPSource), + localVerificationData: jsonRepresentation ?? '', + // receiptData is the JWS representation of the transaction + serverVerificationData: receiptData ?? '', + source: kIAPSource, + ), transactionDate: purchaseDate, // Note that with SK2, any transactions that *can* be returned will // require to be finished, and are already purchased. @@ -146,8 +149,10 @@ class SK2TransactionObserverWrapper implements InAppPurchase2CallbackAPI { @override void onTransactionsUpdated(List newTransactions) { - transactionsCreatedController.add(newTransactions - .map((SK2TransactionMessage e) => e.convertToDetails()) - .toList()); + transactionsCreatedController.add( + newTransactions + .map((SK2TransactionMessage e) => e.convertToDetails()) + .toList(), + ); } } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/enum_converters.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/enum_converters.dart index 1fdbfebd6ec..6fb12ee5d54 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/enum_converters.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/enum_converters.dart @@ -24,14 +24,17 @@ class SKTransactionStatusConverter return SKPaymentTransactionStateWrapper.unspecified; } return $enumDecode( - _$SKPaymentTransactionStateWrapperEnumMap - .cast(), - json); + _$SKPaymentTransactionStateWrapperEnumMap + .cast(), + json, + ); } /// Converts an [SKPaymentTransactionStateWrapper] to a [PurchaseStatus]. PurchaseStatus toPurchaseStatus( - SKPaymentTransactionStateWrapper object, SKError? error) { + SKPaymentTransactionStateWrapper object, + SKError? error, + ) { switch (object) { case SKPaymentTransactionStateWrapper.purchasing: case SKPaymentTransactionStateWrapper.deferred: @@ -74,9 +77,10 @@ class SKSubscriptionPeriodUnitConverter return SKSubscriptionPeriodUnit.day; } return $enumDecode( - _$SKSubscriptionPeriodUnitEnumMap - .cast(), - json); + _$SKSubscriptionPeriodUnitEnumMap + .cast(), + json, + ); } @override @@ -99,9 +103,10 @@ class SKProductDiscountPaymentModeConverter return SKProductDiscountPaymentMode.payAsYouGo; } return $enumDecode( - _$SKProductDiscountPaymentModeEnumMap - .cast(), - json); + _$SKProductDiscountPaymentModeEnumMap + .cast(), + json, + ); } @override @@ -133,8 +138,9 @@ class SKProductDiscountTypeConverter return SKProductDiscountType.introductory; } return $enumDecode( - _$SKProductDiscountTypeEnumMap.cast(), - json); + _$SKProductDiscountTypeEnumMap.cast(), + json, + ); } @override diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/enum_converters.g.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/enum_converters.g.dart index dc6c17276c1..a32c63e97c3 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/enum_converters.g.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/enum_converters.g.dart @@ -6,12 +6,17 @@ part of 'enum_converters.dart'; // JsonSerializableGenerator // ************************************************************************** -_SerializedEnums _$SerializedEnumsFromJson(Map json) => _SerializedEnums() - ..response = - $enumDecode(_$SKPaymentTransactionStateWrapperEnumMap, json['response']) - ..unit = $enumDecode(_$SKSubscriptionPeriodUnitEnumMap, json['unit']) - ..discountPaymentMode = $enumDecode( - _$SKProductDiscountPaymentModeEnumMap, json['discountPaymentMode']); +_SerializedEnums _$SerializedEnumsFromJson(Map json) => + _SerializedEnums() + ..response = $enumDecode( + _$SKPaymentTransactionStateWrapperEnumMap, + json['response'], + ) + ..unit = $enumDecode(_$SKSubscriptionPeriodUnitEnumMap, json['unit']) + ..discountPaymentMode = $enumDecode( + _$SKProductDiscountPaymentModeEnumMap, + json['discountPaymentMode'], + ); const _$SKPaymentTransactionStateWrapperEnumMap = { SKPaymentTransactionStateWrapper.purchasing: 0, diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_queue_delegate_wrapper.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_queue_delegate_wrapper.dart index 5c65fb1df6d..c5d0f4fea9c 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_queue_delegate_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_queue_delegate_wrapper.dart @@ -25,8 +25,7 @@ abstract class SKPaymentQueueDelegateWrapper { bool shouldContinueTransaction( SKPaymentTransactionWrapper transaction, SKStorefrontWrapper storefront, - ) => - true; + ) => true; /// Called by the system to check whether to immediately show the price /// consent form. diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.dart index 138ecc8b747..9d36caa7ebd 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.dart @@ -62,8 +62,10 @@ class SKPaymentQueueWrapper { final List pigeonMsgs = await _hostApi.transactions(); return pigeonMsgs - .map((SKPaymentTransactionMessage? msg) => - SKPaymentTransactionWrapper.convertFromPigeon(msg!)) + .map( + (SKPaymentTransactionMessage? msg) => + SKPaymentTransactionWrapper.convertFromPigeon(msg!), + ) .toList(); } @@ -113,8 +115,9 @@ class SKPaymentQueueWrapper { paymentQueueDelegateChannel.setMethodCallHandler(null); } else { await _hostApi.registerPaymentQueueDelegate(); - paymentQueueDelegateChannel - .setMethodCallHandler(handlePaymentQueueDelegateCallbacks); + paymentQueueDelegateChannel.setMethodCallHandler( + handlePaymentQueueDelegateCallbacks, + ); } _paymentQueueDelegate = delegate; @@ -141,8 +144,10 @@ class SKPaymentQueueWrapper { /// Also see [sandbox /// testing](https://developer.apple.com/apple-pay/sandbox-testing/). Future addPayment(SKPaymentWrapper payment) async { - assert(_observer != null, - '[in_app_purchase]: Trying to add a payment without an observer. One must be set using `SkPaymentQueueWrapper.setTransactionObserver` before the app launches.'); + assert( + _observer != null, + '[in_app_purchase]: Trying to add a payment without an observer. One must be set using `SkPaymentQueueWrapper.setTransactionObserver` before the app launches.', + ); await _hostApi.addPayment(payment.toMap()); } @@ -159,7 +164,8 @@ class SKPaymentQueueWrapper { /// This method calls StoreKit's [`-[SKPaymentQueue /// finishTransaction:]`](https://developer.apple.com/documentation/storekit/skpaymentqueue/1506003-finishtransaction?language=objc). Future finishTransaction( - SKPaymentTransactionWrapper transaction) async { + SKPaymentTransactionWrapper transaction, + ) async { final Map requestMap = transaction.toFinishMap(); await _hostApi.finishTransaction(requestMap); } @@ -216,8 +222,10 @@ class SKPaymentQueueWrapper { /// outside this class. @visibleForTesting Future handleObserverCallbacks(MethodCall call) async { - assert(_observer != null, - '[in_app_purchase]: (Fatal)The observer has not been set but we received a purchase transaction notification. Please ensure the observer has been set using `setTransactionObserver`. Make sure the observer is added right at the App Launch.'); + assert( + _observer != null, + '[in_app_purchase]: (Fatal)The observer has not been set but we received a purchase transaction notification. Please ensure the observer has been set using `setTransactionObserver`. Make sure the observer is added right at the App Launch.', + ); final SKTransactionObserverWrapper observer = _observer!; switch (call.method) { case 'updatedTransactions': @@ -238,8 +246,9 @@ class SKPaymentQueueWrapper { } case 'restoreCompletedTransactionsFailed': { - final SKError error = SKError.fromJson(Map.from( - call.arguments as Map)); + final SKError error = SKError.fromJson( + Map.from(call.arguments as Map), + ); return Future(() { observer.restoreCompletedTransactionsFailed(error: error); }); @@ -255,14 +264,18 @@ class SKPaymentQueueWrapper { final Map arguments = call.arguments as Map; final SKPaymentWrapper payment = SKPaymentWrapper.fromJson( - (arguments['payment']! as Map) - .cast()); + (arguments['payment']! as Map) + .cast(), + ); final SKProductWrapper product = SKProductWrapper.fromJson( - (arguments['product']! as Map) - .cast()); + (arguments['product']! as Map) + .cast(), + ); return Future(() { if (observer.shouldAddStorePayment( - payment: payment, product: product)) { + payment: payment, + product: product, + )) { SKPaymentQueueWrapper().addPayment(payment); } }); @@ -271,17 +284,21 @@ class SKPaymentQueueWrapper { break; } throw PlatformException( - code: 'no_such_callback', - message: 'Did not recognize the observer callback ${call.method}.'); + code: 'no_such_callback', + message: 'Did not recognize the observer callback ${call.method}.', + ); } // Get transaction wrapper object list from arguments. List _getTransactionList( - List transactionsData) { + List transactionsData, + ) { return transactionsData.map((dynamic map) { return SKPaymentTransactionWrapper.fromJson( - Map.castFrom( - map as Map)); + Map.castFrom( + map as Map, + ), + ); }).toList(); } @@ -292,8 +309,10 @@ class SKPaymentQueueWrapper { /// outside this class. @visibleForTesting Future handlePaymentQueueDelegateCallbacks(MethodCall call) async { - assert(_paymentQueueDelegate != null, - '[in_app_purchase]: (Fatal)The payment queue delegate has not been set but we received a payment queue notification. Please ensure the payment queue has been set using `setDelegate`.'); + assert( + _paymentQueueDelegate != null, + '[in_app_purchase]: (Fatal)The payment queue delegate has not been set but we received a payment queue notification. Please ensure the payment queue has been set using `setDelegate`.', + ); final SKPaymentQueueDelegateWrapper delegate = _paymentQueueDelegate!; switch (call.method) { @@ -302,11 +321,13 @@ class SKPaymentQueueWrapper { call.arguments as Map; final SKPaymentTransactionWrapper transaction = SKPaymentTransactionWrapper.fromJson( - (arguments['transaction']! as Map) - .cast()); + (arguments['transaction']! as Map) + .cast(), + ); final SKStorefrontWrapper storefront = SKStorefrontWrapper.fromJson( - (arguments['storefront']! as Map) - .cast()); + (arguments['storefront']! as Map) + .cast(), + ); return delegate.shouldContinueTransaction(transaction, storefront); case 'shouldShowPriceConsent': return delegate.shouldShowPriceConsent(); @@ -314,9 +335,10 @@ class SKPaymentQueueWrapper { break; } throw PlatformException( - code: 'no_such_callback', - message: - 'Did not recognize the payment queue delegate callback ${call.method}.'); + code: 'no_such_callback', + message: + 'Did not recognize the payment queue delegate callback ${call.method}.', + ); } } @@ -326,8 +348,11 @@ class SKPaymentQueueWrapper { @JsonSerializable() class SKError { /// Creates a new [SKError] object with the provided information. - const SKError( - {required this.code, required this.domain, required this.userInfo}); + const SKError({ + required this.code, + required this.domain, + required this.userInfo, + }); /// Constructs an instance of this from a key-value map of data. /// @@ -366,23 +391,22 @@ class SKError { return other is SKError && other.code == code && other.domain == domain && - const DeepCollectionEquality.unordered() - .equals(other.userInfo, userInfo); + const DeepCollectionEquality.unordered().equals( + other.userInfo, + userInfo, + ); } @override - int get hashCode => Object.hash( - code, - domain, - userInfo, - ); + int get hashCode => Object.hash(code, domain, userInfo); /// Converts [SKErrorMessage] into the dart equivalent static SKError convertFromPigeon(SKErrorMessage msg) { return SKError( - code: msg.code, - domain: msg.domain, - userInfo: msg.userInfo ?? {}); + code: msg.code, + domain: msg.domain, + userInfo: msg.userInfo ?? {}, + ); } } @@ -496,8 +520,13 @@ class SKPaymentWrapper { } @override - int get hashCode => Object.hash(productIdentifier, applicationUsername, - quantity, simulatesAskToBuyInSandbox, requestData); + int get hashCode => Object.hash( + productIdentifier, + applicationUsername, + quantity, + simulatesAskToBuyInSandbox, + requestData, + ); @override String toString() => _$SKPaymentWrapperToJson(this).toString(); @@ -505,13 +534,15 @@ class SKPaymentWrapper { /// Converts [SKPaymentMessage] into the dart equivalent static SKPaymentWrapper convertFromPigeon(SKPaymentMessage msg) { return SKPaymentWrapper( - productIdentifier: msg.productIdentifier, - applicationUsername: msg.applicationUsername, - quantity: msg.quantity, - simulatesAskToBuyInSandbox: msg.simulatesAskToBuyInSandbox, - requestData: msg.requestData, - paymentDiscount: - SKPaymentDiscountWrapper.convertFromPigeon(msg.paymentDiscount)); + productIdentifier: msg.productIdentifier, + applicationUsername: msg.applicationUsername, + quantity: msg.quantity, + simulatesAskToBuyInSandbox: msg.simulatesAskToBuyInSandbox, + requestData: msg.requestData, + paymentDiscount: SKPaymentDiscountWrapper.convertFromPigeon( + msg.paymentDiscount, + ), + ); } } @@ -614,15 +645,17 @@ class SKPaymentDiscountWrapper { /// Converts [SKPaymentDiscountMessage] into the dart equivalent static SKPaymentDiscountWrapper? convertFromPigeon( - SKPaymentDiscountMessage? msg) { + SKPaymentDiscountMessage? msg, + ) { if (msg == null) { return null; } return SKPaymentDiscountWrapper( - identifier: msg.identifier, - keyIdentifier: msg.keyIdentifier, - nonce: msg.nonce, - signature: msg.signature, - timestamp: msg.timestamp); + identifier: msg.identifier, + keyIdentifier: msg.keyIdentifier, + nonce: msg.nonce, + signature: msg.signature, + timestamp: msg.timestamp, + ); } } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.g.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.g.dart index f594ad45044..7dbd5b82cfb 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.g.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.g.dart @@ -7,22 +7,20 @@ part of 'sk_payment_queue_wrapper.dart'; // ************************************************************************** SKError _$SKErrorFromJson(Map json) => SKError( - code: json['code'] as int? ?? 0, - domain: json['domain'] as String? ?? '', - userInfo: (json['userInfo'] as Map?)?.map( - (k, e) => MapEntry(k as String, e), - ) ?? - {}, - ); + code: json['code'] as int? ?? 0, + domain: json['domain'] as String? ?? '', + userInfo: + (json['userInfo'] as Map?)?.map((k, e) => MapEntry(k as String, e)) ?? {}, +); SKPaymentWrapper _$SKPaymentWrapperFromJson(Map json) => SKPaymentWrapper( - productIdentifier: json['productIdentifier'] as String? ?? '', - applicationUsername: json['applicationUsername'] as String?, - requestData: json['requestData'] as String?, - quantity: json['quantity'] as int? ?? 0, - simulatesAskToBuyInSandbox: - json['simulatesAskToBuyInSandbox'] as bool? ?? false, - ); + productIdentifier: json['productIdentifier'] as String? ?? '', + applicationUsername: json['applicationUsername'] as String?, + requestData: json['requestData'] as String?, + quantity: json['quantity'] as int? ?? 0, + simulatesAskToBuyInSandbox: + json['simulatesAskToBuyInSandbox'] as bool? ?? false, +); Map _$SKPaymentWrapperToJson(SKPaymentWrapper instance) => { @@ -43,11 +41,11 @@ SKPaymentDiscountWrapper _$SKPaymentDiscountWrapperFromJson(Map json) => ); Map _$SKPaymentDiscountWrapperToJson( - SKPaymentDiscountWrapper instance) => - { - 'identifier': instance.identifier, - 'keyIdentifier': instance.keyIdentifier, - 'nonce': instance.nonce, - 'signature': instance.signature, - 'timestamp': instance.timestamp, - }; + SKPaymentDiscountWrapper instance, +) => { + 'identifier': instance.identifier, + 'keyIdentifier': instance.keyIdentifier, + 'nonce': instance.nonce, + 'signature': instance.signature, + 'timestamp': instance.timestamp, +}; diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_transaction_wrappers.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_transaction_wrappers.dart index 7f16e1492a4..034709762a2 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_transaction_wrappers.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_transaction_wrappers.dart @@ -21,12 +21,14 @@ part 'sk_payment_transaction_wrappers.g.dart'; /// This class is a Dart wrapper around [SKTransactionObserver](https://developer.apple.com/documentation/storekit/skpaymenttransactionobserver?language=objc). abstract class SKTransactionObserverWrapper { /// Triggered when any transactions are updated. - void updatedTransactions( - {required List transactions}); + void updatedTransactions({ + required List transactions, + }); /// Triggered when any transactions are removed from the payment queue. - void removedTransactions( - {required List transactions}); + void removedTransactions({ + required List transactions, + }); /// Triggered when there is an error while restoring transactions. void restoreCompletedTransactionsFailed({required SKError error}); @@ -43,8 +45,10 @@ abstract class SKTransactionObserverWrapper { /// transaction if the user is in the middle of onboarding. You can also /// continue the transaction later by calling [addPayment] with the /// `payment` param from this method. - bool shouldAddStorePayment( - {required SKPaymentWrapper payment, required SKProductWrapper product}); + bool shouldAddStorePayment({ + required SKPaymentWrapper payment, + required SKProductWrapper product, + }); } /// The state of a transaction. @@ -95,7 +99,8 @@ enum SKPaymentTransactionStateWrapper { /// Converts [SKPaymentTransactionStateMessages] into the dart equivalent static SKPaymentTransactionStateWrapper convertFromPigeon( - SKPaymentTransactionStateMessage msg) { + SKPaymentTransactionStateMessage msg, + ) { switch (msg) { case SKPaymentTransactionStateMessage.purchased: return SKPaymentTransactionStateWrapper.purchased; @@ -208,31 +213,40 @@ class SKPaymentTransactionWrapper { } @override - int get hashCode => Object.hash(payment, transactionState, - originalTransaction, transactionTimeStamp, transactionIdentifier, error); + int get hashCode => Object.hash( + payment, + transactionState, + originalTransaction, + transactionTimeStamp, + transactionIdentifier, + error, + ); @override String toString() => _$SKPaymentTransactionWrapperToJson(this).toString(); /// The payload that is used to finish this transaction. Map toFinishMap() => { - 'transactionIdentifier': transactionIdentifier, - 'productIdentifier': payment.productIdentifier, - }; + 'transactionIdentifier': transactionIdentifier, + 'productIdentifier': payment.productIdentifier, + }; /// Converts [SKPaymentTransactionMessages] into the dart equivalent static SKPaymentTransactionWrapper convertFromPigeon( - SKPaymentTransactionMessage msg) { + SKPaymentTransactionMessage msg, + ) { return SKPaymentTransactionWrapper( - payment: SKPaymentWrapper.convertFromPigeon(msg.payment), - transactionState: SKPaymentTransactionStateWrapper.convertFromPigeon( - msg.transactionState), - originalTransaction: msg.originalTransaction == null - ? null - : convertFromPigeon(msg.originalTransaction!), - transactionTimeStamp: msg.transactionTimeStamp, - transactionIdentifier: msg.transactionIdentifier, - error: - msg.error == null ? null : SKError.convertFromPigeon(msg.error!)); + payment: SKPaymentWrapper.convertFromPigeon(msg.payment), + transactionState: SKPaymentTransactionStateWrapper.convertFromPigeon( + msg.transactionState, + ), + originalTransaction: + msg.originalTransaction == null + ? null + : convertFromPigeon(msg.originalTransaction!), + transactionTimeStamp: msg.transactionTimeStamp, + transactionIdentifier: msg.transactionIdentifier, + error: msg.error == null ? null : SKError.convertFromPigeon(msg.error!), + ); } } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_transaction_wrappers.g.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_transaction_wrappers.g.dart index fd10d9ad977..1b749c379c1 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_transaction_wrappers.g.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_payment_transaction_wrappers.g.dart @@ -9,28 +9,36 @@ part of 'sk_payment_transaction_wrappers.dart'; SKPaymentTransactionWrapper _$SKPaymentTransactionWrapperFromJson(Map json) => SKPaymentTransactionWrapper( payment: SKPaymentWrapper.fromJson( - Map.from(json['payment'] as Map)), - transactionState: const SKTransactionStatusConverter() - .fromJson(json['transactionState'] as int?), - originalTransaction: json['originalTransaction'] == null - ? null - : SKPaymentTransactionWrapper.fromJson( - Map.from(json['originalTransaction'] as Map)), + Map.from(json['payment'] as Map), + ), + transactionState: const SKTransactionStatusConverter().fromJson( + json['transactionState'] as int?, + ), + originalTransaction: + json['originalTransaction'] == null + ? null + : SKPaymentTransactionWrapper.fromJson( + Map.from(json['originalTransaction'] as Map), + ), transactionTimeStamp: (json['transactionTimeStamp'] as num?)?.toDouble(), transactionIdentifier: json['transactionIdentifier'] as String?, - error: json['error'] == null - ? null - : SKError.fromJson(Map.from(json['error'] as Map)), + error: + json['error'] == null + ? null + : SKError.fromJson( + Map.from(json['error'] as Map), + ), ); Map _$SKPaymentTransactionWrapperToJson( - SKPaymentTransactionWrapper instance) => - { - 'transactionState': const SKTransactionStatusConverter() - .toJson(instance.transactionState), - 'payment': instance.payment, - 'originalTransaction': instance.originalTransaction, - 'transactionTimeStamp': instance.transactionTimeStamp, - 'transactionIdentifier': instance.transactionIdentifier, - 'error': instance.error, - }; + SKPaymentTransactionWrapper instance, +) => { + 'transactionState': const SKTransactionStatusConverter().toJson( + instance.transactionState, + ), + 'payment': instance.payment, + 'originalTransaction': instance.originalTransaction, + 'transactionTimeStamp': instance.transactionTimeStamp, + 'transactionIdentifier': instance.transactionIdentifier, + 'error': instance.error, +}; diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_product_wrapper.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_product_wrapper.dart index 95698271c3f..fcd3616974d 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_product_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_product_wrapper.dart @@ -25,8 +25,10 @@ class SkProductResponseWrapper { // TODO(stuartmorgan): Temporarily ignore const warning in other parts of the // federated package, and remove this. // ignore: prefer_const_constructors_in_immutables - SkProductResponseWrapper( - {required this.products, required this.invalidProductIdentifiers}); + SkProductResponseWrapper({ + required this.products, + required this.invalidProductIdentifiers, + }); /// Constructing an instance from a map from the Objective-C layer. /// @@ -60,8 +62,10 @@ class SkProductResponseWrapper { } return other is SkProductResponseWrapper && const DeepCollectionEquality().equals(other.products, products) && - const DeepCollectionEquality() - .equals(other.invalidProductIdentifiers, invalidProductIdentifiers); + const DeepCollectionEquality().equals( + other.invalidProductIdentifiers, + invalidProductIdentifiers, + ); } @override @@ -69,11 +73,15 @@ class SkProductResponseWrapper { /// Convert from [SkProductResponseMessage] to [SkProductResponseWrapper] static SkProductResponseWrapper convertFromPigeon( - SKProductsResponseMessage msg) { + SKProductsResponseMessage msg, + ) { return SkProductResponseWrapper( - products: msg.products! - .map((SKProductMessage e) => SKProductWrapper.convertFromPigeon(e)) - .toList(), + products: + msg.products! + .map( + (SKProductMessage e) => SKProductWrapper.convertFromPigeon(e), + ) + .toList(), invalidProductIdentifiers: msg.invalidProductIdentifiers ?? [], ); } @@ -81,12 +89,15 @@ class SkProductResponseWrapper { /// Convert from [SkProductResponseWrapper] to [SkProductResponseWrapper] @visibleForTesting static SKProductsResponseMessage convertToPigeon( - SkProductResponseWrapper wrapper) { + SkProductResponseWrapper wrapper, + ) { return SKProductsResponseMessage( - products: wrapper.products - .map((SKProductWrapper e) => SKProductWrapper.convertToPigeon(e)) - .toList(), - invalidProductIdentifiers: wrapper.invalidProductIdentifiers); + products: + wrapper.products + .map((SKProductWrapper e) => SKProductWrapper.convertToPigeon(e)) + .toList(), + invalidProductIdentifiers: wrapper.invalidProductIdentifiers, + ); } } @@ -102,11 +113,9 @@ enum SKSubscriptionPeriodUnit { /// An interval lasting one month. @JsonValue(1) - /// An interval lasting one week. week, @JsonValue(2) - /// An interval lasting one month. month, @@ -116,7 +125,8 @@ enum SKSubscriptionPeriodUnit { /// Convert from [SKSubscriptionPeriodUnitMessage] to [SKSubscriptionPeriodUnit] static SKSubscriptionPeriodUnit convertFromPigeon( - SKSubscriptionPeriodUnitMessage msg) { + SKSubscriptionPeriodUnitMessage msg, + ) { switch (msg) { case SKSubscriptionPeriodUnitMessage.day: return SKSubscriptionPeriodUnit.day; @@ -132,7 +142,8 @@ enum SKSubscriptionPeriodUnit { /// Convert from [SKSubscriptionPeriodUnit] to [SKSubscriptionPeriodUnitMessage] @visibleForTesting static SKSubscriptionPeriodUnitMessage convertToPigeon( - SKSubscriptionPeriodUnit msg) { + SKSubscriptionPeriodUnit msg, + ) { switch (msg) { case SKSubscriptionPeriodUnit.day: return SKSubscriptionPeriodUnitMessage.day; @@ -157,17 +168,22 @@ class SKProductSubscriptionPeriodWrapper { // TODO(stuartmorgan): Temporarily ignore const warning in other parts of the // federated package, and remove this. // ignore: prefer_const_constructors_in_immutables - SKProductSubscriptionPeriodWrapper( - {required this.numberOfUnits, required this.unit}); + SKProductSubscriptionPeriodWrapper({ + required this.numberOfUnits, + required this.unit, + }); /// Constructing an instance from a map from the Objective-C layer. /// /// This method should only be used with `map` values returned by [SKProductDiscountWrapper.fromJson] or [SKProductWrapper.fromJson]. factory SKProductSubscriptionPeriodWrapper.fromJson( - Map? map) { + Map? map, + ) { if (map == null) { return SKProductSubscriptionPeriodWrapper( - numberOfUnits: 0, unit: SKSubscriptionPeriodUnit.day); + numberOfUnits: 0, + unit: SKSubscriptionPeriodUnit.day, + ); } return _$SKProductSubscriptionPeriodWrapperFromJson(map); } @@ -200,19 +216,23 @@ class SKProductSubscriptionPeriodWrapper { /// Convert from [SKProductSubscriptionPeriodMessage] to [SKProductSubscriptionPeriodWrapper] static SKProductSubscriptionPeriodWrapper convertFromPigeon( - SKProductSubscriptionPeriodMessage msg) { + SKProductSubscriptionPeriodMessage msg, + ) { return SKProductSubscriptionPeriodWrapper( - numberOfUnits: msg.numberOfUnits, - unit: SKSubscriptionPeriodUnit.convertFromPigeon(msg.unit)); + numberOfUnits: msg.numberOfUnits, + unit: SKSubscriptionPeriodUnit.convertFromPigeon(msg.unit), + ); } /// Convert from [SKProductSubscriptionPeriodWrapper] to [SKProductSubscriptionPeriodMessage] @visibleForTesting static SKProductSubscriptionPeriodMessage convertToPigeon( - SKProductSubscriptionPeriodWrapper wrapper) { + SKProductSubscriptionPeriodWrapper wrapper, + ) { return SKProductSubscriptionPeriodMessage( - numberOfUnits: wrapper.numberOfUnits, - unit: SKSubscriptionPeriodUnit.convertToPigeon(wrapper.unit)); + numberOfUnits: wrapper.numberOfUnits, + unit: SKSubscriptionPeriodUnit.convertToPigeon(wrapper.unit), + ); } } @@ -240,7 +260,8 @@ enum SKProductDiscountPaymentMode { /// Convert from [SKProductDiscountPaymentModeMessage] to [SKProductDiscountPaymentModeWrapper] static SKProductDiscountPaymentMode convertFromPigeon( - SKProductDiscountPaymentModeMessage msg) { + SKProductDiscountPaymentModeMessage msg, + ) { switch (msg) { case SKProductDiscountPaymentModeMessage.payAsYouGo: return SKProductDiscountPaymentMode.payAsYouGo; @@ -256,7 +277,8 @@ enum SKProductDiscountPaymentMode { /// Convert from [SKProductDiscountPaymentModeMessage] to [SKProductDiscountPaymentMode] @visibleForTesting static SKProductDiscountPaymentModeMessage convertToPigeon( - SKProductDiscountPaymentMode wrapper) { + SKProductDiscountPaymentMode wrapper, + ) { switch (wrapper) { case SKProductDiscountPaymentMode.payAsYouGo: return SKProductDiscountPaymentModeMessage.payAsYouGo; @@ -289,7 +311,8 @@ enum SKProductDiscountType { /// Convert from [SKProductDiscountTypeMessage] to [SKProductDiscountType] static SKProductDiscountType convertFromPigeon( - SKProductDiscountTypeMessage msg) { + SKProductDiscountTypeMessage msg, + ) { switch (msg) { case SKProductDiscountTypeMessage.introductory: return SKProductDiscountType.introductory; @@ -301,7 +324,8 @@ enum SKProductDiscountType { /// Convert from [SKProductDiscountType] to [SKProductDiscountTypeMessage] @visibleForTesting static SKProductDiscountTypeMessage convertToPigeon( - SKProductDiscountType wrapper) { + SKProductDiscountType wrapper, + ) { switch (wrapper) { case SKProductDiscountType.introductory: return SKProductDiscountTypeMessage.introductory; @@ -321,14 +345,15 @@ class SKProductDiscountWrapper { // TODO(stuartmorgan): Temporarily ignore const warning in other parts of the // federated package, and remove this. // ignore: prefer_const_constructors_in_immutables - SKProductDiscountWrapper( - {required this.price, - required this.priceLocale, - required this.numberOfPeriods, - required this.paymentMode, - required this.subscriptionPeriod, - required this.identifier, - required this.type}); + SKProductDiscountWrapper({ + required this.price, + required this.priceLocale, + required this.numberOfPeriods, + required this.paymentMode, + required this.subscriptionPeriod, + required this.identifier, + required this.type, + }); /// Constructing an instance from a map from the Objective-C layer. /// @@ -389,39 +414,53 @@ class SKProductDiscountWrapper { } @override - int get hashCode => Object.hash(price, priceLocale, numberOfPeriods, - paymentMode, subscriptionPeriod, identifier, type); + int get hashCode => Object.hash( + price, + priceLocale, + numberOfPeriods, + paymentMode, + subscriptionPeriod, + identifier, + type, + ); /// Convert from [SKProductDiscountMessage] to [SKProductDiscountWrapper] static SKProductDiscountWrapper convertFromPigeon( - SKProductDiscountMessage msg) { + SKProductDiscountMessage msg, + ) { return SKProductDiscountWrapper( - price: msg.price, - priceLocale: SKPriceLocaleWrapper.convertFromPigeon(msg.priceLocale), - numberOfPeriods: msg.numberOfPeriods, - paymentMode: - SKProductDiscountPaymentMode.convertFromPigeon(msg.paymentMode), - subscriptionPeriod: - SKProductSubscriptionPeriodWrapper.convertFromPigeon( - msg.subscriptionPeriod), - identifier: msg.identifier, - type: SKProductDiscountType.convertFromPigeon(msg.type)); + price: msg.price, + priceLocale: SKPriceLocaleWrapper.convertFromPigeon(msg.priceLocale), + numberOfPeriods: msg.numberOfPeriods, + paymentMode: SKProductDiscountPaymentMode.convertFromPigeon( + msg.paymentMode, + ), + subscriptionPeriod: SKProductSubscriptionPeriodWrapper.convertFromPigeon( + msg.subscriptionPeriod, + ), + identifier: msg.identifier, + type: SKProductDiscountType.convertFromPigeon(msg.type), + ); } /// Convert from [SKProductDiscountWrapper] to [SKProductDiscountMessage] @visibleForTesting static SKProductDiscountMessage convertToPigeon( - SKProductDiscountWrapper wrapper) { + SKProductDiscountWrapper wrapper, + ) { return SKProductDiscountMessage( - price: wrapper.price, - priceLocale: SKPriceLocaleWrapper.convertToPigeon(wrapper.priceLocale), - numberOfPeriods: wrapper.numberOfPeriods, - paymentMode: - SKProductDiscountPaymentMode.convertToPigeon(wrapper.paymentMode), - subscriptionPeriod: SKProductSubscriptionPeriodWrapper.convertToPigeon( - wrapper.subscriptionPeriod), - identifier: wrapper.identifier, - type: SKProductDiscountType.convertToPigeon(wrapper.type)); + price: wrapper.price, + priceLocale: SKPriceLocaleWrapper.convertToPigeon(wrapper.priceLocale), + numberOfPeriods: wrapper.numberOfPeriods, + paymentMode: SKProductDiscountPaymentMode.convertToPigeon( + wrapper.paymentMode, + ), + subscriptionPeriod: SKProductSubscriptionPeriodWrapper.convertToPigeon( + wrapper.subscriptionPeriod, + ), + identifier: wrapper.identifier, + type: SKProductDiscountType.convertToPigeon(wrapper.type), + ); } } @@ -532,61 +571,79 @@ class SKProductWrapper { @override int get hashCode => Object.hash( - productIdentifier, - localizedTitle, - localizedDescription, - priceLocale, - subscriptionGroupIdentifier, - price, - subscriptionPeriod, - introductoryPrice, - discounts); + productIdentifier, + localizedTitle, + localizedDescription, + priceLocale, + subscriptionGroupIdentifier, + price, + subscriptionPeriod, + introductoryPrice, + discounts, + ); /// Convert from [SKProductMessage] to [SKProductWrapper] static SKProductWrapper convertFromPigeon(SKProductMessage msg) { return SKProductWrapper( - productIdentifier: msg.productIdentifier, - localizedTitle: msg.localizedTitle, - localizedDescription: msg.localizedDescription ?? '', - priceLocale: SKPriceLocaleWrapper.convertFromPigeon(msg.priceLocale), - price: msg.price, - subscriptionGroupIdentifier: msg.subscriptionGroupIdentifier, - subscriptionPeriod: msg.subscriptionPeriod != null - ? SKProductSubscriptionPeriodWrapper.convertFromPigeon( - msg.subscriptionPeriod!) - : null, - introductoryPrice: msg.introductoryPrice != null - ? SKProductDiscountWrapper.convertFromPigeon(msg.introductoryPrice!) - : null, - discounts: msg.discounts != null - ? msg.discounts! - .map((SKProductDiscountMessage e) => - SKProductDiscountWrapper.convertFromPigeon(e)) - .toList() - : []); + productIdentifier: msg.productIdentifier, + localizedTitle: msg.localizedTitle, + localizedDescription: msg.localizedDescription ?? '', + priceLocale: SKPriceLocaleWrapper.convertFromPigeon(msg.priceLocale), + price: msg.price, + subscriptionGroupIdentifier: msg.subscriptionGroupIdentifier, + subscriptionPeriod: + msg.subscriptionPeriod != null + ? SKProductSubscriptionPeriodWrapper.convertFromPigeon( + msg.subscriptionPeriod!, + ) + : null, + introductoryPrice: + msg.introductoryPrice != null + ? SKProductDiscountWrapper.convertFromPigeon( + msg.introductoryPrice!, + ) + : null, + discounts: + msg.discounts != null + ? msg.discounts! + .map( + (SKProductDiscountMessage e) => + SKProductDiscountWrapper.convertFromPigeon(e), + ) + .toList() + : [], + ); } /// Convert from [SKProductWrapper] to [SKProductMessage] static SKProductMessage convertToPigeon(SKProductWrapper wrapper) { return SKProductMessage( - productIdentifier: wrapper.productIdentifier, - localizedTitle: wrapper.localizedTitle, - localizedDescription: wrapper.localizedDescription, - priceLocale: SKPriceLocaleWrapper.convertToPigeon(wrapper.priceLocale), - price: wrapper.price, - subscriptionGroupIdentifier: wrapper.subscriptionGroupIdentifier, - subscriptionPeriod: wrapper.subscriptionPeriod != null - ? SKProductSubscriptionPeriodWrapper.convertToPigeon( - wrapper.subscriptionPeriod!) - : null, - introductoryPrice: wrapper.introductoryPrice != null - ? SKProductDiscountWrapper.convertToPigeon( - wrapper.introductoryPrice!) - : null, - discounts: wrapper.discounts - .map((SKProductDiscountWrapper e) => - SKProductDiscountWrapper.convertToPigeon(e)) - .toList()); + productIdentifier: wrapper.productIdentifier, + localizedTitle: wrapper.localizedTitle, + localizedDescription: wrapper.localizedDescription, + priceLocale: SKPriceLocaleWrapper.convertToPigeon(wrapper.priceLocale), + price: wrapper.price, + subscriptionGroupIdentifier: wrapper.subscriptionGroupIdentifier, + subscriptionPeriod: + wrapper.subscriptionPeriod != null + ? SKProductSubscriptionPeriodWrapper.convertToPigeon( + wrapper.subscriptionPeriod!, + ) + : null, + introductoryPrice: + wrapper.introductoryPrice != null + ? SKProductDiscountWrapper.convertToPigeon( + wrapper.introductoryPrice!, + ) + : null, + discounts: + wrapper.discounts + .map( + (SKProductDiscountWrapper e) => + SKProductDiscountWrapper.convertToPigeon(e), + ) + .toList(), + ); } } @@ -615,7 +672,10 @@ class SKPriceLocaleWrapper { factory SKPriceLocaleWrapper.fromJson(Map? map) { if (map == null) { return SKPriceLocaleWrapper( - currencyCode: '', currencySymbol: '', countryCode: ''); + currencyCode: '', + currencySymbol: '', + countryCode: '', + ); } return _$SKPriceLocaleWrapperFromJson(map); } @@ -651,17 +711,19 @@ class SKPriceLocaleWrapper { /// Convert from [SKPriceLocaleMessage] to [SKPriceLocaleWrapper] static SKPriceLocaleWrapper convertFromPigeon(SKPriceLocaleMessage msg) { return SKPriceLocaleWrapper( - currencySymbol: msg.currencySymbol, - currencyCode: msg.currencyCode, - countryCode: msg.countryCode); + currencySymbol: msg.currencySymbol, + currencyCode: msg.currencyCode, + countryCode: msg.countryCode, + ); } /// Convert from [SKPriceLocaleWrapper] to [SKPriceLocaleMessage] @visibleForTesting static SKPriceLocaleMessage convertToPigeon(SKPriceLocaleWrapper msg) { return SKPriceLocaleMessage( - currencySymbol: msg.currencySymbol, - currencyCode: msg.currencyCode, - countryCode: msg.countryCode); + currencySymbol: msg.currencySymbol, + currencyCode: msg.currencyCode, + countryCode: msg.countryCode, + ); } } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart index 9e891e75b49..341d521a248 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart @@ -8,72 +8,85 @@ part of 'sk_product_wrapper.dart'; SkProductResponseWrapper _$SkProductResponseWrapperFromJson(Map json) => SkProductResponseWrapper( - products: (json['products'] as List?) - ?.map((e) => SKProductWrapper.fromJson( - Map.from(e as Map))) + products: + (json['products'] as List?) + ?.map( + (e) => SKProductWrapper.fromJson( + Map.from(e as Map), + ), + ) .toList() ?? [], invalidProductIdentifiers: (json['invalidProductIdentifiers'] as List?) - ?.map((e) => e as String) - .toList() ?? - [], + ?.map((e) => e as String) + .toList() ?? + [], ); SKProductSubscriptionPeriodWrapper _$SKProductSubscriptionPeriodWrapperFromJson( - Map json) => - SKProductSubscriptionPeriodWrapper( - numberOfUnits: json['numberOfUnits'] as int? ?? 0, - unit: const SKSubscriptionPeriodUnitConverter() - .fromJson(json['unit'] as int?), - ); + Map json, +) => SKProductSubscriptionPeriodWrapper( + numberOfUnits: json['numberOfUnits'] as int? ?? 0, + unit: const SKSubscriptionPeriodUnitConverter().fromJson( + json['unit'] as int?, + ), +); SKProductDiscountWrapper _$SKProductDiscountWrapperFromJson(Map json) => SKProductDiscountWrapper( price: json['price'] as String? ?? '', - priceLocale: - SKPriceLocaleWrapper.fromJson((json['priceLocale'] as Map?)?.map( - (k, e) => MapEntry(k as String, e), - )), + priceLocale: SKPriceLocaleWrapper.fromJson( + (json['priceLocale'] as Map?)?.map((k, e) => MapEntry(k as String, e)), + ), numberOfPeriods: json['numberOfPeriods'] as int? ?? 0, - paymentMode: const SKProductDiscountPaymentModeConverter() - .fromJson(json['paymentMode'] as int?), + paymentMode: const SKProductDiscountPaymentModeConverter().fromJson( + json['paymentMode'] as int?, + ), subscriptionPeriod: SKProductSubscriptionPeriodWrapper.fromJson( - (json['subscriptionPeriod'] as Map?)?.map( - (k, e) => MapEntry(k as String, e), - )), + (json['subscriptionPeriod'] as Map?)?.map( + (k, e) => MapEntry(k as String, e), + ), + ), identifier: json['identifier'] as String? ?? null, - type: - const SKProductDiscountTypeConverter().fromJson(json['type'] as int?), + type: const SKProductDiscountTypeConverter().fromJson( + json['type'] as int?, + ), ); SKProductWrapper _$SKProductWrapperFromJson(Map json) => SKProductWrapper( - productIdentifier: json['productIdentifier'] as String? ?? '', - localizedTitle: json['localizedTitle'] as String? ?? '', - localizedDescription: json['localizedDescription'] as String? ?? '', - priceLocale: - SKPriceLocaleWrapper.fromJson((json['priceLocale'] as Map?)?.map( - (k, e) => MapEntry(k as String, e), - )), - subscriptionGroupIdentifier: - json['subscriptionGroupIdentifier'] as String?, - price: json['price'] as String? ?? '', - subscriptionPeriod: json['subscriptionPeriod'] == null + productIdentifier: json['productIdentifier'] as String? ?? '', + localizedTitle: json['localizedTitle'] as String? ?? '', + localizedDescription: json['localizedDescription'] as String? ?? '', + priceLocale: SKPriceLocaleWrapper.fromJson( + (json['priceLocale'] as Map?)?.map((k, e) => MapEntry(k as String, e)), + ), + subscriptionGroupIdentifier: json['subscriptionGroupIdentifier'] as String?, + price: json['price'] as String? ?? '', + subscriptionPeriod: + json['subscriptionPeriod'] == null ? null : SKProductSubscriptionPeriodWrapper.fromJson( - (json['subscriptionPeriod'] as Map?)?.map( + (json['subscriptionPeriod'] as Map?)?.map( (k, e) => MapEntry(k as String, e), - )), - introductoryPrice: json['introductoryPrice'] == null + ), + ), + introductoryPrice: + json['introductoryPrice'] == null ? null : SKProductDiscountWrapper.fromJson( - Map.from(json['introductoryPrice'] as Map)), - discounts: (json['discounts'] as List?) - ?.map((e) => SKProductDiscountWrapper.fromJson( - Map.from(e as Map))) - .toList() ?? - [], - ); + Map.from(json['introductoryPrice'] as Map), + ), + discounts: + (json['discounts'] as List?) + ?.map( + (e) => SKProductDiscountWrapper.fromJson( + Map.from(e as Map), + ), + ) + .toList() ?? + [], +); SKPriceLocaleWrapper _$SKPriceLocaleWrapperFromJson(Map json) => SKPriceLocaleWrapper( diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_request_maker.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_request_maker.dart index 64d00922d11..f152d31dc8e 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_request_maker.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_request_maker.dart @@ -27,9 +27,10 @@ class SKRequestMaker { /// [SkProductResponseWrapper] is returned if there is no error during the request. /// A [PlatformException] is thrown if the platform code making the request fails. Future startProductRequest( - List productIdentifiers) async { - final SKProductsResponseMessage productResponsePigeon = - await _hostApi.startProductRequest(productIdentifiers); + List productIdentifiers, + ) async { + final SKProductsResponseMessage productResponsePigeon = await _hostApi + .startProductRequest(productIdentifiers); // should products be null or [] ? if (productResponsePigeon.products == null) { @@ -51,8 +52,9 @@ class SKRequestMaker { /// * isExpired: whether the receipt is expired. /// * isRevoked: whether the receipt has been revoked. /// * isVolumePurchase: whether the receipt is a Volume Purchase Plan receipt. - Future startRefreshReceiptRequest( - {Map? receiptProperties}) { + Future startRefreshReceiptRequest({ + Map? receiptProperties, + }) { return _hostApi.refreshReceipt(receiptProperties: receiptProperties); } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_storefront_wrapper.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_storefront_wrapper.dart index 2ba25e08616..c42ba96066b 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_storefront_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_storefront_wrapper.dart @@ -20,10 +20,7 @@ class SKStorefrontWrapper { // TODO(stuartmorgan): Temporarily ignore const warning in other parts of the // federated package, and remove this. // ignore: prefer_const_constructors_in_immutables - SKStorefrontWrapper({ - required this.countryCode, - required this.identifier, - }); + SKStorefrontWrapper({required this.countryCode, required this.identifier}); /// Constructs an instance of the [SKStorefrontWrapper] from a key value map /// of data. @@ -56,10 +53,7 @@ class SKStorefrontWrapper { } @override - int get hashCode => Object.hash( - countryCode, - identifier, - ); + int get hashCode => Object.hash(countryCode, identifier); @override String toString() => _$SKStorefrontWrapperToJson(this).toString(); @@ -71,6 +65,8 @@ class SKStorefrontWrapper { /// Converts the pigeon equivalent to an instance of SKStorefrontWrapper static SKStorefrontWrapper convertFromPigeon(SKStorefrontMessage msg) { return SKStorefrontWrapper( - countryCode: msg.countryCode, identifier: msg.identifier); + countryCode: msg.countryCode, + identifier: msg.identifier, + ); } } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_storefront_wrapper.g.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_storefront_wrapper.g.dart index b2d5d3a06d1..bb71ee2919b 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_storefront_wrapper.g.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_wrappers/sk_storefront_wrapper.g.dart @@ -13,8 +13,8 @@ SKStorefrontWrapper _$SKStorefrontWrapperFromJson(Map json) => ); Map _$SKStorefrontWrapperToJson( - SKStorefrontWrapper instance) => - { - 'countryCode': instance.countryCode, - 'identifier': instance.identifier, - }; + SKStorefrontWrapper instance, +) => { + 'countryCode': instance.countryCode, + 'identifier': instance.identifier, +}; diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_product_details.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_product_details.dart index 6e1a38f1661..71cabafe62d 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_product_details.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_product_details.dart @@ -32,9 +32,10 @@ class AppStoreProductDetails extends ProductDetails { price: product.priceLocale.currencySymbol + product.price, rawPrice: double.parse(product.price), currencyCode: product.priceLocale.currencyCode, - currencySymbol: product.priceLocale.currencySymbol.isNotEmpty - ? product.priceLocale.currencySymbol - : product.priceLocale.currencyCode, + currencySymbol: + product.priceLocale.currencySymbol.isNotEmpty + ? product.priceLocale.currencySymbol + : product.priceLocale.currencyCode, skProduct: product, ); } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_purchase_details.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_purchase_details.dart index 335ff6ad264..d21b2824c8f 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_purchase_details.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_purchase_details.dart @@ -34,15 +34,19 @@ class AppStorePurchaseDetails extends PurchaseDetails { productID: transaction.payment.productIdentifier, purchaseID: transaction.transactionIdentifier, skPaymentTransaction: transaction, - status: const SKTransactionStatusConverter() - .toPurchaseStatus(transaction.transactionState, transaction.error), - transactionDate: transaction.transactionTimeStamp != null - ? (transaction.transactionTimeStamp! * 1000).toInt().toString() - : null, + status: const SKTransactionStatusConverter().toPurchaseStatus( + transaction.transactionState, + transaction.error, + ), + transactionDate: + transaction.transactionTimeStamp != null + ? (transaction.transactionTimeStamp! * 1000).toInt().toString() + : null, verificationData: PurchaseVerificationData( - localVerificationData: base64EncodedReceipt, - serverVerificationData: base64EncodedReceipt, - source: kIAPSource), + localVerificationData: base64EncodedReceipt, + serverVerificationData: base64EncodedReceipt, + source: kIAPSource, + ), ); if (purchaseDetails.status == PurchaseStatus.error || @@ -82,12 +86,13 @@ class AppStorePurchaseDetails extends PurchaseDetails { /// AppStore, when using Storekit2 class SK2PurchaseDetails extends PurchaseDetails { /// Creates new instance of [SK2PurchaseDetails] - SK2PurchaseDetails( - {required super.productID, - required super.purchaseID, - required super.verificationData, - required super.transactionDate, - required super.status}); + SK2PurchaseDetails({ + required super.productID, + required super.purchaseID, + required super.verificationData, + required super.transactionDate, + required super.status, + }); @override bool get pendingCompletePurchase => status == PurchaseStatus.purchased; diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/sk2_promotional_offer.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/sk2_promotional_offer.dart index 0f12901dbc9..226d78f33b2 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/sk2_promotional_offer.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/sk2_promotional_offer.dart @@ -33,10 +33,7 @@ class SK2SubscriptionOfferSignature { /// cryptographic signature. final class SK2PromotionalOffer { /// Creates a new [SK2PromotionalOffer] object. - SK2PromotionalOffer({ - required this.offerId, - required this.signature, - }); + SK2PromotionalOffer({required this.offerId, required this.signature}); /// The promotional offer identifier. final String offerId; diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/sk2_purchase_param.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/sk2_purchase_param.dart index 906ad0d8f07..0f743e7d47a 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/sk2_purchase_param.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/sk2_purchase_param.dart @@ -48,9 +48,7 @@ class Sk2PurchaseParam extends PurchaseParam { ), ); case SK2SubscriptionOfferType.introductory: - return Sk2PurchaseParam( - productDetails: productDetails, - ); + return Sk2PurchaseParam(productDetails: productDetails); } } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/pigeons/messages.dart b/packages/in_app_purchase/in_app_purchase_storekit/pigeons/messages.dart index 5fc6cc57ebe..90361c6c900 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/pigeons/messages.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/pigeons/messages.dart @@ -4,19 +4,21 @@ import 'package:pigeon/pigeon.dart'; -@ConfigurePigeon(PigeonOptions( - dartOut: 'lib/src/messages.g.dart', - dartTestOut: 'test/test_api.g.dart', - objcHeaderOut: - 'darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit_objc/include/in_app_purchase_storekit_objc/messages.g.h', - objcSourceOut: - 'darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit_objc/messages.g.m', - objcOptions: ObjcOptions( - prefix: 'FIA', - headerIncludePath: './include/in_app_purchase_storekit_objc/messages.g.h', +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/src/messages.g.dart', + dartTestOut: 'test/test_api.g.dart', + objcHeaderOut: + 'darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit_objc/include/in_app_purchase_storekit_objc/messages.g.h', + objcSourceOut: + 'darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit_objc/messages.g.m', + objcOptions: ObjcOptions( + prefix: 'FIA', + headerIncludePath: './include/in_app_purchase_storekit_objc/messages.g.h', + ), + copyrightHeader: 'pigeons/copyright.txt', ), - copyrightHeader: 'pigeons/copyright.txt', -)) +) class SKPaymentTransactionMessage { SKPaymentTransactionMessage({ required this.payment, @@ -92,8 +94,11 @@ class SKPaymentMessage { } class SKErrorMessage { - const SKErrorMessage( - {required this.code, required this.domain, required this.userInfo}); + const SKErrorMessage({ + required this.code, + required this.domain, + required this.userInfo, + }); final int code; final String domain; @@ -127,23 +132,26 @@ class SKStorefrontMessage { } class SKProductsResponseMessage { - const SKProductsResponseMessage( - {required this.products, required this.invalidProductIdentifiers}); + const SKProductsResponseMessage({ + required this.products, + required this.invalidProductIdentifiers, + }); final List? products; final List? invalidProductIdentifiers; } class SKProductMessage { - const SKProductMessage( - {required this.productIdentifier, - required this.localizedTitle, - required this.priceLocale, - required this.price, - this.localizedDescription, - this.subscriptionGroupIdentifier, - this.subscriptionPeriod, - this.introductoryPrice, - this.discounts}); + const SKProductMessage({ + required this.productIdentifier, + required this.localizedTitle, + required this.priceLocale, + required this.price, + this.localizedDescription, + this.subscriptionGroupIdentifier, + this.subscriptionPeriod, + this.introductoryPrice, + this.discounts, + }); final String productIdentifier; final String localizedTitle; @@ -177,14 +185,15 @@ class SKPriceLocaleMessage { } class SKProductDiscountMessage { - const SKProductDiscountMessage( - {required this.price, - required this.priceLocale, - required this.numberOfPeriods, - required this.paymentMode, - required this.subscriptionPeriod, - required this.identifier, - required this.type}); + const SKProductDiscountMessage({ + required this.price, + required this.priceLocale, + required this.numberOfPeriods, + required this.paymentMode, + required this.subscriptionPeriod, + required this.identifier, + required this.type, + }); final String price; final SKPriceLocaleMessage priceLocale; @@ -218,19 +227,16 @@ enum SKProductDiscountPaymentModeMessage { } class SKProductSubscriptionPeriodMessage { - SKProductSubscriptionPeriodMessage( - {required this.numberOfUnits, required this.unit}); + SKProductSubscriptionPeriodMessage({ + required this.numberOfUnits, + required this.unit, + }); final int numberOfUnits; final SKSubscriptionPeriodUnitMessage unit; } -enum SKSubscriptionPeriodUnitMessage { - day, - week, - month, - year, -} +enum SKSubscriptionPeriodUnitMessage { day, week, month, year } @HostApi(dartHostTestHandler: 'TestInAppPurchaseApi') abstract class InAppPurchaseAPI { @@ -245,7 +251,8 @@ abstract class InAppPurchaseAPI { @async SKProductsResponseMessage startProductRequest( - List productIdentifiers); + List productIdentifiers, + ); void finishTransaction(Map finishMap); diff --git a/packages/in_app_purchase/in_app_purchase_storekit/pigeons/sk2_pigeon.dart b/packages/in_app_purchase/in_app_purchase_storekit/pigeons/sk2_pigeon.dart index 1afb97dbdcf..98ca749afb3 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/pigeons/sk2_pigeon.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/pigeons/sk2_pigeon.dart @@ -4,13 +4,15 @@ import 'package:pigeon/pigeon.dart'; -@ConfigurePigeon(PigeonOptions( - dartOut: 'lib/src/sk2_pigeon.g.dart', - dartTestOut: 'test/sk2_test_api.g.dart', - swiftOut: - 'darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/sk2_pigeon.g.swift', - copyrightHeader: 'pigeons/copyright.txt', -)) +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/src/sk2_pigeon.g.dart', + dartTestOut: 'test/sk2_test_api.g.dart', + swiftOut: + 'darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/sk2_pigeon.g.swift', + copyrightHeader: 'pigeons/copyright.txt', + ), +) enum SK2ProductTypeMessage { /// A consumable in-app purchase. consumable, @@ -22,14 +24,10 @@ enum SK2ProductTypeMessage { nonRenewable, /// An auto-renewable subscription. - autoRenewable + autoRenewable, } -enum SK2SubscriptionOfferTypeMessage { - introductory, - promotional, - winBack, -} +enum SK2SubscriptionOfferTypeMessage { introductory, promotional, winBack } enum SK2SubscriptionOfferPaymentModeMessage { payAsYouGo, @@ -86,15 +84,16 @@ class SK2SubscriptionInfoMessage { /// A Pigeon message class representing a Product /// https://developer.apple.com/documentation/storekit/product class SK2ProductMessage { - const SK2ProductMessage( - {required this.id, - required this.displayName, - required this.displayPrice, - required this.description, - required this.price, - required this.type, - this.subscription, - required this.priceLocale}); + const SK2ProductMessage({ + required this.id, + required this.displayName, + required this.displayPrice, + required this.description, + required this.price, + required this.type, + this.subscription, + required this.priceLocale, + }); /// The unique product identifier. final String id; @@ -172,18 +171,19 @@ class SK2ProductPurchaseOptionsMessage { } class SK2TransactionMessage { - SK2TransactionMessage( - {required this.id, - required this.originalId, - required this.productId, - required this.purchaseDate, - this.expirationDate, - this.purchasedQuantity = 1, - this.appAccountToken, - this.error, - this.receiptData, - this.jsonRepresentation, - this.restoring = false}); + SK2TransactionMessage({ + required this.id, + required this.originalId, + required this.productId, + required this.purchaseDate, + this.expirationDate, + this.purchasedQuantity = 1, + this.appAccountToken, + this.error, + this.receiptData, + this.jsonRepresentation, + this.restoring = false, + }); final int id; final int originalId; final String productId; @@ -198,8 +198,11 @@ class SK2TransactionMessage { } class SK2ErrorMessage { - const SK2ErrorMessage( - {required this.code, required this.domain, required this.userInfo}); + const SK2ErrorMessage({ + required this.code, + required this.domain, + required this.userInfo, + }); final int code; final String domain; @@ -219,8 +222,10 @@ abstract class InAppPurchase2API { // https://developer.apple.com/documentation/storekit/product/3791971-purchase @async - SK2ProductPurchaseResultMessage purchase(String id, - {SK2ProductPurchaseOptionsMessage? options}); + SK2ProductPurchaseResultMessage purchase( + String id, { + SK2ProductPurchaseOptionsMessage? options, + }); @async bool isWinBackOfferEligible(String productId, String offerId); 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 53c27bdebf8..fa934243821 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.4.4 environment: - sdk: ^3.6.0 - flutter: ">=3.27.0" + sdk: ^3.7.0 + flutter: ">=3.29.0" flutter: plugin: diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/fakes/fake_storekit_platform.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/fakes/fake_storekit_platform.dart index 3e417378fe7..ecfadc270ca 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/fakes/fake_storekit_platform.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/fakes/fake_storekit_platform.dart @@ -41,8 +41,9 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { validProductIDs = {'123', '456', '789'}; validProducts = {}; for (final String validID in validProductIDs) { - final Map productWrapperMap = - buildProductMap(dummyProductWrapper); + final Map productWrapperMap = buildProductMap( + dummyProductWrapper, + ); productWrapperMap['productIdentifier'] = validID; if (validID == '456') { productWrapperMap['priceLocale'] = buildLocaleMap(noSymbolLocale); @@ -68,8 +69,10 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { _countryIdentifier = 'LL'; } - SKPaymentTransactionWrapper createPendingTransaction(String id, - {int quantity = 1}) { + SKPaymentTransactionWrapper createPendingTransaction( + String id, { + int quantity = 1, + }) { return SKPaymentTransactionWrapper( transactionIdentifier: '', payment: SKPaymentWrapper(productIdentifier: id, quantity: quantity), @@ -79,54 +82,76 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { } SKPaymentTransactionWrapper createPurchasedTransaction( - String productId, String transactionId, - {int quantity = 1}) { + String productId, + String transactionId, { + int quantity = 1, + }) { return SKPaymentTransactionWrapper( - payment: - SKPaymentWrapper(productIdentifier: productId, quantity: quantity), - transactionState: SKPaymentTransactionStateWrapper.purchased, - transactionTimeStamp: 123123.121, - transactionIdentifier: transactionId); + payment: SKPaymentWrapper( + productIdentifier: productId, + quantity: quantity, + ), + transactionState: SKPaymentTransactionStateWrapper.purchased, + transactionTimeStamp: 123123.121, + transactionIdentifier: transactionId, + ); } - SKPaymentTransactionWrapper createFailedTransaction(String productId, - {int quantity = 1}) { + SKPaymentTransactionWrapper createFailedTransaction( + String productId, { + int quantity = 1, + }) { return SKPaymentTransactionWrapper( - transactionIdentifier: '', - payment: - SKPaymentWrapper(productIdentifier: productId, quantity: quantity), - transactionState: SKPaymentTransactionStateWrapper.failed, - transactionTimeStamp: 123123.121, - error: const SKError( - code: 0, - domain: 'ios_domain', - userInfo: {'message': 'an error message'})); + transactionIdentifier: '', + payment: SKPaymentWrapper( + productIdentifier: productId, + quantity: quantity, + ), + transactionState: SKPaymentTransactionStateWrapper.failed, + transactionTimeStamp: 123123.121, + error: const SKError( + code: 0, + domain: 'ios_domain', + userInfo: {'message': 'an error message'}, + ), + ); } SKPaymentTransactionWrapper createCanceledTransaction( - String productId, int errorCode, - {int quantity = 1}) { + String productId, + int errorCode, { + int quantity = 1, + }) { return SKPaymentTransactionWrapper( - transactionIdentifier: '', - payment: - SKPaymentWrapper(productIdentifier: productId, quantity: quantity), - transactionState: SKPaymentTransactionStateWrapper.failed, - transactionTimeStamp: 123123.121, - error: SKError( - code: errorCode, - domain: 'ios_domain', - userInfo: const {'message': 'an error message'})); + transactionIdentifier: '', + payment: SKPaymentWrapper( + productIdentifier: productId, + quantity: quantity, + ), + transactionState: SKPaymentTransactionStateWrapper.failed, + transactionTimeStamp: 123123.121, + error: SKError( + code: errorCode, + domain: 'ios_domain', + userInfo: const {'message': 'an error message'}, + ), + ); } SKPaymentTransactionWrapper createRestoredTransaction( - String productId, String transactionId, - {int quantity = 1}) { + String productId, + String transactionId, { + int quantity = 1, + }) { return SKPaymentTransactionWrapper( - payment: - SKPaymentWrapper(productIdentifier: productId, quantity: quantity), - transactionState: SKPaymentTransactionStateWrapper.restored, - transactionTimeStamp: 123123.121, - transactionIdentifier: transactionId); + payment: SKPaymentWrapper( + productIdentifier: productId, + quantity: quantity, + ), + transactionState: SKPaymentTransactionStateWrapper.restored, + transactionTimeStamp: 123123.121, + transactionIdentifier: transactionId, + ); } @override @@ -150,34 +175,47 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { } } - final SKPaymentTransactionWrapper transaction = - createPendingTransaction(id, quantity: quantity); + final SKPaymentTransactionWrapper transaction = createPendingTransaction( + id, + quantity: quantity, + ); transactionList.add(transaction); InAppPurchaseStoreKitPlatform.observer.updatedTransactions( - transactions: [transaction]); + transactions: [transaction], + ); if (testTransactionFail) { final SKPaymentTransactionWrapper transactionFailed = createFailedTransaction(id, quantity: quantity); InAppPurchaseStoreKitPlatform.observer.updatedTransactions( - transactions: [transactionFailed]); + transactions: [transactionFailed], + ); } else if (testTransactionCancel > 0) { final SKPaymentTransactionWrapper transactionCanceled = - createCanceledTransaction(id, testTransactionCancel, - quantity: quantity); + createCanceledTransaction( + id, + testTransactionCancel, + quantity: quantity, + ); InAppPurchaseStoreKitPlatform.observer.updatedTransactions( - transactions: [transactionCanceled]); + transactions: [transactionCanceled], + ); } else { final SKPaymentTransactionWrapper transactionFinished = createPurchasedTransaction( - id, transaction.transactionIdentifier ?? '', - quantity: quantity); + id, + transaction.transactionIdentifier ?? '', + quantity: quantity, + ); InAppPurchaseStoreKitPlatform.observer.updatedTransactions( - transactions: [transactionFinished]); + transactions: [transactionFinished], + ); } } - void setStoreFrontInfo( - {required String countryCode, required String identifier}) { + void setStoreFrontInfo({ + required String countryCode, + required String identifier, + }) { _countryCode = countryCode; _countryIdentifier = identifier; } @@ -185,7 +223,9 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { @override SKStorefrontMessage storefront() { return SKStorefrontMessage( - countryCode: _countryCode, identifier: _countryIdentifier); + countryCode: _countryCode, + identifier: _countryIdentifier, + ); } @override @@ -195,10 +235,13 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { @override void finishTransaction(Map finishMap) { - finishedTransactions.add(createPurchasedTransaction( + finishedTransactions.add( + createPurchasedTransaction( finishMap['productIdentifier']! as String, finishMap['transactionIdentifier']! as String, - quantity: transactionList.first.payment.quantity)); + quantity: transactionList.first.payment.quantity, + ), + ); } @override @@ -210,13 +253,15 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { throw restoreException!; } if (testRestoredError != null) { - InAppPurchaseStoreKitPlatform.observer - .restoreCompletedTransactionsFailed(error: testRestoredError!); + InAppPurchaseStoreKitPlatform.observer.restoreCompletedTransactionsFailed( + error: testRestoredError!, + ); return; } if (!testRestoredTransactionsNull) { - InAppPurchaseStoreKitPlatform.observer - .updatedTransactions(transactions: transactionList); + InAppPurchaseStoreKitPlatform.observer.updatedTransactions( + transactions: transactionList, + ); } InAppPurchaseStoreKitPlatform.observer .paymentQueueRestoreCompletedTransactionsFinished(); @@ -224,7 +269,8 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { @override Future startProductRequest( - List productIdentifiers) { + List productIdentifiers, + ) { if (queryProductException != null) { throw queryProductException!; } @@ -239,10 +285,13 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { } } final SkProductResponseWrapper response = SkProductResponseWrapper( - products: products, invalidProductIdentifiers: invalidFound); + products: products, + invalidProductIdentifiers: invalidFound, + ); return Future.value( - SkProductResponseWrapper.convertToPigeon(response)); + SkProductResponseWrapper.convertToPigeon(response), + ); } @override @@ -308,14 +357,14 @@ class FakeStoreKit2Platform implements TestInAppPurchase2Api { validProducts = {}; for (final String validID in validProductIDs) { final SK2Product product = SK2Product( - id: validID, - displayName: 'test_product', - displayPrice: '0.99', - description: 'description', - price: 0.99, - type: SK2ProductType.consumable, - priceLocale: - SK2PriceLocale(currencyCode: 'USD', currencySymbol: r'$')); + id: validID, + displayName: 'test_product', + displayPrice: '0.99', + description: 'description', + price: 0.99, + type: SK2ProductType.consumable, + priceLocale: SK2PriceLocale(currencyCode: 'USD', currencySymbol: r'$'), + ); validProducts[validID] = product; } eligibleWinBackOffers = >{}; @@ -323,15 +372,18 @@ class FakeStoreKit2Platform implements TestInAppPurchase2Api { } SK2TransactionMessage createRestoredTransaction( - String productId, String transactionId, - {int quantity = 1}) { + String productId, + String transactionId, { + int quantity = 1, + }) { return SK2TransactionMessage( - id: 123, - originalId: 321, - productId: '', - purchaseDate: '', - appAccountToken: '', - restoring: true); + id: 123, + originalId: 321, + productId: '', + purchaseDate: '', + appAccountToken: '', + restoring: true, + ); } @override @@ -360,15 +412,19 @@ class FakeStoreKit2Platform implements TestInAppPurchase2Api { } @override - Future purchase(String id, - {SK2ProductPurchaseOptionsMessage? options}) { + Future purchase( + String id, { + SK2ProductPurchaseOptionsMessage? options, + }) { lastPurchaseOptions = options; final SK2TransactionMessage transaction = createPendingTransaction(id); - InAppPurchaseStoreKitPlatform.sk2TransactionObserver - .onTransactionsUpdated([transaction]); + InAppPurchaseStoreKitPlatform.sk2TransactionObserver.onTransactionsUpdated( + [transaction], + ); return Future.value( - SK2ProductPurchaseResultMessage.success); + SK2ProductPurchaseResultMessage.success, + ); } @override @@ -380,10 +436,11 @@ class FakeStoreKit2Platform implements TestInAppPurchase2Api { Future> transactions() { return Future>.value([ SK2TransactionMessage( - id: 123, - originalId: 123, - productId: 'product_id', - purchaseDate: '12-12') + id: 123, + originalId: 123, + productId: 'product_id', + purchaseDate: '12-12', + ), ]); } @@ -399,8 +456,9 @@ class FakeStoreKit2Platform implements TestInAppPurchase2Api { @override Future restorePurchases() async { - InAppPurchaseStoreKitPlatform.sk2TransactionObserver - .onTransactionsUpdated(transactionList); + InAppPurchaseStoreKitPlatform.sk2TransactionObserver.onTransactionsUpdated( + transactionList, + ); } @override @@ -414,10 +472,7 @@ class FakeStoreKit2Platform implements TestInAppPurchase2Api { } @override - Future isWinBackOfferEligible( - String productId, - String offerId, - ) async { + Future isWinBackOfferEligible(String productId, String offerId) async { if (!validProductIDs.contains(productId)) { throw PlatformException( code: 'storekit2_failed_to_fetch_product', @@ -438,9 +493,7 @@ class FakeStoreKit2Platform implements TestInAppPurchase2Api { } @override - Future isIntroductoryOfferEligible( - String productId, - ) async { + Future isIntroductoryOfferEligible(String productId) async { if (!validProductIDs.contains(productId)) { throw PlatformException( code: 'storekit2_failed_to_fetch_product', @@ -463,11 +516,12 @@ class FakeStoreKit2Platform implements TestInAppPurchase2Api { SK2TransactionMessage createPendingTransaction(String id, {int quantity = 1}) { return SK2TransactionMessage( - id: 1, - originalId: 2, - productId: id, - purchaseDate: 'purchaseDate', - appAccountToken: 'appAccountToken', - receiptData: 'receiptData', - jsonRepresentation: 'jsonRepresentation'); + id: 1, + originalId: 2, + productId: id, + purchaseDate: 'purchaseDate', + appAccountToken: 'appAccountToken', + receiptData: 'receiptData', + jsonRepresentation: 'jsonRepresentation', + ); } 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 75ad5311e8d..4535dcd2963 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 @@ -16,13 +16,14 @@ import 'test_api.g.dart'; void main() { final SK2Product dummyProductWrapper = SK2Product( - id: '2', - displayName: 'name', - displayPrice: '0.99', - description: 'desc', - price: 0.99, - type: SK2ProductType.consumable, - priceLocale: SK2PriceLocale(currencyCode: 'USD', currencySymbol: r'$')); + id: '2', + displayName: 'name', + displayPrice: '0.99', + description: 'desc', + price: 0.99, + type: SK2ProductType.consumable, + priceLocale: SK2PriceLocale(currencyCode: 'USD', currencySymbol: r'$'), + ); TestWidgetsFlutterBinding.ensureInitialized(); @@ -55,8 +56,8 @@ void main() { test('should get product list and correct invalid identifiers', () async { final InAppPurchaseStoreKitPlatform connection = InAppPurchaseStoreKitPlatform(); - final ProductDetailsResponse response = - await connection.queryProductDetails({'123', '456', '789'}); + final ProductDetailsResponse response = await connection + .queryProductDetails({'123', '456', '789'}); final List products = response.productDetails; expect(products.first.id, '123'); expect(products[1].id, '456'); @@ -66,130 +67,159 @@ void main() { expect(response.productDetails[1].currencySymbol, r'$'); }); test( - 'if query products throws error, should get error object in the response', - () async { - fakeStoreKit2Platform.queryProductException = PlatformException( + 'if query products throws error, should get error object in the response', + () async { + fakeStoreKit2Platform.queryProductException = PlatformException( code: 'error_code', message: 'error_message', - details: {'info': 'error_info'}); - final InAppPurchaseStoreKitPlatform connection = - InAppPurchaseStoreKitPlatform(); - final ProductDetailsResponse response = - await connection.queryProductDetails({'123', '456', '789'}); - expect(response.productDetails, []); - expect(response.notFoundIDs, ['123', '456', '789']); - expect(response.error, isNotNull); - expect(response.error!.source, kIAPSource); - expect(response.error!.code, 'error_code'); - expect(response.error!.message, 'error_message'); - expect(response.error!.details, {'info': 'error_info'}); - }); + details: {'info': 'error_info'}, + ); + final InAppPurchaseStoreKitPlatform connection = + InAppPurchaseStoreKitPlatform(); + final ProductDetailsResponse response = await connection + .queryProductDetails({'123', '456', '789'}); + expect(response.productDetails, []); + expect(response.notFoundIDs, ['123', '456', '789']); + expect(response.error, isNotNull); + expect(response.error!.source, kIAPSource); + expect(response.error!.code, 'error_code'); + expect(response.error!.message, 'error_message'); + expect(response.error!.details, {'info': 'error_info'}); + }, + ); }); group('make payment', () { test( - 'buying non consumable, should get purchase objects in the purchase update callback', - () async { - final List details = []; - final Completer> completer = - Completer>(); - final Stream> stream = - iapStoreKitPlatform.purchaseStream; - - late StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - details.addAll(purchaseDetailsList); - if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { - completer.complete(details); - subscription.cancel(); - } - }); - final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( - productDetails: - AppStoreProduct2Details.fromSK2Product(dummyProductWrapper), - applicationUserName: 'appName'); - await iapStoreKitPlatform.buyNonConsumable(purchaseParam: purchaseParam); - - final List result = await completer.future; - expect(result.length, 1); - expect(result.first.productID, dummyProductWrapper.id); - }); + 'buying non consumable, should get purchase objects in the purchase update callback', + () async { + final List details = []; + final Completer> completer = + Completer>(); + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + + late StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + details.addAll(purchaseDetailsList); + if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { + completer.complete(details); + subscription.cancel(); + } + }); + final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( + productDetails: AppStoreProduct2Details.fromSK2Product( + dummyProductWrapper, + ), + applicationUserName: 'appName', + ); + await iapStoreKitPlatform.buyNonConsumable( + purchaseParam: purchaseParam, + ); + + final List result = await completer.future; + expect(result.length, 1); + expect(result.first.productID, dummyProductWrapper.id); + }, + ); test( - 'buying consumable, should get purchase objects in the purchase update callback', - () async { - final List details = []; - final Completer> completer = - Completer>(); - final Stream> stream = - iapStoreKitPlatform.purchaseStream; + 'buying consumable, should get purchase objects in the purchase update callback', + () async { + final List details = []; + final Completer> completer = + Completer>(); + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + + late StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + details.addAll(purchaseDetailsList); + if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { + completer.complete(details); + subscription.cancel(); + } + }); + final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( + productDetails: AppStoreProduct2Details.fromSK2Product( + dummyProductWrapper, + ), + applicationUserName: 'appName', + ); + await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); - late StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - details.addAll(purchaseDetailsList); - if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { - completer.complete(details); - subscription.cancel(); - } - }); - final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( - productDetails: - AppStoreProduct2Details.fromSK2Product(dummyProductWrapper), - applicationUserName: 'appName'); - await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); - - final List result = await completer.future; - expect(result.length, 1); - expect(result.first.productID, dummyProductWrapper.id); - }); + final List result = await completer.future; + expect(result.length, 1); + expect(result.first.productID, dummyProductWrapper.id); + }, + ); test('buying consumable, should throw when autoConsume is false', () async { final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( - productDetails: - AppStoreProduct2Details.fromSK2Product(dummyProductWrapper), - applicationUserName: 'appName'); + productDetails: AppStoreProduct2Details.fromSK2Product( + dummyProductWrapper, + ), + applicationUserName: 'appName', + ); expect( - () => iapStoreKitPlatform.buyConsumable( - purchaseParam: purchaseParam, autoConsume: false), - throwsA(isInstanceOf())); + () => iapStoreKitPlatform.buyConsumable( + purchaseParam: purchaseParam, + autoConsume: false, + ), + throwsA(isInstanceOf()), + ); }); test( - 'buying consumable, should get PurchaseVerificationData with serverVerificationData and localVerificationData', - () async { - final List details = []; - final Completer> completer = - Completer>(); - final Stream> stream = - iapStoreKitPlatform.purchaseStream; - - late final StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - details.addAll(purchaseDetailsList); - if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { - completer.complete(details); - subscription.cancel(); - } - }); - final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( - productDetails: - AppStoreProduct2Details.fromSK2Product(dummyProductWrapper), - applicationUserName: 'appName'); - await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); - - final List result = await completer.future; - expect(result.length, 1); - expect(result.first.productID, dummyProductWrapper.id); - expect( - result.first.verificationData.serverVerificationData, 'receiptData'); - expect(result.first.verificationData.localVerificationData, - 'jsonRepresentation'); - }); + 'buying consumable, should get PurchaseVerificationData with serverVerificationData and localVerificationData', + () async { + final List details = []; + final Completer> completer = + Completer>(); + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + + late final StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + details.addAll(purchaseDetailsList); + if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { + completer.complete(details); + subscription.cancel(); + } + }); + final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( + productDetails: AppStoreProduct2Details.fromSK2Product( + dummyProductWrapper, + ), + applicationUserName: 'appName', + ); + await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); + + final List result = await completer.future; + expect(result.length, 1); + expect(result.first.productID, dummyProductWrapper.id); + expect( + result.first.verificationData.serverVerificationData, + 'receiptData', + ); + expect( + result.first.verificationData.localVerificationData, + 'jsonRepresentation', + ); + }, + ); test('should process Sk2PurchaseParam with winBackOfferId only', () async { final Sk2PurchaseParam purchaseParam = Sk2PurchaseParam( - productDetails: - AppStoreProduct2Details.fromSK2Product(dummyProductWrapper), + productDetails: AppStoreProduct2Details.fromSK2Product( + dummyProductWrapper, + ), applicationUserName: 'testUser', winBackOfferId: 'winBack123', ); @@ -205,105 +235,125 @@ void main() { expect(lastPurchaseOptions.promotionalOffer, isNull); }); - test('should process Sk2PurchaseParam with promotionalOffer only', - () async { - final SK2SubscriptionOfferSignature fakeSignature = - SK2SubscriptionOfferSignature( - keyID: 'key123', - signature: 'signature123', - nonce: 'nonce123', - timestamp: 1234567890, - ); - - final Sk2PurchaseParam purchaseParam = Sk2PurchaseParam( - productDetails: - AppStoreProduct2Details.fromSK2Product(dummyProductWrapper), - applicationUserName: 'testUser', - quantity: 2, - promotionalOffer: SK2PromotionalOffer( - signature: fakeSignature, - offerId: 'promo123', - ), - ); - - await iapStoreKitPlatform.buyNonConsumable(purchaseParam: purchaseParam); - - final SK2ProductPurchaseOptionsMessage lastPurchaseOptions = - fakeStoreKit2Platform.lastPurchaseOptions!; - - expect(lastPurchaseOptions.appAccountToken, 'testUser'); - expect(lastPurchaseOptions.quantity, 2); - expect( - lastPurchaseOptions.promotionalOffer!.promotionalOfferId, 'promo123'); - expect( + test( + 'should process Sk2PurchaseParam with promotionalOffer only', + () async { + final SK2SubscriptionOfferSignature fakeSignature = + SK2SubscriptionOfferSignature( + keyID: 'key123', + signature: 'signature123', + nonce: 'nonce123', + timestamp: 1234567890, + ); + + final Sk2PurchaseParam purchaseParam = Sk2PurchaseParam( + productDetails: AppStoreProduct2Details.fromSK2Product( + dummyProductWrapper, + ), + applicationUserName: 'testUser', + quantity: 2, + promotionalOffer: SK2PromotionalOffer( + signature: fakeSignature, + offerId: 'promo123', + ), + ); + + await iapStoreKitPlatform.buyNonConsumable( + purchaseParam: purchaseParam, + ); + + final SK2ProductPurchaseOptionsMessage lastPurchaseOptions = + fakeStoreKit2Platform.lastPurchaseOptions!; + + expect(lastPurchaseOptions.appAccountToken, 'testUser'); + expect(lastPurchaseOptions.quantity, 2); + expect( + lastPurchaseOptions.promotionalOffer!.promotionalOfferId, + 'promo123', + ); + expect( lastPurchaseOptions.promotionalOffer!.promotionalOfferSignature.keyID, - 'key123'); - expect(lastPurchaseOptions.winBackOfferId, isNull); - }); + 'key123', + ); + expect(lastPurchaseOptions.winBackOfferId, isNull); + }, + ); test( - 'should process Sk2PurchaseParam with no winBackOfferId or promotionalOffer', - () async { - final Sk2PurchaseParam purchaseParam = Sk2PurchaseParam( - productDetails: - AppStoreProduct2Details.fromSK2Product(dummyProductWrapper), - applicationUserName: 'testUser', - ); + 'should process Sk2PurchaseParam with no winBackOfferId or promotionalOffer', + () async { + final Sk2PurchaseParam purchaseParam = Sk2PurchaseParam( + productDetails: AppStoreProduct2Details.fromSK2Product( + dummyProductWrapper, + ), + applicationUserName: 'testUser', + ); - await iapStoreKitPlatform.buyNonConsumable(purchaseParam: purchaseParam); + await iapStoreKitPlatform.buyNonConsumable( + purchaseParam: purchaseParam, + ); - final SK2ProductPurchaseOptionsMessage lastPurchaseOptions = - fakeStoreKit2Platform.lastPurchaseOptions!; + final SK2ProductPurchaseOptionsMessage lastPurchaseOptions = + fakeStoreKit2Platform.lastPurchaseOptions!; - expect(lastPurchaseOptions.appAccountToken, 'testUser'); - expect(lastPurchaseOptions.quantity, 1); - expect(lastPurchaseOptions.winBackOfferId, isNull); - expect(lastPurchaseOptions.promotionalOffer, isNull); - }); + expect(lastPurchaseOptions.appAccountToken, 'testUser'); + expect(lastPurchaseOptions.quantity, 1); + 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', - ); + 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); + await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); - final SK2ProductPurchaseOptionsMessage lastPurchaseOptions = - fakeStoreKit2Platform.lastPurchaseOptions!; + final SK2ProductPurchaseOptionsMessage lastPurchaseOptions = + fakeStoreKit2Platform.lastPurchaseOptions!; - expect(lastPurchaseOptions.appAccountToken, 'testUser'); - expect(lastPurchaseOptions.quantity, 3); - expect(lastPurchaseOptions.winBackOfferId, isNull); - expect(lastPurchaseOptions.promotionalOffer, isNull); - }); + 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', - ); + 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); + await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); - final SK2ProductPurchaseOptionsMessage lastPurchaseOptions = - fakeStoreKit2Platform.lastPurchaseOptions!; + final SK2ProductPurchaseOptionsMessage lastPurchaseOptions = + fakeStoreKit2Platform.lastPurchaseOptions!; - expect(lastPurchaseOptions.quantity, 1); - }); + expect(lastPurchaseOptions.quantity, 1); + }, + ); }); group('restore purchases', () { test('should emit restored transactions on purchase stream', () async { - fakeStoreKit2Platform.transactionList - .add(fakeStoreKit2Platform.createRestoredTransaction('foo', 'RT1')); - fakeStoreKit2Platform.transactionList - .add(fakeStoreKit2Platform.createRestoredTransaction('foo', 'RT2')); + fakeStoreKit2Platform.transactionList.add( + fakeStoreKit2Platform.createRestoredTransaction('foo', 'RT1'), + ); + fakeStoreKit2Platform.transactionList.add( + fakeStoreKit2Platform.createRestoredTransaction('foo', 'RT2'), + ); final Completer> completer = Completer>(); final Stream> stream = @@ -356,7 +406,7 @@ void main() { test('should return true when offer is eligible', () async { fakeStoreKit2Platform.validProductIDs = {'sub1'}; fakeStoreKit2Platform.eligibleWinBackOffers['sub1'] = { - 'winback1' + 'winback1', }; fakeStoreKit2Platform.validProducts['sub1'] = SK2Product( id: 'sub1', @@ -419,56 +469,66 @@ void main() { 'invalid_product', 'winback1', ), - throwsA(isA().having( - (PlatformException e) => e.code, - 'code', - 'storekit2_failed_to_fetch_product', - )), - ); - }); - - test('should throw subscription error for non-subscription product', - () async { - fakeStoreKit2Platform.validProductIDs = {'consumable1'}; - fakeStoreKit2Platform.validProducts['consumable1'] = SK2Product( - id: 'consumable1', - displayName: 'Coins', - displayPrice: r'$0.99', - description: 'Game currency', - price: 0.99, - type: SK2ProductType.consumable, - priceLocale: SK2PriceLocale(currencyCode: 'USD', currencySymbol: r'$'), - ); - - expect( - () => iapStoreKitPlatform.isWinBackOfferEligible( - 'consumable1', - 'winback1', + throwsA( + isA().having( + (PlatformException e) => e.code, + 'code', + 'storekit2_failed_to_fetch_product', + ), ), - throwsA(isA().having( - (PlatformException e) => e.code, - 'code', - 'storekit2_not_subscription', - )), ); }); - test('should throw platform exception when StoreKit2 is not supported', - () async { - await InAppPurchaseStoreKitPlatform.enableStoreKit1(); + test( + 'should throw subscription error for non-subscription product', + () async { + fakeStoreKit2Platform.validProductIDs = {'consumable1'}; + fakeStoreKit2Platform.validProducts['consumable1'] = SK2Product( + id: 'consumable1', + displayName: 'Coins', + displayPrice: r'$0.99', + description: 'Game currency', + price: 0.99, + type: SK2ProductType.consumable, + priceLocale: SK2PriceLocale( + currencyCode: 'USD', + currencySymbol: r'$', + ), + ); - expect( - () => iapStoreKitPlatform.isWinBackOfferEligible( - 'sub1', - 'winback1', - ), - throwsA(isA().having( - (PlatformException e) => e.code, - 'code', - 'storekit2_not_enabled', - )), - ); - }); + expect( + () => iapStoreKitPlatform.isWinBackOfferEligible( + 'consumable1', + 'winback1', + ), + throwsA( + isA().having( + (PlatformException e) => e.code, + 'code', + 'storekit2_not_subscription', + ), + ), + ); + }, + ); + + test( + 'should throw platform exception when StoreKit2 is not supported', + () async { + await InAppPurchaseStoreKitPlatform.enableStoreKit1(); + + expect( + () => iapStoreKitPlatform.isWinBackOfferEligible('sub1', 'winback1'), + throwsA( + isA().having( + (PlatformException e) => e.code, + 'code', + 'storekit2_not_enabled', + ), + ), + ); + }, + ); }); group('introductory offers eligibility', () { @@ -502,87 +562,106 @@ void main() { priceLocale: SK2PriceLocale(currencyCode: 'USD', currencySymbol: r'$'), ); - final bool result = - await iapStoreKitPlatform.isIntroductoryOfferEligible('sub1'); + final bool result = await iapStoreKitPlatform.isIntroductoryOfferEligible( + 'sub1', + ); expect(result, isTrue); }); - test('should return false when introductory offer is not eligible', - () async { - fakeStoreKit2Platform.validProductIDs = {'sub1'}; - fakeStoreKit2Platform.eligibleIntroductoryOffers['sub1'] = false; - fakeStoreKit2Platform.validProducts['sub1'] = SK2Product( - id: 'sub1', - displayName: 'Subscription', - displayPrice: r'$9.99', - description: 'Monthly subscription', - price: 9.99, - type: SK2ProductType.autoRenewable, - subscription: const SK2SubscriptionInfo( - subscriptionGroupID: 'group1', - promotionalOffers: [], - subscriptionPeriod: SK2SubscriptionPeriod( - value: 1, - unit: SK2SubscriptionPeriodUnit.month, + test( + 'should return false when introductory offer is not eligible', + () async { + fakeStoreKit2Platform.validProductIDs = {'sub1'}; + fakeStoreKit2Platform.eligibleIntroductoryOffers['sub1'] = false; + fakeStoreKit2Platform.validProducts['sub1'] = SK2Product( + id: 'sub1', + displayName: 'Subscription', + displayPrice: r'$9.99', + description: 'Monthly subscription', + price: 9.99, + type: SK2ProductType.autoRenewable, + subscription: const SK2SubscriptionInfo( + subscriptionGroupID: 'group1', + promotionalOffers: [], + subscriptionPeriod: SK2SubscriptionPeriod( + value: 1, + unit: SK2SubscriptionPeriodUnit.month, + ), ), - ), - priceLocale: SK2PriceLocale(currencyCode: 'USD', currencySymbol: r'$'), - ); + priceLocale: SK2PriceLocale( + currencyCode: 'USD', + currencySymbol: r'$', + ), + ); - final bool result = - await iapStoreKitPlatform.isIntroductoryOfferEligible('sub1'); + final bool result = await iapStoreKitPlatform + .isIntroductoryOfferEligible('sub1'); - expect(result, isFalse); - }); + expect(result, isFalse); + }, + ); test('should throw product not found error for invalid product', () async { expect( () => iapStoreKitPlatform.isIntroductoryOfferEligible('invalid_product'), - throwsA(isA().having( - (PlatformException e) => e.code, - 'code', - 'storekit2_failed_to_fetch_product', - )), - ); - }); - - test('should throw subscription error for non-subscription product', - () async { - fakeStoreKit2Platform.validProductIDs = {'consumable1'}; - fakeStoreKit2Platform.validProducts['consumable1'] = SK2Product( - id: 'consumable1', - displayName: 'Coins', - displayPrice: r'$0.99', - description: 'Game currency', - price: 0.99, - type: SK2ProductType.consumable, - priceLocale: SK2PriceLocale(currencyCode: 'USD', currencySymbol: r'$'), - ); - - expect( - () => iapStoreKitPlatform.isIntroductoryOfferEligible('consumable1'), - throwsA(isA().having( - (PlatformException e) => e.code, - 'code', - 'storekit2_not_subscription', - )), + throwsA( + isA().having( + (PlatformException e) => e.code, + 'code', + 'storekit2_failed_to_fetch_product', + ), + ), ); }); - test('should throw platform exception when StoreKit2 is not supported', - () async { - await InAppPurchaseStoreKitPlatform.enableStoreKit1(); + test( + 'should throw subscription error for non-subscription product', + () async { + fakeStoreKit2Platform.validProductIDs = {'consumable1'}; + fakeStoreKit2Platform.validProducts['consumable1'] = SK2Product( + id: 'consumable1', + displayName: 'Coins', + displayPrice: r'$0.99', + description: 'Game currency', + price: 0.99, + type: SK2ProductType.consumable, + priceLocale: SK2PriceLocale( + currencyCode: 'USD', + currencySymbol: r'$', + ), + ); + + expect( + () => iapStoreKitPlatform.isIntroductoryOfferEligible('consumable1'), + throwsA( + isA().having( + (PlatformException e) => e.code, + 'code', + 'storekit2_not_subscription', + ), + ), + ); + }, + ); - expect( - () => iapStoreKitPlatform.isIntroductoryOfferEligible('sub1'), - throwsA(isA().having( - (PlatformException e) => e.code, - 'code', - 'storekit2_not_enabled', - )), - ); - }); + test( + 'should throw platform exception when StoreKit2 is not supported', + () async { + await InAppPurchaseStoreKitPlatform.enableStoreKit1(); + + expect( + () => iapStoreKitPlatform.isIntroductoryOfferEligible('sub1'), + throwsA( + isA().having( + (PlatformException e) => e.code, + 'code', + 'storekit2_not_enabled', + ), + ), + ); + }, + ); }); } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_platform_addtion_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_platform_addtion_test.dart index dfa3c11ca6b..0276cdabd9c 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_platform_addtion_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_platform_addtion_test.dart @@ -21,8 +21,9 @@ void main() { group('present code redemption sheet', () { test('null', () async { expect( - InAppPurchaseStoreKitPlatformAddition().presentCodeRedemptionSheet(), - completes); + InAppPurchaseStoreKitPlatformAddition().presentCodeRedemptionSheet(), + completes, + ); }); }); diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_platform_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_platform_test.dart index eb32ceb9b3f..162f11664aa 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_platform_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_platform_test.dart @@ -59,32 +59,38 @@ void main() { }); test( - 'if query products throws error, should get error object in the response', - () async { - fakeStoreKitPlatform.queryProductException = PlatformException( + 'if query products throws error, should get error object in the response', + () async { + fakeStoreKitPlatform.queryProductException = PlatformException( code: 'error_code', message: 'error_message', - details: {'info': 'error_info'}); - final InAppPurchaseStoreKitPlatform connection = - InAppPurchaseStoreKitPlatform(); - final ProductDetailsResponse response = - await connection.queryProductDetails({'123', '456', '789'}); - expect(response.productDetails, []); - expect(response.notFoundIDs, ['123', '456', '789']); - expect(response.error, isNotNull); - expect(response.error!.source, kIAPSource); - expect(response.error!.code, 'error_code'); - expect(response.error!.message, 'error_message'); - expect(response.error!.details, {'info': 'error_info'}); - }); + details: {'info': 'error_info'}, + ); + final InAppPurchaseStoreKitPlatform connection = + InAppPurchaseStoreKitPlatform(); + final ProductDetailsResponse response = await connection + .queryProductDetails({'123', '456', '789'}); + expect(response.productDetails, []); + expect(response.notFoundIDs, ['123', '456', '789']); + expect(response.error, isNotNull); + expect(response.error!.source, kIAPSource); + expect(response.error!.code, 'error_code'); + expect(response.error!.message, 'error_message'); + expect(response.error!.details, {'info': 'error_info'}); + }, + ); }); group('restore purchases', () { test('should emit restored transactions on purchase stream', () async { fakeStoreKitPlatform.transactionList.insert( - 0, fakeStoreKitPlatform.createRestoredTransaction('foo', 'RT1')); + 0, + fakeStoreKitPlatform.createRestoredTransaction('foo', 'RT1'), + ); fakeStoreKitPlatform.transactionList.insert( - 1, fakeStoreKitPlatform.createRestoredTransaction('foo', 'RT2')); + 1, + fakeStoreKitPlatform.createRestoredTransaction('foo', 'RT2'), + ); final Completer> completer = Completer>(); final Stream> stream = @@ -110,41 +116,54 @@ void main() { expect(actual.purchaseID, expected.transactionIdentifier); expect(actual.verificationData, isNotNull); expect(actual.status, PurchaseStatus.restored); - expect(actual.verificationData.localVerificationData, - fakeStoreKitPlatform.receiptData); - expect(actual.verificationData.serverVerificationData, - fakeStoreKitPlatform.receiptData); + expect( + actual.verificationData.localVerificationData, + fakeStoreKitPlatform.receiptData, + ); + expect( + actual.verificationData.serverVerificationData, + fakeStoreKitPlatform.receiptData, + ); expect(actual.pendingCompletePurchase, true); } }); test( - 'should emit empty transaction list on purchase stream when there is nothing to restore', - () async { - fakeStoreKitPlatform.testRestoredTransactionsNull = true; - final Completer?> completer = - Completer?>(); - final Stream> stream = - iapStoreKitPlatform.purchaseStream; - - late StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - expect(purchaseDetailsList.isEmpty, true); - subscription.cancel(); - completer.complete(); - }); + 'should emit empty transaction list on purchase stream when there is nothing to restore', + () async { + fakeStoreKitPlatform.testRestoredTransactionsNull = true; + final Completer?> completer = + Completer?>(); + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + + late StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + expect(purchaseDetailsList.isEmpty, true); + subscription.cancel(); + completer.complete(); + }); - await iapStoreKitPlatform.restorePurchases(); - await completer.future; - }); + await iapStoreKitPlatform.restorePurchases(); + await completer.future; + }, + ); test('should not block transaction updates', () async { fakeStoreKitPlatform.transactionList.insert( - 0, fakeStoreKitPlatform.createRestoredTransaction('foo', 'RT1')); + 0, + fakeStoreKitPlatform.createRestoredTransaction('foo', 'RT1'), + ); fakeStoreKitPlatform.transactionList.insert( - 1, fakeStoreKitPlatform.createPurchasedTransaction('foo', 'bar')); + 1, + fakeStoreKitPlatform.createPurchasedTransaction('foo', 'bar'), + ); fakeStoreKitPlatform.transactionList.insert( - 2, fakeStoreKitPlatform.createRestoredTransaction('foo', 'RT2')); + 2, + fakeStoreKitPlatform.createRestoredTransaction('foo', 'RT2'), + ); final Completer> completer = Completer>(); final Stream> stream = @@ -169,175 +188,222 @@ void main() { expect(actual.verificationData, isNotNull); expect( actual.status, - const SKTransactionStatusConverter() - .toPurchaseStatus(expected.transactionState, expected.error), + const SKTransactionStatusConverter().toPurchaseStatus( + expected.transactionState, + expected.error, + ), + ); + expect( + actual.verificationData.localVerificationData, + fakeStoreKitPlatform.receiptData, + ); + expect( + actual.verificationData.serverVerificationData, + fakeStoreKitPlatform.receiptData, ); - expect(actual.verificationData.localVerificationData, - fakeStoreKitPlatform.receiptData); - expect(actual.verificationData.serverVerificationData, - fakeStoreKitPlatform.receiptData); expect(actual.pendingCompletePurchase, true); } }); test( - 'should emit empty transaction if transactions array does not contain a transaction with PurchaseStatus.restored status.', - () async { - fakeStoreKitPlatform.transactionList.insert( - 0, fakeStoreKitPlatform.createPurchasedTransaction('foo', 'bar')); - final Completer>> completer = - Completer>>(); - final Stream> stream = - iapStoreKitPlatform.purchaseStream; - final List> purchaseDetails = - >[]; - - late StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - purchaseDetails.add(purchaseDetailsList); - - if (purchaseDetails.length == 2) { - completer.complete(purchaseDetails); - subscription.cancel(); + 'should emit empty transaction if transactions array does not contain a transaction with PurchaseStatus.restored status.', + () async { + fakeStoreKitPlatform.transactionList.insert( + 0, + fakeStoreKitPlatform.createPurchasedTransaction('foo', 'bar'), + ); + final Completer>> completer = + Completer>>(); + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + final List> purchaseDetails = + >[]; + + late StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + purchaseDetails.add(purchaseDetailsList); + + if (purchaseDetails.length == 2) { + completer.complete(purchaseDetails); + subscription.cancel(); + } + }); + await iapStoreKitPlatform.restorePurchases(); + final List> details = await completer.future; + expect(details.length, 2); + expect(details[0], >[]); + for (int i = 0; i < fakeStoreKitPlatform.transactionList.length; i++) { + final SKPaymentTransactionWrapper expected = + fakeStoreKitPlatform.transactionList[i]; + final PurchaseDetails actual = details[1][i]; + + expect(actual.purchaseID, expected.transactionIdentifier); + expect(actual.verificationData, isNotNull); + expect( + actual.status, + const SKTransactionStatusConverter().toPurchaseStatus( + expected.transactionState, + expected.error, + ), + ); + expect( + actual.verificationData.localVerificationData, + fakeStoreKitPlatform.receiptData, + ); + expect( + actual.verificationData.serverVerificationData, + fakeStoreKitPlatform.receiptData, + ); + expect(actual.pendingCompletePurchase, true); } - }); - await iapStoreKitPlatform.restorePurchases(); - final List> details = await completer.future; - expect(details.length, 2); - expect(details[0], >[]); - for (int i = 0; i < fakeStoreKitPlatform.transactionList.length; i++) { - final SKPaymentTransactionWrapper expected = - fakeStoreKitPlatform.transactionList[i]; - final PurchaseDetails actual = details[1][i]; + }, + ); - expect(actual.purchaseID, expected.transactionIdentifier); - expect(actual.verificationData, isNotNull); - expect( - actual.status, - const SKTransactionStatusConverter() - .toPurchaseStatus(expected.transactionState, expected.error), + test( + 'receipt error should populate null to verificationData.data', + () async { + fakeStoreKitPlatform.transactionList.insert( + 0, + fakeStoreKitPlatform.createRestoredTransaction('foo', 'RT1'), ); - expect(actual.verificationData.localVerificationData, - fakeStoreKitPlatform.receiptData); - expect(actual.verificationData.serverVerificationData, - fakeStoreKitPlatform.receiptData); - expect(actual.pendingCompletePurchase, true); - } - }); + fakeStoreKitPlatform.transactionList.insert( + 1, + fakeStoreKitPlatform.createRestoredTransaction('foo', 'RT2'), + ); + fakeStoreKitPlatform.receiptData = null; + final Completer> completer = + Completer>(); + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + + late StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + if (purchaseDetailsList.first.status == PurchaseStatus.restored) { + completer.complete(purchaseDetailsList); + subscription.cancel(); + } + }); - test('receipt error should populate null to verificationData.data', - () async { - fakeStoreKitPlatform.transactionList.insert( - 0, fakeStoreKitPlatform.createRestoredTransaction('foo', 'RT1')); - fakeStoreKitPlatform.transactionList.insert( - 1, fakeStoreKitPlatform.createRestoredTransaction('foo', 'RT2')); - fakeStoreKitPlatform.receiptData = null; - final Completer> completer = - Completer>(); - final Stream> stream = - iapStoreKitPlatform.purchaseStream; + await iapStoreKitPlatform.restorePurchases(); + final List details = await completer.future; - late StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - if (purchaseDetailsList.first.status == PurchaseStatus.restored) { - completer.complete(purchaseDetailsList); - subscription.cancel(); + for (final PurchaseDetails purchase in details) { + expect(purchase.verificationData.localVerificationData, isEmpty); + expect(purchase.verificationData.serverVerificationData, isEmpty); } - }); - - await iapStoreKitPlatform.restorePurchases(); - final List details = await completer.future; - - for (final PurchaseDetails purchase in details) { - expect(purchase.verificationData.localVerificationData, isEmpty); - expect(purchase.verificationData.serverVerificationData, isEmpty); - } - }); + }, + ); test('test restore error', () { fakeStoreKitPlatform.testRestoredError = const SKError( - code: 123, - domain: 'error_test', - userInfo: {'message': 'errorMessage'}); + code: 123, + domain: 'error_test', + userInfo: {'message': 'errorMessage'}, + ); expect( - () => iapStoreKitPlatform.restorePurchases(), - throwsA( - isA() - .having((SKError error) => error.code, 'code', 123) - .having((SKError error) => error.domain, 'domain', 'error_test') - .having((SKError error) => error.userInfo, 'userInfo', - {'message': 'errorMessage'}), - )); + () => iapStoreKitPlatform.restorePurchases(), + throwsA( + isA() + .having((SKError error) => error.code, 'code', 123) + .having((SKError error) => error.domain, 'domain', 'error_test') + .having( + (SKError error) => error.userInfo, + 'userInfo', + {'message': 'errorMessage'}, + ), + ), + ); }); }); group('make payment', () { test( - 'buying non consumable, should get purchase objects in the purchase update callback', - () async { - final List details = []; - final Completer> completer = - Completer>(); - final Stream> stream = - iapStoreKitPlatform.purchaseStream; - - late StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - details.addAll(purchaseDetailsList); - if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { - completer.complete(details); - subscription.cancel(); - } - }); - final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( - productDetails: - AppStoreProductDetails.fromSKProduct(dummyProductWrapper), - applicationUserName: 'appName'); - await iapStoreKitPlatform.buyNonConsumable(purchaseParam: purchaseParam); + 'buying non consumable, should get purchase objects in the purchase update callback', + () async { + final List details = []; + final Completer> completer = + Completer>(); + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + + late StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + details.addAll(purchaseDetailsList); + if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { + completer.complete(details); + subscription.cancel(); + } + }); + final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( + productDetails: AppStoreProductDetails.fromSKProduct( + dummyProductWrapper, + ), + applicationUserName: 'appName', + ); + await iapStoreKitPlatform.buyNonConsumable( + purchaseParam: purchaseParam, + ); - final List result = await completer.future; - expect(result.length, 2); - expect(result.first.productID, dummyProductWrapper.productIdentifier); - }); + final List result = await completer.future; + expect(result.length, 2); + expect(result.first.productID, dummyProductWrapper.productIdentifier); + }, + ); test( - 'buying consumable, should get purchase objects in the purchase update callback', - () async { - final List details = []; - final Completer> completer = - Completer>(); - final Stream> stream = - iapStoreKitPlatform.purchaseStream; - - late StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - details.addAll(purchaseDetailsList); - if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { - completer.complete(details); - subscription.cancel(); - } - }); - final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( - productDetails: - AppStoreProductDetails.fromSKProduct(dummyProductWrapper), - applicationUserName: 'appName'); - await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); + 'buying consumable, should get purchase objects in the purchase update callback', + () async { + final List details = []; + final Completer> completer = + Completer>(); + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + + late StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + details.addAll(purchaseDetailsList); + if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { + completer.complete(details); + subscription.cancel(); + } + }); + final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( + productDetails: AppStoreProductDetails.fromSKProduct( + dummyProductWrapper, + ), + applicationUserName: 'appName', + ); + await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); - final List result = await completer.future; - expect(result.length, 2); - expect(result.first.productID, dummyProductWrapper.productIdentifier); - }); + final List result = await completer.future; + expect(result.length, 2); + expect(result.first.productID, dummyProductWrapper.productIdentifier); + }, + ); test('buying consumable, should throw when autoConsume is false', () async { final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( - productDetails: - AppStoreProductDetails.fromSKProduct(dummyProductWrapper), - applicationUserName: 'appName'); + productDetails: AppStoreProductDetails.fromSKProduct( + dummyProductWrapper, + ), + applicationUserName: 'appName', + ); expect( - () => iapStoreKitPlatform.buyConsumable( - purchaseParam: purchaseParam, autoConsume: false), - throwsA(isInstanceOf())); + () => iapStoreKitPlatform.buyConsumable( + purchaseParam: purchaseParam, + autoConsume: false, + ), + throwsA(isInstanceOf()), + ); }); test('should get failed purchase status', () async { @@ -360,170 +426,209 @@ void main() { } }); final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( - productDetails: - AppStoreProductDetails.fromSKProduct(dummyProductWrapper), - applicationUserName: 'appName'); + productDetails: AppStoreProductDetails.fromSKProduct( + dummyProductWrapper, + ), + applicationUserName: 'appName', + ); await iapStoreKitPlatform.buyNonConsumable(purchaseParam: purchaseParam); final IAPError completerError = await completer.future; expect(completerError.code, 'purchase_error'); expect(completerError.source, kIAPSource); expect(completerError.message, 'ios_domain'); - expect(completerError.details, - {'message': 'an error message'}); + expect(completerError.details, { + 'message': 'an error message', + }); }); test( - 'should get canceled purchase status when error code is SKErrorPaymentCancelled', - () async { - fakeStoreKitPlatform.testTransactionCancel = 2; - final List details = []; - final Completer completer = Completer(); - - final Stream> stream = - iapStoreKitPlatform.purchaseStream; - late StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - details.addAll(purchaseDetailsList); - for (final PurchaseDetails purchaseDetails in purchaseDetailsList) { - if (purchaseDetails.status == PurchaseStatus.canceled) { - completer.complete(purchaseDetails.status); - subscription.cancel(); + 'should get canceled purchase status when error code is SKErrorPaymentCancelled', + () async { + fakeStoreKitPlatform.testTransactionCancel = 2; + final List details = []; + final Completer completer = Completer(); + + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + late StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + details.addAll(purchaseDetailsList); + for (final PurchaseDetails purchaseDetails in purchaseDetailsList) { + if (purchaseDetails.status == PurchaseStatus.canceled) { + completer.complete(purchaseDetails.status); + subscription.cancel(); + } } - } - }); - final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( - productDetails: - AppStoreProductDetails.fromSKProduct(dummyProductWrapper), - applicationUserName: 'appName'); - await iapStoreKitPlatform.buyNonConsumable(purchaseParam: purchaseParam); + }); + final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( + productDetails: AppStoreProductDetails.fromSKProduct( + dummyProductWrapper, + ), + applicationUserName: 'appName', + ); + await iapStoreKitPlatform.buyNonConsumable( + purchaseParam: purchaseParam, + ); - final PurchaseStatus purchaseStatus = await completer.future; - expect(purchaseStatus, PurchaseStatus.canceled); - }); + final PurchaseStatus purchaseStatus = await completer.future; + expect(purchaseStatus, PurchaseStatus.canceled); + }, + ); test( - 'should get canceled purchase status when error code is SKErrorOverlayCancelled', - () async { - fakeStoreKitPlatform.testTransactionCancel = 15; - final List details = []; - final Completer completer = Completer(); - - final Stream> stream = - iapStoreKitPlatform.purchaseStream; - late StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - details.addAll(purchaseDetailsList); - for (final PurchaseDetails purchaseDetails in purchaseDetailsList) { - if (purchaseDetails.status == PurchaseStatus.canceled) { - completer.complete(purchaseDetails.status); - subscription.cancel(); + 'should get canceled purchase status when error code is SKErrorOverlayCancelled', + () async { + fakeStoreKitPlatform.testTransactionCancel = 15; + final List details = []; + final Completer completer = Completer(); + + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + late StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + details.addAll(purchaseDetailsList); + for (final PurchaseDetails purchaseDetails in purchaseDetailsList) { + if (purchaseDetails.status == PurchaseStatus.canceled) { + completer.complete(purchaseDetails.status); + subscription.cancel(); + } } - } - }); - final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( - productDetails: - AppStoreProductDetails.fromSKProduct(dummyProductWrapper), - applicationUserName: 'appName'); - await iapStoreKitPlatform.buyNonConsumable(purchaseParam: purchaseParam); + }); + final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( + productDetails: AppStoreProductDetails.fromSKProduct( + dummyProductWrapper, + ), + applicationUserName: 'appName', + ); + await iapStoreKitPlatform.buyNonConsumable( + purchaseParam: purchaseParam, + ); - final PurchaseStatus purchaseStatus = await completer.future; - expect(purchaseStatus, PurchaseStatus.canceled); - }); + final PurchaseStatus purchaseStatus = await completer.future; + expect(purchaseStatus, PurchaseStatus.canceled); + }, + ); test( - 'buying non consumable, should be able to purchase multiple quantity of one product', - () async { - final List details = []; - final Completer> completer = - Completer>(); - final Stream> stream = - iapStoreKitPlatform.purchaseStream; - late StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - details.addAll(purchaseDetailsList); - for (final PurchaseDetails purchaseDetails in purchaseDetailsList) { - if (purchaseDetails.pendingCompletePurchase) { - iapStoreKitPlatform.completePurchase(purchaseDetails); - completer.complete(details); - subscription.cancel(); + 'buying non consumable, should be able to purchase multiple quantity of one product', + () async { + final List details = []; + final Completer> completer = + Completer>(); + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + late StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + details.addAll(purchaseDetailsList); + for (final PurchaseDetails purchaseDetails in purchaseDetailsList) { + if (purchaseDetails.pendingCompletePurchase) { + iapStoreKitPlatform.completePurchase(purchaseDetails); + completer.complete(details); + subscription.cancel(); + } } - } - }); - final AppStoreProductDetails productDetails = - AppStoreProductDetails.fromSKProduct(dummyProductWrapper); - final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( + }); + final AppStoreProductDetails productDetails = + AppStoreProductDetails.fromSKProduct(dummyProductWrapper); + final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( productDetails: productDetails, quantity: 5, - applicationUserName: 'appName'); - await iapStoreKitPlatform.buyNonConsumable(purchaseParam: purchaseParam); - await completer.future; - expect( - fakeStoreKitPlatform.finishedTransactions.first.payment.quantity, 5); - }); + applicationUserName: 'appName', + ); + await iapStoreKitPlatform.buyNonConsumable( + purchaseParam: purchaseParam, + ); + await completer.future; + expect( + fakeStoreKitPlatform.finishedTransactions.first.payment.quantity, + 5, + ); + }, + ); test( - 'buying consumable, should be able to purchase multiple quantity of one product', - () async { - final List details = []; - final Completer> completer = - Completer>(); - final Stream> stream = - iapStoreKitPlatform.purchaseStream; - late StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - details.addAll(purchaseDetailsList); - for (final PurchaseDetails purchaseDetails in purchaseDetailsList) { - if (purchaseDetails.pendingCompletePurchase) { - iapStoreKitPlatform.completePurchase(purchaseDetails); - completer.complete(details); - subscription.cancel(); + 'buying consumable, should be able to purchase multiple quantity of one product', + () async { + final List details = []; + final Completer> completer = + Completer>(); + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + late StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + details.addAll(purchaseDetailsList); + for (final PurchaseDetails purchaseDetails in purchaseDetailsList) { + if (purchaseDetails.pendingCompletePurchase) { + iapStoreKitPlatform.completePurchase(purchaseDetails); + completer.complete(details); + subscription.cancel(); + } } - } - }); - final AppStoreProductDetails productDetails = - AppStoreProductDetails.fromSKProduct(dummyProductWrapper); - final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( + }); + final AppStoreProductDetails productDetails = + AppStoreProductDetails.fromSKProduct(dummyProductWrapper); + final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( productDetails: productDetails, quantity: 5, - applicationUserName: 'appName'); - await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); - await completer.future; - expect( - fakeStoreKitPlatform.finishedTransactions.first.payment.quantity, 5); - }); + applicationUserName: 'appName', + ); + await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); + await completer.future; + expect( + fakeStoreKitPlatform.finishedTransactions.first.payment.quantity, + 5, + ); + }, + ); test( - 'buying non consumable with discount, should get purchase objects in the purchase update callback', - () async { - final List details = []; - final Completer> completer = - Completer>(); - final Stream> stream = - iapStoreKitPlatform.purchaseStream; - - late StreamSubscription> subscription; - subscription = stream.listen((List purchaseDetailsList) { - details.addAll(purchaseDetailsList); - if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { - completer.complete(details); - subscription.cancel(); - } - }); - final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( - productDetails: - AppStoreProductDetails.fromSKProduct(dummyProductWrapper), - applicationUserName: 'userWithDiscount', - discount: dummyPaymentDiscountWrapper, - ); - await iapStoreKitPlatform.buyNonConsumable(purchaseParam: purchaseParam); + 'buying non consumable with discount, should get purchase objects in the purchase update callback', + () async { + final List details = []; + final Completer> completer = + Completer>(); + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + + late StreamSubscription> subscription; + subscription = stream.listen(( + List purchaseDetailsList, + ) { + details.addAll(purchaseDetailsList); + if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { + completer.complete(details); + subscription.cancel(); + } + }); + final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( + productDetails: AppStoreProductDetails.fromSKProduct( + dummyProductWrapper, + ), + applicationUserName: 'userWithDiscount', + discount: dummyPaymentDiscountWrapper, + ); + await iapStoreKitPlatform.buyNonConsumable( + purchaseParam: purchaseParam, + ); - final List result = await completer.future; - expect(result.length, 2); - expect(result.first.productID, dummyProductWrapper.productIdentifier); - expect(fakeStoreKitPlatform.discountReceived, - dummyPaymentDiscountWrapper.toMap()); - }); + final List result = await completer.future; + expect(result.length, 2); + expect(result.first.productID, dummyProductWrapper.productIdentifier); + expect( + fakeStoreKitPlatform.discountReceived, + dummyPaymentDiscountWrapper.toMap(), + ); + }, + ); }); group('complete purchase', () { @@ -545,9 +650,11 @@ void main() { } }); final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( - productDetails: - AppStoreProductDetails.fromSKProduct(dummyProductWrapper), - applicationUserName: 'appName'); + productDetails: AppStoreProductDetails.fromSKProduct( + dummyProductWrapper, + ), + applicationUserName: 'appName', + ); await iapStoreKitPlatform.buyNonConsumable(purchaseParam: purchaseParam); final List result = await completer.future; expect(result.length, 2); @@ -561,11 +668,11 @@ void main() { final Stream> stream = iapStoreKitPlatform.purchaseStream; expect(fakeStoreKitPlatform.queueIsActive, false); - final StreamSubscription> subscription1 = - stream.listen((List event) {}); + final StreamSubscription> subscription1 = stream + .listen((List event) {}); expect(fakeStoreKitPlatform.queueIsActive, true); - final StreamSubscription> subscription2 = - stream.listen((List event) {}); + final StreamSubscription> subscription2 = stream + .listen((List event) {}); expect(fakeStoreKitPlatform.queueIsActive, true); subscription1.cancel(); expect(fakeStoreKitPlatform.queueIsActive, true); @@ -578,7 +685,9 @@ void main() { test('country_code', () async { const String expectedCountryCode = 'CA'; fakeStoreKitPlatform.setStoreFrontInfo( - countryCode: expectedCountryCode, identifier: 'ABC'); + countryCode: expectedCountryCode, + identifier: 'ABC', + ); final String countryCode = await iapStoreKitPlatform.countryCode(); expect(countryCode, expectedCountryCode); // Ensure deprecated code keeps working until removed. diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/sk2_test_api.g.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/sk2_test_api.g.dart index 8dd95cfdd3e..9dcb09e41d0 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/sk2_test_api.g.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/sk2_test_api.g.dart @@ -131,8 +131,10 @@ abstract class TestInAppPurchase2Api { Future> products(List identifiers); - Future purchase(String id, - {SK2ProductPurchaseOptionsMessage? options}); + Future purchase( + String id, { + SK2ProductPurchaseOptionsMessage? options, + }); Future isWinBackOfferEligible(String productId, String offerId); @@ -160,355 +162,438 @@ abstract class TestInAppPurchase2Api { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.canMakePayments$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.canMakePayments$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - final bool output = api.canMakePayments(); - return [output]; - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + final bool output = api.canMakePayments(); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.products$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.products$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.products was null.'); - final List args = (message as List?)!; - final List? arg_identifiers = - (args[0] as List?)?.cast(); - assert(arg_identifiers != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.products was null, expected non-null List.'); - try { - final List output = - await api.products(arg_identifiers!); - return [output]; - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.products was null.', + ); + final List args = (message as List?)!; + final List? arg_identifiers = + (args[0] as List?)?.cast(); + assert( + arg_identifiers != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.products was null, expected non-null List.', + ); + try { + final List output = await api.products( + arg_identifiers!, + ); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.purchase$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.purchase$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.purchase was null.'); - final List args = (message as List?)!; - final String? arg_id = (args[0] as String?); - assert(arg_id != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.purchase was null, expected non-null String.'); - final SK2ProductPurchaseOptionsMessage? arg_options = - (args[1] as SK2ProductPurchaseOptionsMessage?); - try { - final SK2ProductPurchaseResultMessage output = - await api.purchase(arg_id!, options: arg_options); - return [output]; - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.purchase was null.', + ); + final List args = (message as List?)!; + final String? arg_id = (args[0] as String?); + assert( + arg_id != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.purchase was null, expected non-null String.', + ); + final SK2ProductPurchaseOptionsMessage? arg_options = + (args[1] as SK2ProductPurchaseOptionsMessage?); + try { + final SK2ProductPurchaseResultMessage output = await api + .purchase(arg_id!, options: arg_options); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isWinBackOfferEligible$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isWinBackOfferEligible$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { - _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isWinBackOfferEligible was null.'); + _testBinaryMessengerBinding!.defaultBinaryMessenger.setMockDecodedMessageHandler< + Object? + >(pigeonVar_channel, (Object? message) async { + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isWinBackOfferEligible was null.', + ); final List args = (message as List?)!; final String? arg_productId = (args[0] as String?); - assert(arg_productId != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isWinBackOfferEligible was null, expected non-null String.'); + assert( + arg_productId != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isWinBackOfferEligible was null, expected non-null String.', + ); final String? arg_offerId = (args[1] as String?); - assert(arg_offerId != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isWinBackOfferEligible was null, expected non-null String.'); + assert( + arg_offerId != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isWinBackOfferEligible was null, expected non-null String.', + ); try { - final bool output = - await api.isWinBackOfferEligible(arg_productId!, arg_offerId!); + final bool output = await api.isWinBackOfferEligible( + arg_productId!, + arg_offerId!, + ); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isIntroductoryOfferEligible$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isIntroductoryOfferEligible$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isIntroductoryOfferEligible was null.'); - final List args = (message as List?)!; - final String? arg_productId = (args[0] as String?); - assert(arg_productId != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isIntroductoryOfferEligible was null, expected non-null String.'); - try { - final bool output = - await api.isIntroductoryOfferEligible(arg_productId!); - return [output]; - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isIntroductoryOfferEligible was null.', + ); + final List args = (message as List?)!; + final String? arg_productId = (args[0] as String?); + assert( + arg_productId != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.isIntroductoryOfferEligible was null, expected non-null String.', + ); + try { + final bool output = await api.isIntroductoryOfferEligible( + arg_productId!, + ); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.transactions$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.transactions$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - final List output = await api.transactions(); - return [output]; - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + final List output = + await api.transactions(); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.finish$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.finish$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.finish was null.'); - final List args = (message as List?)!; - final int? arg_id = (args[0] as int?); - assert(arg_id != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.finish was null, expected non-null int.'); - try { - await api.finish(arg_id!); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.finish was null.', + ); + final List args = (message as List?)!; + final int? arg_id = (args[0] as int?); + assert( + arg_id != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.finish was null, expected non-null int.', + ); + try { + await api.finish(arg_id!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.startListeningToTransactions$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.startListeningToTransactions$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - api.startListeningToTransactions(); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + api.startListeningToTransactions(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.stopListeningToTransactions$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.stopListeningToTransactions$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - api.stopListeningToTransactions(); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + api.stopListeningToTransactions(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.restorePurchases$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.restorePurchases$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - await api.restorePurchases(); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + await api.restorePurchases(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.countryCode$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.countryCode$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - final String output = await api.countryCode(); - return [output]; - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + final String output = await api.countryCode(); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.sync$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchase2API.sync$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - await api.sync(); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + await api.sync(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/pigeon_converter_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/pigeon_converter_test.dart index 5cbdd2f9719..98cec59f1dd 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/pigeon_converter_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/pigeon_converter_test.dart @@ -9,37 +9,46 @@ import 'package:in_app_purchase_storekit/store_kit_wrappers.dart'; void main() { final SKPriceLocaleWrapper locale = SKPriceLocaleWrapper( - currencySymbol: r'$', currencyCode: 'USD', countryCode: 'USA'); + currencySymbol: r'$', + currencyCode: 'USD', + countryCode: 'USA', + ); final SKProductSubscriptionPeriodWrapper subPeriod = SKProductSubscriptionPeriodWrapper( - numberOfUnits: 1, unit: SKSubscriptionPeriodUnit.month); + numberOfUnits: 1, + unit: SKSubscriptionPeriodUnit.month, + ); final SKProductDiscountWrapper discount = SKProductDiscountWrapper( - price: '0.99', - priceLocale: locale, - numberOfPeriods: 1, - paymentMode: SKProductDiscountPaymentMode.payUpFront, - subscriptionPeriod: subPeriod, - identifier: 'discount', - type: SKProductDiscountType.subscription); + price: '0.99', + priceLocale: locale, + numberOfPeriods: 1, + paymentMode: SKProductDiscountPaymentMode.payUpFront, + subscriptionPeriod: subPeriod, + identifier: 'discount', + type: SKProductDiscountType.subscription, + ); final SKProductWrapper product = SKProductWrapper( - productIdentifier: 'fake_product', - localizedTitle: 'title', - localizedDescription: 'description', - priceLocale: locale, - price: '3.99', - subscriptionGroupIdentifier: 'sub_group', - discounts: [discount]); + productIdentifier: 'fake_product', + localizedTitle: 'title', + localizedDescription: 'description', + priceLocale: locale, + price: '3.99', + subscriptionGroupIdentifier: 'sub_group', + discounts: [discount], + ); final SkProductResponseWrapper productResponse = SkProductResponseWrapper( - products: [product], - invalidProductIdentifiers: const ['invalid_identifier']); + products: [product], + invalidProductIdentifiers: const ['invalid_identifier'], + ); test('test SKPriceLocale pigeon converters', () { - final SKPriceLocaleMessage msg = - SKPriceLocaleWrapper.convertToPigeon(locale); + final SKPriceLocaleMessage msg = SKPriceLocaleWrapper.convertToPigeon( + locale, + ); expect(msg.currencySymbol, r'$'); expect(msg.currencyCode, 'USD'); expect(msg.countryCode, 'USA'); @@ -108,13 +117,14 @@ void main() { test('test AppStoreProduct2Details conversion', () { final SK2Product product = SK2Product( - id: '123', - displayName: 'name', - displayPrice: '0.99', - description: 'description', - price: 9.99, - type: SK2ProductType.consumable, - priceLocale: SK2PriceLocale(currencyCode: 'USD', currencySymbol: r'$')); + id: '123', + displayName: 'name', + displayPrice: '0.99', + description: 'description', + price: 9.99, + type: SK2ProductType.consumable, + priceLocale: SK2PriceLocale(currencyCode: 'USD', currencySymbol: r'$'), + ); final AppStoreProduct2Details details = AppStoreProduct2Details.fromSK2Product(product); diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_methodchannel_apis_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_methodchannel_apis_test.dart index 8bd00d7de93..e99895faf4d 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_methodchannel_apis_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_methodchannel_apis_test.dart @@ -30,10 +30,7 @@ void main() { test('get products method channel', () async { final SkProductResponseWrapper productResponseWrapper = await SKRequestMaker().startProductRequest(['xxx']); - expect( - productResponseWrapper.products, - isNotEmpty, - ); + expect(productResponseWrapper.products, isNotEmpty); expect( productResponseWrapper.products.first.priceLocale.currencySymbol, r'$', @@ -51,15 +48,9 @@ void main() { productResponseWrapper.products.first.priceLocale.countryCode, 'US', ); - expect( - productResponseWrapper.invalidProductIdentifiers, - isNotEmpty, - ); + expect(productResponseWrapper.invalidProductIdentifiers, isNotEmpty); - expect( - fakeStoreKitPlatform.startProductRequestParam, - ['xxx'], - ); + expect(fakeStoreKitPlatform.startProductRequestParam, ['xxx']); }); test('get products method channel should throw exception', () async { @@ -74,25 +65,31 @@ void main() { test('refreshed receipt', () async { final int receiptCountBefore = fakeStoreKitPlatform.refreshReceiptCount; await SKRequestMaker().startRefreshReceiptRequest( - receiptProperties: {'isExpired': true}); + receiptProperties: {'isExpired': true}, + ); expect(fakeStoreKitPlatform.refreshReceiptCount, receiptCountBefore + 1); - expect(fakeStoreKitPlatform.refreshReceiptParam, - {'isExpired': true}); + expect(fakeStoreKitPlatform.refreshReceiptParam, { + 'isExpired': true, + }); }); test('should get null receipt if any exceptions are raised', () async { fakeStoreKitPlatform.getReceiptFailTest = true; - expect(() async => SKReceiptManager.retrieveReceiptData(), - throwsA(const TypeMatcher())); + expect( + () async => SKReceiptManager.retrieveReceiptData(), + throwsA(const TypeMatcher()), + ); }); }); group('sk_receipt_manager', () { - test('should get receipt (faking it by returning a `receipt data` string)', - () async { - final String receiptData = await SKReceiptManager.retrieveReceiptData(); - expect(receiptData, 'receipt data'); - }); + test( + 'should get receipt (faking it by returning a `receipt data` string)', + () async { + final String receiptData = await SKReceiptManager.retrieveReceiptData(); + expect(receiptData, 'receipt data'); + }, + ); }); group('sk_payment_queue', () { @@ -103,11 +100,12 @@ void main() { test('storefront returns valid SKStoreFrontWrapper object', () async { final SKPaymentQueueWrapper queue = SKPaymentQueueWrapper(); expect( - await queue.storefront(), - SKStorefrontWrapper.fromJson(const { - 'countryCode': 'USA', - 'identifier': 'unique_identifier', - })); + await queue.storefront(), + SKStorefrontWrapper.fromJson(const { + 'countryCode': 'USA', + 'identifier': 'unique_identifier', + }), + ); }); test('transactions should return a valid list of transactions', () async { @@ -115,11 +113,14 @@ void main() { }); test( - 'throws if observer is not set for payment queue before adding payment', - () async { - expect(SKPaymentQueueWrapper().addPayment(dummyPayment), - throwsAssertionError); - }); + 'throws if observer is not set for payment queue before adding payment', + () async { + expect( + SKPaymentQueueWrapper().addPayment(dummyPayment), + throwsAssertionError, + ); + }, + ); test('should add payment to the payment queue', () async { final SKPaymentQueueWrapper queue = SKPaymentQueueWrapper(); @@ -136,8 +137,10 @@ void main() { TestPaymentTransactionObserver(); queue.setTransactionObserver(observer); await queue.finishTransaction(dummyTransaction); - expect(fakeStoreKitPlatform.transactionsFinished.first, - equals(dummyTransaction.toFinishMap())); + expect( + fakeStoreKitPlatform.transactionsFinished.first, + equals(dummyTransaction.toFinishMap()), + ); }); test('should restore transaction', () async { @@ -146,8 +149,10 @@ void main() { TestPaymentTransactionObserver(); queue.setTransactionObserver(observer); await queue.restoreTransactions(applicationUserName: 'aUserID'); - expect(fakeStoreKitPlatform.applicationNameHasTransactionRestored, - 'aUserID'); + expect( + fakeStoreKitPlatform.applicationNameHasTransactionRestored, + 'aUserID', + ); }); test('startObservingTransactionQueue should call methodChannel', () async { @@ -219,8 +224,9 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { @override void addPayment(Map paymentMap) { - payments - .add(SKPaymentWrapper.fromJson(Map.from(paymentMap))); + payments.add( + SKPaymentWrapper.fromJson(Map.from(paymentMap)), + ); } @override @@ -231,7 +237,9 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { @override SKStorefrontMessage storefront() { return SKStorefrontMessage( - countryCode: 'USA', identifier: 'unique_identifier'); + countryCode: 'USA', + identifier: 'unique_identifier', + ); } @override @@ -255,11 +263,13 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { @override Future startProductRequest( - List productIdentifiers) { + List productIdentifiers, + ) { startProductRequestParam = productIdentifiers; if (getProductRequestFailTest) { return Future.value( - SKProductsResponseMessage()); + SKProductsResponseMessage(), + ); } return Future.value(dummyProductResponseMessage); } @@ -295,8 +305,9 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi { @override Future refreshReceipt({Map? receiptProperties}) { refreshReceiptCount++; - refreshReceiptParam = - Map.castFrom(receiptProperties!); + refreshReceiptParam = Map.castFrom( + receiptProperties!, + ); return Future.sync(() {}); } @@ -315,12 +326,14 @@ class TestPaymentQueueDelegate extends SKPaymentQueueDelegateWrapper {} class TestPaymentTransactionObserver extends SKTransactionObserverWrapper { @override - void updatedTransactions( - {required List transactions}) {} + void updatedTransactions({ + required List transactions, + }) {} @override - void removedTransactions( - {required List transactions}) {} + void removedTransactions({ + required List transactions, + }) {} @override void restoreCompletedTransactionsFailed({required SKError error}) {} @@ -329,8 +342,10 @@ class TestPaymentTransactionObserver extends SKTransactionObserverWrapper { void paymentQueueRestoreCompletedTransactionsFinished() {} @override - bool shouldAddStorePayment( - {required SKPaymentWrapper payment, required SKProductWrapper product}) { + bool shouldAddStorePayment({ + required SKPaymentWrapper payment, + required SKProductWrapper product, + }) { return true; } } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_payment_queue_delegate_api_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_payment_queue_delegate_api_test.dart index f9efd427bfc..ba40c270a6a 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_payment_queue_delegate_api_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_payment_queue_delegate_api_test.dart @@ -19,96 +19,90 @@ void main() { }); test( - 'handlePaymentQueueDelegateCallbacks should call SKPaymentQueueDelegateWrapper.shouldContinueTransaction', - () async { - final SKPaymentQueueWrapper queue = SKPaymentQueueWrapper(); - final TestPaymentQueueDelegate testDelegate = TestPaymentQueueDelegate(); - await queue.setDelegate(testDelegate); - - final Map arguments = { - 'storefront': { - 'countryCode': 'USA', - 'identifier': 'unique_identifier', - }, - 'transaction': { - 'payment': { - 'productIdentifier': 'product_identifier', - } - }, - }; - - final Object? result = await queue.handlePaymentQueueDelegateCallbacks( - MethodCall('shouldContinueTransaction', arguments), - ); - - expect(result, false); - expect( - testDelegate.log, - { - equals('shouldContinueTransaction'), - }, - ); - }); + 'handlePaymentQueueDelegateCallbacks should call SKPaymentQueueDelegateWrapper.shouldContinueTransaction', + () async { + final SKPaymentQueueWrapper queue = SKPaymentQueueWrapper(); + final TestPaymentQueueDelegate testDelegate = TestPaymentQueueDelegate(); + await queue.setDelegate(testDelegate); + + final Map arguments = { + 'storefront': { + 'countryCode': 'USA', + 'identifier': 'unique_identifier', + }, + 'transaction': { + 'payment': { + 'productIdentifier': 'product_identifier', + }, + }, + }; + + final Object? result = await queue.handlePaymentQueueDelegateCallbacks( + MethodCall('shouldContinueTransaction', arguments), + ); + + expect(result, false); + expect(testDelegate.log, {equals('shouldContinueTransaction')}); + }, + ); test( - 'handlePaymentQueueDelegateCallbacks should call SKPaymentQueueDelegateWrapper.shouldShowPriceConsent', - () async { - final SKPaymentQueueWrapper queue = SKPaymentQueueWrapper(); - final TestPaymentQueueDelegate testDelegate = TestPaymentQueueDelegate(); - await queue.setDelegate(testDelegate); - - final bool result = (await queue.handlePaymentQueueDelegateCallbacks( - const MethodCall('shouldShowPriceConsent'), - ))! as bool; - - expect(result, false); - expect( - testDelegate.log, - { - equals('shouldShowPriceConsent'), - }, - ); - }); + 'handlePaymentQueueDelegateCallbacks should call SKPaymentQueueDelegateWrapper.shouldShowPriceConsent', + () async { + final SKPaymentQueueWrapper queue = SKPaymentQueueWrapper(); + final TestPaymentQueueDelegate testDelegate = TestPaymentQueueDelegate(); + await queue.setDelegate(testDelegate); + + final bool result = + (await queue.handlePaymentQueueDelegateCallbacks( + const MethodCall('shouldShowPriceConsent'), + ))! + as bool; + + expect(result, false); + expect(testDelegate.log, {equals('shouldShowPriceConsent')}); + }, + ); test( - 'handleObserverCallbacks should call SKTransactionObserverWrapper.restoreCompletedTransactionsFailed', - () async { - final SKPaymentQueueWrapper queue = SKPaymentQueueWrapper(); - final TestTransactionObserverWrapper testObserver = - TestTransactionObserverWrapper(); - queue.setTransactionObserver(testObserver); - - final Map arguments = { - 'code': 100, - 'domain': 'domain', - 'userInfo': {'error': 'underlying_error'}, - }; - - await queue.handleObserverCallbacks( - MethodCall('restoreCompletedTransactionsFailed', arguments), - ); - - expect( - testObserver.log, - { + 'handleObserverCallbacks should call SKTransactionObserverWrapper.restoreCompletedTransactionsFailed', + () async { + final SKPaymentQueueWrapper queue = SKPaymentQueueWrapper(); + final TestTransactionObserverWrapper testObserver = + TestTransactionObserverWrapper(); + queue.setTransactionObserver(testObserver); + + final Map arguments = { + 'code': 100, + 'domain': 'domain', + 'userInfo': {'error': 'underlying_error'}, + }; + + await queue.handleObserverCallbacks( + MethodCall('restoreCompletedTransactionsFailed', arguments), + ); + + expect(testObserver.log, { equals('restoreCompletedTransactionsFailed'), - }, - ); - }); + }); + }, + ); } class TestTransactionObserverWrapper extends SKTransactionObserverWrapper { final List log = []; @override - void updatedTransactions( - {required List transactions}) { + void updatedTransactions({ + required List transactions, + }) { log.add('updatedTransactions'); } @override - void removedTransactions( - {required List transactions}) { + void removedTransactions({ + required List transactions, + }) { log.add('removedTransactions'); } @@ -123,8 +117,10 @@ class TestTransactionObserverWrapper extends SKTransactionObserverWrapper { } @override - bool shouldAddStorePayment( - {required SKPaymentWrapper payment, required SKProductWrapper product}) { + bool shouldAddStorePayment({ + required SKPaymentWrapper payment, + required SKProductWrapper product, + }) { log.add('shouldAddStorePayment'); return false; } @@ -135,7 +131,9 @@ class TestPaymentQueueDelegate extends SKPaymentQueueDelegateWrapper { @override bool shouldContinueTransaction( - SKPaymentTransactionWrapper transaction, SKStorefrontWrapper storefront) { + SKPaymentTransactionWrapper transaction, + SKStorefrontWrapper storefront, + ) { log.add('shouldContinueTransaction'); return false; } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_product_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_product_test.dart index b6de5e035c5..020203be402 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_product_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_product_test.dart @@ -12,94 +12,112 @@ import 'sk_test_stub_objects.dart'; void main() { group('product related object wrapper test', () { test( - 'SKProductSubscriptionPeriodWrapper should have property values consistent with map', - () { - final SKProductSubscriptionPeriodWrapper wrapper = - SKProductSubscriptionPeriodWrapper.fromJson( - buildSubscriptionPeriodMap(dummySubscription)); - expect(wrapper, equals(dummySubscription)); - }); + 'SKProductSubscriptionPeriodWrapper should have property values consistent with map', + () { + final SKProductSubscriptionPeriodWrapper wrapper = + SKProductSubscriptionPeriodWrapper.fromJson( + buildSubscriptionPeriodMap(dummySubscription), + ); + expect(wrapper, equals(dummySubscription)); + }, + ); test( - 'SKProductSubscriptionPeriodWrapper should have properties to be default values if map is empty', - () { - final SKProductSubscriptionPeriodWrapper wrapper = - SKProductSubscriptionPeriodWrapper.fromJson( - const {}); - expect(wrapper.numberOfUnits, 0); - expect(wrapper.unit, SKSubscriptionPeriodUnit.day); - }); + 'SKProductSubscriptionPeriodWrapper should have properties to be default values if map is empty', + () { + final SKProductSubscriptionPeriodWrapper wrapper = + SKProductSubscriptionPeriodWrapper.fromJson( + const {}, + ); + expect(wrapper.numberOfUnits, 0); + expect(wrapper.unit, SKSubscriptionPeriodUnit.day); + }, + ); test( - 'SKProductDiscountWrapper should have property values consistent with map', - () { - final SKProductDiscountWrapper wrapper = - SKProductDiscountWrapper.fromJson(buildDiscountMap(dummyDiscount)); - expect(wrapper, equals(dummyDiscount)); - }); + 'SKProductDiscountWrapper should have property values consistent with map', + () { + final SKProductDiscountWrapper wrapper = + SKProductDiscountWrapper.fromJson(buildDiscountMap(dummyDiscount)); + expect(wrapper, equals(dummyDiscount)); + }, + ); - test( - 'SKProductDiscountWrapper missing identifier and type should have ' + test('SKProductDiscountWrapper missing identifier and type should have ' 'property values consistent with map', () { final SKProductDiscountWrapper wrapper = SKProductDiscountWrapper.fromJson( - buildDiscountMapMissingIdentifierAndType( - dummyDiscountMissingIdentifierAndType)); + buildDiscountMapMissingIdentifierAndType( + dummyDiscountMissingIdentifierAndType, + ), + ); expect(wrapper, equals(dummyDiscountMissingIdentifierAndType)); }); test( - 'SKProductDiscountWrapper should have properties to be default if map is empty', - () { - final SKProductDiscountWrapper wrapper = - SKProductDiscountWrapper.fromJson(const {}); - expect(wrapper.price, ''); - expect( + 'SKProductDiscountWrapper should have properties to be default if map is empty', + () { + final SKProductDiscountWrapper wrapper = + SKProductDiscountWrapper.fromJson(const {}); + expect(wrapper.price, ''); + expect( wrapper.priceLocale, SKPriceLocaleWrapper( currencyCode: '', currencySymbol: '', countryCode: '', - )); - expect(wrapper.numberOfPeriods, 0); - expect(wrapper.paymentMode, SKProductDiscountPaymentMode.payAsYouGo); - expect( + ), + ); + expect(wrapper.numberOfPeriods, 0); + expect(wrapper.paymentMode, SKProductDiscountPaymentMode.payAsYouGo); + expect( wrapper.subscriptionPeriod, SKProductSubscriptionPeriodWrapper( - numberOfUnits: 0, unit: SKSubscriptionPeriodUnit.day)); - }); + numberOfUnits: 0, + unit: SKSubscriptionPeriodUnit.day, + ), + ); + }, + ); - test('SKProductWrapper should have property values consistent with map', - () { - final SKProductWrapper wrapper = - SKProductWrapper.fromJson(buildProductMap(dummyProductWrapper)); - expect(wrapper, equals(dummyProductWrapper)); - }); + test( + 'SKProductWrapper should have property values consistent with map', + () { + final SKProductWrapper wrapper = SKProductWrapper.fromJson( + buildProductMap(dummyProductWrapper), + ); + expect(wrapper, equals(dummyProductWrapper)); + }, + ); test( - 'SKProductWrapper should have properties to be default if map is empty', - () { - final SKProductWrapper wrapper = - SKProductWrapper.fromJson(const {}); - expect(wrapper.productIdentifier, ''); - expect(wrapper.localizedTitle, ''); - expect(wrapper.localizedDescription, ''); - expect( + 'SKProductWrapper should have properties to be default if map is empty', + () { + final SKProductWrapper wrapper = SKProductWrapper.fromJson( + const {}, + ); + expect(wrapper.productIdentifier, ''); + expect(wrapper.localizedTitle, ''); + expect(wrapper.localizedDescription, ''); + expect( wrapper.priceLocale, SKPriceLocaleWrapper( currencyCode: '', currencySymbol: '', countryCode: '', - )); - expect(wrapper.subscriptionGroupIdentifier, null); - expect(wrapper.price, ''); - expect(wrapper.subscriptionPeriod, null); - expect(wrapper.discounts, []); - }); + ), + ); + expect(wrapper.subscriptionGroupIdentifier, null); + expect(wrapper.price, ''); + expect(wrapper.subscriptionPeriod, null); + expect(wrapper.discounts, []); + }, + ); test('toProductDetails() should return correct Product object', () { - final SKProductWrapper wrapper = - SKProductWrapper.fromJson(buildProductMap(dummyProductWrapper)); + final SKProductWrapper wrapper = SKProductWrapper.fromJson( + buildProductMap(dummyProductWrapper), + ); final AppStoreProductDetails product = AppStoreProductDetails.fromSKProduct(wrapper); expect(product.title, wrapper.localizedTitle); @@ -112,15 +130,16 @@ void main() { test('SKProductResponse wrapper should match', () { final SkProductResponseWrapper wrapper = SkProductResponseWrapper.fromJson( - buildProductResponseMap(dummyProductResponseWrapper)); + buildProductResponseMap(dummyProductResponseWrapper), + ); expect(wrapper, equals(dummyProductResponseWrapper)); }); test('SKProductResponse wrapper should default to empty list', () { final Map> productResponseMapEmptyList = >{ - 'products': >[], - 'invalidProductIdentifiers': [], - }; + 'products': >[], + 'invalidProductIdentifiers': [], + }; final SkProductResponseWrapper wrapper = SkProductResponseWrapper.fromJson(productResponseMapEmptyList); expect(wrapper.products.length, 0); @@ -128,33 +147,45 @@ void main() { }); test('LocaleWrapper should have property values consistent with map', () { - final SKPriceLocaleWrapper wrapper = - SKPriceLocaleWrapper.fromJson(buildLocaleMap(dollarLocale)); + final SKPriceLocaleWrapper wrapper = SKPriceLocaleWrapper.fromJson( + buildLocaleMap(dollarLocale), + ); expect(wrapper, equals(dollarLocale)); }); }); group('Payment queue related object tests', () { test('Should construct correct SKPaymentWrapper from json', () { - final SKPaymentWrapper payment = - SKPaymentWrapper.fromJson(dummyPayment.toMap()); + final SKPaymentWrapper payment = SKPaymentWrapper.fromJson( + dummyPayment.toMap(), + ); expect(payment, equals(dummyPayment)); }); - test('SKPaymentWrapper should have propery values consistent with .toMap()', - () { - final Map mapResult = dummyPaymentWithDiscount.toMap(); - expect(mapResult['productIdentifier'], - dummyPaymentWithDiscount.productIdentifier); - expect(mapResult['applicationUsername'], - dummyPaymentWithDiscount.applicationUsername); - expect(mapResult['requestData'], dummyPaymentWithDiscount.requestData); - expect(mapResult['quantity'], dummyPaymentWithDiscount.quantity); - expect(mapResult['simulatesAskToBuyInSandbox'], - dummyPaymentWithDiscount.simulatesAskToBuyInSandbox); - expect(mapResult['paymentDiscount'], - equals(dummyPaymentWithDiscount.paymentDiscount?.toMap())); - }); + test( + 'SKPaymentWrapper should have propery values consistent with .toMap()', + () { + final Map mapResult = dummyPaymentWithDiscount.toMap(); + expect( + mapResult['productIdentifier'], + dummyPaymentWithDiscount.productIdentifier, + ); + expect( + mapResult['applicationUsername'], + dummyPaymentWithDiscount.applicationUsername, + ); + expect(mapResult['requestData'], dummyPaymentWithDiscount.requestData); + expect(mapResult['quantity'], dummyPaymentWithDiscount.quantity); + expect( + mapResult['simulatesAskToBuyInSandbox'], + dummyPaymentWithDiscount.simulatesAskToBuyInSandbox, + ); + expect( + mapResult['paymentDiscount'], + equals(dummyPaymentWithDiscount.paymentDiscount?.toMap()), + ); + }, + ); test('Should construct correct SKError from json', () { final SKError error = SKError.fromJson(buildErrorMap(dummyError)); @@ -164,19 +195,24 @@ void main() { test('Should construct correct SKTransactionWrapper from json', () { final SKPaymentTransactionWrapper transaction = SKPaymentTransactionWrapper.fromJson( - buildTransactionMap(dummyTransaction)); + buildTransactionMap(dummyTransaction), + ); expect(transaction, equals(dummyTransaction)); }); test('toPurchaseDetails() should return correct PurchaseDetail object', () { final AppStorePurchaseDetails details = AppStorePurchaseDetails.fromSKTransaction( - dummyTransaction, 'receipt data'); + dummyTransaction, + 'receipt data', + ); expect(dummyTransaction.transactionIdentifier, details.purchaseID); expect(dummyTransaction.payment.productIdentifier, details.productID); expect(dummyTransaction.transactionTimeStamp, isNotNull); - expect((dummyTransaction.transactionTimeStamp! * 1000).toInt().toString(), - details.transactionDate); + expect( + (dummyTransaction.transactionTimeStamp! * 1000).toInt().toString(), + details.transactionDate, + ); expect(details.verificationData.localVerificationData, 'receipt data'); expect(details.verificationData.serverVerificationData, 'receipt data'); expect(details.verificationData.source, 'app_store'); @@ -187,24 +223,27 @@ void main() { test('SKPaymentTransactionWrapper.toFinishMap set correct value', () { final SKPaymentTransactionWrapper transactionWrapper = SKPaymentTransactionWrapper( - payment: dummyPayment, - transactionState: SKPaymentTransactionStateWrapper.failed, - transactionIdentifier: 'abcd'); + payment: dummyPayment, + transactionState: SKPaymentTransactionStateWrapper.failed, + transactionIdentifier: 'abcd', + ); final Map finishMap = transactionWrapper.toFinishMap(); expect(finishMap['transactionIdentifier'], 'abcd'); expect(finishMap['productIdentifier'], dummyPayment.productIdentifier); }); test( - 'SKPaymentTransactionWrapper.toFinishMap should set transactionIdentifier to null when necessary', - () { - final SKPaymentTransactionWrapper transactionWrapper = - SKPaymentTransactionWrapper( + 'SKPaymentTransactionWrapper.toFinishMap should set transactionIdentifier to null when necessary', + () { + final SKPaymentTransactionWrapper transactionWrapper = + SKPaymentTransactionWrapper( payment: dummyPayment, - transactionState: SKPaymentTransactionStateWrapper.failed); - final Map finishMap = transactionWrapper.toFinishMap(); - expect(finishMap['transactionIdentifier'], null); - }); + transactionState: SKPaymentTransactionStateWrapper.failed, + ); + final Map finishMap = transactionWrapper.toFinishMap(); + expect(finishMap['transactionIdentifier'], null); + }, + ); test('Should generate correct map of the payment object', () { final Map map = dummyPayment.toMap(); @@ -215,8 +254,10 @@ void main() { expect(map['quantity'], dummyPayment.quantity); - expect(map['simulatesAskToBuyInSandbox'], - dummyPayment.simulatesAskToBuyInSandbox); + expect( + map['simulatesAskToBuyInSandbox'], + dummyPayment.simulatesAskToBuyInSandbox, + ); }); }); } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_test_stub_objects.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_test_stub_objects.dart index 59022aa2fd2..cc9d43e87c8 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_test_stub_objects.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/store_kit_wrappers/sk_test_stub_objects.dart @@ -6,55 +6,60 @@ import 'package:in_app_purchase_storekit/src/messages.g.dart'; import 'package:in_app_purchase_storekit/store_kit_wrappers.dart'; const SKPaymentWrapper dummyPayment = SKPaymentWrapper( - productIdentifier: 'prod-id', - applicationUsername: 'app-user-name', - requestData: 'fake-data-utf8', - quantity: 2, - simulatesAskToBuyInSandbox: true); + productIdentifier: 'prod-id', + applicationUsername: 'app-user-name', + requestData: 'fake-data-utf8', + quantity: 2, + simulatesAskToBuyInSandbox: true, +); SKPaymentMessage dummyPaymentMessage = SKPaymentMessage( - productIdentifier: 'prod-id', - applicationUsername: 'app-user-name', - requestData: 'fake-data-utf8', - quantity: 2, - simulatesAskToBuyInSandbox: true); + productIdentifier: 'prod-id', + applicationUsername: 'app-user-name', + requestData: 'fake-data-utf8', + quantity: 2, + simulatesAskToBuyInSandbox: true, +); final SKPaymentWrapper dummyPaymentWithDiscount = SKPaymentWrapper( - productIdentifier: 'prod-id', - applicationUsername: 'app-user-name', - requestData: 'fake-data-utf8', - quantity: 2, - simulatesAskToBuyInSandbox: true, - paymentDiscount: dummyPaymentDiscountWrapper); + productIdentifier: 'prod-id', + applicationUsername: 'app-user-name', + requestData: 'fake-data-utf8', + quantity: 2, + simulatesAskToBuyInSandbox: true, + paymentDiscount: dummyPaymentDiscountWrapper, +); const SKError dummyError = SKError( - code: 111, - domain: 'dummy-domain', - userInfo: {'key': 'value'}); + code: 111, + domain: 'dummy-domain', + userInfo: {'key': 'value'}, +); final SKPaymentTransactionWrapper dummyOriginalTransaction = SKPaymentTransactionWrapper( - transactionState: SKPaymentTransactionStateWrapper.purchased, - payment: dummyPayment, - transactionTimeStamp: 1231231231.00, - transactionIdentifier: '123123', - error: dummyError, -); + transactionState: SKPaymentTransactionStateWrapper.purchased, + payment: dummyPayment, + transactionTimeStamp: 1231231231.00, + transactionIdentifier: '123123', + error: dummyError, + ); final SKPaymentTransactionWrapper dummyTransaction = SKPaymentTransactionWrapper( - transactionState: SKPaymentTransactionStateWrapper.purchased, - payment: dummyPayment, - originalTransaction: dummyOriginalTransaction, - transactionTimeStamp: 1231231231.00, - transactionIdentifier: '123123', - error: dummyError, -); + transactionState: SKPaymentTransactionStateWrapper.purchased, + payment: dummyPayment, + originalTransaction: dummyOriginalTransaction, + transactionTimeStamp: 1231231231.00, + transactionIdentifier: '123123', + error: dummyError, + ); final SKPaymentTransactionMessage dummyTransactionMessage = SKPaymentTransactionMessage( - payment: dummyPaymentMessage, - transactionState: SKPaymentTransactionStateMessage.purchased); + payment: dummyPaymentMessage, + transactionState: SKPaymentTransactionStateMessage.purchased, + ); final SKPriceLocaleWrapper dollarLocale = SKPriceLocaleWrapper( currencySymbol: r'$', @@ -76,15 +81,15 @@ final SKPriceLocaleWrapper noSymbolLocale = SKPriceLocaleWrapper( final SKProductSubscriptionPeriodWrapper dummySubscription = SKProductSubscriptionPeriodWrapper( - numberOfUnits: 1, - unit: SKSubscriptionPeriodUnit.month, -); + numberOfUnits: 1, + unit: SKSubscriptionPeriodUnit.month, + ); final SKProductSubscriptionPeriodMessage dummySubscriptionMessage = SKProductSubscriptionPeriodMessage( - numberOfUnits: 1, - unit: SKSubscriptionPeriodUnitMessage.month, -); + numberOfUnits: 1, + unit: SKSubscriptionPeriodUnitMessage.month, + ); final SKProductDiscountWrapper dummyDiscount = SKProductDiscountWrapper( price: '1.0', @@ -108,14 +113,14 @@ final SKProductDiscountMessage dummyDiscountMessage = SKProductDiscountMessage( final SKProductDiscountWrapper dummyDiscountMissingIdentifierAndType = SKProductDiscountWrapper( - price: '1.0', - priceLocale: dollarLocale, - numberOfPeriods: 1, - paymentMode: SKProductDiscountPaymentMode.payUpFront, - subscriptionPeriod: dummySubscription, - identifier: null, - type: SKProductDiscountType.introductory, -); + price: '1.0', + priceLocale: dollarLocale, + numberOfPeriods: 1, + paymentMode: SKProductDiscountPaymentMode.payUpFront, + subscriptionPeriod: dummySubscription, + identifier: null, + type: SKProductDiscountType.introductory, + ); final SKProductWrapper dummyProductWrapper = SKProductWrapper( productIdentifier: 'id', @@ -143,15 +148,15 @@ final SKProductMessage dummyProductMessage = SKProductMessage( final SkProductResponseWrapper dummyProductResponseWrapper = SkProductResponseWrapper( - products: [dummyProductWrapper], - invalidProductIdentifiers: const ['123'], -); + products: [dummyProductWrapper], + invalidProductIdentifiers: const ['123'], + ); final SKProductsResponseMessage dummyProductResponseMessage = SKProductsResponseMessage( - products: [dummyProductMessage], - invalidProductIdentifiers: const ['123'], -); + products: [dummyProductMessage], + invalidProductIdentifiers: const ['123'], + ); Map buildLocaleMap(SKPriceLocaleWrapper local) { return { @@ -162,7 +167,8 @@ Map buildLocaleMap(SKPriceLocaleWrapper local) { } Map? buildSubscriptionPeriodMap( - SKProductSubscriptionPeriodWrapper? sub) { + SKProductSubscriptionPeriodWrapper? sub, +) { if (sub == null) { return null; } @@ -177,25 +183,30 @@ Map buildDiscountMap(SKProductDiscountWrapper discount) { 'price': discount.price, 'priceLocale': buildLocaleMap(discount.priceLocale), 'numberOfPeriods': discount.numberOfPeriods, - 'paymentMode': - SKProductDiscountPaymentMode.values.indexOf(discount.paymentMode), - 'subscriptionPeriod': - buildSubscriptionPeriodMap(discount.subscriptionPeriod), + 'paymentMode': SKProductDiscountPaymentMode.values.indexOf( + discount.paymentMode, + ), + 'subscriptionPeriod': buildSubscriptionPeriodMap( + discount.subscriptionPeriod, + ), 'identifier': discount.identifier, - 'type': SKProductDiscountType.values.indexOf(discount.type) + 'type': SKProductDiscountType.values.indexOf(discount.type), }; } Map buildDiscountMapMissingIdentifierAndType( - SKProductDiscountWrapper discount) { + SKProductDiscountWrapper discount, +) { return { 'price': discount.price, 'priceLocale': buildLocaleMap(discount.priceLocale), 'numberOfPeriods': discount.numberOfPeriods, - 'paymentMode': - SKProductDiscountPaymentMode.values.indexOf(discount.paymentMode), - 'subscriptionPeriod': - buildSubscriptionPeriodMap(discount.subscriptionPeriod) + 'paymentMode': SKProductDiscountPaymentMode.values.indexOf( + discount.paymentMode, + ), + 'subscriptionPeriod': buildSubscriptionPeriodMap( + discount.subscriptionPeriod, + ), }; } @@ -207,21 +218,24 @@ Map buildProductMap(SKProductWrapper product) { 'priceLocale': buildLocaleMap(product.priceLocale), 'subscriptionGroupIdentifier': product.subscriptionGroupIdentifier, 'price': product.price, - 'subscriptionPeriod': - buildSubscriptionPeriodMap(product.subscriptionPeriod), + 'subscriptionPeriod': buildSubscriptionPeriodMap( + product.subscriptionPeriod, + ), 'introductoryPrice': buildDiscountMap(product.introductoryPrice!), 'discounts': [buildDiscountMap(product.introductoryPrice!)], }; } Map buildProductResponseMap( - SkProductResponseWrapper response) { - final List productsMap = response.products - .map((SKProductWrapper product) => buildProductMap(product)) - .toList(); + SkProductResponseWrapper response, +) { + final List productsMap = + response.products + .map((SKProductWrapper product) => buildProductMap(product)) + .toList(); return { 'products': productsMap, - 'invalidProductIdentifiers': response.invalidProductIdentifiers + 'invalidProductIdentifiers': response.invalidProductIdentifiers, }; } @@ -234,14 +248,17 @@ Map buildErrorMap(SKError error) { } Map buildTransactionMap( - SKPaymentTransactionWrapper transaction) { + SKPaymentTransactionWrapper transaction, +) { final Map map = { - 'transactionState': SKPaymentTransactionStateWrapper.values - .indexOf(SKPaymentTransactionStateWrapper.purchased), + 'transactionState': SKPaymentTransactionStateWrapper.values.indexOf( + SKPaymentTransactionStateWrapper.purchased, + ), 'payment': transaction.payment.toMap(), - 'originalTransaction': transaction.originalTransaction == null - ? null - : buildTransactionMap(transaction.originalTransaction!), + 'originalTransaction': + transaction.originalTransaction == null + ? null + : buildTransactionMap(transaction.originalTransaction!), 'transactionTimeStamp': transaction.transactionTimeStamp, 'transactionIdentifier': transaction.transactionIdentifier, 'error': buildErrorMap(transaction.error!), @@ -250,14 +267,17 @@ Map buildTransactionMap( } Map buildTransactionMessage( - SKPaymentTransactionWrapper transaction) { + SKPaymentTransactionWrapper transaction, +) { final Map map = { - 'transactionState': SKPaymentTransactionStateWrapper.values - .indexOf(SKPaymentTransactionStateWrapper.purchased), + 'transactionState': SKPaymentTransactionStateWrapper.values.indexOf( + SKPaymentTransactionStateWrapper.purchased, + ), 'payment': transaction.payment.toMap(), - 'originalTransaction': transaction.originalTransaction == null - ? null - : buildTransactionMap(transaction.originalTransaction!), + 'originalTransaction': + transaction.originalTransaction == null + ? null + : buildTransactionMap(transaction.originalTransaction!), 'transactionTimeStamp': transaction.transactionTimeStamp, 'transactionIdentifier': transaction.transactionIdentifier, 'error': buildErrorMap(transaction.error!), @@ -267,9 +287,9 @@ Map buildTransactionMessage( final SKPaymentDiscountWrapper dummyPaymentDiscountWrapper = SKPaymentDiscountWrapper.fromJson(const { - 'identifier': 'dummy-discount-identifier', - 'keyIdentifier': 'KEYIDTEST1', - 'nonce': '00000000-0000-0000-0000-000000000000', - 'signature': 'dummy-signature-string', - 'timestamp': 1231231231, -}); + 'identifier': 'dummy-discount-identifier', + 'keyIdentifier': 'KEYIDTEST1', + 'nonce': '00000000-0000-0000-0000-000000000000', + 'signature': 'dummy-signature-string', + 'timestamp': 1231231231, + }); diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/test_api.g.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/test_api.g.dart index 9b3ea2a14d6..4dced3a963d 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/test_api.g.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/test_api.g.dart @@ -131,7 +131,8 @@ abstract class TestInAppPurchaseApi { void addPayment(Map paymentMap); Future startProductRequest( - List productIdentifiers); + List productIdentifiers, + ); void finishTransaction(Map finishMap); @@ -163,450 +164,549 @@ abstract class TestInAppPurchaseApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.canMakePayments$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.canMakePayments$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - final bool output = api.canMakePayments(); - return [output]; - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + final bool output = api.canMakePayments(); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.transactions$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.transactions$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - final List output = api.transactions(); - return [output]; - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + final List output = + api.transactions(); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.storefront$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.storefront$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - final SKStorefrontMessage output = api.storefront(); - return [output]; - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + final SKStorefrontMessage output = api.storefront(); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.addPayment$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.addPayment$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.addPayment was null.'); - final List args = (message as List?)!; - final Map? arg_paymentMap = - (args[0] as Map?)?.cast(); - assert(arg_paymentMap != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.addPayment was null, expected non-null Map.'); - try { - api.addPayment(arg_paymentMap!); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.addPayment was null.', + ); + final List args = (message as List?)!; + final Map? arg_paymentMap = + (args[0] as Map?)?.cast(); + assert( + arg_paymentMap != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.addPayment was null, expected non-null Map.', + ); + try { + api.addPayment(arg_paymentMap!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.startProductRequest$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.startProductRequest$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.startProductRequest was null.'); - final List args = (message as List?)!; - final List? arg_productIdentifiers = - (args[0] as List?)?.cast(); - assert(arg_productIdentifiers != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.startProductRequest was null, expected non-null List.'); - try { - final SKProductsResponseMessage output = - await api.startProductRequest(arg_productIdentifiers!); - return [output]; - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.startProductRequest was null.', + ); + final List args = (message as List?)!; + final List? arg_productIdentifiers = + (args[0] as List?)?.cast(); + assert( + arg_productIdentifiers != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.startProductRequest was null, expected non-null List.', + ); + try { + final SKProductsResponseMessage output = await api + .startProductRequest(arg_productIdentifiers!); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.finishTransaction$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.finishTransaction$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.finishTransaction was null.'); - final List args = (message as List?)!; - final Map? arg_finishMap = - (args[0] as Map?)?.cast(); - assert(arg_finishMap != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.finishTransaction was null, expected non-null Map.'); - try { - api.finishTransaction(arg_finishMap!); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.finishTransaction was null.', + ); + final List args = (message as List?)!; + final Map? arg_finishMap = + (args[0] as Map?)?.cast(); + assert( + arg_finishMap != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.finishTransaction was null, expected non-null Map.', + ); + try { + api.finishTransaction(arg_finishMap!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.restoreTransactions$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.restoreTransactions$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.restoreTransactions was null.'); - final List args = (message as List?)!; - final String? arg_applicationUserName = (args[0] as String?); - try { - api.restoreTransactions(arg_applicationUserName); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.restoreTransactions was null.', + ); + final List args = (message as List?)!; + final String? arg_applicationUserName = (args[0] as String?); + try { + api.restoreTransactions(arg_applicationUserName); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.presentCodeRedemptionSheet$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.presentCodeRedemptionSheet$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - api.presentCodeRedemptionSheet(); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + api.presentCodeRedemptionSheet(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.retrieveReceiptData$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.retrieveReceiptData$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - final String? output = api.retrieveReceiptData(); - return [output]; - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + final String? output = api.retrieveReceiptData(); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.refreshReceipt$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.refreshReceipt$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.refreshReceipt was null.'); - final List args = (message as List?)!; - final Map? arg_receiptProperties = - (args[0] as Map?)?.cast(); - try { - await api.refreshReceipt(receiptProperties: arg_receiptProperties); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + assert( + message != null, + 'Argument for dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.refreshReceipt was null.', + ); + final List args = (message as List?)!; + final Map? arg_receiptProperties = + (args[0] as Map?)?.cast(); + try { + await api.refreshReceipt( + receiptProperties: arg_receiptProperties, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.startObservingPaymentQueue$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.startObservingPaymentQueue$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - api.startObservingPaymentQueue(); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + api.startObservingPaymentQueue(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.stopObservingPaymentQueue$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.stopObservingPaymentQueue$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - api.stopObservingPaymentQueue(); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + api.stopObservingPaymentQueue(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.registerPaymentQueueDelegate$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.registerPaymentQueueDelegate$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - api.registerPaymentQueueDelegate(); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + api.registerPaymentQueueDelegate(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.removePaymentQueueDelegate$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.removePaymentQueueDelegate$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - api.removePaymentQueueDelegate(); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + api.removePaymentQueueDelegate(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.showPriceConsentIfNeeded$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.showPriceConsentIfNeeded$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - api.showPriceConsentIfNeeded(); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + api.showPriceConsentIfNeeded(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.supportsStoreKit2$messageChannelSuffix', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.in_app_purchase_storekit.InAppPurchaseAPI.supportsStoreKit2$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(pigeonVar_channel, - (Object? message) async { - try { - final bool output = api.supportsStoreKit2(); - return [output]; - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); + .setMockDecodedMessageHandler(pigeonVar_channel, ( + Object? message, + ) async { + try { + final bool output = api.supportsStoreKit2(); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException( + code: 'error', + message: e.toString(), + ), + ); + } + }); } } }