├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── pull_request_template.md
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── pay
├── .pubignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── example
│ ├── .gitignore
│ ├── .metadata
│ ├── README.md
│ ├── analysis_options.yaml
│ ├── android
│ │ ├── .gitignore
│ │ ├── app
│ │ │ ├── build.gradle
│ │ │ └── src
│ │ │ │ ├── debug
│ │ │ │ └── AndroidManifest.xml
│ │ │ │ ├── main
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── res
│ │ │ │ │ ├── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ └── values
│ │ │ │ │ └── styles.xml
│ │ │ │ └── profile
│ │ │ │ └── AndroidManifest.xml
│ │ ├── build.gradle
│ │ ├── gradle.properties
│ │ ├── gradle
│ │ │ └── wrapper
│ │ │ │ └── gradle-wrapper.properties
│ │ └── settings.gradle
│ ├── assets
│ │ ├── default_apple_pay_config.json
│ │ ├── default_google_pay_config.json
│ │ └── images
│ │ │ └── ts_10_11019a.jpg
│ ├── integration_test
│ │ └── payment_flow_test.dart
│ ├── ios
│ │ ├── .gitignore
│ │ ├── Flutter
│ │ │ ├── AppFrameworkInfo.plist
│ │ │ ├── Debug.xcconfig
│ │ │ └── Release.xcconfig
│ │ ├── Podfile
│ │ ├── Podfile.lock
│ │ ├── Runner.xcodeproj
│ │ │ ├── project.pbxproj
│ │ │ ├── project.xcworkspace
│ │ │ │ ├── contents.xcworkspacedata
│ │ │ │ └── xcshareddata
│ │ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ │ └── WorkspaceSettings.xcsettings
│ │ │ └── xcshareddata
│ │ │ │ └── xcschemes
│ │ │ │ └── Runner.xcscheme
│ │ ├── Runner.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ └── Runner
│ │ │ ├── AppDelegate.h
│ │ │ ├── AppDelegate.m
│ │ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ │ └── LaunchImage.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ └── README.md
│ │ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ │ ├── Info.plist
│ │ │ ├── de.lproj
│ │ │ ├── LaunchScreen.strings
│ │ │ └── Main.strings
│ │ │ ├── es.lproj
│ │ │ ├── LaunchScreen.strings
│ │ │ └── Main.strings
│ │ │ └── main.m
│ ├── lib
│ │ ├── advanced.dart
│ │ ├── main.dart
│ │ └── payment_configurations.dart
│ └── pubspec.yaml
├── lib
│ ├── pay.dart
│ └── src
│ │ ├── pay.dart
│ │ └── widgets
│ │ ├── apple_pay_button.dart
│ │ ├── google_pay_button.dart
│ │ └── pay_button.dart
├── pubspec.yaml
└── test
│ ├── assets
│ └── google_pay_default_payment_profile.json
│ └── pay_test.dart
├── pay_android
├── .pubignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android
│ ├── .gitignore
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── settings.gradle
│ └── src
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ └── kotlin
│ │ │ └── io
│ │ │ └── flutter
│ │ │ └── plugins
│ │ │ └── pay_android
│ │ │ ├── GooglePayHandler.kt
│ │ │ ├── PayMethodCallHandler.kt
│ │ │ ├── PayPlugin.kt
│ │ │ ├── util
│ │ │ └── PaymentsUtil.kt
│ │ │ └── view
│ │ │ ├── PayButtonView.kt
│ │ │ └── PayButtonViewFactory.kt
│ │ └── test
│ │ └── kotlin
│ │ └── io
│ │ └── flutter
│ │ └── plugins
│ │ └── pay_android
│ │ └── GooglePayHandlerTest.kt
├── lib
│ ├── pay_android.dart
│ └── src
│ │ └── widgets
│ │ └── google_pay_button.dart
├── pubspec.yaml
└── test
│ └── pay_button_test.dart
├── pay_ios
├── .pubignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── ios
│ ├── .gitignore
│ ├── Assets
│ │ └── .gitkeep
│ ├── Classes
│ │ ├── ApplePayButtonView.swift
│ │ ├── PayPlugin.swift
│ │ ├── PaymentExtensions.swift
│ │ └── PaymentHandler.swift
│ └── pay_ios.podspec
├── lib
│ ├── pay_ios.dart
│ └── src
│ │ └── widgets
│ │ └── apple_pay_button.dart
├── pubspec.yaml
└── test
│ └── pay_button_test.dart
└── pay_platform_interface
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── lib
├── core
│ ├── payment_configuration.dart
│ └── payment_item.dart
├── pay_channel.dart
├── pay_platform_interface.dart
└── util
│ └── configurations.dart
├── pubspec.yaml
└── test
├── assets
├── google_pay_default_payment_profile.json
├── google_pay_prod_payment_profile.json
└── google_pay_test_payment_profile.json
├── pay_channel_test.dart
└── payment_configuration_test.dart
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **`flutter doctor`** output
27 | Include a copy of the output after running `flutter doctor` if you suspect your issue is related with structural properties in Flutter or other libraries.
28 |
29 | **Additional context**
30 | Add any other context about the problem here.
31 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | > :warning:
2 | > Hello, and thank you for your contributions!
3 | > Please review the following checklist before creating a new pull request:
4 | >
5 | > - Review and contribute to existing pull requests and open issues to avoid redundant efforts.
6 | > - Read [the contribution guidelines](CONTRIBUTING.md).
7 | > - Assign reviewers.
8 | > - If applicable, include a reference to related issues.
9 | > - If this is a new feature, create an issue and coordinate with other contributors to make sure the feature can be made available in all platforms supported.
10 | >
11 | > :warning: Delete this block before creating the pull request.
12 |
13 | **Describe the changes proposed**
14 | A clear and concise description of the changes included in this pull request.
15 |
16 | **Screenshots / Videos**
17 | If useful, include any screeshots or screencasts to better explain the change.
18 |
19 | **Additional context**
20 | Add any other context about the change here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://www.dartlang.org/guides/libraries/private-files
2 |
3 | # Files and directories created by pub
4 | .dart_tool/
5 | .packages
6 | build/
7 |
8 | # If you're building an application, you may want to check-in your pubspec.lock
9 | pubspec.lock
10 |
11 | # iOS
12 | Podfile.lock
13 | Pods/
14 | .symlinks/
15 |
16 | # Directory created by dartdoc
17 | # If you don't generate documentation locally you can remove this line.
18 | doc/api/
19 |
20 | # Generated files on example apps
21 | flutter_export_environment.sh
22 | .flutter-plugins*
23 | local.properties
24 | keystore.properties
25 | **/Flutter/Generated.xcconfig
26 | **/Flutter/App.framework/
27 | **/Flutter/ephemeral/
28 | **/Flutter/Flutter.podspec
29 | **/Flutter/Flutter.framework/
30 | **/Flutter/flutter_assets/
31 |
32 | ServiceDefinitions.json
33 | xcuserdata/
34 | **/DerivedData/
35 |
36 | generated_plugin_registrant.*
37 | GeneratedPluginRegistrant.*
38 |
39 | # Gradle
40 | **/gradle-wrapper.jar
41 | .gradle/
42 | gradlew
43 | gradlew.bat
44 |
45 | .project
46 | .classpath
47 | .settings
48 |
49 | # Avoid committing generated Javascript files:
50 | *.dart.js
51 | *.info.json # Produced by the --dump-info flag.
52 | *.js # When generated by dart2js. Don't specify *.js if your
53 | # project includes source files written in JavaScript.
54 | *.js_
55 | *.js.deps
56 | *.js.map
57 | .idea
58 | .flutter-plugins
59 | .flutter-plugins-dependencies
60 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 | _See also: [Flutter's code of conduct](https://flutter.io/design-principles/#code-of-conduct)_
3 |
4 | We'd love to accept your patches and contributions to this project. There are just a few small guidelines you need to
5 | follow.
6 |
7 | Please use the
8 | [Flutter style guide](https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo) and
9 | [design principles](https://flutter.io/design-principles/) before
10 | working on anything non-trivial. These guidelines are intended to
11 | keep the code consistent and avoid common pitfalls.
12 |
13 | ## Contributor License Agreement
14 |
15 | Contributions to this project must be accompanied by a Contributor License Agreement (CLA). You (or your employer)
16 | retain the copyright to your contribution; this simply gives us permission to use and redistribute your contributions as
17 | part of the project. Head over to to see your current agreements on file or to sign
18 | a new one.
19 |
20 | You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different
21 | project), you probably don't need to do it again.
22 |
23 | ## 1. Things you will need
24 |
25 | - Linux, Mac OS X, or Windows.
26 | - [git](https://git-scm.com) (used for source version control).
27 | - An SSH client (used to authenticate with GitHub).
28 | - An IDE such as [Android Studio](https://developer.android.com/studio) or [Visual Studio Code](https://code.visualstudio.com/).
29 | - [`tuneup`](https://pub.dev/packages/tuneup) locally activated.
30 |
31 | ## 2. Forking & cloning the repository
32 |
33 | - Fork the [repository](repo-url) into your own GitHub account.
34 | - If you haven't configured your machine with an SSH key that's known to github, then
35 | follow [GitHub's directions](https://help.github.com/articles/generating-ssh-keys/)
36 | to generate an SSH key.
37 | - Clone your new forked repository: `git clone git@github.com:/plugins.git`
38 | - Add the original repository to the list of remotes: `git remote add upstream git@github.com:flutter/plugins.git`
39 |
40 | ## 3. Running examples
41 |
42 | To run an example, run the `flutter run` command from the `example` directory of each plugins' main
43 | directory. For example, for the `pay` example:
44 |
45 | ```bash
46 | cd pay/example
47 | flutter run
48 | ```
49 |
50 | ## 4. Running tests
51 |
52 | This plugin comprises of a number of end-to-end (e2e) and unit tests.
53 |
54 | ### Unit tests
55 |
56 | Unit tests are responsible for ensuring expected behavior whilst developing the plugins Dart code. Unit tests do not
57 | interact with 3rd party services, and mock where possible. To run unit tests for a specific plugin, run the
58 | `flutter test` command from the plugins root directory. For example:
59 |
60 | ```bash
61 | cd pay
62 | flutter test
63 | ```
64 |
65 | ### End-to-end (e2e) tests
66 |
67 | E2e tests are those which directly communicate with Flutter, whose results cannot be mocked. **These tests run directly from
68 | an example application.**
69 |
70 | To run e2e tests, run the `flutter drive` command from the plugins' main `example` directory, targeting the
71 | entry e2e test file.
72 |
73 | ```bash
74 | cd pay/example
75 | flutter drive \
76 | --driver=test_driver/integration_test.dart \
77 | --target=integration_test/payment_flow_test.dart
78 | ```
79 |
80 | ## 5. Start contributing
81 | To start working on a patch:
82 |
83 | 1. `git fetch upstream`
84 | 2. `git checkout upstream/main -b `
85 | 3. Hack away!
86 |
87 | Once you have made your changes, ensure that it passes the internal analyzer & formatting checks. The following
88 | commands can be run locally to highlight any issues before committing your code:
89 |
90 | Assuming all is successful, commit and push your code:
91 |
92 | 1. `git commit -a -m ""`
93 | 2. `git push origin `
94 |
95 | ### Commit Messages
96 |
97 | We follow the [Conventional Commits specification][conventional-commits] to help keep the commit history readable and to
98 | automate release process with updated changelog details.
99 |
100 | The commit messages should follow this format:
101 |
102 | ```text
103 | [optional scope]:
104 |
105 | [optional body]
106 |
107 | [optional footer(s)]
108 | ```
109 |
110 | For example:
111 |
112 | `fix(pay_android): fixed a bug!`
113 |
114 | Refer to the [specification][conventional-commits] for more information.
115 |
116 | ## 6. Create a pull request
117 | Go to the [repository](repo-url) and click the "Compare & pull request" button
118 |
119 | Plugins tests are run automatically on contributions using GitHub Actions. Depending on your code contributions, various tests will be run against your updated code automatically.
120 |
121 | Once you've gotten an LGTM from a project maintainer and once your PR has received the green light from all our automated testing, wait for one the package maintainers to merge the pull request.
122 |
123 | ## 7. The review process
124 |
125 | Newly opened PRs first go through initial triage which results in one of:
126 |
127 | - **Merging the PR** - if the PR can be quickly reviewed and looks good.
128 | - **Closing the PR** - if the PR maintainer decides that the PR should not be merged.
129 | - **Moving the PR to the backlog** - if the review requires non trivial effort and the issue isn't a priority; in this case the maintainer will:
130 | - Make sure that the PR has an associated issue labeled with "plugin".
131 | - Add the "backlog" label to the issue.
132 | - Leave a comment on the PR explaining that the review is not trivial and that the issue will be looked at according to priority order.
133 | - **Starting a non trivial review** - if the review requires non trivial effort and the issue is a priority; in this case the maintainer will:
134 | - Add the "in review" label to the issue.
135 | - Self assign the PR.
136 |
137 | ## 8. The release process
138 |
139 | Changelogs and version updates are automatically updated by a project maintainer. The new version is automatically
140 | generated via the commit types and changelogs via the commit messages.
141 |
142 | ## Community Guidelines
143 |
144 | This project follows [Google's Open Source Community Guidelines](https://opensource.google/conduct/).
145 |
146 | [conventional-commits]: https://www.conventionalcommits.org/en/v1.0.0/
147 | [repo-url]: https://github.com/flutter/plugins
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | A plugin to add payments to your Flutter application.
2 |
3 | | pay | pay_android | pay_ios | pay_platform_interface |
4 | |:---:|:---:|:---:|:---:|
5 | | [](https://pub.dartlang.org/packages/pay) | [](https://pub.dartlang.org/packages/pay_android) | [](https://pub.dartlang.org/packages/pay_ios) | [](https://pub.dartlang.org/packages/pay_platform_interface) |
6 |
7 | ## Platform Support
8 | | Android | iOS |
9 | |:---:|:---:|
10 | | Google Pay | Apple Pay |
11 |
12 | ## Getting started
13 | Before you start, create an account with the payment providers you are planning to support and follow the setup instructions:
14 |
15 | #### Apple Pay:
16 | 1. Take a look at the [integration requirements](https://developer.apple.com/documentation/passkit/apple_pay/setting_up_apple_pay_requirements).
17 | 2. Create a [merchant identifier](https://developer.apple.com/help/account/configure-app-capabilities/configure-apple-pay#create-a-merchant-identifier) for your business.
18 | 3. Create a [payment processing certificate](https://developer.apple.com/help/account/configure-app-capabilities/configure-apple-pay#create-a-payment-processing-certificate) to encrypt payment information.
19 |
20 | #### Google Pay:
21 | 1. Take a look at the [integration requirements](https://developers.google.com/pay/api/android/overview).
22 | 2. Sign up to the [business console](https://pay.google.com/business/console) and create an account.
23 |
24 | ## Installation
25 | This adds the `pay` package to the [list of dependencies in your pubspec.yaml file](https://flutter.io/platform-plugins/) with the following command:
26 |
27 | ```shell
28 | flutter pub add pay
29 | ```
30 |
31 | ## Usage
32 |
33 | Define the configuration for your payment provider(s). Take a look at the parameters available in the documentation for [Apple Pay](https://developer.apple.com/documentation/passkit/pkpaymentrequest) and [Google Pay](https://developers.google.com/pay/api/android/reference/request-objects), and explore the [sample configurations in this package](https://github.com/google-pay/flutter-plugin/tree/main/pay/example/lib/payment_configurations.dart).
34 |
35 | ### Example
36 | This snippet assumes the existence of a payment configuration for Apple Pay ([`defaultApplePayConfig`](https://github.com/google-pay/flutter-plugin/tree/main/pay/example/lib/payment_configurations.dart#L29)) and another one for Google Pay ([`defaultGooglePayConfig`](https://github.com/google-pay/flutter-plugin/tree/main/pay/example/lib/payment_configurations.dart#L69)):
37 |
38 | ```dart
39 | import 'package:pay/pay.dart';
40 | import 'payment_configurations.dart' as payment_configurations;
41 |
42 | const _paymentItems = [
43 | PaymentItem(
44 | label: 'Total',
45 | amount: '99.99',
46 | status: PaymentItemStatus.final_price,
47 | )
48 | ];
49 |
50 | ApplePayButton(
51 | paymentConfiguration: payment_configurations.defaultApplePayConfig,
52 | paymentItems: _paymentItems,
53 | style: ApplePayButtonStyle.black,
54 | type: ApplePayButtonType.buy,
55 | margin: const EdgeInsets.only(top: 15.0),
56 | onPaymentResult: onApplePayResult,
57 | loadingIndicator: const Center(
58 | child: CircularProgressIndicator(),
59 | ),
60 | ),
61 |
62 | GooglePayButton(
63 | paymentConfiguration: payment_configurations.defaultGooglePayConfig,
64 | paymentItems: _paymentItems,
65 | type: GooglePayButtonType.buy,
66 | margin: const EdgeInsets.only(top: 15.0),
67 | onPaymentResult: onGooglePayResult,
68 | loadingIndicator: const Center(
69 | child: CircularProgressIndicator(),
70 | ),
71 | ),
72 |
73 | void onApplePayResult(paymentResult) {
74 | // Send the resulting Apple Pay token to your server / PSP
75 | }
76 |
77 | void onGooglePayResult(paymentResult) {
78 | // Send the resulting Google Pay token to your server / PSP
79 | }
80 | ```
81 |
82 | To learn more about the `pay` plugin and alternative integration paths, check out [the readme in the `pay` folder](./pay/README.md).
83 |
84 | ## Other packages in this plugin
85 |
86 | The packages in this repository follow the [federated plugin](https://docs.flutter.dev/packages-and-plugins/developing-packages#federated-plugins) architecture. Each package has a specific responsibility and can be used independently to fulfil less conventional integration needs:
87 |
88 | | Package | Description | When to use |
89 | |:---:|:---:|:---:|
90 | | [pay](./pay/) | An app-facing package with support for all the platforms supported by this plugin. | This package offers an agnostic integration for the platforms supported in this plugin and features the easiest path to add payments to your Flutter application. |
91 | | [pay_android](./pay_android/) | The endorsed implementation of this plugin for Android. | This package contains the necessary business logic to support the Android platform. You can integrate this package separately or use it to build your own app-facing package. |
92 | | [pay_ios](./pay_ios/) | The endorsed implementation of this plugin for iOS. | This package contains the necessary business logic to support the iOS platform. You can integrate this package separately or use it to build your own app-facing package. |
93 | | [pay_platform_interface](./pay_platform_interface/) | A common API contract for platform-specific implementations. | Folow the contract in this package to add new platforms to the plugin or create your own Android or iOS implementations. Take a look at the [guide about plugin development](https://flutter.dev/docs/development/packages-and-plugins/developing-packages#federated-plugins) to learn more. |
94 |
95 | ## Additional resources
96 | Check out the following resources to manage your payment accounts and learn more about the APIs for the supported providers:
97 |
98 | | | Google Pay | Apple Pay |
99 | |:---|:---|:---|
100 | | Platforms | Android | iOS |
101 | | Documentation | [Overview](https://developers.google.com/pay/api/android/overview) | [Overview](https://developer.apple.com/apple-pay/implementation/)
102 | | Console | [Google Pay Business Console](https://pay.google.com/business/console/) | [Developer portal](https://developer.apple.com/account/) |
103 | | Reference | [API reference](https://developers.google.com/pay/api/android/reference/client) | [Apple Pay API](https://developer.apple.com/documentation/passkit/apple_pay/)
104 | | Style guidelines | [Brand guidelines](https://developers.google.com/pay/api/android/guides/brand-guidelines) | [Buttons and Marks](https://developer.apple.com/design/human-interface-guidelines/apple-pay/overview/buttons-and-marks/)
105 |
106 |
107 | Note: This is not an officially supported Google product.
108 |
109 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
2 |
3 | analyzer:
4 | language:
5 | strict-casts: true
6 | strict-raw-types: true
7 | errors:
8 | deprecated_member_use_from_same_package: ignore
9 |
10 | linter:
11 | rules:
12 | - annotate_overrides
13 | - avoid_annotating_with_dynamic
14 | - avoid_empty_else
15 | - avoid_function_literals_in_foreach_calls
16 | - avoid_init_to_null
17 | - avoid_null_checks_in_equality_operators
18 | - avoid_relative_lib_imports
19 | - avoid_renaming_method_parameters
20 | - avoid_return_types_on_setters
21 | - avoid_returning_null_for_void
22 | - avoid_shadowing_type_parameters
23 | - avoid_single_cascade_in_expression_statements
24 | - avoid_types_as_parameter_names
25 | - await_only_futures
26 | - camel_case_extensions
27 | - camel_case_types
28 | - constant_identifier_names
29 | - control_flow_in_finally
30 | - curly_braces_in_flow_control_structures
31 | - depend_on_referenced_packages
32 | - empty_catches
33 | - empty_constructor_bodies
34 | - empty_statements
35 | - exhaustive_cases
36 | - file_names
37 | - library_names
38 | - library_prefixes
39 | - library_private_types_in_public_api
40 | - no_duplicate_case_values
41 | - no_leading_underscores_for_library_prefixes
42 | - no_leading_underscores_for_local_identifiers
43 | - non_constant_identifier_names
44 | - null_check_on_nullable_type_parameter
45 | - null_closures
46 | - overridden_fields
47 | - package_names
48 | - package_prefixed_library_names
49 | - prefer_adjacent_string_concatenation
50 | - prefer_collection_literals
51 | - prefer_conditional_assignment
52 | - prefer_contains
53 | - prefer_final_fields
54 | - prefer_for_elements_to_map_fromIterable
55 | - prefer_function_declarations_over_variables
56 | - prefer_if_null_operators
57 | - prefer_initializing_formals
58 | - prefer_inlined_adds
59 | - prefer_interpolation_to_compose_strings
60 | - prefer_is_empty
61 | - prefer_is_not_empty
62 | - prefer_is_not_operator
63 | - prefer_iterable_whereType
64 | - prefer_null_aware_operators
65 | - prefer_spread_collections
66 | - prefer_typing_uninitialized_variables
67 | - prefer_void_to_null
68 | - provide_deprecation_message
69 | - recursive_getters
70 | - slash_for_doc_comments
71 | - type_init_formals
72 | - unnecessary_brace_in_string_interps
73 | - unnecessary_const
74 | - unnecessary_constructor_name
75 | - unnecessary_getters_setters
76 | - unnecessary_late
77 | - unnecessary_new
78 | - unnecessary_null_aware_assignments
79 | - unnecessary_null_in_if_null_operators
80 | - unnecessary_nullable_for_final_variable_declarations
81 | - unnecessary_overrides
82 | - unnecessary_string_escapes
83 | - unnecessary_string_interpolations
84 | - unnecessary_this
85 | - unrelated_type_equality_checks
86 | - use_function_type_syntax_for_parameters
87 | - use_rethrow_when_possible
88 | - valid_regexps
89 | - void_checks
--------------------------------------------------------------------------------
/pay/.pubignore:
--------------------------------------------------------------------------------
1 | # Dirs created by pub and Android
2 | .dart_tool/
3 | build/
4 |
5 | # Test files
6 | test/
7 | integration_test/
--------------------------------------------------------------------------------
/pay/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: ../analysis_options.yaml
--------------------------------------------------------------------------------
/pay/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Web related
35 | lib/generated_plugin_registrant.dart
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
43 | # Exceptions to above rules.
44 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
45 |
--------------------------------------------------------------------------------
/pay/example/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: fba99f6cf9a14512e461e3122c8ddfaa25394e89
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/pay/example/README.md:
--------------------------------------------------------------------------------
1 | # pay_example
2 |
3 | Demonstrates how to use the `pay` plugin.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
13 |
14 | For help getting started with Flutter, view our
15 | [online documentation](https://flutter.dev/docs), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/pay/example/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: ../../analysis_options.yaml
--------------------------------------------------------------------------------
/pay/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 |
--------------------------------------------------------------------------------
/pay/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | id "dev.flutter.flutter-gradle-plugin"
5 | }
6 |
7 | def localProperties = new Properties()
8 | def localPropertiesFile = rootProject.file('local.properties')
9 | if (localPropertiesFile.exists()) {
10 | localPropertiesFile.withReader('UTF-8') { reader ->
11 | localProperties.load(reader)
12 | }
13 | }
14 |
15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
16 | if (flutterVersionCode == null) {
17 | flutterVersionCode = '1'
18 | }
19 |
20 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
21 | if (flutterVersionName == null) {
22 | flutterVersionName = '1.0'
23 |
24 | }
25 |
26 | android {
27 | namespace 'io.flutter.plugins.pay_example'
28 | compileSdk flutter.compileSdkVersion
29 |
30 | defaultConfig {
31 | applicationId 'io.flutter.plugins.pay_example'
32 | minSdkVersion 21
33 | targetSdkVersion flutter.targetSdkVersion
34 | versionCode flutterVersionCode.toInteger()
35 | versionName flutterVersionName
36 | }
37 |
38 | compileOptions {
39 | sourceCompatibility JavaVersion.VERSION_1_8
40 | targetCompatibility JavaVersion.VERSION_1_8
41 | }
42 |
43 | kotlinOptions {
44 | jvmTarget = '1.8'
45 | }
46 |
47 | sourceSets {
48 | main.java.srcDirs += 'src/main/kotlin'
49 | }
50 |
51 | lint {
52 | disable 'InvalidPackage'
53 | }
54 | }
55 |
56 | flutter {
57 | source '../..'
58 | }
59 |
--------------------------------------------------------------------------------
/pay/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/pay/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
15 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/pay/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/pay/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pay/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pay/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pay/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pay/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/pay/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/pay/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/pay/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | rootProject.buildDir = '../build'
9 | subprojects {
10 | project.buildDir = "${rootProject.buildDir}/${project.name}"
11 | }
12 | subprojects {
13 | project.evaluationDependsOn(':app')
14 | }
15 |
16 | tasks.register("clean", Delete) {
17 | delete rootProject.buildDir
18 | }
19 |
--------------------------------------------------------------------------------
/pay/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/pay/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
--------------------------------------------------------------------------------
/pay/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | def flutterSdkPath = {
3 | def properties = new Properties()
4 | file("local.properties").withInputStream { properties.load(it) }
5 | def flutterSdkPath = properties.getProperty("flutter.sdk")
6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
7 | return flutterSdkPath
8 | }()
9 |
10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
11 |
12 | repositories {
13 | google()
14 | mavenCentral()
15 | gradlePluginPortal()
16 | }
17 | }
18 |
19 | plugins {
20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0"
21 | id "com.android.application" version "8.3.2" apply false
22 | id "org.jetbrains.kotlin.android" version "2.0.20" apply false
23 | }
24 |
25 | rootProject.name = "Google Pay Flutter sample application"
26 | include ":app"
--------------------------------------------------------------------------------
/pay/example/assets/default_apple_pay_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "provider": "apple_pay",
3 | "data": {
4 | "merchantIdentifier": "merchant.com.sams.fish",
5 | "displayName": "Sam's Fish",
6 | "merchantCapabilities": ["3DS", "debit", "credit"],
7 | "supportedNetworks": ["amex", "visa", "discover", "masterCard"],
8 | "countryCode": "US",
9 | "currencyCode": "USD",
10 | "requiredBillingContactFields": ["emailAddress", "name", "phoneNumber", "postalAddress"],
11 | "requiredShippingContactFields": [],
12 | "shippingMethods": [
13 | {
14 | "amount": "0.00",
15 | "detail": "Available within an hour",
16 | "identifier": "in_store_pickup",
17 | "label": "In-Store Pickup"
18 | },
19 | {
20 | "amount": "4.99",
21 | "detail": "5-8 Business Days",
22 | "identifier": "flat_rate_shipping_id_2",
23 | "label": "UPS Ground"
24 | },
25 | {
26 | "amount": "29.99",
27 | "detail": "1-3 Business Days",
28 | "identifier": "flat_rate_shipping_id_1",
29 | "label": "FedEx Priority Mail"
30 | }
31 | ]
32 | }
33 | }
--------------------------------------------------------------------------------
/pay/example/assets/default_google_pay_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "provider": "google_pay",
3 | "data": {
4 | "environment": "TEST",
5 | "apiVersion": 2,
6 | "apiVersionMinor": 0,
7 | "allowedPaymentMethods": [
8 | {
9 | "type": "CARD",
10 | "tokenizationSpecification": {
11 | "type": "PAYMENT_GATEWAY",
12 | "parameters": {
13 | "gateway": "example",
14 | "gatewayMerchantId": "exampleGatewayMerchantId"
15 | }
16 | },
17 | "parameters": {
18 | "allowedCardNetworks": ["VISA", "MASTERCARD"],
19 | "allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"],
20 | "billingAddressRequired": true,
21 | "billingAddressParameters": {
22 | "format": "FULL",
23 | "phoneNumberRequired": true
24 | }
25 | }
26 | }
27 | ],
28 | "merchantInfo": {
29 | "merchantName": "Example Merchant Name"
30 | },
31 | "transactionInfo": {
32 | "countryCode": "US",
33 | "currencyCode": "USD"
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/pay/example/assets/images/ts_10_11019a.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/assets/images/ts_10_11019a.jpg
--------------------------------------------------------------------------------
/pay/example/integration_test/payment_flow_test.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter_test/flutter_test.dart';
16 | import 'package:integration_test/integration_test.dart';
17 | import 'package:pay/pay.dart';
18 |
19 | void main() {
20 | IntegrationTestWidgetsFlutterBinding.ensureInitialized();
21 |
22 | testWidgets("correctly creates an instance of the client", (_) async {
23 | Pay client = Pay({});
24 | await expectLater(client, isNotNull);
25 | });
26 | }
27 |
--------------------------------------------------------------------------------
/pay/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/pay/example/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 12.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/pay/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/pay/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/pay/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '12.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/pay/example/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Flutter (1.0.0)
3 | - integration_test (0.0.1):
4 | - Flutter
5 | - pay_ios (0.0.1):
6 | - Flutter
7 |
8 | DEPENDENCIES:
9 | - Flutter (from `Flutter`)
10 | - integration_test (from `.symlinks/plugins/integration_test/ios`)
11 | - pay_ios (from `.symlinks/plugins/pay_ios/ios`)
12 |
13 | EXTERNAL SOURCES:
14 | Flutter:
15 | :path: Flutter
16 | integration_test:
17 | :path: ".symlinks/plugins/integration_test/ios"
18 | pay_ios:
19 | :path: ".symlinks/plugins/pay_ios/ios"
20 |
21 | SPEC CHECKSUMS:
22 | Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
23 | integration_test: ce0a3ffa1de96d1a89ca0ac26fca7ea18a749ef4
24 | pay_ios: 8c7beb9c61d885f3f51b61f75f8793023fc8843a
25 |
26 | PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011
27 |
28 | COCOAPODS: 1.11.3
29 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner/AppDelegate.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2021 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 |
20 | @interface AppDelegate : FlutterAppDelegate
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner/AppDelegate.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2021 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import "AppDelegate.h"
18 | #import "GeneratedPluginRegistrant.h"
19 |
20 | @implementation AppDelegate
21 |
22 | - (BOOL)application:(UIApplication *)application
23 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
24 | [GeneratedPluginRegistrant registerWithRegistry:self];
25 | // Override point for customization after application launch.
26 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
27 | }
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google-pay/flutter-plugin/4fc0c8b76448a76b26b9fe2a3514270e977b91a4/pay/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | pay_example
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 | CADisableMinimumFrameDurationOnPhone
45 |
46 | UIApplicationSupportsIndirectInputEvents
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner/de.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner/de.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner/es.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner/es.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/pay/example/ios/Runner/main.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2021 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import
18 | #import
19 | #import "AppDelegate.h"
20 |
21 | int main(int argc, char* argv[]) {
22 | @autoreleasepool {
23 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/pay/example/lib/advanced.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:async';
16 |
17 | import 'package:flutter/foundation.dart';
18 | import 'package:flutter/material.dart';
19 | import 'package:flutter/services.dart';
20 | import 'package:flutter_localizations/flutter_localizations.dart';
21 | import 'package:pay/pay.dart';
22 |
23 | import 'payment_configurations.dart' as payment_configurations;
24 |
25 | void main() {
26 | runApp(const PayAdvancedMaterialApp());
27 | }
28 |
29 | const googlePayEventChannelName = 'plugins.flutter.io/pay/payment_result';
30 | const _paymentItems = [
31 | PaymentItem(
32 | label: 'Total',
33 | amount: '99.99',
34 | status: PaymentItemStatus.final_price,
35 | )
36 | ];
37 |
38 | class PayAdvancedMaterialApp extends StatelessWidget {
39 | const PayAdvancedMaterialApp({super.key});
40 |
41 | @override
42 | Widget build(BuildContext context) {
43 | return MaterialApp(
44 | title: 'Pay for Flutter Advanced Integration Demo',
45 | localizationsDelegates: const [
46 | ...GlobalMaterialLocalizations.delegates,
47 | GlobalWidgetsLocalizations.delegate,
48 | ],
49 | supportedLocales: const [
50 | Locale('en', ''),
51 | Locale('es', ''),
52 | Locale('de', ''),
53 | ],
54 | home: PayAdvancedSampleApp(),
55 | );
56 | }
57 | }
58 |
59 | class PayAdvancedSampleApp extends StatefulWidget {
60 | final Pay payClient;
61 |
62 | PayAdvancedSampleApp({super.key})
63 | : payClient = Pay({
64 | PayProvider.google_pay: payment_configurations.defaultGooglePayConfig,
65 | PayProvider.apple_pay: payment_configurations.defaultApplePayConfig,
66 | });
67 |
68 | @override
69 | State createState() => _PayAdvancedSampleAppState();
70 | }
71 |
72 | class _PayAdvancedSampleAppState extends State {
73 | static const eventChannel = EventChannel(googlePayEventChannelName);
74 | StreamSubscription? _googlePayResultSubscription;
75 |
76 | late final Future _canPayGoogleFuture;
77 | late final Future _canPayAppleFuture;
78 |
79 | // A method to listen to events coming from the event channel on Android
80 | void _startListeningForPaymentResults() {
81 | _googlePayResultSubscription = eventChannel
82 | .receiveBroadcastStream()
83 | .cast()
84 | .listen(debugPrint, onError: (error) => debugPrint(error.toString()));
85 | }
86 |
87 | final bool _collectPaymentResultSynchronously =
88 | defaultTargetPlatform == TargetPlatform.iOS;
89 |
90 | @override
91 | void initState() {
92 | super.initState();
93 | if (!_collectPaymentResultSynchronously) {
94 | _startListeningForPaymentResults();
95 | }
96 |
97 | // Initialize userCanPay futures
98 | _canPayGoogleFuture = widget.payClient.userCanPay(PayProvider.google_pay);
99 | _canPayAppleFuture = widget.payClient.userCanPay(PayProvider.apple_pay);
100 | }
101 |
102 | void _onGooglePayPressed() =>
103 | _showPaymentSelectorForProvider(PayProvider.google_pay);
104 |
105 | void _onApplePayPressed() =>
106 | _showPaymentSelectorForProvider(PayProvider.apple_pay);
107 |
108 | void _showPaymentSelectorForProvider(PayProvider provider) async {
109 | try {
110 | final result =
111 | await widget.payClient.showPaymentSelector(provider, _paymentItems);
112 | if (_collectPaymentResultSynchronously) debugPrint(result.toString());
113 | } catch (error) {
114 | debugPrint(error.toString());
115 | }
116 | }
117 |
118 | @override
119 | void dispose() {
120 | _googlePayResultSubscription?.cancel();
121 | _googlePayResultSubscription = null;
122 | super.dispose();
123 | }
124 |
125 | @override
126 | Widget build(BuildContext context) {
127 | return Scaffold(
128 | appBar: AppBar(
129 | title: const Text('T-shirt Shop'),
130 | ),
131 | backgroundColor: Colors.white,
132 | body: ListView(
133 | padding: const EdgeInsets.symmetric(horizontal: 20),
134 | children: [
135 | Container(
136 | margin: const EdgeInsets.symmetric(vertical: 20),
137 | child: const Image(
138 | image: AssetImage('assets/images/ts_10_11019a.jpg'),
139 | height: 350,
140 | ),
141 | ),
142 | const Text(
143 | 'Amanda\'s Polo Shirt',
144 | style: TextStyle(
145 | fontSize: 20,
146 | color: Color(0xff333333),
147 | fontWeight: FontWeight.bold,
148 | ),
149 | ),
150 | const SizedBox(height: 5),
151 | const Text(
152 | '\$50.20',
153 | style: TextStyle(
154 | color: Color(0xff777777),
155 | fontSize: 15,
156 | ),
157 | ),
158 | const SizedBox(height: 15),
159 | const Text(
160 | 'Description',
161 | style: TextStyle(
162 | fontSize: 15,
163 | color: Color(0xff333333),
164 | fontWeight: FontWeight.bold,
165 | ),
166 | ),
167 | const SizedBox(height: 5),
168 | const Text(
169 | 'A versatile full-zip that you can wear all day long and even...',
170 | style: TextStyle(
171 | color: Color(0xff777777),
172 | fontSize: 15,
173 | ),
174 | ),
175 | const SizedBox(height: 15),
176 |
177 | // Google Pay button
178 | FutureBuilder(
179 | future: _canPayGoogleFuture,
180 | builder: (context, snapshot) {
181 | if (snapshot.connectionState == ConnectionState.done) {
182 | if (snapshot.data == true) {
183 | return RawGooglePayButton(
184 | paymentConfiguration:
185 | payment_configurations.defaultGooglePayConfig,
186 | type: GooglePayButtonType.buy,
187 | onPressed: _onGooglePayPressed);
188 | } else {
189 | // userCanPay returned false
190 | // Consider showing an alternative payment method
191 | }
192 | } else {
193 | // The operation hasn't finished loading
194 | // Consider showing a loading indicator
195 | }
196 | // This example shows an empty box if userCanPay returns false
197 | return const SizedBox.shrink();
198 | },
199 | ),
200 |
201 | // Apple Pay button
202 | FutureBuilder(
203 | future: _canPayAppleFuture,
204 | builder: (context, snapshot) {
205 | if (snapshot.connectionState == ConnectionState.done) {
206 | if (snapshot.data == true) {
207 | return RawApplePayButton(
208 | type: ApplePayButtonType.buy,
209 | onPressed: _onApplePayPressed);
210 | } else {
211 | // userCanPay returned false
212 | // Consider showing an alternative payment method
213 | }
214 | } else {
215 | // The operation hasn't finished loading
216 | // Consider showing a loading indicator
217 | }
218 | // This example shows an empty box if userCanPay returns false
219 | return const SizedBox.shrink();
220 | },
221 | ),
222 | ],
223 | ),
224 | );
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/pay/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/material.dart';
16 | import 'package:flutter_localizations/flutter_localizations.dart';
17 | import 'package:pay/pay.dart';
18 |
19 | import 'payment_configurations.dart' as payment_configurations;
20 |
21 | void main() {
22 | runApp(const PayMaterialApp());
23 | }
24 |
25 | const _paymentItems = [
26 | PaymentItem(
27 | label: 'Total',
28 | amount: '99.99',
29 | status: PaymentItemStatus.final_price,
30 | )
31 | ];
32 |
33 | class PayMaterialApp extends StatelessWidget {
34 | const PayMaterialApp({super.key});
35 |
36 | @override
37 | Widget build(BuildContext context) {
38 | return const MaterialApp(
39 | title: 'Pay for Flutter Demo',
40 | localizationsDelegates: [
41 | ...GlobalMaterialLocalizations.delegates,
42 | GlobalWidgetsLocalizations.delegate,
43 | ],
44 | supportedLocales: [
45 | Locale('en', ''),
46 | Locale('es', ''),
47 | Locale('de', ''),
48 | ],
49 | home: PaySampleApp(),
50 | );
51 | }
52 | }
53 |
54 | class PaySampleApp extends StatefulWidget {
55 | const PaySampleApp({super.key});
56 |
57 | @override
58 | State createState() => _PaySampleAppState();
59 | }
60 |
61 | class _PaySampleAppState extends State {
62 | late final Future _googlePayConfigFuture;
63 |
64 | @override
65 | void initState() {
66 | super.initState();
67 | _googlePayConfigFuture =
68 | PaymentConfiguration.fromAsset('default_google_pay_config.json');
69 | }
70 |
71 | void onGooglePayResult(paymentResult) {
72 | debugPrint(paymentResult.toString());
73 | }
74 |
75 | void onApplePayResult(paymentResult) {
76 | debugPrint(paymentResult.toString());
77 | }
78 |
79 | @override
80 | Widget build(BuildContext context) {
81 | return Scaffold(
82 | appBar: AppBar(
83 | title: const Text('T-shirt Shop'),
84 | ),
85 | backgroundColor: Colors.white,
86 | body: ListView(
87 | padding: const EdgeInsets.symmetric(horizontal: 20),
88 | children: [
89 | Container(
90 | margin: const EdgeInsets.symmetric(vertical: 20),
91 | child: const Image(
92 | image: AssetImage('assets/images/ts_10_11019a.jpg'),
93 | height: 350,
94 | ),
95 | ),
96 | const Text(
97 | 'Amanda\'s Polo Shirt',
98 | style: TextStyle(
99 | fontSize: 20,
100 | color: Color(0xff333333),
101 | fontWeight: FontWeight.bold,
102 | ),
103 | ),
104 | const SizedBox(height: 5),
105 | const Text(
106 | '\$50.20',
107 | style: TextStyle(
108 | color: Color(0xff777777),
109 | fontSize: 15,
110 | ),
111 | ),
112 | const SizedBox(height: 15),
113 | const Text(
114 | 'Description',
115 | style: TextStyle(
116 | fontSize: 15,
117 | color: Color(0xff333333),
118 | fontWeight: FontWeight.bold,
119 | ),
120 | ),
121 | const SizedBox(height: 5),
122 | const Text(
123 | 'A versatile full-zip that you can wear all day long and even...',
124 | style: TextStyle(
125 | color: Color(0xff777777),
126 | fontSize: 15,
127 | ),
128 | ),
129 | // Example pay button configured using an asset
130 | FutureBuilder(
131 | future: _googlePayConfigFuture,
132 | builder: (context, snapshot) => snapshot.hasData
133 | ? GooglePayButton(
134 | paymentConfiguration: snapshot.data!,
135 | paymentItems: _paymentItems,
136 | type: GooglePayButtonType.buy,
137 | margin: const EdgeInsets.only(top: 15.0),
138 | onPaymentResult: onGooglePayResult,
139 | loadingIndicator: const Center(
140 | child: CircularProgressIndicator(),
141 | ),
142 | )
143 | : const SizedBox.shrink()),
144 | // Example pay button configured using a string
145 | ApplePayButton(
146 | paymentConfiguration: payment_configurations.defaultApplePayConfig,
147 | paymentItems: _paymentItems,
148 | style: ApplePayButtonStyle.black,
149 | type: ApplePayButtonType.buy,
150 | margin: const EdgeInsets.only(top: 15.0),
151 | onPaymentResult: onApplePayResult,
152 | loadingIndicator: const Center(
153 | child: CircularProgressIndicator(),
154 | ),
155 | ),
156 | const SizedBox(height: 15)
157 | ],
158 | ),
159 | );
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/pay/example/lib/payment_configurations.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | /// This file contain sample payment configurations that can be used with the
16 | /// payment providers in this library.
17 | ///
18 | /// Although payment configurations can be hardcoded in your application source
19 | /// (as displayed in this example), we recommend you to keep this information in
20 | /// a remote location that can be accessed from your application (e.g.: a
21 | /// backend server). That way, you benefit from being able to use multiple
22 | /// payment configurations that can be modified without the need to update your
23 | /// application.
24 | library;
25 |
26 | import 'package:pay/pay.dart';
27 |
28 | /// Sample [PaymentConfiguration] for Apple Pay
29 | final defaultApplePayConfig =
30 | PaymentConfiguration.fromJsonString(defaultApplePay);
31 |
32 | /// Sample configuration for Apple Pay. Contains the same content as the file
33 | /// under `assets/default_payment_profile_apple_pay.json`.
34 | const String defaultApplePay = '''{
35 | "provider": "apple_pay",
36 | "data": {
37 | "merchantIdentifier": "merchant.com.sams.fish",
38 | "displayName": "Sam's Fish",
39 | "merchantCapabilities": ["3DS", "debit", "credit"],
40 | "supportedNetworks": ["amex", "visa", "discover", "masterCard"],
41 | "countryCode": "US",
42 | "currencyCode": "USD",
43 | "requiredBillingContactFields": ["emailAddress", "name", "phoneNumber", "postalAddress"],
44 | "requiredShippingContactFields": [],
45 | "shippingMethods": [
46 | {
47 | "amount": "0.00",
48 | "detail": "Available within an hour",
49 | "identifier": "in_store_pickup",
50 | "label": "In-Store Pickup"
51 | },
52 | {
53 | "amount": "4.99",
54 | "detail": "5-8 Business Days",
55 | "identifier": "flat_rate_shipping_id_2",
56 | "label": "UPS Ground"
57 | },
58 | {
59 | "amount": "29.99",
60 | "detail": "1-3 Business Days",
61 | "identifier": "flat_rate_shipping_id_1",
62 | "label": "FedEx Priority Mail"
63 | }
64 | ]
65 | }
66 | }''';
67 |
68 | /// Sample [PaymentConfiguration] for Google Pay
69 | final defaultGooglePayConfig =
70 | PaymentConfiguration.fromJsonString(defaultGooglePay);
71 |
72 | /// Sample configuration for Google Pay. Contains the same content as the file
73 | /// under `assets/default_payment_profile_google_pay.json`.
74 | const String defaultGooglePay = '''{
75 | "provider": "google_pay",
76 | "data": {
77 | "environment": "TEST",
78 | "apiVersion": 2,
79 | "apiVersionMinor": 0,
80 | "allowedPaymentMethods": [
81 | {
82 | "type": "CARD",
83 | "tokenizationSpecification": {
84 | "type": "PAYMENT_GATEWAY",
85 | "parameters": {
86 | "gateway": "example",
87 | "gatewayMerchantId": "exampleGatewayMerchantId"
88 | }
89 | },
90 | "parameters": {
91 | "allowedCardNetworks": ["VISA", "MASTERCARD"],
92 | "allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"],
93 | "billingAddressRequired": true,
94 | "billingAddressParameters": {
95 | "format": "FULL",
96 | "phoneNumberRequired": true
97 | }
98 | }
99 | }
100 | ],
101 | "merchantInfo": {
102 | "merchantName": "Example Merchant Name"
103 | },
104 | "transactionInfo": {
105 | "countryCode": "US",
106 | "currencyCode": "USD"
107 | }
108 | }
109 | }''';
110 |
111 | const String basicGooglePayIsReadyToPay = '''{
112 | "provider": "google_pay",
113 | "data": {
114 | "apiVersion": 2,
115 | "apiVersionMinor": 0,
116 | "allowedPaymentMethods": [
117 | {
118 | "type": "CARD",
119 | "parameters": {
120 | "allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"],
121 | "allowedCardNetworks": ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"]
122 | }
123 | }
124 | ]
125 | }
126 | }''';
127 |
128 | const String basicGooglePayLoadPaymentData = '''{
129 | "provider": "google_pay",
130 | "data": {
131 | "apiVersion": 2,
132 | "apiVersionMinor": 0,
133 | "merchantInfo": {
134 | "merchantName": "Example Merchant"
135 | },
136 | "allowedPaymentMethods": [
137 | {
138 | "type": "CARD",
139 | "parameters": {
140 | "allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"],
141 | "allowedCardNetworks": ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"]
142 | },
143 | "tokenizationSpecification": {
144 | "type": "PAYMENT_GATEWAY",
145 | "parameters": {
146 | "gateway": "example",
147 | "gatewayMerchantId": "exampleGatewayMerchantId"
148 | }
149 | }
150 | }
151 | ],
152 | "transactionInfo": {
153 | "totalPriceStatus": "FINAL",
154 | "totalPrice": "12.34",
155 | "currencyCode": "USD"
156 | }
157 | }
158 | }''';
159 |
160 | const String invalidGooglePayIsReadyToPay = '''{
161 | "provider": "google_pay",
162 | "data": {
163 | "apiVersion": 2,
164 | "apiVersionMinor": 0,
165 | "allowedPaymentMethods": [
166 | {
167 | "type": "CARD",
168 | "parameters": {}
169 | }
170 | ]
171 | }
172 | }''';
173 |
174 | const String invalidGooglePayLoadPaymentData = '''{
175 | "provider": "google_pay",
176 | "data": {
177 | "apiVersion": 2,
178 | "apiVersionMinor": 0,
179 | "merchantInfo": {
180 | "merchantName": "Example Merchant"
181 | },
182 | "allowedPaymentMethods": [
183 | {
184 | "type": "CARD",
185 | "parameters": {
186 | "allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"],
187 | "allowedCardNetworks": ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"]
188 | },
189 | "tokenizationSpecification": {
190 | "type": "PAYMENT_GATEWAY",
191 | "parameters": {
192 | "gateway": "example",
193 | "gatewayMerchantId": "exampleGatewayMerchantId"
194 | }
195 | }
196 | }
197 | ],
198 | "transactionInfo": {
199 | "totalPriceStatus": "FINAL",
200 | "totalPrice": "12.34",
201 | "currencyCode": "USD"
202 | }
203 | }
204 | }''';
205 |
--------------------------------------------------------------------------------
/pay/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | name: pay_example
16 | description: Shows how to use the pay plugin.
17 | publish_to: none
18 |
19 | environment:
20 | sdk: ">=3.0.0 <4.0.0"
21 | flutter: ">=3.10.0"
22 |
23 | flutter:
24 | uses-material-design: true
25 | assets:
26 | - assets/
27 | - assets/images/
28 |
29 | dependencies:
30 | flutter:
31 | sdk: flutter
32 | flutter_localizations:
33 | sdk: flutter
34 | pay:
35 | path: ../
36 |
37 | # The following adds the Cupertino Icons font to your application.
38 | # Use with the CupertinoIcons class for iOS style icons.
39 | cupertino_icons: ^1.0.3
40 |
41 | dependency_overrides:
42 | pay_android:
43 | path: ../../pay_android
44 | pay_ios:
45 | path: ../../pay_ios
46 | pay_platform_interface:
47 | path: ../../pay_platform_interface
48 |
49 | dev_dependencies:
50 | flutter_test:
51 | sdk: flutter
52 | integration_test:
53 | sdk: flutter
54 | flutter_lints: ^5.0.0
55 |
--------------------------------------------------------------------------------
/pay/lib/pay.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | library;
16 |
17 | import 'dart:convert';
18 | import 'dart:async';
19 |
20 | import 'package:flutter/foundation.dart';
21 | import 'package:flutter/material.dart';
22 | import 'package:flutter/services.dart';
23 | import 'package:pay_ios/pay_ios.dart';
24 | import 'package:pay_android/pay_android.dart';
25 | import 'package:pay_platform_interface/core/payment_configuration.dart';
26 | import 'package:pay_platform_interface/core/payment_item.dart';
27 | import 'package:pay_platform_interface/pay_channel.dart';
28 | import 'package:pay_platform_interface/pay_platform_interface.dart';
29 |
30 | export 'package:pay_platform_interface/core/payment_configuration.dart'
31 | show PayProvider, PaymentConfiguration;
32 |
33 | export 'package:pay_platform_interface/core/payment_item.dart'
34 | show PaymentItem, PaymentItemType, PaymentItemStatus;
35 |
36 | export 'package:pay_android/pay_android.dart'
37 | show RawGooglePayButton, GooglePayButtonTheme, GooglePayButtonType;
38 |
39 | export 'package:pay_ios/pay_ios.dart'
40 | show RawApplePayButton, ApplePayButtonStyle, ApplePayButtonType;
41 |
42 | part 'src/pay.dart';
43 | part 'src/widgets/pay_button.dart';
44 | part 'src/widgets/apple_pay_button.dart';
45 | part 'src/widgets/google_pay_button.dart';
46 |
--------------------------------------------------------------------------------
/pay/lib/src/pay.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | part of '../pay.dart';
16 |
17 | /// List of supported payment providers and platform pairs.
18 | const supportedProviders = {
19 | TargetPlatform.android: [PayProvider.google_pay],
20 | TargetPlatform.iOS: [PayProvider.apple_pay],
21 | };
22 |
23 | /// High level layer to easily manage cross-platform integrations.
24 | ///
25 | /// This class simplifies using the plugin and abstracts platform-specific
26 | /// directives.
27 | /// To use it, instantiate it with a list of configurations for the payment
28 | /// providers supported:
29 | /// ```dart
30 | /// final payConfiguration = PaymentConfiguration.fromJsonString();
31 | /// final payClient = Pay({: payConfiguration});
32 | /// await payClient.showPaymentSelector(, paymentItems);
33 | /// ```
34 | class Pay {
35 | /// The implementation of the platform interface to talk to the native ends.
36 | final PayPlatform _payPlatform;
37 |
38 | /// Map of configurations for the payment providers targeted.
39 | final Map _configurations;
40 |
41 | /// Creates an instance with a dictionary of [_configurations] and
42 | /// instantiates the [_payPlatform] to communicate with the native platforms.
43 | Pay(this._configurations) : _payPlatform = PayMethodChannel();
44 |
45 | /// Determines whether a user can pay with the selected [provider].
46 | ///
47 | /// This method wraps the [userCanPay] method in the platform interface. It
48 | /// makes sure that the [provider] exists and is available in the platform
49 | /// running the logic.
50 | Future userCanPay(PayProvider provider) async {
51 | await throwIfProviderIsNotDefined(provider);
52 | if (supportedProviders[defaultTargetPlatform]!.contains(provider)) {
53 | return _payPlatform.userCanPay(_configurations[provider]!);
54 | }
55 |
56 | return Future.value(false);
57 | }
58 |
59 | /// Shows the payment selector to initiate a payment process.
60 | ///
61 | /// This method wraps the [showPaymentSelector] method in the platform
62 | /// interface, and opens the payment selector for the [provider] of choice,
63 | /// with the [paymentItems] in the price summary.
64 | Future