From 26fd2745e5c731c26f06902b1f9ba060b137da60 Mon Sep 17 00:00:00 2001 From: Remon <> Date: Wed, 11 Oct 2023 20:21:42 +0100 Subject: [PATCH] DOC: customer sheet --- README.md | 2 + docs.json | 3 + docs/customer_sheet.mdx | 186 ++++++++++++++++++ .../customer_sheet/customer_sheet_screen.dart | 4 +- packages/stripe/README.md | 2 + 5 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 docs/customer_sheet.mdx diff --git a/README.md b/README.md index 6f0f11a91..bb14fb34b 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,8 @@ Payment sheet | Easy | Our recommended way of handling payments. It off Cardfield | Medium | Single line cardfield. Offers more flexibility but has less built-in functionality. | [docs](https://docs.page/flutter-stripe/flutter_stripe/card_field) | Card form | Medium | Similar as the cardfield but the entry fields are spread across multi lines | [docs](https://docs.page/flutter-stripe/flutter_stripe/card_field) | +### Mobile elements [BETA] +We also support the customer sheet mobile element. Check out the [docs](https://docs.page/flutter-stripe/flutter_stripe/customer_sheet) to learn more on how to set it up. ### Financial connections We also support Financial connections in our latest sdk. Check out the [docs](https://docs.page/flutter-stripe/flutter_stripe/financial_connections) to learn more on how to set it up. diff --git a/docs.json b/docs.json index 58d046c99..ebd8a89c1 100644 --- a/docs.json +++ b/docs.json @@ -11,6 +11,9 @@ ["CardFormField", "/card_field"] ] ], + ["Mobile elements", + ["Customer Sheet", "/customer_sheet"] + ], ["Regional payments", [ ["ACH direct debit", "/ach"], ["Ideal", "/ideal"] diff --git a/docs/customer_sheet.mdx b/docs/customer_sheet.mdx new file mode 100644 index 000000000..0dc23e636 --- /dev/null +++ b/docs/customer_sheet.mdx @@ -0,0 +1,186 @@ +--- +title: Customer sheet +description: Offer a pre-built UI for your customers to manage their saved payment methods. +--- + +# Mobile elements - Customer Sheet + +### Let customers manage their own payments. + + + +Important the customer sheet is in Beta so it is not guaranteed to work under all circumstances. + +## 1. Set up Stripe [Server Side] [Client Side] + +First, you need a Stripe account. [Register now](https://dashboard.stripe.com/register). + +#### Server-side + +This integration requires endpoints on your server that talk to the Stripe API. Use one official libraries for access to the Stripe API from your server. [Follow the steps here](https://stripe.com/docs/payments/accept-a-payment?platform=ios&ui=payment-sheet#setup-server-side) + +#### Client-side + +The Flutter SDK is open source, fully documented. + +To install the SDK, follow these steps: + - Run the commmand `flutter pub add flutter_stripe` + - This will add a line like this to your project's pubspec.yaml with the latest package version + + +For details on the latest SDK release and past versions, see the [Releases](https://github.com/flutter-stripe/flutter_stripe/releases) page on GitHub. To receive notifications when a new release is published, [watch releases for the repository](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/managing-subscriptions-for-activity-on-github/viewing-your-subscriptions#watching-releases-for-a-repository). + + +When your app starts, configure the SDK with your Stripe [publishable key](https://dashboard.stripe.com/) so that it can make requests to the Stripe API. + +```dart +void main() async { + Stripe.publishableKey = stripePublishableKey; + runApp(const App()); +} +``` + +Use your [test mode](https://stripe.com/docs/keys#obtain-api-keys) keys while you test and develop, and your [live mode](https://stripe.com/docs/keys#test-live-modes) keys when you publish your app. + +## 2. Add an enpoint [Server Side] + +First, you need a Stripe account. [Register now](https://dashboard.stripe.com/register). + +#### Server-side + +This integration uses three Stripe API objects: + +1. A [PaymentIntent](https://stripe.com/docs/api/payment_intents). Stripe uses this to represent your intent to collect payment from a customer, tracking your charge attempts and payment state changes throughout the process. + +2. A [Customer](https://stripe.com/docs/api/customers) (optional). To set up a card for future payments, it must be attached to a Customer. Create a Customer object when your customer creates an account with your business. If your customer is making a payment as a guest, you can create a Customer object before payment and associate it with your own internal representation of the customer’s account later. + +3. A Customer Ephemeral Key (optional). Information on the Customer object is sensitive, and can’t be retrieved directly from an app. An Ephemeral Key grants the SDK temporary access to the Customer. + +>> If you never save cards to a Customer and don’t allow returning Customers to reuse saved cards, you can omit the Customer and Customer Ephemeral Key objects from your integration. + +For security reasons, your app can’t create these objects. Instead, add an endpoint on your server that: + +1. Retrieves the Customer, or creates a new one. +2. Creates an Ephemeral Key for the Customer. +3. Creates a PaymentIntent, passing the Customer id. +4. Returns the Payment Intent’s [client secret](https://stripe.com/docs/api/payment_intents/object#payment_intent_object-client_secret), the Ephemeral Key’s secret, and the Customer’s id to your app. + +Check examples implementations for your server [here](https://stripe.com/docs/payments/accept-a-payment?platform=ios#add-server-endpoint) + +## 3. Collect customer details [Client Side] + +First initialize the customer sheet + +```dart + Future initCustomerSheet() async { + try { + // 1. retrieve customer from backend. + final data = await _createTestCustomerSheet(); + + // create some billingdetails + final billingDetails = BillingDetails( + name: 'Flutter Stripe', + email: 'email@stripe.com', + phone: '+48888000888', + address: Address( + city: 'Houston', + country: 'US', + line1: '1459 Circle Drive', + line2: '', + state: 'Texas', + postalCode: '77063', + ), + ); // mocked data for tests + + // 2. initialize the customer sheet + await Stripe.instance.initCustomerSheet( + customerSheetInitParams: CustomerSheetInitParams( + // Main params + setupIntentClientSecret: data['setupIntent'], + merchantDisplayName: 'Flutter Stripe Store Demo', + // Customer params + customerId: data['customer'], + customerEphemeralKeySecret: data['ephemeralKeySecret'], + style: ThemeMode.system, + defaultBillingDetails: billingDetails, + ), + ); + setState(() { + step = 1; + }); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Error: $e')), + ); + rethrow; + } + } + ``` + + Then you can show the customer sheet + + ```dart + Future confirmCustomerSheet() async { + try { + // 3. display the customer sheet. + final result = await Stripe.instance.presentCustomerSheet(); + + setState(() { + step = 0; + }); + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Payment succesfully modified option selected: ${result?.paymentOption?.label}}'), + ), + ); + } on Exception catch (e) { + if (e is StripeException) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Error from Stripe: ${e.error.localizedMessage}'), + ), + ); + } else { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Unforeseen error: ${e}'), + ), + ); + } + } + } + ``` + +## 3. Optional configuration + +### Change appearance + +It is possible to change the appearance of the customer sheet. + +```dart + await Stripe.instance.initCustomerSheet( + appearance: PaymentSheetAppearance( + colors: PaymentSheetAppearanceColors( + background: Colors.lightBlue, + primary: Colors.blue, + componentBorder: Colors.red, + ), + shapes: PaymentSheetShape( + borderWidth: 4, + shadow: PaymentSheetShadowParams(color: Colors.red), + ), + primaryButton: PaymentSheetPrimaryButtonAppearance( + shapes: PaymentSheetPrimaryButtonShape(blurRadius: 8), + colors: PaymentSheetPrimaryButtonTheme( + light: PaymentSheetPrimaryButtonThemeColors( + background: Color.fromARGB(255, 231, 235, 30), + text: Color.fromARGB(255, 235, 92, 30), + border: Color.fromARGB(255, 235, 92, 30), + ), + ), + ), + ), +); +``` diff --git a/example/lib/screens/customer_sheet/customer_sheet_screen.dart b/example/lib/screens/customer_sheet/customer_sheet_screen.dart index df982ba3f..4410a98d6 100644 --- a/example/lib/screens/customer_sheet/customer_sheet_screen.dart +++ b/example/lib/screens/customer_sheet/customer_sheet_screen.dart @@ -83,7 +83,7 @@ class _CustomerSheetScreenState extends State { ), ); // mocked data for tests - // 2. initialize the payment sheet + // 2. initialize the customer sheet await Stripe.instance.initCustomerSheet( customerSheetInitParams: CustomerSheetInitParams( // Main params @@ -119,7 +119,7 @@ class _CustomerSheetScreenState extends State { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( - 'Payment succesfully completed option selected: ${result?.paymentOption?.label}}'), + 'Payment preferences modfied completed option selected: ${result?.paymentOption?.label}}'), ), ); } on Exception catch (e) { diff --git a/packages/stripe/README.md b/packages/stripe/README.md index 6f0f11a91..bb14fb34b 100644 --- a/packages/stripe/README.md +++ b/packages/stripe/README.md @@ -92,6 +92,8 @@ Payment sheet | Easy | Our recommended way of handling payments. It off Cardfield | Medium | Single line cardfield. Offers more flexibility but has less built-in functionality. | [docs](https://docs.page/flutter-stripe/flutter_stripe/card_field) | Card form | Medium | Similar as the cardfield but the entry fields are spread across multi lines | [docs](https://docs.page/flutter-stripe/flutter_stripe/card_field) | +### Mobile elements [BETA] +We also support the customer sheet mobile element. Check out the [docs](https://docs.page/flutter-stripe/flutter_stripe/customer_sheet) to learn more on how to set it up. ### Financial connections We also support Financial connections in our latest sdk. Check out the [docs](https://docs.page/flutter-stripe/flutter_stripe/financial_connections) to learn more on how to set it up.