### Run Pay Example Source: https://github.com/google-pay/flutter-plugin/blob/main/CONTRIBUTING.md Navigate to the example directory and run the Flutter application to test the pay example. ```bash cd pay/example flutter run ``` -------------------------------- ### Run End-to-End Tests Source: https://github.com/google-pay/flutter-plugin/blob/main/CONTRIBUTING.md Execute end-to-end tests by running the 'flutter drive' command from the example directory, specifying the driver and target files. ```bash cd pay/example flutter drive \ --driver=test_driver/integration_test.dart \ --target=integration_test/payment_flow_test.dart ``` -------------------------------- ### Instantiate Payment Client and Define Payment Items Source: https://github.com/google-pay/flutter-plugin/blob/main/pay/README.md Manually instantiate the Pay client and define payment items for more granular control over payment requests. This setup is useful when you need to manage the payment flow beyond the basic button integration. ```dart import 'package:pay/pay.dart'; const _paymentItems = [ PaymentItem( label: 'Total', amount: '99.99', status: PaymentItemStatus.final_price, ) ]; final Pay _payClient = Pay({ PayProvider.google_pay: payment_configurations.defaultGooglePayConfig, PayProvider.apple_pay: payment_configurations.defaultApplePayConfig, }); ``` -------------------------------- ### Display Apple Pay and Google Pay Buttons Source: https://github.com/google-pay/flutter-plugin/blob/main/pay/README.md This example demonstrates how to display both Apple Pay and Google Pay buttons using pre-configured JSON strings. Ensure you have the respective payment configuration strings defined elsewhere. ```dart import 'package:pay/pay.dart'; const _paymentItems = [ PaymentItem( label: 'Total', amount: '99.99', status: PaymentItemStatus.final_price, ) ]; ApplePayButton( paymentConfiguration: PaymentConfiguration.fromJsonString( defaultApplePayConfigString), paymentItems: _paymentItems, style: ApplePayButtonStyle.black, type: ApplePayButtonType.buy, margin: const EdgeInsets.only(top: 15.0), onPaymentResult: onApplePayResult, loadingIndicator: const Center( child: CircularProgressIndicator(), ), ), GooglePayButton( paymentConfiguration: PaymentConfiguration.fromJsonString( defaultGooglePayConfigString), paymentItems: _paymentItems, type: GooglePayButtonType.buy, margin: const EdgeInsets.only(top: 15.0), onPaymentResult: onGooglePayResult, loadingIndicator: const Center( child: CircularProgressIndicator(), ), ), void onApplePayResult(paymentResult) { // Send the resulting Apple Pay token to your server / PSP } void onGooglePayResult(paymentResult) { // Send the resulting Google Pay token to your server / PSP } ``` -------------------------------- ### Conventional Commits Specification Example Source: https://github.com/google-pay/flutter-plugin/blob/main/CONTRIBUTING.md An example commit message following the Conventional Commits specification format. ```text fix(pay_android): fixed a bug! ``` -------------------------------- ### Check User Payment Availability with FutureBuilder Source: https://github.com/google-pay/flutter-plugin/blob/main/pay/README.md Use the `userCanPay` method to determine if a user can initiate a payment with a specific provider. This example demonstrates integrating the result into a `FutureBuilder` to conditionally display a payment button. ```dart @override Widget build(BuildContext context) { return FutureBuilder( future: _payClient.userCanPay(PayProvider.apple_pay), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { if (snapshot.data == true) { return RawApplePayButton( type: ApplePayButtonType.buy, onPressed: _onApplePayPressed); } else { // userCanPay returned false // Consider showing an alternative payment method } } else { // The operation hasn't finished loading // Consider showing a loading indicator } }, ); } ``` -------------------------------- ### Load Google Pay Configuration from Asset Source: https://github.com/google-pay/flutter-plugin/blob/main/pay/README.md This example shows how to load Google Pay payment configurations from a JSON file located in your Flutter project's assets folder using `PaymentConfiguration.fromAsset`. It utilizes a `FutureBuilder` to handle the asynchronous loading. ```dart final Future _googlePayConfigFuture = PaymentConfiguration.fromAsset('google_pay_config.json'); FutureBuilder( future: _googlePayConfigFuture, builder: (context, snapshot) => snapshot.hasData ? GooglePayButton( paymentConfiguration: snapshot.data!, paymentItems: _paymentItems, type: GooglePayButtonType.buy, margin: const EdgeInsets.only(top: 15.0), onPaymentResult: onGooglePayResult, loadingIndicator: const Center( child: CircularProgressIndicator(), ), ) : const SizedBox.shrink()), ``` -------------------------------- ### Initialize Pay Client and Check Payment Readiness Source: https://context7.com/google-pay/flutter-plugin/llms.txt Demonstrates how to initialize the Pay client with configurations for both Google Pay and Apple Pay, and how to check if the user can pay with a specific provider before initiating the payment selector. ```dart import 'package:pay/pay.dart'; // Define payment items for the transaction const _paymentItems = [ PaymentItem( label: 'Total', amount: '99.99', status: PaymentItemStatus.final_price, ) ]; // Create payment configurations final googlePayConfig = PaymentConfiguration.fromJsonString('''{ "provider": "google_pay", "data": { "environment": "TEST", "apiVersion": 2, "apiVersionMinor": 0, "allowedPaymentMethods": [{ "type": "CARD", "tokenizationSpecification": { "type": "PAYMENT_GATEWAY", "parameters": { "gateway": "example", "gatewayMerchantId": "exampleGatewayMerchantId" } }, "parameters": { "allowedCardNetworks": ["VISA", "MASTERCARD"], "allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"] } }], "merchantInfo": {"merchantName": "Example Merchant"}, "transactionInfo": {"countryCode": "US", "currencyCode": "USD"} } }'''); final applePayConfig = PaymentConfiguration.fromJsonString('''{ "provider": "apple_pay", "data": { "merchantIdentifier": "merchant.com.example", "displayName": "Example Store", "merchantCapabilities": ["3DS", "debit", "credit"], "supportedNetworks": ["amex", "visa", "masterCard"], "countryCode": "US", "currencyCode": "USD" } }'''); // Initialize the Pay client with configurations for both providers final Pay _payClient = Pay({ PayProvider.google_pay: googlePayConfig, PayProvider.apple_pay: applePayConfig, }); // Check if user can pay with a specific provider Future checkAndPay() async { final canPayWithGoogle = await _payClient.userCanPay(PayProvider.google_pay); final canPayWithApple = await _payClient.userCanPay(PayProvider.apple_pay); if (canPayWithGoogle) { final result = await _payClient.showPaymentSelector( PayProvider.google_pay, _paymentItems, ); // Send result to your server/PSP print('Payment token: ${result['paymentMethodData']}'); } } ``` -------------------------------- ### Initialize Payment Configuration and Button Source: https://github.com/google-pay/flutter-plugin/blob/main/pay_android/README.md Use this snippet to initialize the PaymentConfiguration from a JSON string and display a RawGooglePayButton for the 'buy' action. Ensure you replace '' with your actual payment configuration. ```dart final PaymentConfiguration configuration = PaymentConfiguration.fromJsonString(''); RawGooglePayButton( paymentConfiguration: configuration, type: GooglePayButtonType.buy), ``` -------------------------------- ### Load Payment Configuration from JSON String Source: https://context7.com/google-pay/flutter-plugin/llms.txt Illustrates how to load payment configurations directly from a JSON string, which is useful for dynamically providing configuration details, such as for production environments. ```dart import 'package:pay/pay.dart'; // Load configuration from a JSON string (useful for remote configurations) final configFromString = PaymentConfiguration.fromJsonString('''{ "provider": "google_pay", "data": { "environment": "PRODUCTION", "apiVersion": 2, "apiVersionMinor": 0, "allowedPaymentMethods": [{ "type": "CARD", "tokenizationSpecification": { "type": "PAYMENT_GATEWAY", "parameters": { "gateway": "stripe", "stripe:publishableKey": "pk_live_xxx" } }, "parameters": { "allowedCardNetworks": ["VISA", "MASTERCARD", "AMEX"], "allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"], "billingAddressRequired": true, "billingAddressParameters": { "format": "FULL", "phoneNumberRequired": true } } }], "merchantInfo": {"merchantName": "My Store"}, "transactionInfo": {"countryCode": "US", "currencyCode": "USD"} } }'''); ``` -------------------------------- ### Show Payment Selector Source: https://github.com/google-pay/flutter-plugin/blob/main/pay_platform_interface/README.md Initiates the payment process by displaying the payment selector to the user. ```APIDOC ## POST /showPaymentSelector ### Description Shows the payment selector to users and starts the payment process. ### Method POST ### Endpoint /showPaymentSelector ### Parameters #### Request Body - **paymentConfiguration** (PaymentConfiguration) - Required - Provider-specific payment configuration. - **paymentItems** (List) - Required - A list of payment items (e.g., articles, taxes, subtotal). ### Request Example ```json { "paymentConfiguration": { "provider": "PayProvider.google_pay", "data": {} }, "paymentItems": [ { "label": "Subtotal", "amount": "100.00" } ] } ``` ### Response #### Success Response (200) - **Map** - A map containing the payment result. #### Response Example ```json { "transactionId": "12345", "status": "success" } ``` ``` -------------------------------- ### Load Payment Configuration with Custom Loader Source: https://context7.com/google-pay/flutter-plugin/llms.txt Demonstrates how to use a custom loader function to fetch payment configurations from a remote source, such as a backend API. This allows for dynamic loading of configurations. ```dart import 'package:pay/pay.dart'; import 'dart:convert'; import 'package:http/http.dart' as http; // Load with custom loader (e.g., from file system or remote API) Future> _remoteLoader(String url) async { // Fetch configuration from your backend final response = await http.get(Uri.parse(url)); return jsonDecode(response.body); } final configFromRemote = await PaymentConfiguration.fromAsset( 'https://api.example.com/payment-config', profileLoader: _remoteLoader, ); ``` -------------------------------- ### Load Payment Configuration from Asset File Source: https://context7.com/google-pay/flutter-plugin/llms.txt Shows how to load payment configurations from a JSON file located in the application's assets folder. This is a common approach for managing static configuration data. ```dart import 'package:pay/pay.dart'; // Load configuration from an asset file final Future configFromAsset = PaymentConfiguration.fromAsset('google_pay_config.json'); ``` -------------------------------- ### Run Unit Tests Source: https://github.com/google-pay/flutter-plugin/blob/main/CONTRIBUTING.md Execute unit tests for a specific plugin by running the 'flutter test' command from the plugin's root directory. ```bash cd pay flutter test ``` -------------------------------- ### Add pay_ios Dependency to pubspec.yaml Source: https://github.com/google-pay/flutter-plugin/blob/main/pay_ios/README.md To use this package directly, add it as a dependency in your pubspec.yaml file. Ensure you use a compatible version. ```yaml dependencies: pay_ios: ^1.1.0 ``` -------------------------------- ### Add pay_platform_interface Dependency Source: https://github.com/google-pay/flutter-plugin/blob/main/pay_platform_interface/README.md To implement a new platform-specific payment plugin, add this package as a dependency in your pubspec.yaml file. ```yaml dependencies: pay_platform_interface: ^2.0.0 ``` -------------------------------- ### Add pay_android Dependency Source: https://github.com/google-pay/flutter-plugin/blob/main/pay_android/README.md Add this package as a dependency in your pubspec.yaml file to integrate or extend this package separately. ```shell flutter pub add pay_android ``` -------------------------------- ### Add pay package to pubspec.yaml Source: https://github.com/google-pay/flutter-plugin/blob/main/README.md Use this command to add the `pay` package as a dependency in your Flutter project. ```shell flutter pub add pay ``` -------------------------------- ### Handle Android Payment Results with EventChannel Source: https://context7.com/google-pay/flutter-plugin/llms.txt Implement `AndroidPaymentHandler` to listen for payment results delivered via an `EventChannel`. This pattern is crucial for handling activity recreation events and preventing payment token loss on Android. ```dart import 'dart:async'; import 'dart:convert'; import 'package:flutter/services.dart'; import 'package:pay/pay.dart'; class AndroidPaymentHandler { static const _eventChannel = EventChannel('plugins.flutter.io/pay/payment_result'); StreamSubscription>? _subscription; void startListening({ required Function(Map) onResult, required Function(dynamic) onError, }) { _subscription = _eventChannel .receiveBroadcastStream() .cast() .map((result) => jsonDecode(result) as Map) .listen( onResult, onError: onError, ); } void stopListening() { _subscription?.cancel(); _subscription = null; } } // Usage in a StatefulWidget class PaymentScreen extends StatefulWidget { @override State createState() => _PaymentScreenState(); } class _PaymentScreenState extends State { final _handler = AndroidPaymentHandler(); final _payClient = Pay({PayProvider.google_pay: googlePayConfig}); @override void initState() { super.initState(); _handler.startListening( onResult: (result) { // Process the Google Pay token final token = result['paymentMethodData']['tokenizationData']['token']; _processPaymentOnServer(token); }, onError: (error) => print('Payment error: $error'), ); } void _initiatePayment() { // This only initiates the payment flow on Android // Result comes through the EventChannel _payClient.showPaymentSelector( PayProvider.google_pay, [PaymentItem(label: 'Total', amount: '25.00', status: PaymentItemStatus.final_price)], ); } @override void dispose() { _handler.stopListening(); super.dispose(); } @override Widget build(BuildContext context) => /* ... */; } ``` -------------------------------- ### Define Payment Items for Google Pay Source: https://context7.com/google-pay/flutter-plugin/llms.txt Use the PaymentItem class to define individual entries in the payment summary, including labels, amounts, types, and statuses. This is useful for constructing the payment request. ```dart import 'package:pay/pay.dart'; // Define multiple payment items for a shopping cart const paymentItems = [ // Individual item entries PaymentItem( label: 'Premium Subscription', amount: '49.99', status: PaymentItemStatus.final_price, type: PaymentItemType.item, ), PaymentItem( label: 'Setup Fee', amount: '9.99', status: PaymentItemStatus.final_price, type: PaymentItemType.item, ), // Pending price (may change based on user selection) PaymentItem( label: 'Shipping', amount: '5.00', status: PaymentItemStatus.pending, type: PaymentItemType.item, ), // Total amount PaymentItem( label: 'Total', amount: '64.98', status: PaymentItemStatus.final_price, type: PaymentItemType.total, ), ]; ``` -------------------------------- ### User Payment Availability Check Source: https://github.com/google-pay/flutter-plugin/blob/main/pay_platform_interface/README.md Checks if the user can pay with a selected payment provider based on the provided configuration. ```APIDOC ## GET /userCanPay ### Description Checks if the user can pay with a selected provider. ### Method GET ### Endpoint /userCanPay ### Parameters #### Query Parameters - **paymentConfiguration** (PaymentConfiguration) - Required - The configuration for the payment provider. ### Response #### Success Response (200) - **bool** - True if the user can pay, false otherwise. #### Response Example ```json { "canPay": true } ``` ``` -------------------------------- ### Handle Android Payment Results via Event Channel Source: https://github.com/google-pay/flutter-plugin/blob/main/pay/README.md On Android, payment results are received through an event channel to manage activity recreation. Subscribe to the payment results channel to receive tokens or handle errors. ```dart static const eventChannel = EventChannel('plugins.flutter.io/pay/payment_result'); final _paymentResultSubscription = eventChannel .receiveBroadcastStream() .map((result) => jsonDecode(result as String) as Map) .listen((result) { // TODO: Send the resulting Google Pay token to your server / PSP }, onError: (error) { // TODO: Handle errors }); ``` -------------------------------- ### RawGooglePayButton Widget for Advanced Integrations Source: https://context7.com/google-pay/flutter-plugin/llms.txt Use RawGooglePayButton for manual control over the Google Pay payment flow. It requires checking user payment capability and initiating the payment selector. ```dart import 'package:flutter/material.dart'; import 'package:pay/pay.dart'; class AdvancedCheckout extends StatefulWidget { @override State createState() => _AdvancedCheckoutState(); } class _AdvancedCheckoutState extends State { final _config = PaymentConfiguration.fromJsonString('{"provider": "google_pay", "data": {...}}'); late final Pay _payClient; late final Future _canPayFuture; @override void initState() { super.initState(); _payClient = Pay({PayProvider.google_pay: _config}); _canPayFuture = _payClient.userCanPay(PayProvider.google_pay); } void _handleGooglePayPress() async { try { final result = await _payClient.showPaymentSelector( PayProvider.google_pay, [PaymentItem(label: 'Total', amount: '99.99', status: PaymentItemStatus.final_price)], ); // Process payment result _processPayment(result); } catch (e) { ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Payment failed: $e'))); } } @override Widget build(BuildContext context) { return FutureBuilder( future: _canPayFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done && snapshot.data == true) { return RawGooglePayButton( paymentConfiguration: _config, type: GooglePayButtonType.pay, theme: GooglePayButtonTheme.dark, cornerRadius: 4, onPressed: _handleGooglePayPress, ); } return const SizedBox.shrink(); }, ); } } ``` -------------------------------- ### Render Raw Apple Pay Button Source: https://github.com/google-pay/flutter-plugin/blob/main/pay_ios/README.md Use the RawApplePayButton widget to display an Apple Pay button. Customize its style and type according to your needs. ```dart RawApplePayButton( style: ApplePayButtonStyle.black, type: ApplePayButtonType.buy); ``` -------------------------------- ### Integrate GooglePayButton Widget Source: https://context7.com/google-pay/flutter-plugin/llms.txt The GooglePayButton widget simplifies Google Pay integration. It automatically handles the payment flow and checks for user eligibility. Configure payment details, button appearance, and callbacks for payment results and errors. ```dart import 'package:flutter/material.dart'; import 'package:pay/pay.dart'; class CheckoutPage extends StatelessWidget { final _googlePayConfig = PaymentConfiguration.fromJsonString('''{ "provider": "google_pay", "data": { "environment": "TEST", "apiVersion": 2, "apiVersionMinor": 0, "allowedPaymentMethods": [{ "type": "CARD", "tokenizationSpecification": { "type": "PAYMENT_GATEWAY", "parameters": {"gateway": "example", "gatewayMerchantId": "exampleId"} }, "parameters": { "allowedCardNetworks": ["VISA", "MASTERCARD"], "allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"] } }], "merchantInfo": {"merchantName": "My Store"}, "transactionInfo": {"countryCode": "US", "currencyCode": "USD"} } }'''); final _paymentItems = const [ PaymentItem(label: 'Total', amount: '99.99', status: PaymentItemStatus.final_price) ]; @override Widget build(BuildContext context) { return GooglePayButton( paymentConfiguration: _googlePayConfig, paymentItems: _paymentItems, type: GooglePayButtonType.buy, // Options: buy, checkout, donate, order, pay, plain, subscribe, book, pix theme: GooglePayButtonTheme.dark, // Options: dark, light cornerRadius: 24, margin: const EdgeInsets.only(top: 15.0), loadingIndicator: const Center(child: CircularProgressIndicator()), childOnError: const Text('Google Pay not available'), onPaymentResult: (result) { // Handle successful payment - send token to your server final paymentToken = result['paymentMethodData']['tokenizationData']['token']; print('Payment successful: $paymentToken'); }, onError: (error) { // Handle payment errors print('Payment error: $error'); }, ); } } ``` -------------------------------- ### Trigger Payment Selector Source: https://github.com/google-pay/flutter-plugin/blob/main/pay/README.md Handle the `onPressed` event for payment buttons to trigger the payment selector. This function initiates the payment process with the selected provider and payment items. ```dart void _onApplePayPressed() async { final result = await _payClient.showPaymentSelector( PayProvider.apple_pay, _paymentItems, ); // Send the resulting Google Pay token to your server / PSP } ``` -------------------------------- ### ApplePayButton Widget Integration Source: https://context7.com/google-pay/flutter-plugin/llms.txt Use ApplePayButton for a pre-built Apple Pay button that adheres to HIG. Configure payment details, supported networks, and shipping options. ```dart import 'package:flutter/material.dart'; import 'package:pay/pay.dart'; class CheckoutPage extends StatelessWidget { final _applePayConfig = PaymentConfiguration.fromJsonString('''{ "provider": "apple_pay", "data": { "merchantIdentifier": "merchant.com.example.app", "displayName": "Example Store", "merchantCapabilities": ["3DS", "debit", "credit"], "supportedNetworks": ["amex", "visa", "discover", "masterCard"], "countryCode": "US", "currencyCode": "USD", "requiredBillingContactFields": ["emailAddress", "name", "postalAddress"], "requiredShippingContactFields": ["emailAddress", "name", "phoneNumber", "postalAddress"], "shippingMethods": [ {"amount": "0.00", "detail": "Available within an hour", "identifier": "pickup", "label": "In-Store Pickup"}, {"amount": "4.99", "detail": "5-8 Business Days", "identifier": "ground", "label": "Ground Shipping"}, {"amount": "12.99", "detail": "1-3 Business Days", "identifier": "express", "label": "Express Shipping"} ] } }'''); final _paymentItems = const [ PaymentItem(label: 'Subtotal', amount: '89.99', status: PaymentItemStatus.final_price, type: PaymentItemType.item), PaymentItem(label: 'Shipping', amount: '4.99', status: PaymentItemStatus.final_price, type: PaymentItemType.item), PaymentItem(label: 'Total', amount: '94.98', status: PaymentItemStatus.final_price, type: PaymentItemType.total) ]; @override Widget build(BuildContext context) { return ApplePayButton( paymentConfiguration: _applePayConfig, paymentItems: _paymentItems, type: ApplePayButtonType.buy, // Options: plain, buy, setUp, inStore, donate, checkout, book, subscribe, reload, addMoney, topUp, order, rent, support, contribute, tip style: ApplePayButtonStyle.black, // Options: white, whiteOutline, black, automatic cornerRadius: 8.0, margin: const EdgeInsets.only(top: 15.0), loadingIndicator: const Center(child: CircularProgressIndicator()), childOnError: const Text('Apple Pay not available'), onPaymentResult: (result) { // Handle successful payment final paymentData = result['token']; print('Apple Pay token received: $paymentData'); }, onError: (error) { print('Apple Pay error: $error'); }, ); } } ``` -------------------------------- ### Display Apple Pay and Google Pay buttons Source: https://github.com/google-pay/flutter-plugin/blob/main/README.md This snippet shows how to render Apple Pay and Google Pay buttons in your Flutter UI. Ensure you have configured payment details and handlers. ```dart import 'package:pay/pay.dart'; import 'payment_configurations.dart' as payment_configurations; const _paymentItems = [ PaymentItem( label: 'Total', amount: '99.99', status: PaymentItemStatus.final_price, ) ]; ApplePayButton( paymentConfiguration: payment_configurations.defaultApplePayConfig, paymentItems: _paymentItems, style: ApplePayButtonStyle.black, type: ApplePayButtonType.buy, margin: const EdgeInsets.only(top: 15.0), onPaymentResult: onApplePayResult, loadingIndicator: const Center( child: CircularProgressIndicator(), ), ), GooglePayButton( paymentConfiguration: payment_configurations.defaultGooglePayConfig, paymentItems: _paymentItems, type: GooglePayButtonType.buy, margin: const EdgeInsets.only(top: 15.0), onPaymentResult: onGooglePayResult, loadingIndicator: const Center( child: CircularProgressIndicator(), ), ), void onApplePayResult(paymentResult) { // Send the resulting Apple Pay token to your server / PSP } void onGooglePayResult(paymentResult) { // Send the resulting Google Pay token to your server / PSP } ``` -------------------------------- ### Display RawApplePayButton on iOS Source: https://context7.com/google-pay/flutter-plugin/llms.txt Use `RawApplePayButton` to render a native Apple Pay button. Ensure `userCanPay` returns true before displaying the button. This widget does not manage the payment flow itself. ```dart import 'package:flutter/material.dart'; import 'package:pay/pay.dart'; class AdvancedIOSCheckout extends StatefulWidget { @override State createState() => _AdvancedIOSCheckoutState(); } class _AdvancedIOSCheckoutState extends State { final _config = PaymentConfiguration.fromJsonString('{"provider": "apple_pay", "data": {...}}'); late final Pay _payClient; late final Future _canPayFuture; @override void initState() { super.initState(); _payClient = Pay({PayProvider.apple_pay: _config}); _canPayFuture = _payClient.userCanPay(PayProvider.apple_pay); } void _handleApplePayPress() async { try { final result = await _payClient.showPaymentSelector( PayProvider.apple_pay, [PaymentItem(label: 'Total', amount: '49.99', status: PaymentItemStatus.final_price)], ); // Apple Pay returns result synchronously on iOS await _sendTokenToServer(result); } catch (e) { print('Apple Pay failed: $e'); } } @override Widget build(BuildContext context) { return FutureBuilder( future: _canPayFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done && snapshot.data == true) { return RawApplePayButton( type: ApplePayButtonType.checkout, style: ApplePayButtonStyle.automatic, cornerRadius: 10, onPressed: _handleApplePayPress, ); } return ElevatedButton(onPressed: null, child: Text('Apple Pay Unavailable')); }, ); } } ``` -------------------------------- ### Cancel Payment Result Subscription Source: https://github.com/google-pay/flutter-plugin/blob/main/pay/README.md Ensure that the event channel subscription for payment results is cancelled when no longer needed to prevent memory leaks. This is crucial for proper resource management. ```dart _paymentResultSubscription.cancel(); _paymentResultSubscription = null; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.