# Save directly without charging Collect details of a present card and save them for online use. > #### Accounts v2 API support > > The Terminal SDK doesn’t support *customer-configured Accounts* (Account configurations represent role-based functionality that you can enable for accounts, such as merchant, customer, or recipient). It only supports `Customer` objects. You can use Terminal with the Accounts v2 API if all of your customer code is on the server side and doesn’t use the SDK. Use [SetupIntents](https://docs.stripe.com/payments/setup-intents.md) to collect card or mobile wallet details without charging the card. A `SetupIntent` can’t save a `card_present` *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) directly, but in most cases you can create a reusable `generated_card` type `PaymentMethod` that represents the same card. From your customer’s perspective, they’re the same payment method. > All charges made using the `generated_card` PaymentMethod are card-not-present (CNP) transactions, and features available to card-present transactions (such as *liability shifts* (With some 3D Secure transactions, the liability for fraudulent chargebacks (stolen or counterfeit cards) shifts from you to the card issuer) and [pricing](https://stripe.com/terminal#pricing))don’t apply to these charges. You can use [SetupIntents](https://docs.stripe.com/payments/setup-intents.md) to collect card details on Visa, Mastercard, American Express, Discover, and co-branded Interac, eftpos, and girocard cards. `SetupIntents` don’t support single-branded Interac, eftpos, and girocard cards. [Tap to Pay](https://docs.stripe.com/terminal/payments/setup-reader/tap-to-pay.md) doesn’t support co-branded Interac cards, which must be inserted into a reader. Saving cards with Stripe Terminal using `SetupIntents` requires you to: 1. Create or retrieve a *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) or *customer-configured* (Account configurations represent role-based functionality that you can enable for accounts, such as merchant, customer, or recipient) `Account` object. 1. Create a [SetupIntent](https://docs.stripe.com/api/setup_intents.md) object to track the process. 1. After you collect the customer’s consent, collect the payment method and submit the details to Stripe. # Server-driven > The server-driven-based SetupIntents API is compatible with BBPOS WisePOS E and Stripe Reader S700/S710. ## Create or retrieve a customer To charge a card saved with Stripe, you must attach it to a [Customer](https://docs.stripe.com/api/customers.md) or a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts.md). When you include a customer in your [SetupIntent](https://docs.stripe.com/api/setup_intents.md) before confirming, Stripe automatically attaches the generated card payment method to the customer object you provide. ## Create a SetupIntent A [SetupIntent](https://docs.stripe.com/api/setup_intents.md) is an object that represents your intent to set up a customer’s payment method for future payments. The `SetupIntent` tracks the steps of this setup process. For Terminal, this includes collecting and recording cardholder consent. When you create a `SetupIntent`, provide the customer object ID in the [customer](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-customer) or [customer_account](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-customer_account) parameter to automatically attach the payment method to the customer upon successful setup. If you don’t provide the ID on creation, you must attach the payment method to the customer in a separate call. - [Create a SetupIntent](https://docs.stripe.com/api/setup_intents/create.md) You must create the `SetupIntent` on your server and include `card_present` in the `payment_method_types` array. Set `usage` to `on_session` if you only intend to reuse the payment method when the customer is in your checkout flow. #### Accounts v2 ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d "payment_method_types[]=card_present" \ -d usage=on_session ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d "payment_method_types[]=card_present" \ -d usage=on_session ``` ## Collect a payment method for saving - [process_setup_intent](https://docs.stripe.com/api/terminal/readers/process_setup_intent.md) After you create a `SetupIntent`, you need to collect a payment method and collect customer consent. Set `allow_redisplay` to `always` or `limited`, indicating the degree to which the payment method can be shown in a customer checkout flow. Collect customer consent verbally or with a checkbox in your application. You must comply with all applicable laws, rules, and regulations in your region. You must call the [process_setup_intent](https://docs.stripe.com/api/terminal/readers/process_setup_intent.md) endpoint, which handles both collecting and confirming the `SetupIntent`. If the customer provides consent, set `allow_redisplay` to either `always` or `limited`. ```curl curl https://api.stripe.com/v1/terminal/readers/{{READER_ID}}/process_setup_intent \ -u "<>:" \ -d setup_intent={{SETUP_INTENT_ID}} \ -d allow_redisplay=always ``` This method collects encrypted payment method data using the connected card reader, and associates the encrypted data with the `SetupIntent`. The collection happens locally and requires no authorization or updates to the `SetupIntent` object until the next step. ### Cancel collection #### Programmatic cancellation - [cancel_action](https://docs.stripe.com/api/terminal/readers/cancel_action.md) You can cancel collecting a payment method by calling [cancel_action](https://docs.stripe.com/api/terminal/readers/cancel_action.md). ## Submit the payment method details to Stripe Your previous call to [process_setup_intent](https://docs.stripe.com/api/terminal/readers/process_setup_intent.md) handles the *confirm* (Confirming an intent indicates that the customer intends to use the current or provided payment method. Upon confirmation, the intent attempts to initiate the portions of the flow that have real-world side effects) for you, so no further action is necessary. A successful setup returns a `succeeded` value for the `SetupIntent`’s [status](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-status) property, along with a [SetupAttempt.payment_method_details.card_present.generated_card](https://docs.stripe.com/api/setup_attempts/object.md#setup_attempt_object-payment_method_details-card_present-generated_card), which is a reusable `card` payment method you can use for online payments. > The [SetupIntent.payment_method](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-payment_method) is a `card_present` `PaymentMethod` that represents the tokenization of the physically present card. You can’t charge it online. Future payments use the generated card instead. From the customer’s perspective, they’re the same payment method. The `generated_card` payment method automatically attaches to the customer you provided during [SetupIntent creation](https://docs.stripe.com/terminal/features/saving-payment-details/save-directly.md#create-setupintent). You can retrieve the `generated_card` payment method by expanding the `SetupIntent`’s `latest_attempt` property. Always check for a `generated_card` value, because for payment methods that don’t allow generated cards, the value is empty. ```curl curl -G https://api.stripe.com/v1/setup_intents/{{SETUPINTENT_ID}} \ -u "<>:" \ -d "expand[]=latest_attempt" ``` Alternatively, you can retrieve the attached payment method by fetching the list of payment methods that gets attached to the customer. #### Accounts v2 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d type=card ``` #### Customers v1 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d type=card ``` If you didn’t provide a customer during `SetupIntent` creation, you can attach the `generated_card` to the customer in a separate call. #### Accounts v2 ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}}/attach \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}}/attach \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" ``` If the setup isn’t successful, inspect the returned error to determine the cause. For example, failing to collect and notify Stripe of customer consent results in an error. ## Mobile wallets considerations You can only use saved mobile wallets for [off_session](https://docs.stripe.com/api/payment_intents/confirm.md#confirm_payment_intent-off_session) payments that you initiate on behalf of your customer, such as recurring subscription payments. When you save a digital wallet payment method, the `generated_card` has `allow_redisplay=limited`, to indicate its specific usage considerations. When you attempt to charge a mobile wallet, make sure to set `off_session` to true when confirming the `PaymentIntent`. If the customer is present in your checkout flow, you need to instead use the appropriate mobile wallet integration to prompt them for their payment method. ## Compliance You’re responsible for your compliance with all applicable laws, regulations, and network rules when saving a customer’s payment details. For example, the European Data Protection Board has issued guidance regarding saving payment details. These requirements generally apply if you want to save your customer’s payment method for future use. This applies in situations such as presenting a customer’s payment method to them in the checkout flow for a future purchase, or charging them when they’re not actively using your website or app, placing a MOTO order, or in your store. Add terms to your checkout flow that state how you plan to save payment method details and allow customers to opt in. If you plan to charge the customer while they’re not actively checking out, make sure (at a minimum) that your terms also cover the following: - The customer’s agreement to your initiating a payment or a series of payments on their behalf for specified transactions. - The anticipated timing and frequency of payments (for instance, whether charges are for scheduled installment or subscription payments, or for unscheduled top-ups). - How the payment amount is determined. - Your cancellation policy, if you’re setting up the payment method for a subscription service. Make sure you keep a record of your customer’s written agreement to these terms. When you save a payment method, you can only use it for the specific purpose that you included in your terms. If you want to charge customers when they’re not actively checking out and also save the customer’s payment method to present to them as a saved payment method for future purchases, you must explicitly collect consent from the customer. One way to do so is with a “Save my payment method for future use” checkbox. # JavaScript ## Create or retrieve a customer To charge a card saved with Stripe, you must attach it to a [Customer](https://docs.stripe.com/api/customers.md) or a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts.md). When you include a customer in your [SetupIntent](https://docs.stripe.com/api/setup_intents.md) before confirming, Stripe automatically attaches the generated card payment method to the customer object you provide. ## Create a SetupIntent A [SetupIntent](https://docs.stripe.com/api/setup_intents.md) is an object that represents your intent to set up a customer’s payment method for future payments. The `SetupIntent` tracks the steps of this setup process. For Terminal, this includes collecting and recording cardholder consent. When you create a `SetupIntent`, provide the customer object ID in the [customer](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-customer) or [customer_account](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-customer_account) parameter to automatically attach the payment method to the customer upon successful setup. If you don’t provide the ID on creation, you must attach the payment method to the customer in a separate call. - [Create a SetupIntent](https://docs.stripe.com/api/setup_intents/create.md) You must create the `SetupIntent` on your server and include `card_present` in the `payment_method_types` array. Set `usage` to `on_session` if you only intend to reuse the payment method when the customer is in your checkout flow. The `SetupIntent` contains a *client secret* (The client secret is a unique key returned from Stripe as part of a SetupIntent. This key lets the client access important fields from the SetupIntent (for example, status)), which you can pass to the client instead of passing the entire object. #### Accounts v2 ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d "payment_method_types[]=card_present" \ -d usage=on_session ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d "payment_method_types[]=card_present" \ -d usage=on_session ``` ## Collect a payment method for saving - [collectSetupIntentPaymentMethod (JavaScript)](https://docs.stripe.com/terminal/references/api/js-sdk.md#collect-setup-intent-payment-method) After you create a `SetupIntent`, you need to collect a payment method using the SDK and collect customer consent. Set `allowRedisplay` to `always` or `limited`, indicating the degree to which the payment method can be shown in a customer checkout flow. Collect customer consent verbally or with a checkbox in your application. You must comply with all applicable laws, rules, and regulations in your region. To collect a payment method, make sure that you’re connected to a reader. The connected reader waits for a card after your app calls `collectSetupIntentPaymentMethod`. ```javascript async () => { // clientSecret is the client_secret from the SetupIntent you created in Step 1. const result = await terminal.collectSetupIntentPaymentMethod(clientSecret, "always"); if (result.error) { // Placeholder for handling result.error } else { // Placeholder for confirming result.setupIntent } } ``` This method collects encrypted payment method data using the connected card reader, and associates the encrypted data with the `SetupIntent`. The collection happens locally and requires no authorization or updates to the `SetupIntent` object until the next step. ### Cancel collection #### Programmatic cancellation You can cancel collecting a payment method by calling [cancelCollectSetupIntentPaymentMethod](https://docs.stripe.com/terminal/references/api/js-sdk.md#cancel-collect-setup-intent-payment-method) in the SDK. #### Customer-initiated cancellation When you set [enable_customer_cancellation](https://docs.stripe.com/terminal/references/api/js-sdk.md#collect-setup-intent-payment-method) to true for a transaction, smart reader users see a cancel button. Tapping the cancel button cancels the active transaction. ```javascript terminal.collectSetupIntentPaymentMethod( setupIntent, allowRedisplay,{ enable_customer_cancellation: true } ) ``` ## Submit the payment method details to Stripe - [confirmSetupIntent (JavaScript)](https://docs.stripe.com/terminal/references/api/js-sdk.md#confirm-setup-intent) Use `confirmSetupIntent` to complete the setup. A successful setup returns a `succeeded` value for the `SetupIntent`’s [status](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-status) property, along with a [SetupAttempt.payment_method_details.card_present.generated_card](https://docs.stripe.com/api/setup_attempts/object.md#setup_attempt_object-payment_method_details-card_present-generated_card), which is a reusable `card` payment method you can use for online payments. > The [SetupIntent.payment_method](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-payment_method) is a `card_present` `PaymentMethod` that represents the tokenization of the physically present card. You can’t charge it online. Future payments use the generated card instead. From the customer’s perspective, they’re the same payment method. The `generated_card` payment method automatically attaches to the customer you provided during [SetupIntent creation](https://docs.stripe.com/terminal/features/saving-payment-details/save-directly.md#create-setupintent). You can retrieve the `generated_card` payment method by expanding the `SetupIntent`’s `latest_attempt` property. Always check for a `generated_card` value, because for payment methods that don’t allow generated cards, the value is empty. ```curl curl -G https://api.stripe.com/v1/setup_intents/{{SETUPINTENT_ID}} \ -u "<>:" \ -d "expand[]=latest_attempt" ``` Alternatively, you can retrieve the attached payment method by fetching the list of payment methods that gets attached to the customer. #### Accounts v2 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d type=card ``` #### Customers v1 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d type=card ``` If you didn’t provide a customer during `SetupIntent` creation, you can attach the `generated_card` to the customer in a separate call. #### Accounts v2 ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}}/attach \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}}/attach \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" ``` If the setup isn’t successful, inspect the returned error to determine the cause. For example, failing to collect and notify Stripe of customer consent results in an error. ## Mobile wallets considerations You can only use saved mobile wallets for [off_session](https://docs.stripe.com/api/payment_intents/confirm.md#confirm_payment_intent-off_session) payments that you initiate on behalf of your customer, such as recurring subscription payments. When you save a digital wallet payment method, the `generated_card` has `allow_redisplay=limited`, to indicate its specific usage considerations. When you attempt to charge a mobile wallet, make sure to set `off_session` to true when confirming the `PaymentIntent`. If the customer is present in your checkout flow, you need to instead use the appropriate mobile wallet integration to prompt them for their payment method. ## Compliance You’re responsible for your compliance with all applicable laws, regulations, and network rules when saving a customer’s payment details. For example, the European Data Protection Board has issued guidance regarding saving payment details. These requirements generally apply if you want to save your customer’s payment method for future use. This applies in situations such as presenting a customer’s payment method to them in the checkout flow for a future purchase, or charging them when they’re not actively using your website or app, placing a MOTO order, or in your store. Add terms to your checkout flow that state how you plan to save payment method details and allow customers to opt in. If you plan to charge the customer while they’re not actively checking out, make sure (at a minimum) that your terms also cover the following: - The customer’s agreement to your initiating a payment or a series of payments on their behalf for specified transactions. - The anticipated timing and frequency of payments (for instance, whether charges are for scheduled installment or subscription payments, or for unscheduled top-ups). - How the payment amount is determined. - Your cancellation policy, if you’re setting up the payment method for a subscription service. Make sure you keep a record of your customer’s written agreement to these terms. When you save a payment method, you can only use it for the specific purpose that you included in your terms. If you want to charge customers when they’re not actively checking out and also save the customer’s payment method to present to them as a saved payment method for future purchases, you must explicitly collect consent from the customer. One way to do so is with a “Save my payment method for future use” checkbox. # iOS > In version `5.0.0` of the SDK, the collect and confirm integration steps are now combined into a single `processSetupIntent` step. ## Create or retrieve a customer To charge a card saved with Stripe, you must attach it to a [Customer](https://docs.stripe.com/api/customers.md) or a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts.md). > #### Terminal SDK support for customers > > If you create and manage `SetupIntents` on the client using the Terminal SDK, you must use `Customer` objects. The Terminal SDK doesn’t support the Accounts v2 API. When you include a customer in your [SetupIntent](https://docs.stripe.com/api/setup_intents.md) before confirming, Stripe automatically attaches the generated card payment method to the customer object you provide. ## Create a SetupIntent A [SetupIntent](https://docs.stripe.com/api/setup_intents.md) is an object that represents your intent to set up a customer’s payment method for future payments. The `SetupIntent` tracks the steps of this setup process. For Terminal, this includes collecting and recording cardholder consent. When you create a `SetupIntent`, provide the customer object ID in the [customer](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-customer) or [customer_account](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-customer_account) parameter to automatically attach the payment method to the customer upon successful setup. If you don’t provide the ID on creation, you must attach the payment method to the customer in a separate call. - [SetupIntentParameters (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPSetupIntentParameters.html) You can create a `SetupIntent` providing the `customer` or `customerAccount`, `onBehalfOf` (*Connect* (Connect is Stripe's solution for multi-party businesses, such as marketplace or software platforms, to route payments between sellers, customers, and other recipients) only), and `usage` parameters. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController { // Action for a "Save Card" button func saveCardAction() throws { let params = try SetupIntentParametersBuilder().setCustomer(""{{CUSTOMER_ID}}"") Terminal.shared.createSetupIntent(params) { createResult, createError in if let error = createError { print("createSetupIntent failed: \(error)") } else if let setupIntent = createResult { print("createSetupIntent succeeded") // ... } } } // ... } ``` If the information required to start a payment isn’t readily available in your app, you can [create the SetupIntent](https://docs.stripe.com/api/setup_intents/create.md) on your server. Use the client secret to call `retrieveSetupIntent`, and, then use the retrieved `SetupIntent` to call `processSetupIntent`. ## Collect a payment method for saving - [retrieveSetupIntent (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)retrieveSetupIntent:delegate:completion:) - [processSetupIntent (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)processSetupIntent:collectConfig:completion:) After you create a `SetupIntent`, you need to collect a payment method using the SDK and collect customer consent. Set `allowRedisplay` to `always` or `limited`, indicating the degree to which the payment method can be shown in a customer checkout flow. Collect customer consent verbally or with a checkbox in your application. You must comply with all applicable laws, rules, and regulations in your region. To process a setup intent, make sure that you’re connected to a reader. The connected reader waits for a card after your app calls `processSetupIntent`. #### Swift ```swift import UIKit import StripeTerminal class PaymentViewController: UIViewController, ReaderDisplayDelegate { // Label for displaying messages from the card reader let readerMessageLabel = UILabel(frame: .zero) var collectCancelable: Cancelable? = nil // ... // Action for a "Subscribe" button func subscribeAction() throws { let params = try SetupIntentParametersBuilder().setCustomer(""{{CUSTOMER_ID}}"").build() Terminal.shared.createSetupIntent(params) { createResult, createError in if let error = createError { print("createSetupIntent failed: \(error)") } else if let setupIntent = createResult { print("createSetupIntent succeeded") let config = try CollectSetupIntentConfigurationBuilder() .setAllowRedisplay(.always) .build() self.collectCancelable = Terminal.shared.processSetupIntent(setupIntent, collectConfig: config) { processedSetupIntent, processError in if let error = processError { print("processSetupIntent failed: \(error)") } else if let processedSetupIntent = processedSetupIntent { print("processSetupIntent succeeded") } } } } } } ``` This method collects encrypted payment method data using the connected card reader, and associates the encrypted data with the `SetupIntent`. The collection happens locally and requires no authorization or updates to the `SetupIntent` object until the next step. ### Cancel collection #### Programmatic cancellation You can cancel collecting a payment method by using the [Cancelable](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCancelable.html) object returned by the SDK. #### Customer-initiated cancellation CustomerCancellation is enabled by default, so smart reader users see a cancel button. Tapping the cancel button cancels the active transaction. Use [setCustomerCancellation](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCollectSetupIntentConfigurationBuilder.html#/c:objc\(cs\)SCPCollectSetupIntentConfigurationBuilder\(im\)setCustomerCancellation) to toggle this behavior for a transaction. #### Swift ```swift let setupConfig = try CollectSetupIntentConfiguration() .build() Terminal.shared.collectSetupIntentPaymentMethod(intent, allowRedisplay: AllowRedisplay.always, setupConfig: setupConfig) { collectedSetupIntent, collectError in } ``` ## Submit the payment method details to Stripe Your previous call to `processSetupIntent` handles the *confirm* (Confirming an intent indicates that the customer intends to use the current or provided payment method. Upon confirmation, the intent attempts to initiate the portions of the flow that have real-world side effects) for you, so no further action is necessary. A successful setup returns a `succeeded` value for the `SetupIntent`’s [status](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-status) property, along with a [SetupAttempt.payment_method_details.card_present.generated_card](https://docs.stripe.com/api/setup_attempts/object.md#setup_attempt_object-payment_method_details-card_present-generated_card), which is a reusable `card` payment method you can use for online payments. > The [SetupIntent.payment_method](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-payment_method) is a `card_present` `PaymentMethod` that represents the tokenization of the physically present card. You can’t charge it online. Future payments use the generated card instead. From the customer’s perspective, they’re the same payment method. The `generated_card` payment method automatically attaches to the customer you provided during [SetupIntent creation](https://docs.stripe.com/terminal/features/saving-payment-details/save-directly.md#create-setupintent). You can retrieve the `generated_card` payment method by expanding the `SetupIntent`’s `latest_attempt` property. Always check for a `generated_card` value, because for payment methods that don’t allow generated cards, the value is empty. ```curl curl -G https://api.stripe.com/v1/setup_intents/{{SETUPINTENT_ID}} \ -u "<>:" \ -d "expand[]=latest_attempt" ``` Alternatively, you can retrieve the attached payment method by fetching the list of payment methods that gets attached to the customer. #### Accounts v2 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d type=card ``` #### Customers v1 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d type=card ``` If you didn’t provide a customer during `SetupIntent` creation, you can attach the `generated_card` to the customer in a separate call. #### Accounts v2 ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}}/attach \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}}/attach \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" ``` If the setup isn’t successful, inspect the returned error to determine the cause. For example, failing to collect and notify Stripe of customer consent results in an error. #### Swift ```swift // Action for a "Save Card" button func saveCardAction() throws { let params = try SetupIntentParametersBuilder.setCustomer(""{{CUSTOMER_ID}}"").build() Terminal.shared.createSetupIntent(params) { createResult, createError in if let error = createError { print("createSetupIntent failed: \(error)") } else if let setupIntent = createResult { print("createSetupIntent succeeded") let config = try CollectSetupIntentConfigurationBuilder() .setAllowRedisplay(.always) .build() self.collectCancelable = Terminal.shared.processSetupIntent(setupIntent, collectConfig: config) { processedSetupIntent, processError in if let error = processError { print("processSetupIntent failed: \(error)") } else if let processedSetupIntent = processedSetupIntent { print("processSetupIntent succeeded") } } } } } ``` ## Mobile wallets considerations You can only use saved mobile wallets for [off_session](https://docs.stripe.com/api/payment_intents/confirm.md#confirm_payment_intent-off_session) payments that you initiate on behalf of your customer, such as recurring subscription payments. When you save a digital wallet payment method, the `generated_card` has `allow_redisplay=limited`, to indicate its specific usage considerations. When you attempt to charge a mobile wallet, make sure to set `off_session` to true when confirming the `PaymentIntent`. If the customer is present in your checkout flow, you need to instead use the appropriate mobile wallet integration to prompt them for their payment method. ## Compliance You’re responsible for your compliance with all applicable laws, regulations, and network rules when saving a customer’s payment details. For example, the European Data Protection Board has issued guidance regarding saving payment details. These requirements generally apply if you want to save your customer’s payment method for future use. This applies in situations such as presenting a customer’s payment method to them in the checkout flow for a future purchase, or charging them when they’re not actively using your website or app, placing a MOTO order, or in your store. Add terms to your checkout flow that state how you plan to save payment method details and allow customers to opt in. If you plan to charge the customer while they’re not actively checking out, make sure (at a minimum) that your terms also cover the following: - The customer’s agreement to your initiating a payment or a series of payments on their behalf for specified transactions. - The anticipated timing and frequency of payments (for instance, whether charges are for scheduled installment or subscription payments, or for unscheduled top-ups). - How the payment amount is determined. - Your cancellation policy, if you’re setting up the payment method for a subscription service. Make sure you keep a record of your customer’s written agreement to these terms. When you save a payment method, you can only use it for the specific purpose that you included in your terms. If you want to charge customers when they’re not actively checking out and also save the customer’s payment method to present to them as a saved payment method for future purchases, you must explicitly collect consent from the customer. One way to do so is with a “Save my payment method for future use” checkbox. # Android > In version `5.0.0` of the SDK, the collect and confirm integration steps are now combined into a single `processSetupIntent` step. ## Create or retrieve a customer To charge a card saved with Stripe, you must attach it to a [Customer](https://docs.stripe.com/api/customers.md) or a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts.md). > #### Terminal SDK support for customers > > If you create and manage `SetupIntents` on the client using the Terminal SDK, you must use `Customer` objects. The Terminal SDK doesn’t support the Accounts v2 API. When you include a customer in your [SetupIntent](https://docs.stripe.com/api/setup_intents.md) before confirming, Stripe automatically attaches the generated card payment method to the customer object you provide. ## Create a SetupIntent A [SetupIntent](https://docs.stripe.com/api/setup_intents.md) is an object that represents your intent to set up a customer’s payment method for future payments. The `SetupIntent` tracks the steps of this setup process. For Terminal, this includes collecting and recording cardholder consent. When you create a `SetupIntent`, provide the customer object ID in the [customer](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-customer) or [customer_account](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-customer_account) parameter to automatically attach the payment method to the customer upon successful setup. If you don’t provide the ID on creation, you must attach the payment method to the customer in a separate call. - [SetupIntentParameters (Android)](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-setup-intent-parameters/index.html) You can create a `SetupIntent` providing the `customer` or `customerAccount`, `onBehalfOf` (*Connect* (Connect is Stripe's solution for multi-party businesses, such as marketplace or software platforms, to route payments between sellers, customers, and other recipients) only), and `usage` parameters. #### Kotlin ```kotlin val params = SetupIntentParameters.Builder() .setCustomer(""{{CUSTOMER_ID}}"") .build() Terminal.getInstance().createSetupIntent( params, object : SetupIntentCallback { override fun onSuccess(setupIntent: SetupIntent) { // Placeholder for handling successful operation } override fun onFailure(e: TerminalException) { // Placeholder for handling exception } } ) ``` If the information required to start a payment isn’t readily available in your app, you can [create the SetupIntent](https://docs.stripe.com/api/setup_intents/create.md) on your server. Use the client secret to call `retrieveSetupIntent`, and, then use the retrieved `SetupIntent` to call `processSetupIntent`. ## Collect a payment method for saving - [retrieveSetupIntent (Android)](https://stripe.dev/stripe-terminal-android/core/com.stripe.stripeterminal/-terminal/retrieve-setup-intent.html) - [processSetupIntent (Android)](https://stripe.dev/stripe-terminal-android/core/com.stripe.stripeterminal/-terminal/process-setup-intent.html) After you create a `SetupIntent`, you need to collect a payment method using the SDK and collect customer consent. Set `allowRedisplay` to `always` or `limited`, indicating the degree to which the payment method can be shown in a customer checkout flow. Collect customer consent verbally or with a checkbox in your application. You must comply with all applicable laws, rules, and regulations in your region. To process a setup intent, make sure that you’re connected to a reader. The connected reader waits for a card after your app calls `processSetupIntent`. #### Kotlin ```kotlin val config = CollectSetupIntentConfiguration.Builder() .build() val cancelable = Terminal.getInstance().processSetupIntent( setupIntent, AllowRedisplay.ALWAYS, config, object : SetupIntentCallback { override fun onSuccess(setupIntent: SetupIntent) { // Placeholder for handling successful operation } override fun onFailure(e: TerminalException) { // Placeholder for handling exception } } ) ``` This method collects encrypted payment method data using the connected card reader, and associates the encrypted data with the `SetupIntent`. The collection happens locally and requires no authorization or updates to the `SetupIntent` object until the next step. ### Cancel collection #### Programmatic cancellation You can cancel collecting a payment method by using the [Cancelable](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCancelable.html) object returned by the SDK. #### Customer-initiated cancellation CustomerCancellation is enabled by default, so smart reader users see a cancel button. Tapping the cancel button cancels the active transaction. Use [setCustomerCancellation](https://stripe.dev/stripe-terminal-android/external/com.stripe.stripeterminal.external.models/-collect-setup-intent-configuration/-builder/set-customer-cancellation.html) to toggle this behavior for a transaction. #### Kotlin ```kotlin Terminal.getInstance().collectSetupIntentPaymentMethod( setupIntent, AllowRedisplay.ALWAYS,SetupIntentConfiguration.Builder() .build(), object : SetupIntentCallback { override fun onSuccess(setupIntent: SetupIntent) { // Placeholder for handling successful operation } override fun onFailure(e: TerminalException) { // Placeholder for handling exception } } ) ``` ## Submit the payment method details to Stripe Your previous call to `processSetupIntent` handles the *confirm* (Confirming an intent indicates that the customer intends to use the current or provided payment method. Upon confirmation, the intent attempts to initiate the portions of the flow that have real-world side effects) for you, so no further action is necessary. A successful setup returns a `succeeded` value for the `SetupIntent`’s [status](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-status) property, along with a [SetupAttempt.payment_method_details.card_present.generated_card](https://docs.stripe.com/api/setup_attempts/object.md#setup_attempt_object-payment_method_details-card_present-generated_card), which is a reusable `card` payment method you can use for online payments. > The [SetupIntent.payment_method](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-payment_method) is a `card_present` `PaymentMethod` that represents the tokenization of the physically present card. You can’t charge it online. Future payments use the generated card instead. From the customer’s perspective, they’re the same payment method. The `generated_card` payment method automatically attaches to the customer you provided during [SetupIntent creation](https://docs.stripe.com/terminal/features/saving-payment-details/save-directly.md#create-setupintent). You can retrieve the `generated_card` payment method by expanding the `SetupIntent`’s `latest_attempt` property. Always check for a `generated_card` value, because for payment methods that don’t allow generated cards, the value is empty. ```curl curl -G https://api.stripe.com/v1/setup_intents/{{SETUPINTENT_ID}} \ -u "<>:" \ -d "expand[]=latest_attempt" ``` Alternatively, you can retrieve the attached payment method by fetching the list of payment methods that gets attached to the customer. #### Accounts v2 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d type=card ``` #### Customers v1 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d type=card ``` If you didn’t provide a customer during `SetupIntent` creation, you can attach the `generated_card` to the customer in a separate call. #### Accounts v2 ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}}/attach \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}}/attach \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" ``` If the setup isn’t successful, inspect the returned error to determine the cause. For example, failing to collect and notify Stripe of customer consent results in an error. ## Mobile wallets considerations You can only use saved mobile wallets for [off_session](https://docs.stripe.com/api/payment_intents/confirm.md#confirm_payment_intent-off_session) payments that you initiate on behalf of your customer, such as recurring subscription payments. When you save a digital wallet payment method, the `generated_card` has `allow_redisplay=limited`, to indicate its specific usage considerations. When you attempt to charge a mobile wallet, make sure to set `off_session` to true when confirming the `PaymentIntent`. If the customer is present in your checkout flow, you need to instead use the appropriate mobile wallet integration to prompt them for their payment method. ## Compliance You’re responsible for your compliance with all applicable laws, regulations, and network rules when saving a customer’s payment details. For example, the European Data Protection Board has issued guidance regarding saving payment details. These requirements generally apply if you want to save your customer’s payment method for future use. This applies in situations such as presenting a customer’s payment method to them in the checkout flow for a future purchase, or charging them when they’re not actively using your website or app, placing a MOTO order, or in your store. Add terms to your checkout flow that state how you plan to save payment method details and allow customers to opt in. If you plan to charge the customer while they’re not actively checking out, make sure (at a minimum) that your terms also cover the following: - The customer’s agreement to your initiating a payment or a series of payments on their behalf for specified transactions. - The anticipated timing and frequency of payments (for instance, whether charges are for scheduled installment or subscription payments, or for unscheduled top-ups). - How the payment amount is determined. - Your cancellation policy, if you’re setting up the payment method for a subscription service. Make sure you keep a record of your customer’s written agreement to these terms. When you save a payment method, you can only use it for the specific purpose that you included in your terms. If you want to charge customers when they’re not actively checking out and also save the customer’s payment method to present to them as a saved payment method for future purchases, you must explicitly collect consent from the customer. One way to do so is with a “Save my payment method for future use” checkbox. # React Native > In version `0.0.1-beta.29` of the React Native SDK, you can use the [processSetupIntent](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#processsetupintent) method to combine the collect and confirm integration steps into a single API call. ## Create or retrieve a customer To charge a card saved with Stripe, you must attach it to a [Customer](https://docs.stripe.com/api/customers.md) or a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts.md). > #### Terminal SDK support for customers > > If you create and manage `SetupIntents` on the client using the Terminal SDK, you must use `Customer` objects. The Terminal SDK doesn’t support the Accounts v2 API. When you include a customer in your [SetupIntent](https://docs.stripe.com/api/setup_intents.md) before confirming, Stripe automatically attaches the generated card payment method to the customer object you provide. ## Create a SetupIntent A [SetupIntent](https://docs.stripe.com/api/setup_intents.md) is an object that represents your intent to set up a customer’s payment method for future payments. The `SetupIntent` tracks the steps of this setup process. For Terminal, this includes collecting and recording cardholder consent. When you create a `SetupIntent`, provide the customer object ID in the [customer](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-customer) or [customer_account](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-customer_account) parameter to automatically attach the payment method to the customer upon successful setup. If you don’t provide the ID on creation, you must attach the payment method to the customer in a separate call. - [CreateSetupIntentParams (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#CreateSetupIntentParams) You can create a `SetupIntent` providing the `customer` or `customerAccount`, `onBehalfOf` (*Connect* (Connect is Stripe's solution for multi-party businesses, such as marketplace or software platforms, to route payments between sellers, customers, and other recipients) only), and `usage` parameters. ```js const { createSetupIntent } = useStripeTerminal(); const { paymentIntent, error } = await createSetupIntent({ customer: "{{CUSTOMER_ID}}", }); if (error) { // Placeholder for handling exception return; } // Placeholder for collecting a payment method with setupIntent ``` If the information required to start a payment isn’t readily available in your app, you can [create the SetupIntent](https://docs.stripe.com/api/setup_intents/create.md) on your server. Use the client secret to call `retrieveSetupIntent`, and, then use the retrieved `SetupIntent` to call `collectSetupIntentPaymentMethod`. ## Collect a payment method for saving - [retrieveSetupIntent (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#retrieveSetupIntent) - [collectSetupIntentPaymentMethod (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#collectSetupIntentPaymentMethod) After you create a `SetupIntent`, you need to collect a payment method using the SDK and collect customer consent. Set `allowRedisplay` to `always` or `limited`, indicating the degree to which the payment method can be shown in a customer checkout flow. Collect customer consent verbally or with a checkbox in your application. You must comply with all applicable laws, rules, and regulations in your region. To collect a payment method, make sure that you’re connected to a reader. The connected reader waits for a card after your app calls `collectSetupIntentPaymentMethod`. ```js const { setupIntent, error} = await collectSetupIntentPaymentMethod({ setupIntent: setupIntent, allowRedisplay: "always" }); if (error) { // Placeholder for handling exception return; } // Placeholder for confirming setupIntent ``` This method collects encrypted payment method data using the connected card reader, and associates the encrypted data with the `SetupIntent`. The collection happens locally and requires no authorization or updates to the `SetupIntent` object until the next step. ### Cancel collection #### Programmatic cancellation You can cancel collecting a payment method by calling [cancelCollectSetupIntent](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#cancelCollectSetupIntent) in the SDK. #### Customer-initiated cancellation Smart readers show customers a cancel button by default. You can disable this by setting [customerCancellation](https://stripe.dev/stripe-terminal-react-native/api-reference/types/CollectSetupIntentPaymentMethodParams.html) to `'disableIfAvailable'`. Tapping the cancel button cancels the active transaction. ```js const { setupIntent, error } = await collectSetupIntentPaymentMethod({ setupIntentId: setupIntentId, allowRedisplay: "always",customerCancellation: 'enableIfAvailable', }); if (error) { // Placeholder for handling exception } // Placeholder for processing SetupIntent ``` ## Submit the payment method details to Stripe - [confirmSetupIntent (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#confirmSetupIntent) Use `confirmSetupIntent` to complete the setup. A successful setup returns a `succeeded` value for the `SetupIntent`’s [status](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-status) property, along with a [SetupAttempt.payment_method_details.card_present.generated_card](https://docs.stripe.com/api/setup_attempts/object.md#setup_attempt_object-payment_method_details-card_present-generated_card), which is a reusable `card` payment method you can use for online payments. > The [SetupIntent.payment_method](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-payment_method) is a `card_present` `PaymentMethod` that represents the tokenization of the physically present card. You can’t charge it online. Future payments use the generated card instead. From the customer’s perspective, they’re the same payment method. The `generated_card` payment method automatically attaches to the customer you provided during [SetupIntent creation](https://docs.stripe.com/terminal/features/saving-payment-details/save-directly.md#create-setupintent). You can retrieve the `generated_card` payment method by expanding the `SetupIntent`’s `latest_attempt` property. Always check for a `generated_card` value, because for payment methods that don’t allow generated cards, the value is empty. ```curl curl -G https://api.stripe.com/v1/setup_intents/{{SETUPINTENT_ID}} \ -u "<>:" \ -d "expand[]=latest_attempt" ``` Alternatively, you can retrieve the attached payment method by fetching the list of payment methods that gets attached to the customer. #### Accounts v2 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d type=card ``` #### Customers v1 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d type=card ``` If you didn’t provide a customer during `SetupIntent` creation, you can attach the `generated_card` to the customer in a separate call. #### Accounts v2 ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}}/attach \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}}/attach \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" ``` If the setup isn’t successful, inspect the returned error to determine the cause. For example, failing to collect and notify Stripe of customer consent results in an error. ```js const { setupIntent, error } = await confirmSetupIntent({ setupIntent: setupIntent }); if (error) { // Placeholder for handling exception return; } // The SetupIntent is now ready to be used as a payment method on a future payment ``` ## Mobile wallets considerations You can only use saved mobile wallets for [off_session](https://docs.stripe.com/api/payment_intents/confirm.md#confirm_payment_intent-off_session) payments that you initiate on behalf of your customer, such as recurring subscription payments. When you save a digital wallet payment method, the `generated_card` has `allow_redisplay=limited`, to indicate its specific usage considerations. When you attempt to charge a mobile wallet, make sure to set `off_session` to true when confirming the `PaymentIntent`. If the customer is present in your checkout flow, you need to instead use the appropriate mobile wallet integration to prompt them for their payment method. ## Compliance You’re responsible for your compliance with all applicable laws, regulations, and network rules when saving a customer’s payment details. For example, the European Data Protection Board has issued guidance regarding saving payment details. These requirements generally apply if you want to save your customer’s payment method for future use. This applies in situations such as presenting a customer’s payment method to them in the checkout flow for a future purchase, or charging them when they’re not actively using your website or app, placing a MOTO order, or in your store. Add terms to your checkout flow that state how you plan to save payment method details and allow customers to opt in. If you plan to charge the customer while they’re not actively checking out, make sure (at a minimum) that your terms also cover the following: - The customer’s agreement to your initiating a payment or a series of payments on their behalf for specified transactions. - The anticipated timing and frequency of payments (for instance, whether charges are for scheduled installment or subscription payments, or for unscheduled top-ups). - How the payment amount is determined. - Your cancellation policy, if you’re setting up the payment method for a subscription service. Make sure you keep a record of your customer’s written agreement to these terms. When you save a payment method, you can only use it for the specific purpose that you included in your terms. If you want to charge customers when they’re not actively checking out and also save the customer’s payment method to present to them as a saved payment method for future purchases, you must explicitly collect consent from the customer. One way to do so is with a “Save my payment method for future use” checkbox.