# Set up future card payments
Use manual server-side confirmation or present payment methods separately.
# Advanced integration
> We recommend that you follow the [Set up future payments](https://docs.stripe.com/payments/save-and-reuse.md) guide. Only use this guide if you need to use manual server-side confirmation or your integration requires presenting payment methods separately. If you’ve already integrated with Elements, see the [Payment Element migration guide](https://docs.stripe.com/payments/payment-element/migration.md).
The [Setup Intents API](https://docs.stripe.com/api/setup_intents.md) lets you save a customer’s card without an initial payment. This is helpful if you want to onboard customers now, set them up for payments, and charge them in the future—when they’re offline.
Use this integration to set up recurring payments or to create one-time payments with a final amount determined later, often after the customer receives your service.
## Set up Stripe [Server-side]
Use our official libraries for access to the Stripe API from your application:
#### Java
```java
/*
For Gradle, add the following dependency to your build.gradle and replace with
the version number you want to use from:
- https://mvnrepository.com/artifact/com.stripe/stripe-java or
- https://github.com/stripe/stripe-java/releases/latest
*/
implementation "com.stripe:stripe-java:32.2.0"
```
```xml
com.stripestripe-java32.2.0
```
```bash
# For other environments, manually install the following JARs:
# - The Stripe JAR from https://github.com/stripe/stripe-java/releases/latest
# - Google Gson from https://github.com/google/gson
```
## Create a Customer before setup [Server-side]
To set up a payment method for future payments, you must attach it to an object that represents your customer. When your customer creates an account or has their first transaction with your business, create either a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts/create.md) object with the Accounts v2 API or a [Customer](https://docs.stripe.com/api/customers/create.md) object with the Customers API.
#### Accounts v2
```java
// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
// Find your keys at https://dashboard.stripe.com/apikeys.
StripeClient client = new StripeClient("<>");
AccountCreateParams params =
AccountCreateParams.builder()
.setContactEmail("jenny.rosen@example.com")
.setDisplayName("Jenny Rosen")
.setConfiguration(
AccountCreateParams.Configuration.builder()
.setCustomer(AccountCreateParams.Configuration.Customer.builder().build())
.build()
)
.addInclude(AccountCreateParams.Include.CONFIGURATION__CUSTOMER)
.build();
Account account = client.v2().core().accounts().create(params);
```
Successful creation returns the customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-configuration-customer) object. Inspect the object for the customer’s `id` and store the value in your database for later retrieval.
#### Customers v1
```java
// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
// Find your keys at https://dashboard.stripe.com/apikeys.
StripeClient client = new StripeClient("<>");
CustomerCreateParams params =
CustomerCreateParams.builder()
.setName("Jenny Rosen")
.setEmail("jennyrosen@example.com")
.build();
// For SDK versions 29.4.0 or lower, remove '.v1()' from the following line.
Customer customer = client.v1().customers().create(params);
```
Successful creation returns the [Customer](https://docs.stripe.com/api/customers/object.md) object. Inspect the object for the customer’s `id` and store the value in your database for later retrieval.
You can find these customers in the [Customers](https://dashboard.stripe.com/customers) page in the Dashboard.
## Create a SetupIntent [Server-side]
A [SetupIntent](https://docs.stripe.com/api/setup_intents.md) is an object that represents your intent to set up a customer’s card for future payments.
The `SetupIntent` object contains a [client secret](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-client_secret), a unique key that you need to pass to Stripe.js on the client side to collect card details. The client secret lets you perform certain actions on the client, such as confirming the setup and updating payment method details, while hiding sensitive information like `customer`. You can use the client secret to validate and authenticate card details using the credit card networks. The client secret is sensitive—don’t log it, embed it in URLs, or expose it to anyone but the customer.
If your application uses server-side rendering, use your template framework to embed the client secret in the page using a [data attribute](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes) or a hidden HTML element.
#### Java
```java
```
```java
import java.util.HashMap;
import java.util.Map;
import com.stripe.StripeClient;
import com.stripe.model.SetupIntent;
import spark.ModelAndView;
import static spark.Spark.get;
public class StripeJavaQuickStart {
public static void main(String[] args) {
// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
StripeClient stripeClient = new StripeClient("<>");
get("/card-wallet", (request, response) -> {
Map params = new HashMap<>();
params.put("customer", customer.getId());
SetupIntent intent = stripeClient.v1().setupIntents().create(params);
Map map = new HashMap<>();
map.put("client_secret", intent.getClientSecret());
return new ModelAndView(map, "card_wallet.hbs");
}, new HandlebarsTemplateEngine());
}
}
```
If you only plan on using the card for future payments when your customer is present during the checkout flow, set the [usage](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-usage) parameter to *on\_session* (A payment is described as on-session if it occurs while the customer is actively in your checkout flow and able to authenticate the payment method) to optimize authorization rates.
## Collect card details [Client-side]
The *Setup Intents API* (The Setup Intents API lets you build dynamic flows for collecting payment method details for future payments. It tracks the lifecycle of a payment setup flow and can trigger additional authentication steps if required by law or by the payment method) is fully integrated with [Stripe.js](https://docs.stripe.com/payments/elements.md), which lets you use the Elements UI library to securely collect card details on the client side.
> When saving card details to use for future *off-session payments* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information), especially in Europe because of regulations around card reuse, [get permission to save a card](https://docs.stripe.com/strong-customer-authentication.md#sca-enforcement). Include some text in your checkout flow to inform your user how you intend to use the card.
#### HTML + JS
To get started with Elements, include the following script on your checkout page. Always load Stripe.js directly from js.stripe.com to remain PCI compliant. don’t include the script in a bundle or host a copy of it yourself.
```html
```
To best leverage Stripe’s [advanced fraud functionality](https://docs.stripe.com/radar.md), include this script on every page on your site, not just the checkout page. Including the script on every page [allows Stripe to detect suspicious behavior](https://docs.stripe.com/disputes/prevention/advanced-fraud-detection.md) that may be indicative of fraud as users browse your website.
### Add Elements to your page
Next, create an instance of the [Stripe object](https://docs.stripe.com/js.md#stripe-function), providing your publishable [API key](https://docs.stripe.com/keys.md) as the first parameter. After, create an instance of the [Elements object](https://docs.stripe.com/js.md#stripe-elements) and use it to mount a `card` element in the DOM.
The `card` Element simplifies the payment form and minimizes the number of required fields by inserting a single, flexible input field that securely collects all necessary card details. Otherwise, combine `cardNumber`, `cardExpiry`, and `cardCvc` Elements for a flexible, multi-input card form.
See [example payment forms](https://stripe.com/payments/elements/examples) created with Elements on GitHub.
> Always collect a postal code to increase card acceptance rates and reduce fraud.
>
> The [single line Card Element](https://docs.stripe.com/js/element/other_element?type=card) automatically collects and sends the customer’s postal code to Stripe. If you build your payment form with split Elements ([Card Number](https://docs.stripe.com/js/element/other_element?type=cardNumber), [Expiry](https://docs.stripe.com/js/element/other_element?type=cardExpiry), [CVC](https://docs.stripe.com/js/element/other_element?type=cardCvc)), add a separate input field for the customer’s postal code.
```javascript
const stripe = Stripe('<>');
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');
```
A Stripe Element contains an iframe that securely sends the payment information to Stripe over an HTTPS connection. The checkout page address must also start with https:// rather than http:// for your integration to work.
You can test your integration without using HTTPS. [Enable it](https://docs.stripe.com/security/guide.md#tls) when you’re ready to accept live payments.
### Confirm the SetupIntent
To complete the setup, retrieve the client secret from the SetupIntent created in the previous step and use [stripe.confirmCardSetup](https://docs.stripe.com/js/setup_intents/confirm_card_setup) and the Card element to complete the setup. When the setup completes successfully, the value of the returned SetupIntent’s `status` property is `succeeded`.
```javascript
const cardholderName = document.getElementById('cardholder-name');
const setupForm = document.getElementById('setup-form');
const clientSecret = setupForm.dataset.secret;
setupForm.addEventListener('submit', async (ev) => {
ev.preventDefault();
const {setupIntent, error} = await stripe.confirmCardSetup(
clientSecret,
{
payment_method: {
card: cardElement,
billing_details: {
name: cardholderName.value,
},
},
}
);
if (error) {
// Display error.message in your UI.
} else {
if (setupIntent.status === 'succeeded') {
// The setup has succeeded. Display a success message. Send
// setupIntent.payment_method to your server to save the card to a Customer
}
}
});
```
#### React
#### npm
Install [React Stripe.js](https://www.npmjs.com/package/@stripe/react-stripe-js) and the [Stripe.js loader](https://www.npmjs.com/package/@stripe/stripe-js) from the npm public registry.
```bash
npm install --save @stripe/react-stripe-js @stripe/stripe-js
```
#### umd
We also provide a UMD build for sites that don’t use npm or modules.
Include the Stripe.js script, which exports a global `Stripe` function, and the UMD build of React Stripe.js, which exports a global `ReactStripe` object. Always load the Stripe.js script directly from **js.stripe.com** to remain PCI compliant. Don’t include the script in a bundle or host a copy of it yourself.
```html
```
> The [demo in CodeSandbox](https://codesandbox.io/s/react-stripe-official-q1loc?fontsize=14&hidenavigation=1&theme=dark) lets you try out React Stripe.js without having to create a new project.
### Add Stripe.js and Elements to your page
To use Element components, wrap your checkout page component in an [Elements provider](https://docs.stripe.com/sdks/stripejs-react.md#elements-provider). Call `loadStripe` with your publishable key and pass the returned `Promise` to the `Elements` provider.
```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import {Elements} from '@stripe/react-stripe-js';
import {loadStripe} from '@stripe/stripe-js';
import CardSetupForm from './CardSetupForm';
// Make sure to call `loadStripe` outside of a component's render to avoid
// recreating the `Stripe` object on every render.
const stripePromise = loadStripe('<>');
function App() {
return (
);
};
ReactDOM.render(, document.getElementById('root'));
```
### Add and configure a CardElement component
Use individual Element components, such as `CardElement`, to build your form.
#### JSX
```jsx
/**
* Use the CSS tab above to style your Element's container.
*/
import React from 'react';
import {CardElement} from '@stripe/react-stripe-js';
import './Styles.css'
const CARD_ELEMENT_OPTIONS = {
style: {
base: {
color: "#32325d",
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: "antialiased",
fontSize: "16px",
"::placeholder": {
color: "#aab7c4",
},
},
invalid: {
color: "#fa755a",
iconColor: "#fa755a",
},
},
};
function CardSection() {
return (
);
};
export default CardSection;
```
Elements are completely customizable. You can [style Elements](https://docs.stripe.com/js/elements_object/create_element?type=card#elements_create-options) to match the look and feel of your site, providing seamless checkout for your customers. It’s also possible to style various input states, for example when the Element has focus.
The `CardElement` simplifies the form and minimizes the number of required fields by inserting a single, flexible input field that securely collects all necessary card and billing details. Otherwise, combine `CardNumberElement`, `CardExpiryElement`, and `CardCvcElement` elements for a flexible, multi-input card form.
> Always collect a postal code to increase card acceptance rates and reduce fraud.
>
> The [single line Card Element](https://docs.stripe.com/js/element/other_element?type=card) automatically collects and sends the customer’s postal code to Stripe. If you build your payment form with split Elements ([Card Number](https://docs.stripe.com/js/element/other_element?type=cardNumber), [Expiry](https://docs.stripe.com/js/element/other_element?type=cardExpiry), [CVC](https://docs.stripe.com/js/element/other_element?type=cardCvc)), add a separate input field for the customer’s postal code.
### Confirm the SetupIntent
To complete the setup, retrieve the client secret from the SetupIntent created in [step three](https://docs.stripe.com/payments/save-and-reuse-cards-only.md#web-create-setup-intent) and use [stripe.confirmCardSetup](https://docs.stripe.com/js/setup_intents/confirm_card_setup) and the Card element to complete the setup. When the setup completes successfully, the value of the returned SetupIntent’s `status` property is `succeeded`.
To call `stripe.confirmCardSetup` from your payment form component, use the [useStripe](https://docs.stripe.com/sdks/stripejs-react.md#usestripe-hook) and [useElements](https://docs.stripe.com/sdks/stripejs-react.md#useelements-hook) hooks. If you prefer traditional class components over hooks, you can instead use an [ElementsConsumer](https://docs.stripe.com/sdks/stripejs-react.md#elements-consumer).
#### Hooks
```jsx
import React from 'react';
import {useStripe, useElements, CardElement} from '@stripe/react-stripe-js';
import CardSection from './CardSection';
export default function CardSetupForm() {
const stripe = useStripe();
const elements = useElements();
const handleSubmit = async (event) => {
// We don't want to let default form submission happen here,
// which would refresh the page.
event.preventDefault();
if (!stripe || !elements) {
// Stripe.js hasn't yet loaded.
// Make sure to disable form submission until Stripe.js has loaded.
return;
}
const result = await stripe.confirmCardSetup('{{CLIENT_SECRET}}', {
payment_method: {
card: elements.getElement(CardElement),
billing_details: {
name: 'Jenny Rosen',
},
}
});
if (result.error) {
// Display result.error.message in your UI.
} else {
// The setup has succeeded. Display a success message and send
// result.setupIntent.payment_method to your server to save the
// card to a Customer
}
};
return (
);
}
```
#### Class Components
```jsx
import React from 'react';
import {ElementsConsumer, CardElement} from '@stripe/react-stripe-js';
import CardSection from './CardSection';
class CardSetupForm extends React.Component {
handleSubmit = async (event) => {
// We don't want to let default form submission happen here,
// which would refresh the page.
event.preventDefault();
const {stripe, elements} = this.props;
if (!stripe || !elements) {
// Stripe.js hasn't yet loaded.
// Make sure to disable form submission until Stripe.js has loaded.
return;
}
const result = await stripe.confirmCardSetup('{{CLIENT_SECRET}}', {
payment_method: {
card: elements.getElement(CardElement),
billing_details: {
name: 'Jenny Rosen',
},
}
});
if (result.error) {
// Display result.error.message in your UI.
} else {
// The setup has succeeded. Display a success message and send
// result.setupIntent.payment_method to your server to save the
// card to a Customer
}
};
render() {
return (
);
}
}
export default function InjectedCardSetupForm() {
return (
{({stripe, elements}) => (
)}
);
}
```
> `stripe.confirmCardSetup` may take several seconds to complete. During that time, disable your form from being resubmitted and show a waiting indicator like a spinner. If you receive an error, show it to the customer, re-enable the form, and hide the waiting indicator. If the customer must perform additional steps to complete the payment, such as authentication, Stripe.js walks them through that process.
The SetupIntent verifies that the card information your customer is using is valid on the network. However, automatic verification isn’t always performed. For details on this, see [Check if a card is valid without a charge](https://support.stripe.com/questions/check-if-a-card-is-valid-without-a-charge). Also, don’t maintain long-lived, unhandled SetupIntents as they may no longer be valid when you call [stripe.confirmCardSetup](https://docs.stripe.com/js.md#stripe-confirm-card-setup).
You now have a flow to collect card details and handle any authentication requests. Use the test card `4000 0025 0000 3155`, along with any CVC, postal code, and future expiration date to test the authentication process.
When saving cards to charge later, it’s important to get customer permission up front. Add text in your checkout flow that references the terms of the payment, for example:
> I authorise [your business name] to send instructions to the financial institution that issued my card to take payments from my card account in accordance with the terms of my agreement with you.
When the SetupIntent succeeds, the resulting *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) ID (in `result.setupIntent.payment_method`) will be saved to the provided *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments).
## Charge the saved card later [Server-side]
When you’re ready to charge your customer off-session, use the Customer and PaymentMethod IDs to create a PaymentIntent. To find a card to charge, [list](https://docs.stripe.com/api/payment_methods/list.md) the PaymentMethods associated with your Customer.
#### Accounts v2
```java
// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
// Find your keys at https://dashboard.stripe.com/apikeys.
StripeClient client = new StripeClient("<>");
PaymentMethodListParams params =
PaymentMethodListParams.builder()
.setCustomerAccount("{{CUSTOMERACCOUNT_ID}}")
.setType(PaymentMethodListParams.Type.CARD)
.build();
// For SDK versions 29.4.0 or lower, remove '.v1()' from the following line.
StripeCollection stripeCollection =
client.v1().paymentMethods().list(params);
```
#### Customers v1
```java
// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
// Find your keys at https://dashboard.stripe.com/apikeys.
StripeClient client = new StripeClient("<>");
PaymentMethodListParams params =
PaymentMethodListParams.builder()
.setCustomer("{{CUSTOMER_ID}}")
.setType(PaymentMethodListParams.Type.CARD)
.build();
// For SDK versions 29.4.0 or lower, remove '.v1()' from the following line.
StripeCollection stripeCollection =
client.v1().paymentMethods().list(params);
```
When you have the Customer and PaymentMethod IDs, create a PaymentIntent with the amount and currency of the payment. Set a few other parameters to make the off-session payment:
- Set [off_session](https://docs.stripe.com/api/payment_intents/confirm.md#confirm_payment_intent-off_session) to `true` to indicate that the customer isn’t in your checkout flow during this payment attempt. This causes the PaymentIntent to throw an error if authentication is required.
- Set the value of the PaymentIntent’s [confirm](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-confirm) property to `true`, which causes confirmation to occur immediately when the PaymentIntent is created.
- Set [payment_method](https://docs.stripe.com/api.md#create_payment_intent-payment_method) to the ID of the PaymentMethod and [customer](https://docs.stripe.com/api.md#create_payment_intent-customer) to the ID of the Customer.
#### Java
```java
// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
// Find your keys at https://dashboard.stripe.com/apikeys.
StripeClient stripeClient = new StripeClient("<>");
PaymentIntentCreateParams params =
PaymentIntentCreateParams.builder()
.setCurrency("usd")
.setAmount(1099).setPaymentMethod("{{PAYMENT_METHOD_ID}}")
.setCustomer("{{CUSTOMER_ID}}")
.setConfirm(true)
.setOffSession(true)
.build();
try {
stripeClient.v1().paymentIntents().create(params);
} catch (CardException err) {
// Error code will be authentication_required if authentication is needed
System.out.println("Error code is : " + err.getCode());
String paymentIntentId = err.getStripeError().getPaymentIntent().getId();
PaymentIntent paymentIntent = stripeClient.v1().paymentIntents().retrieve(paymentIntentId);
System.out.println(paymentIntent.getId());
}
```
When a payment attempt fails, the request also fails with a 402 HTTP status code and the status of the PaymentIntent is *requires\_payment\_method* (This status appears as "requires_source" in API versions before 2019-02-11). You need to notify your customer to return to your application (for example, by sending an email or in-app notification) to complete the payment. Check the code of the [Error](https://docs.stripe.com/api/errors/handling.md) raised by the Stripe API library or check the [last_payment_error.decline_code](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-last_payment_error-decline_code) on the PaymentIntent to inspect why the card issuer declined the payment.
If the payment failed due to an [authentication_required](https://docs.stripe.com/declines/codes.md) decline code, use the declined PaymentIntent’s client secret and [payment method](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-last_payment_error-payment_method) with confirmCardPayment to allow the customer to authenticate the payment.
```javascript
// Pass the failed PaymentIntent to your client from your server
stripe.confirmCardPayment(intent.client_secret, {
payment_method: intent.last_payment_error.payment_method.id
}).then(function(result) {
if (result.error) {
// Show error to your customer
console.log(result.error.message);
} else {
if (result.paymentIntent.status === 'succeeded') {
// The payment is complete!
}
}
});
```
> `stripe.confirmCardPayment` might take several seconds to complete. During that time, disable your form from being resubmitted and show a waiting indicator like a spinner. If you receive an error, show it to the customer, re-enable the form, and hide the waiting indicator. If the customer must perform additional steps to complete the payment, such as authentication, Stripe.js walks them through that process.
If the payment failed for other reasons, such as insufficient funds on the card, send your customer to a payment page to enter a new card. You can reuse the existing PaymentIntent to attempt the payment again with the new card details.
## Test the integration
By this point you should have an integration that:
1. Collects and saves card details without charging the customer by using a SetupIntent
1. Charges the card off-session and has a recovery flow to handle declines and authentication requests
There are several test cards you can use to make sure this integration is ready for production. Use them with any CVC, postal code, and future expiration date.
| Number | Description |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 4242424242424242 | Succeeds and immediately processes the payment. |
| 4000002500003155 | Requires authentication for the initial purchase, but succeeds for subsequent payments (including off-session ones) as long as the card is setup with `setup_future_usage`. |
| 4000002760003184 | Requires authentication for the initial purchase, and fails for subsequent payments (including off-session ones) with an `authentication_required` decline code. |
| 4000008260003178 | Requires authentication for the initial purchase, but fails for subsequent payments (including off-session ones) with an `insufficient_funds` decline code. |
| 4000000000009995 | Always fails (including the initial purchase) with a decline code of `insufficient_funds`. |
See the full list of [test cards](https://docs.stripe.com/testing.md).