diff --git a/analysis_options.yaml b/analysis_options.yaml index 4936a8cbd..ab0363a5c 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -19,6 +19,7 @@ analyzer: # TODO (albertus-stripe): Remove this once the melos PR is merged since this won't be an issue anymore invalid_dependency: ignore invalid_annotation_target: ignore #https://github.com/rrousselGit/freezed#disabling-invalid_annotation_target-warning-and-warning-in-generates-files + library_private_types_in_public_api: ignore exclude: - "bin/cache/**" - "**/*.freezed.dart" diff --git a/example/integration_test/app_test.dart b/example/integration_test/app_test.dart index b1c862b31..f2a31b090 100644 --- a/example/integration_test/app_test.dart +++ b/example/integration_test/app_test.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; @@ -19,9 +20,9 @@ void main() { group('Payment sheet', () { testWidgets('init payment sheet', (_) async { // 1. create payment intent on the server - final _paymentSheetData = await _createTestPaymentSheet(); + final paymentSheetData = await _createTestPaymentSheet(); - expect(_paymentSheetData['paymentIntent'], isNotNull); + expect(paymentSheetData['paymentIntent'], isNotNull); // 2. initialize the payment sheet expect( Stripe.instance.initPaymentSheet( @@ -33,9 +34,9 @@ void main() { ), style: ThemeMode.dark, merchantDisplayName: 'Flutter Stripe Store Demo', - customerId: _paymentSheetData['customer'], - paymentIntentClientSecret: _paymentSheetData['paymentIntent'], - customerEphemeralKeySecret: _paymentSheetData['ephemeralKey'], + customerId: paymentSheetData['customer'], + paymentIntentClientSecret: paymentSheetData['paymentIntent'], + customerEphemeralKeySecret: paymentSheetData['ephemeralKey'], ), ), completes, @@ -90,7 +91,7 @@ void main() { Future> _createTestPaymentSheet() async { // ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' could return multiple IPs, divided by new line - use the last one final ipAddress = kApiUrl.split('\n').last.trim(); - print('IP Address of the server: $ipAddress'); + log('IP Address of the server: $ipAddress'); final url = Uri.parse('http://$ipAddress:4242/payment-sheet'); final response = await http.post( url, diff --git a/example/integration_test/payment_method_test.dart b/example/integration_test/payment_method_test.dart index 7e3f7945f..f3a881fb4 100644 --- a/example/integration_test/payment_method_test.dart +++ b/example/integration_test/payment_method_test.dart @@ -43,7 +43,7 @@ void main() { expirationMonth: 04, expirationYear: 2025, )); - ; + final paymentIntent = await Stripe.instance.confirmPayment( paymentIntentClientSecret: clientSecret['clientSecret'], data: PaymentMethodParams.card( diff --git a/example/lib/main.dart b/example/lib/main.dart index 7622dbdce..c3cea8f09 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,3 +1,5 @@ +// ignore_for_file: use_key_in_widget_constructors + import 'package:flutter/material.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; import 'package:stripe_example/.env.dart'; @@ -14,7 +16,7 @@ void main() async { } class App extends StatelessWidget { - const App({Key? key}) : super(key: key); + const App({super.key}); @override Widget build(BuildContext context) { diff --git a/example/lib/screens/card_payments/custom_card_payment_screen.dart b/example/lib/screens/card_payments/custom_card_payment_screen.dart index af677d666..efaa371d7 100644 --- a/example/lib/screens/card_payments/custom_card_payment_screen.dart +++ b/example/lib/screens/card_payments/custom_card_payment_screen.dart @@ -7,6 +7,8 @@ import 'package:stripe_example/config.dart'; import 'package:stripe_example/widgets/loading_button.dart'; class CustomCardPaymentScreen extends StatefulWidget { + const CustomCardPaymentScreen({super.key}); + @override _CustomCardPaymentScreenState createState() => _CustomCardPaymentScreenState(); @@ -120,6 +122,8 @@ class _CustomCardPaymentScreenState extends State { } Future _handlePayPress() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); + await Stripe.instance.dangerouslyUpdateCardDetails(_card); try { @@ -158,16 +162,18 @@ class _CustomCardPaymentScreenState extends State { if (paymentIntentResult['error'] != null) { // Error during creating or confirming Intent - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: ${paymentIntentResult['error']}'))); - return; + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: Text('Error: ${paymentIntentResult['error']}'))); + return; + } } if (paymentIntentResult['clientSecret'] != null && paymentIntentResult['requiresAction'] == null) { // Payment succedeed - ScaffoldMessenger.of(context).showSnackBar(SnackBar( + scaffoldMessenger.showSnackBar(SnackBar( content: Text('Success!: The payment was confirmed successfully!'))); return; @@ -184,25 +190,27 @@ class _CustomCardPaymentScreenState extends State { await confirmIntent(paymentIntent.id); } else { // Payment succedeed - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('Error: ${paymentIntentResult['error']}'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: Text('Error: ${paymentIntentResult['error']}'))); + } } } } catch (e) { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text('Error: $e'))); + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); rethrow; } } Future confirmIntent(String paymentIntentId) async { + final scaffoldMessenger = ScaffoldMessenger.of(context); final result = await callNoWebhookPayEndpointIntentId( paymentIntentId: paymentIntentId); - if (result['error'] != null) { - ScaffoldMessenger.of(context) + if (result['error'] != null && context.mounted) { + scaffoldMessenger .showSnackBar(SnackBar(content: Text('Error: ${result['error']}'))); } else { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( + scaffoldMessenger.showSnackBar(SnackBar( content: Text('Success!: The payment was confirmed successfully!'))); } } diff --git a/example/lib/screens/card_payments/no_webhook_payment_cardform_screen.dart b/example/lib/screens/card_payments/no_webhook_payment_cardform_screen.dart index a4bb24e66..21313e86c 100644 --- a/example/lib/screens/card_payments/no_webhook_payment_cardform_screen.dart +++ b/example/lib/screens/card_payments/no_webhook_payment_cardform_screen.dart @@ -10,6 +10,8 @@ import 'package:stripe_example/widgets/loading_button.dart'; import 'package:stripe_example/widgets/response_card.dart'; class NoWebhookPaymentCardFormScreen extends StatefulWidget { + const NoWebhookPaymentCardFormScreen({super.key}); + @override _NoWebhookPaymentCardFormScreenState createState() => _NoWebhookPaymentCardFormScreenState(); @@ -86,6 +88,8 @@ class _NoWebhookPaymentCardFormScreenState return; } + final scaffoldMessenger = ScaffoldMessenger.of(context); + try { // 1. Gather customer billing information (ex. email) @@ -120,8 +124,10 @@ class _NoWebhookPaymentCardFormScreenState if (paymentIntentResult['error'] != null) { // Error during creating or confirming Intent - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: ${paymentIntentResult['error']}'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: Text('Error: ${paymentIntentResult['error']}'))); + } return; } @@ -129,10 +135,12 @@ class _NoWebhookPaymentCardFormScreenState paymentIntentResult['requiresAction'] == null) { // Payment succedeed - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: - Text('Success!: The payment was confirmed successfully!'))); - return; + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: + Text('Success!: The payment was confirmed successfully!'))); + return; + } } if (paymentIntentResult['clientSecret'] != null && @@ -153,27 +161,34 @@ class _NoWebhookPaymentCardFormScreenState // 5. Call API to confirm intent await confirmIntent(paymentIntent.id); } else { - // Payment succedeed - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('Error: ${paymentIntentResult['error']}'))); + if (context.mounted) { + // Payment succedeed + scaffoldMessenger.showSnackBar(SnackBar( + content: Text('Error: ${paymentIntentResult['error']}'))); + } } } } catch (e) { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text('Error: $e'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); + } rethrow; } } Future confirmIntent(String paymentIntentId) async { + final scaffoldMessenger = ScaffoldMessenger.of(context); final result = await callNoWebhookPayEndpointIntentId( paymentIntentId: paymentIntentId); - if (result['error'] != null) { - ScaffoldMessenger.of(context) + if (result['error'] != null && context.mounted) { + scaffoldMessenger .showSnackBar(SnackBar(content: Text('Error: ${result['error']}'))); } else { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('Success!: The payment was confirmed successfully!'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: + Text('Success!: The payment was confirmed successfully!'))); + } } } diff --git a/example/lib/screens/card_payments/no_webhook_payment_screen.dart b/example/lib/screens/card_payments/no_webhook_payment_screen.dart index e6b8ae45f..e2c1bdafb 100644 --- a/example/lib/screens/card_payments/no_webhook_payment_screen.dart +++ b/example/lib/screens/card_payments/no_webhook_payment_screen.dart @@ -10,6 +10,8 @@ import 'package:stripe_example/widgets/loading_button.dart'; import 'package:stripe_example/widgets/response_card.dart'; class NoWebhookPaymentScreen extends StatefulWidget { + const NoWebhookPaymentScreen({super.key}); + @override _NoWebhookPaymentScreenState createState() => _NoWebhookPaymentScreenState(); } @@ -85,6 +87,8 @@ class _NoWebhookPaymentScreenState extends State { return; } + final scaffoldMessenger = ScaffoldMessenger.of(context); + try { // 1. Gather customer billing information (ex. email) final billingDetails = BillingDetails( @@ -118,16 +122,19 @@ class _NoWebhookPaymentScreenState extends State { if (paymentIntentResult['error'] != null) { // Error during creating or confirming Intent - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: ${paymentIntentResult['error']}'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: Text('Error: ${paymentIntentResult['error']}'))); + } return; } if (paymentIntentResult['clientSecret'] != null && - paymentIntentResult['requiresAction'] == null) { + paymentIntentResult['requiresAction'] == null && + context.mounted) { // Payment succedeed - ScaffoldMessenger.of(context).showSnackBar(SnackBar( + scaffoldMessenger.showSnackBar(SnackBar( content: Text('Success!: The payment was confirmed successfully!'))); return; @@ -146,26 +153,33 @@ class _NoWebhookPaymentScreenState extends State { await confirmIntent(paymentIntent.id); } else { // Payment succedeed - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('Error: ${paymentIntentResult['error']}'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: Text('Error: ${paymentIntentResult['error']}'))); + } } } } catch (e) { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text('Error: $e'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); + } rethrow; } } Future confirmIntent(String paymentIntentId) async { + final scaffoldMessenger = ScaffoldMessenger.of(context); final result = await callNoWebhookPayEndpointIntentId( paymentIntentId: paymentIntentId); - if (result['error'] != null) { - ScaffoldMessenger.of(context) + if (result['error'] != null && context.mounted) { + scaffoldMessenger .showSnackBar(SnackBar(content: Text('Error: ${result['error']}'))); } else { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('Success!: The payment was confirmed successfully!'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: + Text('Success!: The payment was confirmed successfully!'))); + } } } diff --git a/example/lib/screens/card_payments/webhook_payment_screen.dart b/example/lib/screens/card_payments/webhook_payment_screen.dart index 89842025a..c15c3aad5 100644 --- a/example/lib/screens/card_payments/webhook_payment_screen.dart +++ b/example/lib/screens/card_payments/webhook_payment_screen.dart @@ -10,6 +10,8 @@ import 'package:stripe_example/widgets/loading_button.dart'; import 'package:stripe_example/widgets/response_card.dart'; class WebhookPaymentScreen extends StatefulWidget { + const WebhookPaymentScreen({super.key}); + @override _WebhookPaymentScreenState createState() => _WebhookPaymentScreenState(); } @@ -71,6 +73,7 @@ class _WebhookPaymentScreenState extends State { } Future _handlePayPress() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); if (_card == null) { return; } @@ -107,9 +110,10 @@ class _WebhookPaymentScreenState extends State { _saveCard == true ? PaymentIntentsFutureUsage.OffSession : null, ), ); - - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('Success!: The payment was confirmed successfully!'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: Text('Success!: The payment was confirmed successfully!'))); + } } Future> fetchPaymentIntentClientSecret() async { diff --git a/example/lib/screens/customer_sheet/customer_sheet_screen.dart b/example/lib/screens/customer_sheet/customer_sheet_screen.dart index d49262e23..d6f9a9cb5 100644 --- a/example/lib/screens/customer_sheet/customer_sheet_screen.dart +++ b/example/lib/screens/customer_sheet/customer_sheet_screen.dart @@ -8,6 +8,8 @@ import 'package:stripe_example/widgets/example_scaffold.dart'; import 'package:stripe_example/widgets/loading_button.dart'; class CustomerSheetScreen extends StatefulWidget { + const CustomerSheetScreen({super.key}); + @override _CustomerSheetScreenState createState() => _CustomerSheetScreenState(); } @@ -64,6 +66,7 @@ class _CustomerSheetScreenState extends State { } Future initCustomerSheet() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 1. retrieve customer from backend. final data = await _createTestCustomerSheet(); @@ -101,14 +104,17 @@ class _CustomerSheetScreenState extends State { step = 1; }); } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: $e')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Error: $e')), + ); + } rethrow; } } Future confirmCustomerSheet() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 3. display the customer sheet. final result = await Stripe.instance.presentCustomerSheet(); @@ -117,25 +123,31 @@ class _CustomerSheetScreenState extends State { step = 0; }); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Payment preferences modfied completed option selected: ${result?.paymentOption?.label}}'), - ), - ); - } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Error from Stripe: ${e.error.localizedMessage}'), + content: Text( + 'Payment preferences modfied completed option selected: ${result?.paymentOption?.label}}'), ), ); + } + } on Exception catch (e) { + if (e is StripeException) { + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Error from Stripe: ${e.error.localizedMessage}'), + ), + ); + } } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Unforeseen error: ${e}'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Unforeseen error: $e'), + ), + ); + } } } } diff --git a/example/lib/screens/financial_connections.dart/financial_connections_session_screen.dart b/example/lib/screens/financial_connections.dart/financial_connections_session_screen.dart index 6f2df02b4..7b59d2872 100644 --- a/example/lib/screens/financial_connections.dart/financial_connections_session_screen.dart +++ b/example/lib/screens/financial_connections.dart/financial_connections_session_screen.dart @@ -10,7 +10,7 @@ import '../../config.dart'; import '../../widgets/response_card.dart'; class FinancialConnectionsScreen extends StatefulWidget { - const FinancialConnectionsScreen({Key? key}) : super(key: key); + const FinancialConnectionsScreen({super.key}); @override State createState() => @@ -40,32 +40,31 @@ class _FinancialConnectionsScreenState } Future _collectAccount(BuildContext context) async { - // Precondition: - // 1. Make sure to create a financial connection session on the backend and - // forward the client secret of the session to the app. + final messenger = ScaffoldMessenger.of(context); final result = await _financialConnectionsSheet(); final clientSecret = await result['clientSecret']; - // 2. use the client secret to confirm the payment and handle the result. try { final result = await Stripe.instance.collectFinancialConnectionsAccounts( clientSecret: clientSecret, ); + if (!mounted) return; setState(() { response = result.toString(); }); } on Exception catch (e) { + if (!mounted) return; if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + messenger.showSnackBar( SnackBar( content: Text('Error from Stripe: ${e.error.localizedMessage}'), ), ); } else { - ScaffoldMessenger.of(context).showSnackBar( + messenger.showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Unforeseen error: $e'), ), ); } @@ -73,32 +72,31 @@ class _FinancialConnectionsScreenState } Future _collectBankToken(BuildContext context) async { - // Precondition: - // 1. Make sure to create a financial connection session on the backend and - // forward the client secret of the session to the app. + final messenger = ScaffoldMessenger.of(context); final result = await _financialConnectionsSheet(); final clientSecret = await result['clientSecret']; - // 2. use the client secret to confirm the payment and handle the result. try { final result = await Stripe.instance.collectBankAccountToken( clientSecret: clientSecret, ); + if (!mounted) return; setState(() { response = result.toString(); }); } on Exception catch (e) { + if (!mounted) return; if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + messenger.showSnackBar( SnackBar( content: Text('Error from Stripe: ${e.error.localizedMessage}'), ), ); } else { - ScaffoldMessenger.of(context).showSnackBar( + messenger.showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Unforeseen error: $e'), ), ); } diff --git a/example/lib/screens/others/can_add_to_wallet_screen.dart b/example/lib/screens/others/can_add_to_wallet_screen.dart index 96814f67b..ab204f3a8 100644 --- a/example/lib/screens/others/can_add_to_wallet_screen.dart +++ b/example/lib/screens/others/can_add_to_wallet_screen.dart @@ -6,11 +6,13 @@ import 'package:stripe_example/widgets/loading_button.dart'; import 'package:stripe_example/widgets/response_card.dart'; class CanAddToWalletScreen extends StatefulWidget { + const CanAddToWalletScreen({super.key}); + @override - _CanAddToWalletScreenState createState() => _CanAddToWalletScreenState(); + CanAddToWalletScreenState createState() => CanAddToWalletScreenState(); } -class _CanAddToWalletScreenState extends State { +class CanAddToWalletScreenState extends State { late TextEditingController _controller; CanAddCardToWalletResult? canAddCardToWallet; IsCardInWalletResult? isCardInWallet; @@ -73,33 +75,42 @@ class _CanAddToWalletScreenState extends State { } Future _handleCanAddToWallet(String last4) async { + final scaffoldManager = ScaffoldMessenger.of(context); + try { final result = await Stripe.instance.canAddCardToWallet( CanAddCardToWalletParams( cardLastFour: last4, ), ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Can add card to wallet: ${result}')), - ); + if (mounted) { + scaffoldManager.showSnackBar( + SnackBar(content: Text('Can add card to wallet: $result')), + ); + } return result; } catch (e) { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text('Error: $e'))); + if (mounted) { + scaffoldManager.showSnackBar(SnackBar(content: Text('Error: $e'))); + } rethrow; } } Future _isCardInToWallet(String last4) async { + final scaffoldManager = ScaffoldMessenger.of(context); try { final result = await Stripe.instance.isCardInWallet(last4); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Can add card to wallet: ${result}')), - ); + if (mounted) { + scaffoldManager.showSnackBar( + SnackBar(content: Text('Is card in wallet: $result')), + ); + } return result; } catch (e) { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text('Error: $e'))); + if (mounted) { + scaffoldManager.showSnackBar(SnackBar(content: Text('Error: $e'))); + } rethrow; } } diff --git a/example/lib/screens/others/cvc_re_collection_screen.dart b/example/lib/screens/others/cvc_re_collection_screen.dart index 7e9560219..56dd8e467 100644 --- a/example/lib/screens/others/cvc_re_collection_screen.dart +++ b/example/lib/screens/others/cvc_re_collection_screen.dart @@ -9,11 +9,13 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class CVCReCollectionScreen extends StatefulWidget { + const CVCReCollectionScreen({super.key}); + @override - _CVCReCollectionScreenState createState() => _CVCReCollectionScreenState(); + CVCReCollectionScreenState createState() => CVCReCollectionScreenState(); } -class _CVCReCollectionScreenState extends State { +class CVCReCollectionScreenState extends State { String _email = 'email@stripe.com'; String _cvc = ''; @@ -62,15 +64,18 @@ class _CVCReCollectionScreenState extends State { } // 1. fetch Intent Client Secret from backend - final paymentMethod = await _fetchPaymentIntentWithPaymentMethod(); + final scaffoldMessenger = ScaffoldMessenger.of(context); + final paymentMethod = await _fetchPaymentIntentWithPaymentMethod(); if (paymentMethod['error'] != null) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error code: ${paymentMethod['error']}'))); + if (mounted) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Error code: ${paymentMethod['error']}'))); + } return; } - ScaffoldMessenger.of(context).showSnackBar(SnackBar( + scaffoldMessenger.showSnackBar(SnackBar( content: Text('Success!: The payment was confirmed successfully!'))); } @@ -78,17 +83,23 @@ class _CVCReCollectionScreenState extends State { if (_cvc.isEmpty || _email.isEmpty) { return; } + final scaffoldMessenger = ScaffoldMessenger.of(context); final paymentIntent = await _callChargeCardOffSession( email: _email, ); log('paymentIntent $paymentIntent'); if (paymentIntent['error'] != null) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error code: ${paymentIntent['error']}'))); + if (mounted) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Error code: ${paymentIntent['error']}'))); + } } else if (paymentIntent['succeeded'] == true) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('Success!: The payment was confirmed successfully!'))); + if (mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: + Text('Success!: The payment was confirmed successfully!'))); + } } else { // Handle other statuses accordingly throw UnimplementedError(); diff --git a/example/lib/screens/others/legacy_token_bank_screen.dart b/example/lib/screens/others/legacy_token_bank_screen.dart index 9b198df91..79e46d6b1 100644 --- a/example/lib/screens/others/legacy_token_bank_screen.dart +++ b/example/lib/screens/others/legacy_token_bank_screen.dart @@ -6,11 +6,13 @@ import 'package:stripe_example/widgets/loading_button.dart'; import 'package:stripe_example/widgets/response_card.dart'; class LegacyTokenBankScreen extends StatefulWidget { + const LegacyTokenBankScreen({super.key}); + @override - _LegacyTokenBankScreenState createState() => _LegacyTokenBankScreenState(); + LegacyTokenBankScreenState createState() => LegacyTokenBankScreenState(); } -class _LegacyTokenBankScreenState extends State { +class LegacyTokenBankScreenState extends State { late TextEditingController _controller; TokenData? tokenData; @@ -55,6 +57,7 @@ class _LegacyTokenBankScreenState extends State { } Future _handleCreateTokenPress() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 1. Gather customer billing information (ex. email) final params = BankAccountTokenParams( @@ -71,12 +74,15 @@ class _LegacyTokenBankScreenState extends State { setState(() { this.tokenData = tokenData; }); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('Success: The token was created successfully!'))); + if (mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: Text('Success: The token was created successfully!'))); + } return; } catch (e) { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text('Error: $e'))); + if (mounted) { + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); + } rethrow; } } diff --git a/example/lib/screens/others/legacy_token_card_screen.dart b/example/lib/screens/others/legacy_token_card_screen.dart index 36e08981b..0aa1ec55a 100644 --- a/example/lib/screens/others/legacy_token_card_screen.dart +++ b/example/lib/screens/others/legacy_token_card_screen.dart @@ -6,11 +6,13 @@ import 'package:stripe_example/widgets/loading_button.dart'; import 'package:stripe_example/widgets/response_card.dart'; class LegacyTokenCardScreen extends StatefulWidget { + const LegacyTokenCardScreen({super.key}); + @override - _LegacyTokenCardScreenState createState() => _LegacyTokenCardScreenState(); + LegacyTokenCardScreenState createState() => LegacyTokenCardScreenState(); } -class _LegacyTokenCardScreenState extends State { +class LegacyTokenCardScreenState extends State { CardFieldInputDetails? _card; TokenData? tokenData; @@ -48,6 +50,7 @@ class _LegacyTokenCardScreenState extends State { if (_card == null) { return; } + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 1. Gather customer billing information (ex. email) @@ -67,12 +70,15 @@ class _LegacyTokenCardScreenState extends State { setState(() { this.tokenData = tokenData; }); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('Success: The token was created successfully!'))); + if (mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: Text('Success: The token was created successfully!'))); + } return; } catch (e) { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text('Error: $e'))); + if (mounted) { + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); + } rethrow; } } diff --git a/example/lib/screens/payment_sheet/express_checkout/express_checkout_element.dart b/example/lib/screens/payment_sheet/express_checkout/express_checkout_element.dart index 6a2682e3f..62ee97d9e 100644 --- a/example/lib/screens/payment_sheet/express_checkout/express_checkout_element.dart +++ b/example/lib/screens/payment_sheet/express_checkout/express_checkout_element.dart @@ -9,11 +9,13 @@ import 'platforms/express_checkout_element.dart' if (dart.library.js) 'platforms/express_checkout_element_web.dart'; class ExpressCheckoutElementExample extends StatefulWidget { + const ExpressCheckoutElementExample({super.key}); + @override - _ThemeCardExampleState createState() => _ThemeCardExampleState(); + ThemeCardExampleState createState() => ThemeCardExampleState(); } -class _ThemeCardExampleState extends State { +class ThemeCardExampleState extends State { String? clientSecret; @override @@ -23,19 +25,22 @@ class _ThemeCardExampleState extends State { } Future getClientSecret() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { final client = await createPaymentIntent(); setState(() { clientSecret = client; }); } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - e.toString(), + if (mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text( + e.toString(), + ), ), - ), - ); + ); + } } } diff --git a/example/lib/screens/payment_sheet/express_checkout/platforms/express_checkout_element.dart b/example/lib/screens/payment_sheet/express_checkout/platforms/express_checkout_element.dart index 33c7c24e7..d1c7b657e 100644 --- a/example/lib/screens/payment_sheet/express_checkout/platforms/express_checkout_element.dart +++ b/example/lib/screens/payment_sheet/express_checkout/platforms/express_checkout_element.dart @@ -5,7 +5,7 @@ Future pay() async { } class ExpressCheckoutWidget extends StatelessWidget { - const ExpressCheckoutWidget(this.clientSecret); + const ExpressCheckoutWidget(this.clientSecret, {super.key}); final String? clientSecret; diff --git a/example/lib/screens/payment_sheet/express_checkout/platforms/express_checkout_element_web.dart b/example/lib/screens/payment_sheet/express_checkout/platforms/express_checkout_element_web.dart index c4dac9ad0..57c4a9d00 100644 --- a/example/lib/screens/payment_sheet/express_checkout/platforms/express_checkout_element_web.dart +++ b/example/lib/screens/payment_sheet/express_checkout/platforms/express_checkout_element_web.dart @@ -15,7 +15,7 @@ Future pay() async { } class ExpressCheckoutWidget extends StatelessWidget { - const ExpressCheckoutWidget(this.clientSecret); + const ExpressCheckoutWidget(this.clientSecret, {super.key}); final String? clientSecret; diff --git a/example/lib/screens/payment_sheet/payment_element/payment_element.dart b/example/lib/screens/payment_sheet/payment_element/payment_element.dart index e316bdc6c..657be7c07 100644 --- a/example/lib/screens/payment_sheet/payment_element/payment_element.dart +++ b/example/lib/screens/payment_sheet/payment_element/payment_element.dart @@ -1,14 +1,16 @@ import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; import 'package:stripe_example/config.dart'; +import 'package:stripe_example/widgets/loading_button.dart'; -import 'package:http/http.dart' as http; import 'platforms/payment_element.dart' if (dart.library.js) 'platforms/payment_element_web.dart'; -import 'package:stripe_example/widgets/loading_button.dart'; class PaymentElementExample extends StatefulWidget { + const PaymentElementExample({super.key}); + @override _ThemeCardExampleState createState() => _ThemeCardExampleState(); } @@ -23,13 +25,14 @@ class _ThemeCardExampleState extends State { } Future getClientSecret() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { final client = await createPaymentIntent(); setState(() { clientSecret = client; }); } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( + scaffoldMessenger.showSnackBar( SnackBar( content: Text( e.toString(), diff --git a/example/lib/screens/payment_sheet/payment_element/platforms/payment_element.dart b/example/lib/screens/payment_sheet/payment_element/platforms/payment_element.dart index 9818aa3ec..97aa852ef 100644 --- a/example/lib/screens/payment_sheet/payment_element/platforms/payment_element.dart +++ b/example/lib/screens/payment_sheet/payment_element/platforms/payment_element.dart @@ -5,7 +5,7 @@ Future pay() async { } class PlatformPaymentElement extends StatelessWidget { - const PlatformPaymentElement(this.clientSecret); + const PlatformPaymentElement(this.clientSecret, {super.key}); final String? clientSecret; diff --git a/example/lib/screens/payment_sheet/payment_element/platforms/payment_element_web.dart b/example/lib/screens/payment_sheet/payment_element/platforms/payment_element_web.dart index ca2bdcaea..48621bc77 100644 --- a/example/lib/screens/payment_sheet/payment_element/platforms/payment_element_web.dart +++ b/example/lib/screens/payment_sheet/payment_element/platforms/payment_element_web.dart @@ -15,7 +15,7 @@ Future pay() async { } class PlatformPaymentElement extends StatelessWidget { - const PlatformPaymentElement(this.clientSecret); + const PlatformPaymentElement(this.clientSecret, {super.key}); final String? clientSecret; diff --git a/example/lib/screens/payment_sheet/payment_sheet_deffered_screen.dart b/example/lib/screens/payment_sheet/payment_sheet_deffered_screen.dart index 96e93121b..933cdc296 100644 --- a/example/lib/screens/payment_sheet/payment_sheet_deffered_screen.dart +++ b/example/lib/screens/payment_sheet/payment_sheet_deffered_screen.dart @@ -9,13 +9,15 @@ import 'package:stripe_example/widgets/example_scaffold.dart'; import 'package:stripe_example/widgets/loading_button.dart'; class PaymentSheetDefferedScreen extends StatefulWidget { + const PaymentSheetDefferedScreen({super.key}); + @override _PaymentSheetScreenState createState() => _PaymentSheetScreenState(); } class _PaymentSheetScreenState extends State { int step = 0; - _PaymentMode? mode = null; + _PaymentMode? mode; @override Widget build(BuildContext context) { @@ -122,6 +124,7 @@ class _PaymentSheetScreenState extends State { } Future initPaymentSheetPaymentMode() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // // 1. create payment intent on the server // final data = await _createTestPaymentSheet(); @@ -195,14 +198,15 @@ class _PaymentSheetScreenState extends State { step = 2; }); } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: $e')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); + } rethrow; } } Future initPaymentSheetSetupMode() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // // 1. create payment intent on the server // final data = await _createTestPaymentSheet(); @@ -276,14 +280,15 @@ class _PaymentSheetScreenState extends State { step = 2; }); } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: $e')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); + } rethrow; } } Future confirmPayment() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 3. display the payment sheet. await Stripe.instance.presentPaymentSheet(); @@ -291,25 +296,28 @@ class _PaymentSheetScreenState extends State { setState(() { step = 0; }); - - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Payment succesfully completed'), + ), + ); + } } on Exception catch (e) { if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + scaffoldMessenger.showSnackBar( SnackBar( content: Text('Error from Stripe: ${e.error.localizedMessage}'), ), ); } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Unforeseen error: ${e}'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Unforeseen error: $e'), + ), + ); + } } } } diff --git a/example/lib/screens/payment_sheet/payment_sheet_screen.dart b/example/lib/screens/payment_sheet/payment_sheet_screen.dart index b3ef7244b..d8540187f 100644 --- a/example/lib/screens/payment_sheet/payment_sheet_screen.dart +++ b/example/lib/screens/payment_sheet/payment_sheet_screen.dart @@ -9,6 +9,8 @@ import 'package:stripe_example/widgets/example_scaffold.dart'; import 'package:stripe_example/widgets/loading_button.dart'; class PaymentSheetScreen extends StatefulWidget { + const PaymentSheetScreen({super.key}); + @override _PaymentSheetScreenState createState() => _PaymentSheetScreenState(); } @@ -65,6 +67,7 @@ class _PaymentSheetScreenState extends State { } Future initPaymentSheet() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 1. create payment intent on the server final data = await _createTestPaymentSheet(); @@ -135,14 +138,15 @@ class _PaymentSheetScreenState extends State { step = 1; }); } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: $e')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); + } rethrow; } } Future confirmPayment() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 3. display the payment sheet. await Stripe.instance.presentPaymentSheet(); @@ -151,24 +155,30 @@ class _PaymentSheetScreenState extends State { step = 0; }); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); - } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Error from Stripe: ${e.error.localizedMessage}'), + content: Text('Payment succesfully completed'), ), ); + } + } on Exception catch (e) { + if (e is StripeException) { + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Error from Stripe: ${e.error.localizedMessage}'), + ), + ); + } } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Unforeseen error: ${e}'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Unforeseen error: $e'), + ), + ); + } } } } diff --git a/example/lib/screens/payment_sheet/payment_sheet_screen_custom_flow.dart b/example/lib/screens/payment_sheet/payment_sheet_screen_custom_flow.dart index f4de7cf98..2825d1955 100644 --- a/example/lib/screens/payment_sheet/payment_sheet_screen_custom_flow.dart +++ b/example/lib/screens/payment_sheet/payment_sheet_screen_custom_flow.dart @@ -3,12 +3,13 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; import 'package:http/http.dart' as http; +import 'package:stripe_example/config.dart'; import 'package:stripe_example/widgets/example_scaffold.dart'; import 'package:stripe_example/widgets/loading_button.dart'; -import 'package:stripe_example/config.dart'; - class PaymentSheetScreenWithCustomFlow extends StatefulWidget { + const PaymentSheetScreenWithCustomFlow({super.key}); + @override _PaymentSheetScreenState createState() => _PaymentSheetScreenState(); } @@ -54,6 +55,7 @@ class _PaymentSheetScreenState extends State { } Future initPaymentSheet() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 1. create payment intent on the server final data = await createTestPaymentSheet(); @@ -81,14 +83,17 @@ class _PaymentSheetScreenState extends State { step = 1; }); } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: $e')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Error: $e')), + ); + } rethrow; } } Future presentPaymentSheet() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 3. display the payment sheet. await Stripe.instance.presentPaymentSheet(); @@ -97,29 +102,36 @@ class _PaymentSheetScreenState extends State { step = 2; }); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment option selected'), - ), - ); - } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Error from Stripe: ${e.error.localizedMessage}'), - ), - ); - } else { - ScaffoldMessenger.of(context).showSnackBar( + if (context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Payment option selected'), ), ); } + } on Exception catch (e) { + if (e is StripeException) { + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Error from Stripe: ${e.error.localizedMessage}'), + ), + ); + } else { + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Unforeseen error: $e'), + ), + ); + } + } + } } } Future confirmPayment() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 4. Confirm the payment sheet. await Stripe.instance.confirmPaymentSheetPayment(); @@ -128,24 +140,30 @@ class _PaymentSheetScreenState extends State { step = 0; }); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); - } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Error from Stripe: ${e.error.localizedMessage}'), + content: Text('Payment succesfully completed'), ), ); + } + } on Exception catch (e) { + if (e is StripeException) { + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Error from Stripe: ${e.error.localizedMessage}'), + ), + ); + } } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Unforeseen error: ${e}'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Unforeseen error: $e'), + ), + ); + } } } } @@ -171,4 +189,5 @@ class _PaymentSheetScreenState extends State { } } -final ControlsWidgetBuilder emptyControlBuilder = (_, __) => Container(); +Widget emptyControlBuilder(BuildContext context, ControlsDetails details) => + Container(); diff --git a/example/lib/screens/regional_payment_methods/affirm_screen.dart b/example/lib/screens/regional_payment_methods/affirm_screen.dart index e9de87566..e832ac329 100644 --- a/example/lib/screens/regional_payment_methods/affirm_screen.dart +++ b/example/lib/screens/regional_payment_methods/affirm_screen.dart @@ -9,7 +9,7 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class AffirmScreen extends StatelessWidget { - const AffirmScreen({Key? key}) : super(key: key); + const AffirmScreen({super.key}); Future> _createPaymentIntent() async { final url = Uri.parse('$kApiUrl/create-payment-intent'); @@ -33,6 +33,7 @@ class AffirmScreen extends StatelessWidget { // see file main.dart in this example app. // 1. on the backend create a payment intent for payment method and save the // client secret. + final scaffoldMessenger = ScaffoldMessenger.of(context); final result = await _createPaymentIntent(); final clientSecret = await result['clientSecret']; @@ -43,26 +44,29 @@ class AffirmScreen extends StatelessWidget { data: PaymentMethodParams.affirm(paymentMethodData: PaymentMethodData()), ); - - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Payment succesfully completed'), + ), + ); + } } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (e is StripeException && context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( content: Text( 'Error from Stripe: ${e.error.localizedMessage ?? e.error.code}'), ), ); } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Unforeseen error: ${e}'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Unforeseen error: $e'), + ), + ); + } } } } diff --git a/example/lib/screens/regional_payment_methods/ali_pay_screen.dart b/example/lib/screens/regional_payment_methods/ali_pay_screen.dart index 620461e98..1cc1eb6e7 100644 --- a/example/lib/screens/regional_payment_methods/ali_pay_screen.dart +++ b/example/lib/screens/regional_payment_methods/ali_pay_screen.dart @@ -9,7 +9,7 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class AliPayScreen extends StatelessWidget { - const AliPayScreen({Key? key}) : super(key: key); + const AliPayScreen({super.key}); Future> _createPaymentIntent() async { final url = Uri.parse('$kApiUrl/create-payment-intent'); @@ -34,6 +34,7 @@ class AliPayScreen extends StatelessWidget { // see file main.dart in this example app. // 1. on the backend create a payment intent for payment method and save the // client secret. + final scaffoldMessenger = ScaffoldMessenger.of(context); final result = await _createPaymentIntent(); final clientSecret = await result['clientSecret']; @@ -45,25 +46,28 @@ class AliPayScreen extends StatelessWidget { paymentMethodData: const PaymentMethodData(), ), ); - - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); - } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Error from Stripe: ${e.error.localizedMessage}'), + content: Text('Payment succesfully completed'), ), ); - } else { - ScaffoldMessenger.of(context).showSnackBar( + } + } on Exception catch (e) { + if (e is StripeException && context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Error from Stripe: ${e.error.localizedMessage}'), ), ); + } else { + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Unforeseen error: $e'), + ), + ); + } } } } diff --git a/example/lib/screens/regional_payment_methods/aubecs_debit.dart b/example/lib/screens/regional_payment_methods/aubecs_debit.dart index dbcf2b9af..48aaf687f 100644 --- a/example/lib/screens/regional_payment_methods/aubecs_debit.dart +++ b/example/lib/screens/regional_payment_methods/aubecs_debit.dart @@ -9,7 +9,7 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class AubecsExample extends StatefulWidget { - const AubecsExample({Key? key}) : super(key: key); + const AubecsExample({super.key}); @override State createState() => _AubecsExampleState(); @@ -89,6 +89,7 @@ class _AubecsExampleState extends State { } Future _pay(BuildContext context) async { + final scaffoldMessenger = ScaffoldMessenger.of(context); // Precondition: //Make sure to have set a custom URI scheme in your app and add it to Stripe SDK // see file main.dart in this example app. @@ -105,23 +106,24 @@ class _AubecsExampleState extends State { paymentMethodData: PaymentMethodDataAubecs(formDetails: _details!), ), ); - - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Payment succesfully completed'), + ), + ); + } } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (e is StripeException && context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( content: Text('Error from Stripe: ${e.error.localizedMessage}'), ), ); - } else { - ScaffoldMessenger.of(context).showSnackBar( + } else if (context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Unforeseen error: $e'), ), ); } diff --git a/example/lib/screens/regional_payment_methods/cash_app_screen.dart b/example/lib/screens/regional_payment_methods/cash_app_screen.dart index 44e6e805d..4ea0684c6 100644 --- a/example/lib/screens/regional_payment_methods/cash_app_screen.dart +++ b/example/lib/screens/regional_payment_methods/cash_app_screen.dart @@ -9,7 +9,7 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class CashAppScreen extends StatelessWidget { - const CashAppScreen({Key? key}) : super(key: key); + const CashAppScreen({super.key}); Future> _createPaymentIntent() async { final url = Uri.parse('$kApiUrl/create-payment-intent'); @@ -29,16 +29,17 @@ class CashAppScreen extends StatelessWidget { } Future _pay(BuildContext context) async { - // Precondition: - //Make sure to have set a custom URI scheme in your app and add it to Stripe SDK - // see file main.dart in this example app. - // 1. on the backend create a payment intent for payment method and save the - // client secret. - final result = await _createPaymentIntent(); - final clientSecret = await result['clientSecret']; - - // 2. use the client secret to confirm the payment and handle the result. + final scaffoldMessenger = ScaffoldMessenger.of(context); try { + // Precondition: + //Make sure to have set a custom URI scheme in your app and add it to Stripe SDK + // see file main.dart in this example app. + // 1. on the backend create a payment intent for payment method and save the + // client secret. + final result = await _createPaymentIntent(); + final clientSecret = result['clientSecret']; + + // 2. use the client secret to confirm the payment and handle the result. await Stripe.instance.confirmPayment( paymentIntentClientSecret: clientSecret, data: PaymentMethodParams.cashAppPay( @@ -46,23 +47,25 @@ class CashAppScreen extends StatelessWidget { ), ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( + if (!context.mounted) return; + scaffoldMessenger.showSnackBar( + const SnackBar( content: Text('Payment succesfully completed'), ), ); } on Exception catch (e) { + if (!context.mounted) return; if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + scaffoldMessenger.showSnackBar( SnackBar( content: Text( 'Error from Stripe: ${e.error.localizedMessage ?? e.error.code}'), ), ); } else { - ScaffoldMessenger.of(context).showSnackBar( + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Unforeseen error: $e'), ), ); } diff --git a/example/lib/screens/regional_payment_methods/fpx_screen.dart b/example/lib/screens/regional_payment_methods/fpx_screen.dart index 43c9e68e5..69eefa8b2 100644 --- a/example/lib/screens/regional_payment_methods/fpx_screen.dart +++ b/example/lib/screens/regional_payment_methods/fpx_screen.dart @@ -9,7 +9,7 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class FpxScreen extends StatelessWidget { - const FpxScreen({Key? key}) : super(key: key); + const FpxScreen({super.key}); Future> _createPaymentIntent() async { final url = Uri.parse('$kApiUrl/create-payment-intent'); @@ -29,6 +29,7 @@ class FpxScreen extends StatelessWidget { } Future _pay(BuildContext context) async { + final scaffoldMessenger = ScaffoldMessenger.of(context); // Precondition: //Make sure to have set a custom URI scheme in your app and add it to Stripe SDK // see file main.dart in this example app. @@ -47,23 +48,24 @@ class FpxScreen extends StatelessWidget { ), ), ); - - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Payment succesfully completed'), + ), + ); + } } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (e is StripeException && context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( content: Text('Error from Stripe: ${e.error.localizedMessage}'), ), ); } else { - ScaffoldMessenger.of(context).showSnackBar( + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Unforeseen error: $e'), ), ); } diff --git a/example/lib/screens/regional_payment_methods/grab_pay_screen.dart b/example/lib/screens/regional_payment_methods/grab_pay_screen.dart index 6cc65d4d9..669820639 100644 --- a/example/lib/screens/regional_payment_methods/grab_pay_screen.dart +++ b/example/lib/screens/regional_payment_methods/grab_pay_screen.dart @@ -9,7 +9,7 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class GrabPayScreen extends StatelessWidget { - const GrabPayScreen({Key? key}) : super(key: key); + const GrabPayScreen({super.key}); Future> _createPaymentIntent() async { final url = Uri.parse('$kApiUrl/create-payment-intent'); @@ -34,6 +34,8 @@ class GrabPayScreen extends StatelessWidget { // see file main.dart in this example app. // 1. on the backend create a payment intent for payment method and save the // client secret. + + final scaffoldMessenger = ScaffoldMessenger.of(context); final result = await _createPaymentIntent(); final clientSecret = await result['clientSecret']; @@ -61,23 +63,24 @@ class GrabPayScreen extends StatelessWidget { ), ), ); - - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Payment succesfully completed'), + ), + ); + } } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (e is StripeException && context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( content: Text('Error from Stripe: ${e.error.localizedMessage}'), ), ); - } else { - ScaffoldMessenger.of(context).showSnackBar( + } else if (context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Unforeseen error: $e'), ), ); } diff --git a/example/lib/screens/regional_payment_methods/ideal_screen.dart b/example/lib/screens/regional_payment_methods/ideal_screen.dart index e5632d79a..cb35a8df1 100644 --- a/example/lib/screens/regional_payment_methods/ideal_screen.dart +++ b/example/lib/screens/regional_payment_methods/ideal_screen.dart @@ -10,7 +10,7 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class IdealScreen extends StatelessWidget { - const IdealScreen({Key? key}) : super(key: key); + const IdealScreen({super.key}); Future> _createPaymentIntent() async { final url = Uri.parse('$kApiUrl/create-payment-intent'); @@ -35,6 +35,7 @@ class IdealScreen extends StatelessWidget { // see file main.dart in this example app. // 1. on the backend create a payment intent for payment method and save the // client secret. + final scaffoldMessenger = ScaffoldMessenger.of(context); final result = await _createPaymentIntent(); final clientSecret = await result['clientSecret']; @@ -50,23 +51,25 @@ class IdealScreen extends StatelessWidget { ), ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Payment succesfully completed'), + ), + ); + } } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (e is StripeException && context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( content: Text( 'Error from Stripe: ${e.error.localizedMessage ?? e.error.code}'), ), ); - } else { - ScaffoldMessenger.of(context).showSnackBar( + } else if (context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Unforeseen error: $e'), ), ); } diff --git a/example/lib/screens/regional_payment_methods/klarna_screen.dart b/example/lib/screens/regional_payment_methods/klarna_screen.dart index 2b585d326..e9779a112 100644 --- a/example/lib/screens/regional_payment_methods/klarna_screen.dart +++ b/example/lib/screens/regional_payment_methods/klarna_screen.dart @@ -9,7 +9,7 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class KlarnaScreen extends StatelessWidget { - const KlarnaScreen({Key? key}) : super(key: key); + const KlarnaScreen({super.key}); Future> _createPaymentIntent() async { final url = Uri.parse('$kApiUrl/create-payment-intent'); @@ -34,6 +34,7 @@ class KlarnaScreen extends StatelessWidget { // see file main.dart in this example app. // 1. on the backend create a payment intent for payment method and save the // client secret. + final scaffoldMessenger = ScaffoldMessenger.of(context); final result = await _createPaymentIntent(); final clientSecret = await result['clientSecret']; @@ -60,22 +61,24 @@ class KlarnaScreen extends StatelessWidget { ), ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); - } on Exception catch (e) { - if (e is StripeException) { + if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Payment succesfully completed'), + ), + ); + } + } on Exception catch (e) { + if (e is StripeException && context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( content: Text('Error from Stripe: ${e.error.localizedMessage}'), ), ); - } else { - ScaffoldMessenger.of(context).showSnackBar( + } else if (context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Unforeseen error: $e'), ), ); } diff --git a/example/lib/screens/regional_payment_methods/p24_screen.dart b/example/lib/screens/regional_payment_methods/p24_screen.dart new file mode 100644 index 000000000..9311dfc6a --- /dev/null +++ b/example/lib/screens/regional_payment_methods/p24_screen.dart @@ -0,0 +1,91 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_stripe/flutter_stripe.dart'; +import 'package:http/http.dart' as http; +import 'package:stripe_example/widgets/example_scaffold.dart'; +import 'package:stripe_example/widgets/loading_button.dart'; + +import '../../config.dart'; + +class P24Screen extends StatelessWidget { + const P24Screen({super.key}); + + Future> _createPaymentIntent() async { + final url = Uri.parse('$kApiUrl/create-payment-intent'); + final response = await http.post( + url, + headers: { + 'Content-Type': 'application/json', + }, + body: json.encode({ + 'currency': 'pln', + 'payment_method_types': ['p24'], + 'amount': 5000 + }), + ); + + return json.decode(response.body); + } + + Future _pay(BuildContext context) async { + // 1. Create payment intent on the backend + final scaffoldMessenger = ScaffoldMessenger.of(context); + final result = await _createPaymentIntent(); + final clientSecret = result['clientSecret']; + + // 2. Use the client secret to confirm the payment + try { + await Stripe.instance.confirmPayment( + paymentIntentClientSecret: clientSecret, + data: PaymentMethodParams.p24( + paymentMethodData: PaymentMethodData( + billingDetails: BillingDetails( + email: 'test@example.com', + ), + ), + ), + ); + + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Payment successfully completed'), + ), + ); + } + } on Exception catch (e) { + if (e is StripeException && context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Error from Stripe: ${e.error.localizedMessage ?? e.error.code}'), + ), + ); + } else if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Unforeseen error: $e'), + ), + ); + } + } + } + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + title: 'P24', + tags: ['Payment method'], + padding: const EdgeInsets.all(16), + children: [ + LoadingButton( + onPressed: () async { + await _pay(context); + }, + text: 'Pay with P24', + ), + ], + ); + } +} diff --git a/example/lib/screens/regional_payment_methods/paypal_screen.dart b/example/lib/screens/regional_payment_methods/paypal_screen.dart index 1619a323d..24b5a522a 100644 --- a/example/lib/screens/regional_payment_methods/paypal_screen.dart +++ b/example/lib/screens/regional_payment_methods/paypal_screen.dart @@ -9,7 +9,7 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class PayPalScreen extends StatefulWidget { - const PayPalScreen({Key? key}) : super(key: key); + const PayPalScreen({super.key}); @override State createState() => _PayPalScreenState(); @@ -53,6 +53,7 @@ class _PayPalScreenState extends State { // see file main.dart in this example app. // 1. on the backend create a payment intent for payment method and save the // client secret. + final scaffoldMessenger = ScaffoldMessenger.of(context); final result = await _createPaymentIntent(); final clientSecret = await result['clientSecret']; @@ -78,22 +79,24 @@ class _PayPalScreenState extends State { ), ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Payment succesfully completed'), + ), + ); + } } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (e is StripeException && context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( content: Text('Error from Stripe: ${e.error.localizedMessage}'), ), ); } else { - ScaffoldMessenger.of(context).showSnackBar( + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Unforeseen error: $e'), ), ); } diff --git a/example/lib/screens/regional_payment_methods/revolutpay_screen.dart b/example/lib/screens/regional_payment_methods/revolutpay_screen.dart index 38b17b4b3..ec73fe02a 100644 --- a/example/lib/screens/regional_payment_methods/revolutpay_screen.dart +++ b/example/lib/screens/regional_payment_methods/revolutpay_screen.dart @@ -9,7 +9,7 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class RevolutPayScreen extends StatelessWidget { - const RevolutPayScreen({Key? key}) : super(key: key); + const RevolutPayScreen({super.key}); Future> _createPaymentIntent() async { final url = Uri.parse('$kApiUrl/create-payment-intent'); @@ -29,13 +29,15 @@ class RevolutPayScreen extends StatelessWidget { } Future _pay(BuildContext context) async { + // Store scaffold messenger reference + final scaffoldMessenger = ScaffoldMessenger.of(context); + // Precondition: //Make sure to have set a custom URI scheme in your app and add it to Stripe SDK // see file main.dart in this example app. // 1. on the backend create a payment intent for payment method and save the // client secret. final result = await _createPaymentIntent(); - print('blaat $result'); final clientSecret = await result['clientSecret']; // 2. use the client secret to confirm the payment and handle the result. @@ -47,24 +49,25 @@ class RevolutPayScreen extends StatelessWidget { ), ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), + if (!context.mounted) return; + scaffoldMessenger.showSnackBar( + const SnackBar( + content: Text('Payment successfully completed'), ), ); - } on Exception catch (e, s) { - throw e; + } on Exception catch (e) { + if (!context.mounted) return; if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + scaffoldMessenger.showSnackBar( SnackBar( content: Text( 'Error from Stripe: ${e.error.localizedMessage ?? e.error.code}'), ), ); } else { - ScaffoldMessenger.of(context).showSnackBar( + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Unforeseen error: $e'), ), ); } diff --git a/example/lib/screens/regional_payment_methods/sofort_screen.dart b/example/lib/screens/regional_payment_methods/sofort_screen.dart index bccb79acd..e31aba627 100644 --- a/example/lib/screens/regional_payment_methods/sofort_screen.dart +++ b/example/lib/screens/regional_payment_methods/sofort_screen.dart @@ -9,7 +9,7 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class SofortScreen extends StatelessWidget { - const SofortScreen({Key? key}) : super(key: key); + const SofortScreen({super.key}); Future> _createPaymentIntent() async { final url = Uri.parse('$kApiUrl/create-payment-intent'); @@ -34,6 +34,7 @@ class SofortScreen extends StatelessWidget { // see file main.dart in this example app. // 1. on the backend create a payment intent for payment method and save the // client secret. + final scaffoldMessenger = ScaffoldMessenger.of(context); final result = await _createPaymentIntent(); final clientSecret = await result['clientSecret']; @@ -45,26 +46,29 @@ class SofortScreen extends StatelessWidget { paymentMethodData: PaymentMethodDataSofort(country: 'de'), ), ); - - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Payment succesfully completed'), + ), + ); + } } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (e is StripeException && context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( content: Text( 'Error from Stripe: ${e.error.localizedMessage ?? e.error.code}'), ), ); } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Unforeseen error: ${e}'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Unforeseen error: $e'), + ), + ); + } } } } diff --git a/example/lib/screens/regional_payment_methods/us_bank_account_direct_debit_screen.dart b/example/lib/screens/regional_payment_methods/us_bank_account_direct_debit_screen.dart new file mode 100644 index 000000000..aedb31e7d --- /dev/null +++ b/example/lib/screens/regional_payment_methods/us_bank_account_direct_debit_screen.dart @@ -0,0 +1,198 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_stripe/flutter_stripe.dart'; +import 'package:http/http.dart' as http; +import 'package:stripe_example/widgets/example_scaffold.dart'; +import 'package:stripe_example/widgets/loading_button.dart'; + +import '../../config.dart'; + +class UsBankAccountDirectDebitScreen extends StatefulWidget { + const UsBankAccountDirectDebitScreen({super.key}); + + @override + _UsBankAccountDirectDebitScreenState createState() => + _UsBankAccountDirectDebitScreenState(); +} + +class _UsBankAccountDirectDebitScreenState + extends State { + late TextEditingController _nameController; + late TextEditingController _emailController; + bool canConfirm = false; + String clientSecretForConfirm = ''; + + @override + void initState() { + super.initState(); + + _nameController = TextEditingController(); + _emailController = TextEditingController(); + } + + @override + void dispose() { + _nameController.dispose(); + _emailController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return ExampleScaffold( + title: 'ACH payment Direct debit', + tags: ['Payments'], + padding: EdgeInsets.all(16), + children: [ + SizedBox(height: 20), + TextFormField( + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Email', + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter an email'; + } + // Simple regex for validating email + final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'); + if (!emailRegex.hasMatch(value)) { + return 'Please enter a valid email'; + } + return null; + }, + controller: _emailController, + ), + SizedBox(height: 10), + TextFormField( + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Name', + ), + controller: _nameController, + validator: (value) { + if (value == null || value.isEmpty || value.length < 3) { + return 'Enter a valid name'; + } + return null; + }, + ), + SizedBox(height: 10), + LoadingButton( + onPressed: _handlePayPress, + text: 'Collect account', + ), + SizedBox(height: 10), + LoadingButton( + onPressed: + canConfirm ? () => confirmPayment(clientSecretForConfirm) : null, + text: 'Confirm', + ), + ], + ); + } + + Future _handlePayPress() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); + try { + // 1. call API to create PaymentIntent + final paymentIntentResult = await _createPaymentIntent(); + + if (paymentIntentResult['error'] != null) { + if (context.mounted) { + // Error during creating or confirming Intent + scaffoldMessenger.showSnackBar(SnackBar( + content: Text('Error: ${paymentIntentResult['error']}'))); + } + return; + } + + // collect the bankaccount + final clientSecret = paymentIntentResult['clientSecret']; + + if (paymentIntentResult['clientSecret'] != null) { + final result = await Stripe.instance.collectBankAccount( + clientSecret: clientSecret, + isPaymentIntent: true, + params: CollectBankAccountParams( + paymentMethodData: CollectBankAccountPaymentMethodData( + billingDetails: BillingDetails( + email: _emailController.text, + name: _nameController.text, + phone: '+48888000888', + address: Address( + city: 'Houston', + country: 'US', + line1: '1459 Circle Drive', + line2: '', + state: 'Texas', + postalCode: '77063', + ), + ), + ), + ), + ); + + if (result.status == PaymentIntentsStatus.RequiresConfirmation) { + setState(() { + canConfirm = true; + clientSecretForConfirm = result.clientSecret; + }); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('You can now confirm the payment'), + ), + ); + } + } + } + } catch (e) { + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); + } + rethrow; + } + } + + Future confirmPayment(String clientSecret) async { + final scaffoldMessenger = ScaffoldMessenger.of(context); + try { + await Stripe.instance.confirmPayment( + paymentIntentClientSecret: clientSecret, + ); + + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Payment succesfully completed'), + ), + ); + } + } catch (e) { + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); + } + rethrow; + } + } + + Future> _createPaymentIntent() async { + final url = Uri.parse('$kApiUrl/create-payment-intent'); + final response = await http.post( + url, + headers: { + 'Content-Type': 'application/json', + }, + body: json.encode({ + 'email': 'email@stripe.com', + 'items': ['id-1'], + 'currency': 'usd', + 'payment_method_types': ['us_bank_account'], + }), + ); + + return json.decode(response.body); + } +} diff --git a/example/lib/screens/regional_payment_methods/us_bank_account.dart b/example/lib/screens/regional_payment_methods/us_bank_account_screen.dart similarity index 77% rename from example/lib/screens/regional_payment_methods/us_bank_account.dart rename to example/lib/screens/regional_payment_methods/us_bank_account_screen.dart index 1911b0446..1f6d0e0f9 100644 --- a/example/lib/screens/regional_payment_methods/us_bank_account.dart +++ b/example/lib/screens/regional_payment_methods/us_bank_account_screen.dart @@ -9,6 +9,8 @@ import 'package:stripe_example/widgets/loading_button.dart'; import '../../config.dart'; class UsBankAccountScreen extends StatefulWidget { + const UsBankAccountScreen({super.key}); + @override _UsBankAccountScreenState createState() => _UsBankAccountScreenState(); } @@ -64,6 +66,7 @@ class _UsBankAccountScreenState extends State { } Future _handlePayPress() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 1. Gather customer billing information (ex. email) final billingDetails = BillingDetails( @@ -85,8 +88,10 @@ class _UsBankAccountScreenState extends State { if (paymentIntentResult['error'] != null) { // Error during creating or confirming Intent - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: ${paymentIntentResult['error']}'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: Text('Error: ${paymentIntentResult['error']}'))); + } return; } @@ -104,8 +109,9 @@ class _UsBankAccountScreenState extends State { handleNexAction(intent.nextAction, intent.clientSecret); } } catch (e) { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text('Error: $e'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); + } rethrow; } } @@ -155,8 +161,7 @@ class _VerifyMicroDepositsDialog extends StatefulWidget { const _VerifyMicroDepositsDialog({ required this.clientSecret, required this.microdepositType, - Key? key, - }) : super(key: key); + }); final String clientSecret; final String microdepositType; @@ -188,27 +193,27 @@ class _VerifyMicroDepositsDialogState } Future verifyIntentWithMicroDeposit() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { await Stripe.instance.verifyPaymentIntentWithMicrodeposits( isPaymentIntent: true, clientSecret: widget.clientSecret, params: VerifyMicroDepositsParams( descriptorCode: widget.microdepositType == "descriptorCode" - ? _descriptorController.text + ? _descriptorController.text : null, amounts: widget.microdepositType != "descriptorCode" - ? [ + ? [ int.parse(_amount1Controller.text), int.parse(_amount2Controller.text), ] : null, )); - ScaffoldMessenger.of(context).showSnackBar( + scaffoldMessenger.showSnackBar( SnackBar(content: Text('Account verified successfully'))); } on Exception catch (e) { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text('Error: $e'))); + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e'))); rethrow; } } @@ -223,42 +228,44 @@ class _VerifyMicroDepositsDialogState Text('Enter the details of the micro deposits verification'), SizedBox(height: 10), Visibility( - visible: widget.microdepositType =="descriptorCode", - child: TextField( - controller: _descriptorController, - decoration: InputDecoration( - border: OutlineInputBorder(), - labelText: 'Descriptor', + visible: widget.microdepositType == "descriptorCode", + child: TextField( + controller: _descriptorController, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Descriptor', + ), ), - ),), - Visibility( - visible: widget.microdepositType !="descriptorCode", - child: Column( - children: [ - SizedBox(height: 10), - TextField( - keyboardType: TextInputType.number, - controller: _amount1Controller, - decoration: InputDecoration( - border: OutlineInputBorder(), - labelText: 'Microdeposit 1 value', + ), + Visibility( + visible: widget.microdepositType != "descriptorCode", + child: Column( + children: [ + SizedBox(height: 10), + TextField( + keyboardType: TextInputType.number, + controller: _amount1Controller, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Microdeposit 1 value', + ), ), - ), - SizedBox(height: 10), - TextField( - controller: _amount2Controller, - keyboardType: TextInputType.number, - decoration: InputDecoration( - border: OutlineInputBorder(), - labelText: 'Microdeposit 2 value', + SizedBox(height: 10), + TextField( + controller: _amount2Controller, + keyboardType: TextInputType.number, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Microdeposit 2 value', + ), ), - ), - ], - )), + ], + )), SizedBox(height: 10), LoadingButton( onPressed: () async { await verifyIntentWithMicroDeposit(); + // ignore: use_build_context_synchronously Navigator.of(context).pop(); }, text: 'Confirm', @@ -268,4 +275,4 @@ class _VerifyMicroDepositsDialogState ), ); } -} \ No newline at end of file +} diff --git a/example/lib/screens/regional_payment_methods/wechat_pay_screen.dart b/example/lib/screens/regional_payment_methods/wechat_pay_screen.dart index 3b2200877..57c1bf514 100644 --- a/example/lib/screens/regional_payment_methods/wechat_pay_screen.dart +++ b/example/lib/screens/regional_payment_methods/wechat_pay_screen.dart @@ -4,7 +4,7 @@ import 'package:stripe_example/widgets/example_scaffold.dart'; import 'package:stripe_example/widgets/loading_button.dart'; class WeChatPayScreen extends StatelessWidget { - const WeChatPayScreen({Key? key}) : super(key: key); + const WeChatPayScreen({super.key}); // Future> _createPaymentIntent() async { // final url = Uri.parse('$kApiUrl/create-payment-intent'); @@ -63,7 +63,7 @@ class WeChatPayScreen extends StatelessWidget { } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text('Unforeseen error: ${e}'), + content: Text('Unforeseen error: $e'), ), ); } diff --git a/example/lib/screens/screens.dart b/example/lib/screens/screens.dart index 6de0dc1b3..88e1f00d3 100644 --- a/example/lib/screens/screens.dart +++ b/example/lib/screens/screens.dart @@ -13,10 +13,12 @@ import 'package:stripe_example/screens/regional_payment_methods/cash_app_screen. import 'package:stripe_example/screens/regional_payment_methods/fpx_screen.dart'; import 'package:stripe_example/screens/regional_payment_methods/ideal_screen.dart'; import 'package:stripe_example/screens/regional_payment_methods/klarna_screen.dart'; +import 'package:stripe_example/screens/regional_payment_methods/p24_screen.dart'; import 'package:stripe_example/screens/regional_payment_methods/paypal_screen.dart'; import 'package:stripe_example/screens/regional_payment_methods/revolutpay_screen.dart'; import 'package:stripe_example/screens/regional_payment_methods/sofort_screen.dart'; -import 'package:stripe_example/screens/regional_payment_methods/us_bank_account.dart'; +import 'package:stripe_example/screens/regional_payment_methods/us_bank_account_direct_debit_screen.dart'; +import 'package:stripe_example/screens/regional_payment_methods/us_bank_account_screen.dart'; import 'package:stripe_example/screens/setup_future_payments/setup_future_payments_screen.dart'; import 'package:stripe_example/screens/wallets/apple_pay_screen.dart'; import 'package:stripe_example/screens/wallets/apple_pay_screen_plugin.dart'; @@ -45,11 +47,11 @@ class ExampleSection extends StatelessWidget { final bool expanded; const ExampleSection({ - Key? key, + super.key, required this.title, required this.children, this.expanded = false, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -72,7 +74,8 @@ class Example extends StatelessWidget { final WidgetBuilder builder; - Example({ + const Example({ + super.key, required this.title, required this.builder, this.style, @@ -88,7 +91,7 @@ class Example extends StatelessWidget { Navigator.push(context, route); }, title: Text(title, style: style), - leading: this.leading, + leading: leading, trailing: Row(mainAxisSize: MainAxisSize.min, children: [ PlatformIcons(supported: platformsSupported), Icon(Icons.chevron_right_rounded), @@ -101,6 +104,7 @@ class Example extends StatelessWidget { static List screens = [ ExampleSection( title: 'Payment Sheet', + expanded: true, children: [ Example( title: 'Single Step', @@ -141,7 +145,6 @@ class Example extends StatelessWidget { ], ) ], - expanded: true, ), ExampleSection(title: 'Customer sheet', children: [ Example( @@ -341,6 +344,16 @@ class Example extends StatelessWidget { builder: (contex) => UsBankAccountScreen(), platformsSupported: [DevicePlatform.android, DevicePlatform.ios], ), + Example( + title: 'Us bank accounts Direct debit(ACH)', + builder: (contex) => UsBankAccountDirectDebitScreen(), + platformsSupported: [DevicePlatform.android, DevicePlatform.ios], + ), + Example( + title: 'P24 Payment', + leading: SizedBox(), + builder: (context) => P24Screen(), + ), // TODO: uncomment when we can re-enable wechat pay // Example( // title: 'WeChat Pay', diff --git a/example/lib/screens/setup_future_payments/add_payment_method_screen_loader_mobile.dart b/example/lib/screens/setup_future_payments/add_payment_method_screen_loader_mobile.dart index e77f90741..94dfec887 100644 --- a/example/lib/screens/setup_future_payments/add_payment_method_screen_loader_mobile.dart +++ b/example/lib/screens/setup_future_payments/add_payment_method_screen_loader_mobile.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_stripe/flutter_stripe.dart' as stripe; import 'package:flutter_stripe/flutter_stripe.dart'; @@ -11,73 +10,79 @@ class AddPaymentMethodScreenLoader { Future display({ required BuildContext context, }) async { + final theme = Theme.of(context); + final scaffoldMessenger = ScaffoldMessenger.of(context); final setupKeys = await createSetupIntent(); - await Stripe.instance.initPaymentSheet( - paymentSheetParameters: SetupPaymentSheetParameters( - // Main params - setupIntentClientSecret: setupKeys.clientSecret, - customerId: setupKeys.customerId, - merchantDisplayName: 'Comover', - returnURL: 'flutterstripe://redirect', - allowsDelayedPaymentMethods: true, - allowsRemovalOfLastSavedPaymentMethod: false, - intentConfiguration: IntentConfiguration( - mode: IntentMode.setupMode( - currencyCode: 'EUR', - setupFutureUsage: IntentFutureUsage.OffSession, + if (context.mounted) { + await Stripe.instance.initPaymentSheet( + paymentSheetParameters: SetupPaymentSheetParameters( + // Main params + setupIntentClientSecret: setupKeys.clientSecret, + customerId: setupKeys.customerId, + merchantDisplayName: 'Comover', + returnURL: 'flutterstripe://redirect', + allowsDelayedPaymentMethods: true, + allowsRemovalOfLastSavedPaymentMethod: false, + intentConfiguration: IntentConfiguration( + mode: IntentMode.setupMode( + currencyCode: 'EUR', + setupFutureUsage: IntentFutureUsage.OffSession, + ), + paymentMethodTypes: ['card', 'bancontact'], ), - paymentMethodTypes: ['card', 'bancontact'], - ), - billingDetails: BillingDetails( - name: 'Flutter Stripe', - email: 'email@stripe.com', - phone: '+48888000888', - address: Address( - city: 'Houston', - country: 'US', - line1: '1459 Circle Drive', - line2: '', - state: 'Texas', - postalCode: '77063', + billingDetails: BillingDetails( + name: 'Flutter Stripe', + email: 'email@stripe.com', + phone: '+48888000888', + address: Address( + city: 'Houston', + country: 'US', + line1: '1459 Circle Drive', + line2: '', + state: 'Texas', + postalCode: '77063', + ), ), + billingDetailsCollectionConfiguration: + BillingDetailsCollectionConfiguration( + address: AddressCollectionMode.full, + ), + // Customer params + // Extra params + // applePay: const PaymentSheetApplePay( + // merchantCountryCode: 'BE', + // ), + // googlePay: PaymentSheetGooglePay( + // merchantCountryCode: 'BE', + // label: 'ADD', + // testEnv: kDebugMode, + // ), + primaryButtonLabel: 'confirm', + style: theme.brightness == Brightness.dark + ? ThemeMode.dark + : ThemeMode.light, + appearance: _buildSheetAppearance(context), ), - billingDetailsCollectionConfiguration: - BillingDetailsCollectionConfiguration( - address: AddressCollectionMode.full, - ), - // Customer params - // Extra params - // applePay: const PaymentSheetApplePay( - // merchantCountryCode: 'BE', - // ), - // googlePay: PaymentSheetGooglePay( - // merchantCountryCode: 'BE', - // label: 'ADD', - // testEnv: kDebugMode, - // ), - primaryButtonLabel: 'confirm', - style: Theme.of(context).brightness == Brightness.dark - ? ThemeMode.dark - : ThemeMode.light, - appearance: _buildSheetAppearance(context), - ), - ); + ); + } try { await Stripe.instance.presentPaymentSheet(); } catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (e is StripeException && context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( content: Text('Error from Stripe: ${e.error.localizedMessage}'), ), ); } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Unforeseen error: ${e}'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Unforeseen error: $e'), + ), + ); + } } } } diff --git a/example/lib/screens/setup_future_payments/add_payment_method_screen_loader_web.dart b/example/lib/screens/setup_future_payments/add_payment_method_screen_loader_web.dart index 8497d1994..8e4003e41 100644 --- a/example/lib/screens/setup_future_payments/add_payment_method_screen_loader_web.dart +++ b/example/lib/screens/setup_future_payments/add_payment_method_screen_loader_web.dart @@ -14,13 +14,15 @@ class AddPaymentMethodScreenLoader { required BuildContext context, }) async { final setupKeys = await createSetupIntent(); - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _AddPaymentMethodScreenWeb( - setupKeys: setupKeys, + if (context.mounted) { + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => _AddPaymentMethodScreenWeb( + setupKeys: setupKeys, + ), ), - ), - ); + ); + } } } @@ -93,8 +95,6 @@ class _AddPaymentMethodScreenPlatformState final theme = Theme.of(context); final isDark = theme.brightness == Brightness.dark; - print(theme.colorScheme.surface.toRgb()); - return ElementAppearance( theme: isDark ? ElementTheme.night : ElementTheme.stripe, variables: { diff --git a/example/lib/screens/themes.dart b/example/lib/screens/themes.dart index 8c0e1bb4c..4317630dc 100644 --- a/example/lib/screens/themes.dart +++ b/example/lib/screens/themes.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_stripe/flutter_stripe.dart'; class ThemeCardExample extends StatefulWidget { + const ThemeCardExample({super.key}); + @override _ThemeCardExampleState createState() => _ThemeCardExampleState(); } diff --git a/example/lib/screens/wallets/apple_pay_create_payment_method.dart b/example/lib/screens/wallets/apple_pay_create_payment_method.dart index e160ce99a..19100ef85 100644 --- a/example/lib/screens/wallets/apple_pay_create_payment_method.dart +++ b/example/lib/screens/wallets/apple_pay_create_payment_method.dart @@ -4,6 +4,8 @@ import 'package:stripe_example/widgets/example_scaffold.dart'; import 'package:stripe_example/widgets/response_card.dart'; class ApplePayCreatePaymentMethodScreen extends StatefulWidget { + const ApplePayCreatePaymentMethodScreen({super.key}); + @override _ApplePayScreenState createState() => _ApplePayScreenState(); } @@ -50,6 +52,7 @@ class _ApplePayScreenState extends State { Future _handlePayPress() async { // 1. create payment method + final scaffoldMessenger = ScaffoldMessenger.of(context); final paymentMethod = await Stripe.instance.createPlatformPayPaymentMethod( params: PlatformPayPaymentMethodParams.applePay( applePayParams: ApplePayParams( @@ -86,8 +89,10 @@ class _ApplePayScreenState extends State { response = paymentMethod; }); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - 'Success!: The payment method with id: ${paymentMethod.paymentMethod.id} was created successfully,'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: Text( + 'Success!: The payment method with id: ${paymentMethod.paymentMethod.id} was created successfully,'))); + } } } diff --git a/example/lib/screens/wallets/apple_pay_screen.dart b/example/lib/screens/wallets/apple_pay_screen.dart index 8d358bc6a..1ded3bb50 100644 --- a/example/lib/screens/wallets/apple_pay_screen.dart +++ b/example/lib/screens/wallets/apple_pay_screen.dart @@ -8,6 +8,8 @@ import 'package:stripe_example/widgets/example_scaffold.dart'; import '../../config.dart'; class ApplePayScreen extends StatefulWidget { + const ApplePayScreen({super.key}); + @override _ApplePayScreenState createState() => _ApplePayScreenState(); } @@ -120,6 +122,7 @@ class _ApplePayScreenState extends State { required List summaryItems, required List shippingMethods, }) async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 1. fetch Intent Client Secret from backend final response = await fetchPaymentIntentClientSecret(); @@ -144,14 +147,18 @@ class _ApplePayScreenState extends State { couponCode: 'Coupon'), ), ); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Apple Pay payment succesfully completed')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + const SnackBar( + content: Text('Apple Pay payment succesfully completed')), + ); + } } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: $e')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Error: $e')), + ); + } rethrow; } } diff --git a/example/lib/screens/wallets/apple_pay_screen_plugin.dart b/example/lib/screens/wallets/apple_pay_screen_plugin.dart index 9309c902f..525961329 100644 --- a/example/lib/screens/wallets/apple_pay_screen_plugin.dart +++ b/example/lib/screens/wallets/apple_pay_screen_plugin.dart @@ -16,6 +16,8 @@ const _paymentItems = [ ]; class ApplePayExternalPluginScreen extends StatefulWidget { + const ApplePayExternalPluginScreen({super.key}); + @override _ApplePayExternalPluginScreenState createState() => _ApplePayExternalPluginScreenState(); @@ -69,6 +71,7 @@ class _ApplePayExternalPluginScreenState } Future onApplePayResult(paymentResult) async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { //debugPrint(paymentResult.toString()); // 1. Get Stripe token from payment result @@ -90,14 +93,18 @@ class _ApplePayExternalPluginScreenState data: params, ); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Apple Pay payment succesfully completed')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + const SnackBar( + content: Text('Apple Pay payment succesfully completed')), + ); + } } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: $e')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Error: $e')), + ); + } } } diff --git a/example/lib/screens/wallets/google_pay_screen.dart b/example/lib/screens/wallets/google_pay_screen.dart index 58d41b8c0..82ebe452e 100644 --- a/example/lib/screens/wallets/google_pay_screen.dart +++ b/example/lib/screens/wallets/google_pay_screen.dart @@ -18,6 +18,8 @@ const _paymentItems = [ ]; class GooglePayScreen extends StatefulWidget { + const GooglePayScreen({super.key}); + @override _GooglePayScreenState createState() => _GooglePayScreenState(); } @@ -70,6 +72,7 @@ class _GooglePayScreenState extends State { } Future onGooglePayResult(paymentResult) async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { debugPrint(paymentResult.toString()); // 2. fetch Intent Client Secret from backend @@ -92,14 +95,18 @@ class _GooglePayScreenState extends State { data: params, ); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Google Pay payment succesfully completed')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + const SnackBar( + content: Text('Google Pay payment succesfully completed')), + ); + } } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: $e')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Error: $e')), + ); + } } } diff --git a/example/lib/screens/wallets/google_pay_stripe_screen.dart b/example/lib/screens/wallets/google_pay_stripe_screen.dart index ccffa0250..c9bc8708a 100644 --- a/example/lib/screens/wallets/google_pay_stripe_screen.dart +++ b/example/lib/screens/wallets/google_pay_stripe_screen.dart @@ -9,7 +9,7 @@ import 'package:stripe_example/config.dart'; import 'package:stripe_example/widgets/example_scaffold.dart'; class GooglePayStripeScreen extends StatefulWidget { - const GooglePayStripeScreen({Key? key}) : super(key: key); + const GooglePayStripeScreen({super.key}); @override _GooglePayStripeScreenState createState() => _GooglePayStripeScreenState(); @@ -17,8 +17,10 @@ class GooglePayStripeScreen extends StatefulWidget { class _GooglePayStripeScreenState extends State { Future startGooglePay() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); final googlePaySupported = await Stripe.instance .isPlatformPaySupported(googlePay: IsGooglePaySupportedParams()); + if (googlePaySupported) { try { // 1. fetch Intent Client Secret from backend @@ -39,29 +41,35 @@ class _GooglePayStripeScreenState extends State { // PresentGooglePayParams(clientSecret: clientSecret), ); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Google Pay payment succesfully completed')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + const SnackBar( + content: Text('Google Pay payment succesfully completed')), + ); + } } catch (e) { - if (e is StripeException) { + if (e is StripeException && context.mounted) { log('Error during google pay', error: e.error, stackTrace: StackTrace.current); - ScaffoldMessenger.of(context).showSnackBar( + scaffoldMessenger.showSnackBar( SnackBar(content: Text('Error: ${e.error}')), ); } else { log('Error during google pay', error: e, stackTrace: (e as Error?)?.stackTrace); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: $e')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Error: $e')), + ); + } } } } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Google pay is not supported on this device')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Google pay is not supported on this device')), + ); + } } } diff --git a/example/lib/screens/wallets/mobile_pay_create_payment_method_screen.dart b/example/lib/screens/wallets/mobile_pay_create_payment_method_screen.dart index 6217e2cfa..011540851 100644 --- a/example/lib/screens/wallets/mobile_pay_create_payment_method_screen.dart +++ b/example/lib/screens/wallets/mobile_pay_create_payment_method_screen.dart @@ -59,7 +59,7 @@ class _MobilePayCreatePaymentMethodScreenState Future _handlePayPress() async { // 1. create payment method - + final scaffoldMessenger = ScaffoldMessenger.of(context); final paymentMethod = await Stripe.instance.createPlatformPayPaymentMethod( params: PlatformPayPaymentMethodParams.web( options: PlatformPayWebPaymentRequestCreateOptions( @@ -76,9 +76,10 @@ class _MobilePayCreatePaymentMethodScreenState setState(() { response = paymentMethod; }); - - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - 'Success!: The payment method with id: ${paymentMethod.paymentMethod.id} was created successfully,'))); + if (context.mounted) { + scaffoldMessenger.showSnackBar(SnackBar( + content: Text( + 'Success!: The payment method with id: ${paymentMethod.paymentMethod.id} was created successfully,'))); + } } } diff --git a/example/lib/screens/wallets/open_apple_pay_setup_screen.dart b/example/lib/screens/wallets/open_apple_pay_setup_screen.dart index ea9c60d97..85dbd46b2 100644 --- a/example/lib/screens/wallets/open_apple_pay_setup_screen.dart +++ b/example/lib/screens/wallets/open_apple_pay_setup_screen.dart @@ -3,7 +3,7 @@ import 'package:flutter_stripe/flutter_stripe.dart'; import 'package:stripe_example/widgets/example_scaffold.dart'; class OpenApplePaySetup extends StatefulWidget { - const OpenApplePaySetup({Key? key}) : super(key: key); + const OpenApplePaySetup({super.key}); @override _OpenApplePaySetupState createState() => _OpenApplePaySetupState(); diff --git a/example/lib/screens/wallets/payment_sheet_screen_subscription.dart b/example/lib/screens/wallets/payment_sheet_screen_subscription.dart index c966ccdd9..32f8d384b 100644 --- a/example/lib/screens/wallets/payment_sheet_screen_subscription.dart +++ b/example/lib/screens/wallets/payment_sheet_screen_subscription.dart @@ -9,6 +9,8 @@ import 'package:stripe_example/widgets/example_scaffold.dart'; import 'package:stripe_example/widgets/loading_button.dart'; class ApplePayPaymentSheetScreen extends StatefulWidget { + const ApplePayPaymentSheetScreen({super.key}); + @override _PaymentSheetScreenState createState() => _PaymentSheetScreenState(); } @@ -65,6 +67,7 @@ class _PaymentSheetScreenState extends State { } Future initPaymentSheet() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 1. create payment intent on the server final data = await _createTestPaymentSheet(); @@ -153,14 +156,17 @@ class _PaymentSheetScreenState extends State { step = 1; }); } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error: $e')), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Error: $e')), + ); + } rethrow; } } Future confirmPayment() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); try { // 3. display the payment sheet. await Stripe.instance.presentPaymentSheet(); @@ -169,24 +175,30 @@ class _PaymentSheetScreenState extends State { step = 0; }); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Payment succesfully completed'), - ), - ); - } on Exception catch (e) { - if (e is StripeException) { - ScaffoldMessenger.of(context).showSnackBar( + if (context.mounted) { + scaffoldMessenger.showSnackBar( SnackBar( - content: Text('Error from Stripe: ${e.error.localizedMessage}'), + content: Text('Payment succesfully completed'), ), ); + } + } on Exception catch (e) { + if (e is StripeException) { + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Error from Stripe: ${e.error.localizedMessage}'), + ), + ); + } } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Unforeseen error: ${e}'), - ), - ); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Unforeseen error: $e'), + ), + ); + } } } } diff --git a/example/lib/utils.dart b/example/lib/utils.dart index cb05b2980..982ca833c 100644 --- a/example/lib/utils.dart +++ b/example/lib/utils.dart @@ -2,7 +2,7 @@ import 'dart:convert'; extension PrettyJson on Map { String toPrettyString() { - var encoder = new JsonEncoder.withIndent(" "); + var encoder = JsonEncoder.withIndent(" "); return encoder.convert(this); } } diff --git a/example/lib/widgets/dismiss_focus_overlay.dart b/example/lib/widgets/dismiss_focus_overlay.dart index 904cd6397..e704d56f7 100644 --- a/example/lib/widgets/dismiss_focus_overlay.dart +++ b/example/lib/widgets/dismiss_focus_overlay.dart @@ -3,7 +3,7 @@ import 'package:flutter/widgets.dart'; class DismissFocusOverlay extends StatelessWidget { final Widget? child; - const DismissFocusOverlay({Key? key, this.child}) : super(key: key); + const DismissFocusOverlay({super.key, this.child}); @override Widget build(BuildContext context) { return GestureDetector( diff --git a/example/lib/widgets/example_scaffold.dart b/example/lib/widgets/example_scaffold.dart index 77a07c3b2..552c94947 100644 --- a/example/lib/widgets/example_scaffold.dart +++ b/example/lib/widgets/example_scaffold.dart @@ -6,12 +6,12 @@ class ExampleScaffold extends StatelessWidget { final String title; final EdgeInsets? padding; const ExampleScaffold({ - Key? key, + super.key, this.children = const [], this.tags = const [], this.title = '', this.padding, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -24,18 +24,18 @@ class ExampleScaffold extends StatelessWidget { children: [ SizedBox(height: 60), Padding( + padding: EdgeInsets.symmetric(horizontal: 20), child: Text(title, style: Theme.of(context).textTheme.headlineSmall), - padding: EdgeInsets.symmetric(horizontal: 20), ), SizedBox(height: 4), Padding( + padding: EdgeInsets.symmetric(horizontal: 20), child: Row( children: [ for (final tag in tags) Chip(label: Text(tag)), ], ), - padding: EdgeInsets.symmetric(horizontal: 20), ), SizedBox(height: 20), if (padding != null) diff --git a/example/lib/widgets/loading_button.dart b/example/lib/widgets/loading_button.dart index 9a914a1f2..354c7536e 100644 --- a/example/lib/widgets/loading_button.dart +++ b/example/lib/widgets/loading_button.dart @@ -6,8 +6,7 @@ class LoadingButton extends StatefulWidget { final Future Function()? onPressed; final String text; - const LoadingButton({Key? key, required this.onPressed, required this.text}) - : super(key: key); + const LoadingButton({super.key, required this.onPressed, required this.text}); @override _LoadingButtonState createState() => _LoadingButtonState(); @@ -45,13 +44,13 @@ class _LoadingButtonState extends State { setState(() { _isLoading = true; }); + final scaffoldMessenger = ScaffoldMessenger.of(context); try { await widget.onPressed!(); } catch (e, s) { log(e.toString(), error: e, stackTrace: s); - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text('Error $e'))); + scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error $e'))); rethrow; } finally { setState(() { diff --git a/example/lib/widgets/platform_icons.dart b/example/lib/widgets/platform_icons.dart index 15676d634..63e01d7c7 100644 --- a/example/lib/widgets/platform_icons.dart +++ b/example/lib/widgets/platform_icons.dart @@ -6,17 +6,18 @@ enum DevicePlatform { ios, android, web } DevicePlatform? get selectedPlatform { if (kIsWeb) return DevicePlatform.web; - if (defaultTargetPlatform == TargetPlatform.android) + if (defaultTargetPlatform == TargetPlatform.android) { return DevicePlatform.android; + } if (defaultTargetPlatform == TargetPlatform.iOS) return DevicePlatform.ios; return null; } class PlatformIcons extends StatelessWidget { const PlatformIcons({ - Key? key, + super.key, required this.supported, - }) : super(key: key); + }); final List supported; @@ -36,10 +37,9 @@ class PlatformIcons extends StatelessWidget { class _PlatformIcon extends StatelessWidget { const _PlatformIcon({ - Key? key, required this.supported, required this.platform, - }) : super(key: key); + }); final List supported; final DevicePlatform platform; @@ -54,12 +54,12 @@ class _PlatformIcon extends StatelessWidget { color: isCurrent ? color : color.withOpacity(0.2), borderRadius: BorderRadius.circular(12), ), + padding: EdgeInsets.all(8), child: Icon( platform.icon, size: 16, color: isCurrent ? Colors.white60 : color, ), - padding: EdgeInsets.all(8), ); } } diff --git a/example/lib/widgets/response_card.dart b/example/lib/widgets/response_card.dart index 81cf3b043..249de61d7 100644 --- a/example/lib/widgets/response_card.dart +++ b/example/lib/widgets/response_card.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; class ResponseCard extends StatelessWidget { final String response; - const ResponseCard({Key? key, required this.response}) : super(key: key); + const ResponseCard({super.key, required this.response}); @override Widget build(BuildContext context) { diff --git a/packages/stripe/README.md b/packages/stripe/README.md index e77555bac..cc9dac4d0 100644 --- a/packages/stripe/README.md +++ b/packages/stripe/README.md @@ -60,16 +60,18 @@ This plugin requires several changes to be able to work on Android devices. Plea -dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivityStarter -dontwarn com.stripe.android.pushProvisioning.PushProvisioningEphemeralKeyProvider ``` -8. Rebuild the app, as the above changes don't update with hot reload +8. Add the following line to your `gradle.properties` file: [example](https://github.com/flutter-stripe/flutter_stripe/blob/master/example/android/gradle.properties) +```properties +android.enableR8.fullMode=false +``` +This will prevent crashes with the Stripe SDK on Android (see [issue](https://github.com/flutter-stripe/flutter_stripe/issues/1909)). + +9. Rebuild the app, as the above changes don't update with hot reload These changes are needed because the Android Stripe SDK requires the use of the AppCompat theme for their UI components and the Support Fragment Manager for the Payment Sheets If you are having troubles to make this package to work on Android, join [this discussion](https://github.com/flutter-stripe/flutter_stripe/discussions/538) to get some support. -##### Issue with latest Android plugin - -We are aware of an issue with `com.android.application` plugin version 8.0.0 and above. Do not upgrade to this version as it can crash the payment sheet in release builds. See [issue](https://github.com/flutter-stripe/flutter_stripe/issues/1909) to follow the progress. - #### iOS Compatible with apps targeting iOS 13 or above. @@ -85,8 +87,7 @@ For card scanning add the following to your Info.plist: ```xml NSCameraUsageDescription Scan your card to add it automatically -NSCameraUsageDescription -<string>To scan cards</string> +NSCameraUsageDescription To scan cards ``` diff --git a/packages/stripe/lib/src/stripe.dart b/packages/stripe/lib/src/stripe.dart index dccdd468c..6c19fd650 100644 --- a/packages/stripe/lib/src/stripe.dart +++ b/packages/stripe/lib/src/stripe.dart @@ -540,8 +540,7 @@ class Stripe { /// Collect the bankaccount details for the payment intent. /// - /// Only US bank accounts are supported. This method is only implemented for - /// iOS at the moment. + /// Only US bank accounts are supported. Future collectBankAccount({ /// Whether the clientsecret is associated with setup or paymentintent required bool isPaymentIntent, diff --git a/packages/stripe_js/lib/src/api/core/error.dart b/packages/stripe_js/lib/src/api/core/error.dart index 78d3f7233..e9add8aad 100644 --- a/packages/stripe_js/lib/src/api/core/error.dart +++ b/packages/stripe_js/lib/src/api/core/error.dart @@ -1,3 +1,5 @@ +// ignore_for_file: non_constant_identifier_names + import 'package:freezed_annotation/freezed_annotation.dart'; part 'error.freezed.dart'; diff --git a/packages/stripe_js/lib/src/api/payment_intents/confirm_payment_options.dart b/packages/stripe_js/lib/src/api/payment_intents/confirm_payment_options.dart index ebb7132ba..3d2a31e87 100644 --- a/packages/stripe_js/lib/src/api/payment_intents/confirm_payment_options.dart +++ b/packages/stripe_js/lib/src/api/payment_intents/confirm_payment_options.dart @@ -37,6 +37,7 @@ class ConfirmPaymentOptions with _$ConfirmPaymentOptions { class ConfirmPaymentParams with _$ConfirmPaymentParams { const factory ConfirmPaymentParams({ /// The url your customer will be directed to after they complete payment. + // ignore: non_constant_identifier_names required String return_url, }) = _ConfirmPaymentParams; diff --git a/packages/stripe_js/lib/src/api/payment_methods/payment_method.dart b/packages/stripe_js/lib/src/api/payment_methods/payment_method.dart index b40573d5e..c6704d8ac 100644 --- a/packages/stripe_js/lib/src/api/payment_methods/payment_method.dart +++ b/packages/stripe_js/lib/src/api/payment_methods/payment_method.dart @@ -1,3 +1,5 @@ +// ignore_for_file: constant_identifier_names + import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:stripe_js/stripe_api.dart'; diff --git a/packages/stripe_js/lib/src/api/setup_intents/confirm_setup_options.dart b/packages/stripe_js/lib/src/api/setup_intents/confirm_setup_options.dart index f5e30deb5..ee7540451 100644 --- a/packages/stripe_js/lib/src/api/setup_intents/confirm_setup_options.dart +++ b/packages/stripe_js/lib/src/api/setup_intents/confirm_setup_options.dart @@ -1,3 +1,5 @@ +// ignore_for_file: non_constant_identifier_names + import 'package:stripe_js/src/api/converters/js_converter.dart'; import 'package:stripe_js/stripe_api.dart'; diff --git a/packages/stripe_js/lib/src/api/tokens/token.dart b/packages/stripe_js/lib/src/api/tokens/token.dart index 1d30d531c..1efef4668 100644 --- a/packages/stripe_js/lib/src/api/tokens/token.dart +++ b/packages/stripe_js/lib/src/api/tokens/token.dart @@ -1,3 +1,5 @@ +// ignore_for_file: constant_identifier_names + import 'package:freezed_annotation/freezed_annotation.dart'; part 'token.freezed.dart'; diff --git a/packages/stripe_js/lib/src/js/stripe.dart b/packages/stripe_js/lib/src/js/stripe.dart index 81f70ed54..d8c026ca6 100644 --- a/packages/stripe_js/lib/src/js/stripe.dart +++ b/packages/stripe_js/lib/src/js/stripe.dart @@ -1,9 +1,11 @@ // ignore_for_file: non_constant_identifier_names @JS() +// ignore: unnecessary_library_name library types; import 'dart:js_interop'; + import 'package:stripe_js/stripe_js.dart'; extension type Stripe.__(JSObject o) { diff --git a/packages/stripe_js/lib/src/js/tokens/create_token.dart b/packages/stripe_js/lib/src/js/tokens/create_token.dart index ec587c766..190369b05 100644 --- a/packages/stripe_js/lib/src/js/tokens/create_token.dart +++ b/packages/stripe_js/lib/src/js/tokens/create_token.dart @@ -26,7 +26,7 @@ extension ExtensionCreateTokenMethod on Stripe { CardPaymentElement element, [ CreateTokenCardData? data, ]) { - final jsData = data != null ? data.toJson().jsify() : null; + final jsData = data?.toJson().jsify(); return _createToken(element, jsData) .toDart .then((response) => response.toDart); diff --git a/packages/stripe_js/lib/src/loader/stripe_loader.dart b/packages/stripe_js/lib/src/loader/stripe_loader.dart index c01c40e71..ba471e296 100644 --- a/packages/stripe_js/lib/src/loader/stripe_loader.dart +++ b/packages/stripe_js/lib/src/loader/stripe_loader.dart @@ -44,6 +44,6 @@ Future loadStripe() async { return _injectSrcScript( 'https://js.stripe.com/v3/', - 'stripe_${_version}', + 'stripe_$_version', ); } diff --git a/packages/stripe_js/lib/stripe_js.dart b/packages/stripe_js/lib/stripe_js.dart index 8b7ff6e8e..9dc0ba9f0 100644 --- a/packages/stripe_js/lib/stripe_js.dart +++ b/packages/stripe_js/lib/stripe_js.dart @@ -1,3 +1,5 @@ +// ignore_for_file: unnecessary_library_name + library stripe_js; export 'src/js/js.dart'; diff --git a/packages/stripe_js/test/src/js/elements/element_card_test.dart b/packages/stripe_js/test/src/js/elements/element_card_test.dart index efb929bda..3e2abb85d 100644 --- a/packages/stripe_js/test/src/js/elements/element_card_test.dart +++ b/packages/stripe_js/test/src/js/elements/element_card_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: library_annotations + @TestOn('browser') @Tags(["browser"]) @@ -45,7 +47,7 @@ void main() { test('calls on ready', () async { final child = HTMLDivElement(); - ; + document.body!.append(child); await Future.delayed(Duration(seconds: 4)); final card = elements.createCard(); diff --git a/packages/stripe_js/test/src/js/elements/element_payment_test.dart b/packages/stripe_js/test/src/js/elements/element_payment_test.dart index ac4cd5067..2a4de9938 100644 --- a/packages/stripe_js/test/src/js/elements/element_payment_test.dart +++ b/packages/stripe_js/test/src/js/elements/element_payment_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: library_annotations + @TestOn('browser') @Tags(["browser"]) @@ -51,7 +53,7 @@ void main() { test('calls on ready', () async { final child = HTMLDivElement(); - ; + document.body!.append(child); await Future.delayed(Duration(seconds: 4)); final card = elements.createPayment(); diff --git a/packages/stripe_js/test/src/js/elements/elements_base_test.dart b/packages/stripe_js/test/src/js/elements/elements_base_test.dart index bdd8d802f..cd8b725ef 100644 --- a/packages/stripe_js/test/src/js/elements/elements_base_test.dart +++ b/packages/stripe_js/test/src/js/elements/elements_base_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: library_annotations + @TestOn('browser') @Tags(["browser"]) diff --git a/packages/stripe_js/test/src/js/helpers/stripe_element_helper.dart b/packages/stripe_js/test/src/js/helpers/stripe_element_helper.dart index 50c35eacf..7ab3e4821 100644 --- a/packages/stripe_js/test/src/js/helpers/stripe_element_helper.dart +++ b/packages/stripe_js/test/src/js/helpers/stripe_element_helper.dart @@ -1,8 +1,7 @@ import 'dart:async'; +import 'dart:js_interop'; import 'package:stripe_js/stripe_js.dart'; - -import 'dart:js_interop'; import 'package:web/web.dart' as web; extension type JSIFrameElement(JSObject element) { @@ -26,17 +25,18 @@ extension ElementWaitFor on web.Element { String selectors, { Duration timeout = const Duration(seconds: 2), }) async { - final element = this.querySelector(selectors); + final element = querySelector(selectors); if (element != null) { return element; } final completer = Completer(); + // ignore: prefer_typing_uninitialized_variables late final mutationObserver; mutationObserver = web.MutationObserver( (JSArray entries, web.MutationObserver observer) { - web.console.log("${this.innerHTML}".toJS); - final element = this.querySelector(selectors); + web.console.log("$innerHTML".toJS); + final element = querySelector(selectors); if (element != null) { web.console.log("found".toJS); mutationObserver.disconnect(); @@ -46,9 +46,9 @@ extension ElementWaitFor on web.Element { web.console.log("searching".toJS); mutationObserver.observe(this, childList: true, subtree: true); - this.append(web.HTMLDivElement()); + append(web.HTMLDivElement()); await Future.delayed(Duration(seconds: 2)); - this.append(web.HTMLDivElement()); + append(web.HTMLDivElement()); return completer.future.timeout(timeout, onTimeout: () { mutationObserver.disconnect(); throw TimeoutException('Could not find element $selectors'); diff --git a/packages/stripe_js/test/src/js/payment_intents/retrieve_payment_intent_test.dart b/packages/stripe_js/test/src/js/payment_intents/retrieve_payment_intent_test.dart index 7ba81002d..4eb08f6f0 100644 --- a/packages/stripe_js/test/src/js/payment_intents/retrieve_payment_intent_test.dart +++ b/packages/stripe_js/test/src/js/payment_intents/retrieve_payment_intent_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: library_annotations + @TestOn('browser') @Tags(["browser"]) diff --git a/packages/stripe_js/test/src/js/payment_methods/create_payment_method_test.dart b/packages/stripe_js/test/src/js/payment_methods/create_payment_method_test.dart index ef1cee6ce..929ef8a86 100644 --- a/packages/stripe_js/test/src/js/payment_methods/create_payment_method_test.dart +++ b/packages/stripe_js/test/src/js/payment_methods/create_payment_method_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: library_annotations + @TestOn('browser') @Tags(["browser"]) diff --git a/packages/stripe_js/test/src/js/setup_intents/retrieve_setup_intent_test.dart b/packages/stripe_js/test/src/js/setup_intents/retrieve_setup_intent_test.dart index 922d736d2..2338f47d3 100644 --- a/packages/stripe_js/test/src/js/setup_intents/retrieve_setup_intent_test.dart +++ b/packages/stripe_js/test/src/js/setup_intents/retrieve_setup_intent_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: library_annotations + @TestOn('browser') @Tags(["browser"]) diff --git a/packages/stripe_js/test/src/js/stripe_test.dart b/packages/stripe_js/test/src/js/stripe_test.dart index ece552970..9fcb82ba5 100644 --- a/packages/stripe_js/test/src/js/stripe_test.dart +++ b/packages/stripe_js/test/src/js/stripe_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: library_annotations + @TestOn('browser') @Tags(["browser"]) diff --git a/packages/stripe_js/test/src/js/tokens/create_token_test.dart b/packages/stripe_js/test/src/js/tokens/create_token_test.dart index 72f9857a2..d862bf1da 100644 --- a/packages/stripe_js/test/src/js/tokens/create_token_test.dart +++ b/packages/stripe_js/test/src/js/tokens/create_token_test.dart @@ -1,10 +1,12 @@ +// ignore_for_file: library_annotations + @TestOn('browser') @Tags(["browser"]) -import 'package:web/web.dart'; import 'package:stripe_js/stripe_api.dart'; import 'package:stripe_js/stripe_js.dart'; import 'package:test/test.dart'; +import 'package:web/web.dart'; import '../helpers/helpers.dart'; diff --git a/packages/stripe_js/test/src/loader/initial_state_test.dart b/packages/stripe_js/test/src/loader/initial_state_test.dart index 83442d28c..91d98abb7 100644 --- a/packages/stripe_js/test/src/loader/initial_state_test.dart +++ b/packages/stripe_js/test/src/loader/initial_state_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: library_annotations + @TestOn('browser') @Tags(["browser"]) import 'dart:js'; diff --git a/packages/stripe_js/test/src/loader/stripe_loader_test.dart b/packages/stripe_js/test/src/loader/stripe_loader_test.dart index 4378b82c9..71573938a 100644 --- a/packages/stripe_js/test/src/loader/stripe_loader_test.dart +++ b/packages/stripe_js/test/src/loader/stripe_loader_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: library_annotations + @TestOn('browser') @Tags(["browser"]) import 'dart:js'; diff --git a/packages/stripe_platform_interface/lib/src/method_channel_stripe.dart b/packages/stripe_platform_interface/lib/src/method_channel_stripe.dart index ce017789f..32e1e86ac 100644 --- a/packages/stripe_platform_interface/lib/src/method_channel_stripe.dart +++ b/packages/stripe_platform_interface/lib/src/method_channel_stripe.dart @@ -486,7 +486,7 @@ class MethodChannelStripe extends StripePlatform { }) async { final result = await _methodChannel .invokeMapMethod('collectBankAccount', { - 'isPaymentIntent': isPaymentIntent, + 'intentType': isPaymentIntent, 'params': params.toJson(), 'clientSecret': clientSecret, }); diff --git a/packages/stripe_platform_interface/lib/src/models/ach_params.dart b/packages/stripe_platform_interface/lib/src/models/ach_params.dart index fa2108394..894cefe81 100644 --- a/packages/stripe_platform_interface/lib/src/models/ach_params.dart +++ b/packages/stripe_platform_interface/lib/src/models/ach_params.dart @@ -14,7 +14,7 @@ class CollectBankAccountParams with _$CollectBankAccountParams { /// Billingdetails of the account holder /// /// It is required to fill in the name in the billing details - required BillingDetails billingDetails, + required CollectBankAccountPaymentMethodData paymentMethodData, /// The paymentmethod type. At this point only method [PaymentMethodType.USBankAccount] /// is supported. @@ -26,6 +26,21 @@ class CollectBankAccountParams with _$CollectBankAccountParams { _$CollectBankAccountParamsFromJson(json); } +/// Specific payment method data needed for collecting the bank account of +/// an payment method +@freezed +class CollectBankAccountPaymentMethodData + with _$CollectBankAccountPaymentMethodData { + @JsonSerializable(explicitToJson: true) + const factory CollectBankAccountPaymentMethodData({ + required BillingDetails billingDetails, + }) = _CollectBankAccountPaymentMethodData; + + factory CollectBankAccountPaymentMethodData.fromJson( + Map json) => + _$CollectBankAccountPaymentMethodDataFromJson(json); +} + /// The type of payment intent used for collecting bank accoutn @freezed diff --git a/packages/stripe_platform_interface/lib/src/models/ach_params.freezed.dart b/packages/stripe_platform_interface/lib/src/models/ach_params.freezed.dart index eb76582c3..b85054d80 100644 --- a/packages/stripe_platform_interface/lib/src/models/ach_params.freezed.dart +++ b/packages/stripe_platform_interface/lib/src/models/ach_params.freezed.dart @@ -24,7 +24,8 @@ mixin _$CollectBankAccountParams { /// Billingdetails of the account holder /// /// It is required to fill in the name in the billing details - BillingDetails get billingDetails => throw _privateConstructorUsedError; + CollectBankAccountPaymentMethodData get paymentMethodData => + throw _privateConstructorUsedError; /// The paymentmethod type. At this point only method [PaymentMethodType.USBankAccount] /// is supported. @@ -43,9 +44,10 @@ abstract class $CollectBankAccountParamsCopyWith<$Res> { _$CollectBankAccountParamsCopyWithImpl<$Res, CollectBankAccountParams>; @useResult $Res call( - {BillingDetails billingDetails, PaymentMethodType paymentMethodType}); + {CollectBankAccountPaymentMethodData paymentMethodData, + PaymentMethodType paymentMethodType}); - $BillingDetailsCopyWith<$Res> get billingDetails; + $CollectBankAccountPaymentMethodDataCopyWith<$Res> get paymentMethodData; } /// @nodoc @@ -62,14 +64,14 @@ class _$CollectBankAccountParamsCopyWithImpl<$Res, @pragma('vm:prefer-inline') @override $Res call({ - Object? billingDetails = null, + Object? paymentMethodData = null, Object? paymentMethodType = null, }) { return _then(_value.copyWith( - billingDetails: null == billingDetails - ? _value.billingDetails - : billingDetails // ignore: cast_nullable_to_non_nullable - as BillingDetails, + paymentMethodData: null == paymentMethodData + ? _value.paymentMethodData + : paymentMethodData // ignore: cast_nullable_to_non_nullable + as CollectBankAccountPaymentMethodData, paymentMethodType: null == paymentMethodType ? _value.paymentMethodType : paymentMethodType // ignore: cast_nullable_to_non_nullable @@ -79,9 +81,10 @@ class _$CollectBankAccountParamsCopyWithImpl<$Res, @override @pragma('vm:prefer-inline') - $BillingDetailsCopyWith<$Res> get billingDetails { - return $BillingDetailsCopyWith<$Res>(_value.billingDetails, (value) { - return _then(_value.copyWith(billingDetails: value) as $Val); + $CollectBankAccountPaymentMethodDataCopyWith<$Res> get paymentMethodData { + return $CollectBankAccountPaymentMethodDataCopyWith<$Res>( + _value.paymentMethodData, (value) { + return _then(_value.copyWith(paymentMethodData: value) as $Val); }); } } @@ -96,10 +99,11 @@ abstract class _$$CollectBankAccountParamsImplCopyWith<$Res> @override @useResult $Res call( - {BillingDetails billingDetails, PaymentMethodType paymentMethodType}); + {CollectBankAccountPaymentMethodData paymentMethodData, + PaymentMethodType paymentMethodType}); @override - $BillingDetailsCopyWith<$Res> get billingDetails; + $CollectBankAccountPaymentMethodDataCopyWith<$Res> get paymentMethodData; } /// @nodoc @@ -115,14 +119,14 @@ class __$$CollectBankAccountParamsImplCopyWithImpl<$Res> @pragma('vm:prefer-inline') @override $Res call({ - Object? billingDetails = null, + Object? paymentMethodData = null, Object? paymentMethodType = null, }) { return _then(_$CollectBankAccountParamsImpl( - billingDetails: null == billingDetails - ? _value.billingDetails - : billingDetails // ignore: cast_nullable_to_non_nullable - as BillingDetails, + paymentMethodData: null == paymentMethodData + ? _value.paymentMethodData + : paymentMethodData // ignore: cast_nullable_to_non_nullable + as CollectBankAccountPaymentMethodData, paymentMethodType: null == paymentMethodType ? _value.paymentMethodType : paymentMethodType // ignore: cast_nullable_to_non_nullable @@ -136,7 +140,7 @@ class __$$CollectBankAccountParamsImplCopyWithImpl<$Res> @JsonSerializable(explicitToJson: true) class _$CollectBankAccountParamsImpl implements _CollectBankAccountParams { const _$CollectBankAccountParamsImpl( - {required this.billingDetails, + {required this.paymentMethodData, this.paymentMethodType = PaymentMethodType.USBankAccount}); factory _$CollectBankAccountParamsImpl.fromJson(Map json) => @@ -146,7 +150,7 @@ class _$CollectBankAccountParamsImpl implements _CollectBankAccountParams { /// /// It is required to fill in the name in the billing details @override - final BillingDetails billingDetails; + final CollectBankAccountPaymentMethodData paymentMethodData; /// The paymentmethod type. At this point only method [PaymentMethodType.USBankAccount] /// is supported. @@ -156,7 +160,7 @@ class _$CollectBankAccountParamsImpl implements _CollectBankAccountParams { @override String toString() { - return 'CollectBankAccountParams(billingDetails: $billingDetails, paymentMethodType: $paymentMethodType)'; + return 'CollectBankAccountParams(paymentMethodData: $paymentMethodData, paymentMethodType: $paymentMethodType)'; } @override @@ -164,8 +168,8 @@ class _$CollectBankAccountParamsImpl implements _CollectBankAccountParams { return identical(this, other) || (other.runtimeType == runtimeType && other is _$CollectBankAccountParamsImpl && - (identical(other.billingDetails, billingDetails) || - other.billingDetails == billingDetails) && + (identical(other.paymentMethodData, paymentMethodData) || + other.paymentMethodData == paymentMethodData) && (identical(other.paymentMethodType, paymentMethodType) || other.paymentMethodType == paymentMethodType)); } @@ -173,7 +177,7 @@ class _$CollectBankAccountParamsImpl implements _CollectBankAccountParams { @JsonKey(ignore: true) @override int get hashCode => - Object.hash(runtimeType, billingDetails, paymentMethodType); + Object.hash(runtimeType, paymentMethodData, paymentMethodType); @JsonKey(ignore: true) @override @@ -192,7 +196,7 @@ class _$CollectBankAccountParamsImpl implements _CollectBankAccountParams { abstract class _CollectBankAccountParams implements CollectBankAccountParams { const factory _CollectBankAccountParams( - {required final BillingDetails billingDetails, + {required final CollectBankAccountPaymentMethodData paymentMethodData, final PaymentMethodType paymentMethodType}) = _$CollectBankAccountParamsImpl; @@ -204,7 +208,7 @@ abstract class _CollectBankAccountParams implements CollectBankAccountParams { /// Billingdetails of the account holder /// /// It is required to fill in the name in the billing details - BillingDetails get billingDetails; + CollectBankAccountPaymentMethodData get paymentMethodData; @override /// The paymentmethod type. At this point only method [PaymentMethodType.USBankAccount] @@ -216,6 +220,175 @@ abstract class _CollectBankAccountParams implements CollectBankAccountParams { get copyWith => throw _privateConstructorUsedError; } +CollectBankAccountPaymentMethodData + _$CollectBankAccountPaymentMethodDataFromJson(Map json) { + return _CollectBankAccountPaymentMethodData.fromJson(json); +} + +/// @nodoc +mixin _$CollectBankAccountPaymentMethodData { + BillingDetails get billingDetails => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $CollectBankAccountPaymentMethodDataCopyWith< + CollectBankAccountPaymentMethodData> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CollectBankAccountPaymentMethodDataCopyWith<$Res> { + factory $CollectBankAccountPaymentMethodDataCopyWith( + CollectBankAccountPaymentMethodData value, + $Res Function(CollectBankAccountPaymentMethodData) then) = + _$CollectBankAccountPaymentMethodDataCopyWithImpl<$Res, + CollectBankAccountPaymentMethodData>; + @useResult + $Res call({BillingDetails billingDetails}); + + $BillingDetailsCopyWith<$Res> get billingDetails; +} + +/// @nodoc +class _$CollectBankAccountPaymentMethodDataCopyWithImpl<$Res, + $Val extends CollectBankAccountPaymentMethodData> + implements $CollectBankAccountPaymentMethodDataCopyWith<$Res> { + _$CollectBankAccountPaymentMethodDataCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? billingDetails = null, + }) { + return _then(_value.copyWith( + billingDetails: null == billingDetails + ? _value.billingDetails + : billingDetails // ignore: cast_nullable_to_non_nullable + as BillingDetails, + ) as $Val); + } + + @override + @pragma('vm:prefer-inline') + $BillingDetailsCopyWith<$Res> get billingDetails { + return $BillingDetailsCopyWith<$Res>(_value.billingDetails, (value) { + return _then(_value.copyWith(billingDetails: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$CollectBankAccountPaymentMethodDataImplCopyWith<$Res> + implements $CollectBankAccountPaymentMethodDataCopyWith<$Res> { + factory _$$CollectBankAccountPaymentMethodDataImplCopyWith( + _$CollectBankAccountPaymentMethodDataImpl value, + $Res Function(_$CollectBankAccountPaymentMethodDataImpl) then) = + __$$CollectBankAccountPaymentMethodDataImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({BillingDetails billingDetails}); + + @override + $BillingDetailsCopyWith<$Res> get billingDetails; +} + +/// @nodoc +class __$$CollectBankAccountPaymentMethodDataImplCopyWithImpl<$Res> + extends _$CollectBankAccountPaymentMethodDataCopyWithImpl<$Res, + _$CollectBankAccountPaymentMethodDataImpl> + implements _$$CollectBankAccountPaymentMethodDataImplCopyWith<$Res> { + __$$CollectBankAccountPaymentMethodDataImplCopyWithImpl( + _$CollectBankAccountPaymentMethodDataImpl _value, + $Res Function(_$CollectBankAccountPaymentMethodDataImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? billingDetails = null, + }) { + return _then(_$CollectBankAccountPaymentMethodDataImpl( + billingDetails: null == billingDetails + ? _value.billingDetails + : billingDetails // ignore: cast_nullable_to_non_nullable + as BillingDetails, + )); + } +} + +/// @nodoc + +@JsonSerializable(explicitToJson: true) +class _$CollectBankAccountPaymentMethodDataImpl + implements _CollectBankAccountPaymentMethodData { + const _$CollectBankAccountPaymentMethodDataImpl( + {required this.billingDetails}); + + factory _$CollectBankAccountPaymentMethodDataImpl.fromJson( + Map json) => + _$$CollectBankAccountPaymentMethodDataImplFromJson(json); + + @override + final BillingDetails billingDetails; + + @override + String toString() { + return 'CollectBankAccountPaymentMethodData(billingDetails: $billingDetails)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CollectBankAccountPaymentMethodDataImpl && + (identical(other.billingDetails, billingDetails) || + other.billingDetails == billingDetails)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, billingDetails); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$CollectBankAccountPaymentMethodDataImplCopyWith< + _$CollectBankAccountPaymentMethodDataImpl> + get copyWith => __$$CollectBankAccountPaymentMethodDataImplCopyWithImpl< + _$CollectBankAccountPaymentMethodDataImpl>(this, _$identity); + + @override + Map toJson() { + return _$$CollectBankAccountPaymentMethodDataImplToJson( + this, + ); + } +} + +abstract class _CollectBankAccountPaymentMethodData + implements CollectBankAccountPaymentMethodData { + const factory _CollectBankAccountPaymentMethodData( + {required final BillingDetails billingDetails}) = + _$CollectBankAccountPaymentMethodDataImpl; + + factory _CollectBankAccountPaymentMethodData.fromJson( + Map json) = + _$CollectBankAccountPaymentMethodDataImpl.fromJson; + + @override + BillingDetails get billingDetails; + @override + @JsonKey(ignore: true) + _$$CollectBankAccountPaymentMethodDataImplCopyWith< + _$CollectBankAccountPaymentMethodDataImpl> + get copyWith => throw _privateConstructorUsedError; +} + VerifyMicroDepositsParams _$VerifyMicroDepositsParamsFromJson( Map json) { return _VerifyMicroDepositsParams.fromJson(json); diff --git a/packages/stripe_platform_interface/lib/src/models/ach_params.g.dart b/packages/stripe_platform_interface/lib/src/models/ach_params.g.dart index 35edc1990..e9a444b13 100644 --- a/packages/stripe_platform_interface/lib/src/models/ach_params.g.dart +++ b/packages/stripe_platform_interface/lib/src/models/ach_params.g.dart @@ -9,8 +9,8 @@ part of 'ach_params.dart'; _$CollectBankAccountParamsImpl _$$CollectBankAccountParamsImplFromJson( Map json) => _$CollectBankAccountParamsImpl( - billingDetails: BillingDetails.fromJson( - json['billingDetails'] as Map), + paymentMethodData: CollectBankAccountPaymentMethodData.fromJson( + json['paymentMethodData'] as Map), paymentMethodType: $enumDecodeNullable( _$PaymentMethodTypeEnumMap, json['paymentMethodType']) ?? PaymentMethodType.USBankAccount, @@ -19,7 +19,7 @@ _$CollectBankAccountParamsImpl _$$CollectBankAccountParamsImplFromJson( Map _$$CollectBankAccountParamsImplToJson( _$CollectBankAccountParamsImpl instance) => { - 'billingDetails': instance.billingDetails.toJson(), + 'paymentMethodData': instance.paymentMethodData.toJson(), 'paymentMethodType': _$PaymentMethodTypeEnumMap[instance.paymentMethodType]!, }; @@ -49,6 +49,20 @@ const _$PaymentMethodTypeEnumMap = { PaymentMethodType.Unknown: 'Unknown', }; +_$CollectBankAccountPaymentMethodDataImpl + _$$CollectBankAccountPaymentMethodDataImplFromJson( + Map json) => + _$CollectBankAccountPaymentMethodDataImpl( + billingDetails: BillingDetails.fromJson( + json['billingDetails'] as Map), + ); + +Map _$$CollectBankAccountPaymentMethodDataImplToJson( + _$CollectBankAccountPaymentMethodDataImpl instance) => + { + 'billingDetails': instance.billingDetails.toJson(), + }; + _$VerifyMicroDepositsParamsImpl _$$VerifyMicroDepositsParamsImplFromJson( Map json) => _$VerifyMicroDepositsParamsImpl( diff --git a/packages/stripe_web/lib/flutter_stripe_web.dart b/packages/stripe_web/lib/flutter_stripe_web.dart index 6758f1f21..38678d4d6 100644 --- a/packages/stripe_web/lib/flutter_stripe_web.dart +++ b/packages/stripe_web/lib/flutter_stripe_web.dart @@ -1,4 +1,4 @@ -library stripe_web; +library; export 'package:stripe_js/stripe_api.dart' show ConfirmPaymentParams, ConfirmSetupParams; diff --git a/packages/stripe_web/lib/src/web_stripe.dart b/packages/stripe_web/lib/src/web_stripe.dart index 51f0dfee7..b39de4df8 100644 --- a/packages/stripe_web/lib/src/web_stripe.dart +++ b/packages/stripe_web/lib/src/web_stripe.dart @@ -1,7 +1,6 @@ //@dart=2.12 import 'dart:async'; import 'dart:developer' as dev; -import 'package:web/web.dart' as web; import 'dart:ui' as ui; import 'package:flutter/widgets.dart'; @@ -10,6 +9,7 @@ import 'package:flutter_stripe_web/platform_pay_button.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:stripe_js/stripe_api.dart' as stripe_js; import 'package:stripe_js/stripe_js.dart' as stripe_js; +import 'package:web/web.dart' as web; import 'parser/payment_intent.dart'; import 'parser/payment_methods.dart'; @@ -54,7 +54,7 @@ class WebStripe extends StripePlatform { String? urlScheme, bool? setReturnUrlSchemeOnAndroid, }) async { - this._urlScheme = urlScheme; + _urlScheme = urlScheme; if (__stripe != null) { // Check if the new stripeAccountId is different @@ -105,7 +105,6 @@ class WebStripe extends StripePlatform { if (response.error != null) { throw response.error!; } - print(response); return response.paymentMethod!.parse(); } catch (e) { dev.log('Error $e'); @@ -552,7 +551,7 @@ class WebStripe extends StripePlatform { required PlatformPayPaymentMethodParams params, bool usesDeprecatedTokenFlow = false, }) { - if (!(params is PlatformPayPaymentMethodParamsWeb)) { + if (params is! PlatformPayPaymentMethodParamsWeb) { throw WebUnsupportedError( "platformPayCreatePaymentMethod - ${params.runtimeType} is not supported on web"); } @@ -658,7 +657,7 @@ class WebUnsupportedError extends Error implements UnsupportedError { } extension CanMakePayment on stripe_js.PaymentRequest { - Future get isPaymentAvailable => this.canMakePayment().then((value) => + Future get isPaymentAvailable => canMakePayment().then((value) => value?.applePay == true || value?.googlePay == true || value?.link == true); diff --git a/packages/stripe_web/lib/src/widgets/card_field.dart b/packages/stripe_web/lib/src/widgets/card_field.dart index e2b59fab3..24509d8c6 100644 --- a/packages/stripe_web/lib/src/widgets/card_field.dart +++ b/packages/stripe_web/lib/src/widgets/card_field.dart @@ -18,7 +18,7 @@ class WebCardField extends StatefulWidget { WebCardField({ required this.controller, this.onCardChanged, - Key? key, + super.key, this.onFocus, this.style, this.placeholder, @@ -33,8 +33,7 @@ class WebCardField extends StatefulWidget { constraints = (width != null || height != null) ? constraints?.tighten(width: width, height: height) ?? BoxConstraints.tightFor(width: width, height: height) - : constraints, - super(key: key); + : constraints; final BoxConstraints? constraints; final CardFocusCallback? onFocus; @@ -53,6 +52,7 @@ class WebCardField extends StatefulWidget { class WebStripeCardState extends State with CardFieldContext { CardEditController get controller => widget.controller; + @override void initState() { ui.platformViewRegistry.registerViewFactory( 'stripe_card', @@ -158,7 +158,7 @@ class WebStripeCardState extends State with CardFieldContext { return js.CardElementOptions( style: { 'base': { - if (textColor != null) 'color': '${colorToCssString(textColor)}' + if (textColor != null) 'color': colorToCssString(textColor) } }, hidePostalCode: !widget.enablePostalCode, diff --git a/packages/stripe_web/lib/src/widgets/card_field_io.dart b/packages/stripe_web/lib/src/widgets/card_field_io.dart index 8b440a46a..69482e417 100644 --- a/packages/stripe_web/lib/src/widgets/card_field_io.dart +++ b/packages/stripe_web/lib/src/widgets/card_field_io.dart @@ -5,7 +5,7 @@ class WebCardField extends StatelessWidget { const WebCardField({ required this.controller, this.onCardChanged, - Key? key, + super.key, this.onFocus, this.style, this.placeholder, @@ -16,7 +16,7 @@ class WebCardField extends StatelessWidget { this.focusNode, this.autofocus = false, this.dangerouslyUpdateFullCardDetails = false, - }) : super(key: key); + }); final BoxConstraints? constraints; final CardFocusCallback? onFocus; diff --git a/packages/stripe_web/lib/src/widgets/express_checkout_element.dart b/packages/stripe_web/lib/src/widgets/express_checkout_element.dart index 4b185f4a0..0c778e44b 100644 --- a/packages/stripe_web/lib/src/widgets/express_checkout_element.dart +++ b/packages/stripe_web/lib/src/widgets/express_checkout_element.dart @@ -19,7 +19,7 @@ class ExpressCheckoutElement extends StatefulWidget { final js.ExpressCheckoutLayout? layout; final ValueChanged onConfirm; - ExpressCheckoutElement({ + const ExpressCheckoutElement({ super.key, required this.clientSecret, this.height, @@ -88,7 +88,7 @@ class ExpressCheckoutElementState extends State { ..id = 'express-checkout-element' ..style.border = 'none' ..style.width = '100%' - ..style.height = '${height}' + ..style.height = '$height' ..style.overflow = 'scroll' ..style.overflowX = 'hidden'; diff --git a/packages/stripe_web/lib/src/widgets/payment_element.dart b/packages/stripe_web/lib/src/widgets/payment_element.dart index 21bfb07ce..1ef4ea4ba 100644 --- a/packages/stripe_web/lib/src/widgets/payment_element.dart +++ b/packages/stripe_web/lib/src/widgets/payment_element.dart @@ -44,7 +44,7 @@ class PaymentElement extends StatefulWidget { final js.PaymentElementWalletOptions? wallets; final js.PaymentElementApplePayOptions? applePay; - PaymentElement({ + const PaymentElement({ super.key, required this.clientSecret, this.customerSessionClientSecret, @@ -128,7 +128,7 @@ class PaymentElementState extends State { ..id = 'payment-element' ..style.border = 'none' ..style.width = '100%' - ..style.height = '${height}'; + ..style.height = '$height'; elements = WebStripe.js.elements(createOptions()); mutationObserver!.observe( diff --git a/packages/stripe_web/lib/src/widgets/platform_pay_button.dart b/packages/stripe_web/lib/src/widgets/platform_pay_button.dart index 04c78a752..e80056e0b 100644 --- a/packages/stripe_web/lib/src/widgets/platform_pay_button.dart +++ b/packages/stripe_web/lib/src/widgets/platform_pay_button.dart @@ -17,7 +17,7 @@ class WebPlatformPayButton extends StatefulWidget { this.constraints, this.type, this.style, - required ui.VoidCallback this.onPressed}); + required this.onPressed}); final PlatformPayWebPaymentRequestCreateOptions paymentRequestCreateOptions; final PlatformButtonType? type; @@ -40,6 +40,8 @@ class _WebPlatformPayButtonState extends State { if (web.document.getElementById('platform-pay-button') != null) { mutationObserver.disconnect(); + final currentTheme = Theme.of(context); + PaymentRequest paymentRequest = WebStripe.js .paymentRequest((widget.paymentRequestCreateOptions).toJS()); @@ -49,7 +51,7 @@ class _WebPlatformPayButtonState extends State { paymentRequest: paymentRequest.js, style: JsPaymentRequestButtonElementStyle( paymentRequestButton: PaymentRequestButtonStyleOptions( - theme: theme(Theme.of(context).brightness), + theme: theme(currentTheme.brightness), type: type, height: '${constraints.maxHeight}px', )))) @@ -69,8 +71,8 @@ class _WebPlatformPayButtonState extends State { @override void initState() { // ignore: undefined_prefixed_name - ui.platformViewRegistry.registerViewFactory('stripe_platform_pay_button', - (int viewId) => _divElement); + ui.platformViewRegistry.registerViewFactory( + 'stripe_platform_pay_button', (int viewId) => _divElement); mutationObserver.observe( web.document, diff --git a/pubspec.yaml b/pubspec.yaml index 019607d10..a69e58888 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,3 +5,4 @@ environment: dev_dependencies: melos: ^3.1.0 + flutter_lints: ^5.0.0