Saving Payment Methods

    Learn how to save payment method details in your Stripe account with the Payment Methods API so you can charge customers later.

    Stripe allows you to create Customer objects that make it easy to save payment information for later use. You can use Customer objects for creating subscriptions or off-session payments.

    When you collect a customer’s payment information, a PaymentMethod is created. This PaymentMethod can only be used once unless it’s first attached to a Customer.

    Saving a PaymentMethod on the client side during a payment

    During the payment process, the PaymentMethod can be saved to the customer attached to a PaymentIntent using the save_payment_method flag.

    This is useful in cases where you would like to give the customer the option to choose whether their payment information is saved during the checkout process. The PaymentMethod is attached to the customer regardless of whether the payment succeeds.

    var stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx');
    stripe.handleCardPayment(
      '{{PAYMENT_INTENT_CLIENT_SECRET}}',
      cardElement,
      {
        save_payment_method: true,
      }
    ).then(function(result) {
      // Handle result.error or result.paymentIntent
    });
    const stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx');
    const {paymentIntent, error} = await stripe.handleCardPayment(
      '{{PAYMENT_INTENT_CLIENT_SECRET}}',
      cardElement,
      {
        save_payment_method: true,
      }
    );
    STPAPIClient *client = [[STPAPIClient alloc] initWithPublishableKey:@"pk_test_TYooMQauvdEDq54NiTphI7jx"];
    STPPaymentMethodCardParams *card = [STPPaymentMethodCardParams new];
    // Fill in card details e.g. card.number = @"xxx"
    STPPaymentIntentParams *params = [[STPPaymentIntentParams alloc] initWithClientSecret:@"{{PAYMENT_INTENT_CLIENT_SECRET}}"];
    params.paymentMethodParams = [STPPaymentMethodParams paramsWithCard:card billingDetails:nil metadata:nil];
    params.savePaymentMethod = @YES;
    params.returnURL = @"yourapp://post-authentication-return-url";
    [client confirmPaymentIntentWithParams:params
                                completion:^(STPPaymentIntent * _Nullable paymentIntent, NSError * _Nullable error) {
      // Handle error or paymentIntent
    }];
    let client = STPAPIClient(publishableKey: "pk_test_TYooMQauvdEDq54NiTphI7jx")
    let card = STPPaymentMethodCardParams()
    // Fill in card details e.g. card.number = "xxx"
    let params = STPPaymentIntentParams(clientSecret: "{{PAYMENT_INTENT_CLIENT_SECRET}}")
    params.paymentMethodParams = STPPaymentMethodParams(card: card, billingDetails: nil, metadata: nil)
    params.savePaymentMethod = true
    params.returnURL = "yourapp://post-authentication-return-url"
    client.confirmPaymentIntent(with: params) { paymentIntent, error in
      // Handle error or paymentIntent
    }
    PaymentMethodCreateParams paymentMethodCreateParams =
        PaymentMethodCreateParams.create(
            mCardInputWidget.getCard().toPaymentMethodParamsCard(),
            null);
    boolean savePaymentMethod = true;
    PaymentIntentParams params = PaymentIntentParams
        .createConfirmPaymentIntentWithPaymentMethodCreateParams(
            paymentMethodCreateParams,
            '{{PAYMENT_INTENT_CLIENT_SECRET}}',
            "yourapp://post-authentication-return-url",
            savePaymentMethod);
    
    Stripe stripe = new Stripe();
    // Do not call on the UI thread or your app will crash
    PaymentIntent paymentIntent = stripe.confirmPaymentIntentSynchronous(
        paymentIntentParams,
        "pk_test_TYooMQauvdEDq54NiTphI7jx"
    );

    The save_payment_method parameter is only applied to the current PaymentMethod and Customer at the time it is provided. If the customer changes their payment method, save_payment_method needs to be passed again to save the new payment method.

    Saving a PaymentMethod on the server side

    Collected payment information can be saved and associated with a Customer for later reuse. When you create a PaymentIntent, set the value of save_payment_method to true and specify the desired customer and payment_method. The following example demonstrates how to create a PaymentIntent that saves the customer’s payment information:

    curl https://api.stripe.com/v1/payment_intents \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d amount=1099 \
      -d currency=usd \
      -d payment_method_types[]=card \
      -d save_payment_method=true \
      -d customer="{{CUSTOMER_ID}}" \
      -d payment_method="{{PAYMENT_METHOD_ID}}"
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    intent = Stripe::PaymentIntent.create({
        amount: 1099,
        currency: 'usd',
        payment_method_types: ['card'],
        save_payment_method: true,
        customer: '{{CUSTOMER_ID}}',
        payment_method: '{{PAYMENT_METHOD_ID}}',
    })
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    stripe.PaymentIntent.create(
      amount=1099,
      currency='usd',
      payment_method_types=['card'],
      save_payment_method=true,
      customer='{{CUSTOMER_ID}}',
      payment_method='{{PAYMENT_METHOD_ID}}'
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    \Stripe\PaymentIntent::create([
        'amount' => 1099,
        'currency' => 'usd',
        'payment_method_types' => ['card'],
        'save_payment_method' => true,
        'customer' => '{{CUSTOMER_ID}}',
        'payment_method' => '{{PAYMENT_METHOD_ID}}',
    ]);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Map<String, Object> paymentintentParams = new HashMap<String, Object>();
    paymentintentParams.put("amount", 1099);
    paymentintentParams.put("currency", "usd");
    ArrayList payment_method_types = new ArrayList();
    payment_method_types.add("card");
    paymentintentParams.put("payment_method_types", payment_method_types);
    paymentintentsParams.put("save_payment_method", true);
    paymentintentsParams.put("customer", "{{CUSTOMER_ID}}");
    paymentintentsParams.put("payment_method", "{{PAYMENT_METHOD_ID}}");
    
    PaymentIntent.create(paymentintentParams);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    (async () => {
      const paymentIntent = await stripe.paymentIntents.create({
        amount: 1099,
        currency: 'usd',
        payment_method_types: ['card'],
        save_payment_method: true,
        customer: '{{CUSTOMER_ID}}',
        payment_method: '{{PAYMENT_METHOD_ID}}',
      });
    })();
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.PaymentIntentParams{
      Amount: stripe.Int64(1099),
      Currency: stripe.String(string(stripe.CurrencyUSD)),
      PaymentMethodTypes: stripe.StringSlice([]string{
        "card",
      }),
      SavePaymentMethod: stripe.Boolean(true),
      Customer: stripe.String("{{CUSTOMER_ID}}"),
      PaymentMethod: stripe.String("{{PAYMENT_METHOD_ID}}")
    }
    paymentintent.New(params)
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    StripeConfiguration.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var service = new PaymentIntentService();
    var createOptions = new PaymentIntentCreateOptions
    {
        Amount = 1099,
        Currency = "usd",
        PaymentMethodTypes = new List<string> { "card" },
        SavePaymentMethod = true,
        CustomerId = "{{CUSTOMER_ID}}",
        PaymentMethodId = "{{PAYMENT_METHOD_ID}}"
    };
    paymentIntents.Create(createOptions);
    

    Saving a PaymentMethod outside of a payment

    If you’re collecting payment information outside the context of a PaymentIntent (e.g., with createPaymentMethod on Stripe.js or readReusableCard on Terminal), you can attach the PaymentMethod to a Customer from your server.

    curl https://api.stripe.com/v1/payments_methods/{{PAYMENT_METHOD_ID}}/attach \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d customer="{{CUSTOMER_ID}}"
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    Stripe::PaymentMethod.attach('{{PAYMENT_METHOD_ID}}', {
        customer: '{{CUSTOMER_ID}}'
    })
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    stripe.PaymentMethod.attach('{{PAYMENT_METHOD_ID}}', customer='{{CUSTOMER_ID}}')
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    $payment_method = \Stripe\PaymentMethod::retrieve('{{PAYMENT_METHOD_ID}}');
    $payment_method->attach(['customer' => '{{CUSTOMER_ID}}']);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    PaymentMethod paymentMethod = PaymentMethod.retrieve("{{PAYMENT_METHOD_ID}}");
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("customer", "{{CUSTOMER_ID}}");
    paymentMethod.attach(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    (async () => {
      const paymentMethod = await stripe.paymentMethods.attach(
        '{{PAYMENT_METHOD_ID}}',
        {customer: '{{CUSTOMER_ID}}'}
      );
    })();
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.PaymentMethodAttachParams{
      Customer: "{{CUSTOMER_ID}}",
    }
    PaymentMethod, err := paymentMethod.Attach("{{PAYMENT_METHOD_ID}}", params)
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    StripeConfiguration.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var paymentMethodService = new PaymentMethodService();
    var attachOptions = new PaymentMethodAttachOptions
    {
        Customer = "{{CUSTOMER_ID}}"
    };
    paymentMethodService.Attach("{{PAYMENT_METHOD_ID}}", attachOptions);
    

    Later, when creating a PaymentIntent for this Customer, provide both the Customer and the PaymentMethod.

    curl https://api.stripe.com/v1/payment_intents \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d payment_method_types[]=card \
      -d amount=1099 \
      -d currency=usd \
      -d customer="{{CUSTOMER_ID}}" \
      -d payment_method="{{PAYMENT_METHOD_ID}}"
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    Stripe::PaymentIntent.create({
        payment_method_types: ['card'],
        amount: 1099,
        currency: 'usd',
        customer: '{{CUSTOMER_ID}}',
        payment_method: '{{PAYMENT_METHOD_ID}}',
    })
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    stripe.PaymentIntent.create(
      payment_method_types=['card'],
      amount=1099,
      currency='usd',
      customer: '{{CUSTOMER_ID}}',
      payment_method: '{{PAYMENT_METHOD_ID}}'
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    \Stripe\PaymentIntent::create([
        'payment_method_types' => ['card'],
        'amount' => 1099,
        'currency' => 'usd',
        'customer' => '{{CUSTOMER_ID}}',
        'payment_method' => '{{PAYMENT_METHOD_ID}}',
    ]);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Map<String, Object> paymentintentParams = new HashMap<String, Object>();
    paymentintentParams.put("amount", 1099);
    paymentintentParams.put("currency", "usd");
    ArrayList payment_method_types = new ArrayList();
    payment_method_types.add("card");
    paymentintentParams.put("payment_method_types", payment_method_types);
    
    paymentintentParams.put("customer", "{{CUSTOMER_ID}}")
    paymentintentParams.put("payment_method", "{{PAYMENT_METHOD_ID}}")
    
    PaymentIntent.create(paymentintentParams);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    (async () => {
      const paymentIntent = await stripe.paymentIntents.create({
        payment_method_types: ['card'],
        amount: 1099,
        currency: 'usd',
        customer: '{{CUSTOMER_ID}}',
        payment_method: '{{PAYMENT_METHOD_ID}}'
      });
    })();
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    params := &stripe.PaymentIntentParams{
      PaymentMethodTypes: stripe.StringSlice([]string{
        "card",
      }),
      Amount: stripe.Int64(1099),
      Currency: stripe.String(string(stripe.CurrencyUSD)),
      Customer: stripe.String("{{CUSTOMER_ID}}"),
      PaymentMethod: stripe.String("{{PAYMENT_METHOD_ID}}"),
    }
    paymentintent.New(params)
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    StripeConfiguration.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var paymentIntentService = new PaymentIntentService();
    var createOptions = new PaymentIntentCreateOptions
    {
        PaymentMethodTypes = new List<string> { "card" },
        Amount = 1099,
        Currency = "usd",
        CustomerId = "{{CUSTOMER_ID}}",
        PaymentMethodId = "{{PAYMENT_METHOD_ID}}"
    };
    paymentIntentService.Create(createOptions);
    

    Access saved payment methods

    To display the customer’s previously saved Cards, Sources, and PaymentMethods, list the payment methods instead of reading the sources property of the customer object. This is required because new PaymentMethods added to a customer will not be duplicated in the sources property of the customer object.

    Before
    After
    customer.sources
    curl "https://api.stripe.com/v1/payment_methods?customer={{CUSTOMER_ID}}&type=card" \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc:
    
    Before
    After
    customer.sources
    Stripe::PaymentMethod.list({
        type: 'card',
        customer: '{{CUSTOMER_ID}}',
    })
    Before
    After
    customer.sources
    stripe.PaymentMethod.list(customer='{{CUSTOMER_ID}}', type='card')
    Before
    After
    customer->sources
    \Stripe\PaymentMethod::all(['customer' => '{{CUSTOMER_ID}}', 'type' => 'card']);
    Before
    After
    customer.sources
    Map<String, Object> params = new HashMap<String, Object>();
    paymentmethodParams.put("customer", "{{CUSTOMER_ID}}");
    paymentmethodParams.put("type", "card");
    
    PaymentMethod.list(params);
    
    Before
    After
    customer.sources
    const paymentMethods = await stripe.paymentMethods.list(
      { customer: '{{CUSTOMER_ID}}', type: 'card' }
    );
    
    Before
    After
    customer.sources
    params := &stripe.PaymentMethodListParams{
      Customer: stripe.String("{{CUSTOMER_ID}}"),
      Type: stripe.String(string(stripe.PaymentMethodTypeCard)),
    }
    i := paymentmethod.List(params)
    for i.Next() {
      p := i.PaymentMethod()
    }
    
    
    Before
    After
    customer.Sources
    var service = new PaymentMethodService();
    var options = new PaymentMethodListOptions
    {
        Customer = "{{CUSTOMER_ID}}",
        Limit = 3,
        Type = "card"
    };
    var paymentMethods = service.List(options);
    

    Automatic card updates

    Saved credit card payment method details can continue to work even if the physical card has been replaced by the issuing bank. Stripe works with card networks and automatically attempts to update saved card details whenever a customer receives a new card (e.g., replacing an expired card or one that was reported lost or stolen). This allows your customers to continue using your service without interruption and reduces the need for you to collect new card details whenever a card is replaced.

    Automatic card updates require card issuers to participate with the network and provide this information. It is widely supported in the United States, allowing Stripe to automatically update most American Express, Visa, Mastercard, and Discover cards issued there. International support varies from country to country. It is not possible to identify which cards can be automatically updated.

    You can use webhooks to be notified when a card PaymentMethod is automatically updated. payment_method.updated notifies you of updates to a card that happen via an API call, while payment_method.card_automatically_updated notifies you of automatic card updates from the network. These events include the card’s new expiration date and last four digits, should you need to update your own records.

    Next steps

    Congrats! Now that you can save and update card details, you might find these topics useful:

    Questions?

    We're always happy to help with code or other questions you might have. Search our documentation, contact support, or connect with our sales team. You can also chat live with other developers in #stripe on freenode.

    Was this page helpful? Yes No

    Send

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.

    On this page