# Store card

Save the customer's card during a payment and use it for later payments that the customer confirms on the Payout payment page.

## Before you begin

- Storing cards must be enabled for your account; contact support.
- An API key and a Bearer token, as in [Simple payment](https://developers.payout.tech/guides/payment-gateway-use-cases-simple-payment.html#step-1), steps 1 and 2.

## Steps

1. **Create a checkout that stores the card**

   Create the checkout as in [Simple payment](https://developers.payout.tech/guides/payment-gateway-use-cases-simple-payment.html#step-3), with `"mode": "store_card"` and `"recurring": false`, and redirect the customer to `checkout_url` from the response.

   ```bash
   curl --location --request POST 'https://sandbox.payout.one/api/v1/checkouts' \
   --header 'Content-Type: application/json' \
   --header 'Accept: application/json' \
   --header 'Authorization: Bearer SFMyNTY.EXAMPLE-TOKEN.dGhpcy1pcy1hLWZha2Utc2lnbmF0dXJlLWV4YW1wbGU' \
   --header 'Idempotency-Key: 32737315-b1ee-4668-90ca-67f61c2498b4' \
   --data-raw '{
       "amount": 300,
       "currency": "EUR",
       "mode": "store_card",
       "recurring": false,
       "customer": {
           "first_name": "John",
           "last_name": "Doe",
           "email": "john.doe@example.com"
       },
       "external_id": "order-2001",
       "nonce": "T3hjOURyd0NNOWRZQXd3Vg",
       "redirect_url": "https://eshop.example.com/payment/redirect",
       "signature": "6ea1e196061e9c6270cc87d848515d22f8daba4f86b3f15730f9fe4d4671683e"
   }'
   ```

   `amount` is in cents: 300 is 3.00 EUR. Sign the request as in Simple payment:

   ```text
   Pattern: amount|currency|external_id|nonce|client_secret
   Input:   300|EUR|order-2001|T3hjOURyd0NNOWRZQXd3Vg|q3dpHpYtDrH-KmGD4HMn5OTEx6IsZPBokQ8CqMONWqMSEePWy9bXd3Ua3KvO7f6C
   SHA-256: 6ea1e196061e9c6270cc87d848515d22f8daba4f86b3f15730f9fe4d4671683e
   ```

   > [!NOTE]
   > Signatures are SHA-256 hashes in lowercase hex. Some libraries return uppercase hex; convert it to lowercase before you send or compare it.

2. **Receive the card token**

   After a successful payment, Payout sends two webhooks: `checkout.succeeded`, as in [Simple payment](https://developers.payout.tech/guides/payment-gateway-use-cases-simple-payment.html#step-7), and `payu_token.created`. The second one carries the masked card number in `card_mask` and the token of the stored card in `token_value`. It also contains the card expiry in `exp_month` and `exp_year`.

   `payu_token.created` payload:

   ```json
   {
       "external_id": "order-2001",
       "object": "webhook",
       "type": "payu_token.created",
       "data": {
           "object": "payu_token",
           "checkout_id": 141501,
           "card_mask": "424575******9685",
           "token_value": "QTEyOEdDTQ.ZXhhbXBsZS1lbmNyeXB0ZWQta2V5.ZXhhbXBsZS1pdg.ZXhhbXBsZS1jYXJkLXRva2VuLW5vdC1yZWFs.ZXhhbXBsZS10YWc"
       },
       "nonce": "Z21yWnhhOTkyR3FzZDFqaA",
       "signature": "6743d5f48f5f035a759a2f0c67d21120eb9634a2e82ac7261351a01c4ae7ef85"
   }
   ```

   Verify the signature of both webhooks as in [Simple payment](https://developers.payout.tech/guides/payment-gateway-use-cases-simple-payment.html#step-8). For this webhook:

   ```text
   Pattern: external_id|type|nonce|client_secret
   Input:   order-2001|payu_token.created|Z21yWnhhOTkyR3FzZDFqaA|q3dpHpYtDrH-KmGD4HMn5OTEx6IsZPBokQ8CqMONWqMSEePWy9bXd3Ua3KvO7f6C
   SHA-256: 6743d5f48f5f035a759a2f0c67d21120eb9634a2e82ac7261351a01c4ae7ef85
   ```

   Save `token_value` with the customer's account.

3. **Pay with the stored card**

   For the next payment, create a new checkout with `"mode": "card_on_file"` and the saved token in `card_token`. Give it its own `Idempotency-Key`, `external_id`, `nonce` and `signature`.

   ```bash
   curl --location --request POST 'https://sandbox.payout.one/api/v1/checkouts' \
   --header 'Content-Type: application/json' \
   --header 'Accept: application/json' \
   --header 'Authorization: Bearer SFMyNTY.EXAMPLE-TOKEN.dGhpcy1pcy1hLWZha2Utc2lnbmF0dXJlLWV4YW1wbGU' \
   --header 'Idempotency-Key: 0a38d06d-164e-43fd-ba6b-19d30c64ee41' \
   --data-raw '{
       "amount": 300,
       "currency": "EUR",
       "mode": "card_on_file",
       "card_token": "QTEyOEdDTQ.ZXhhbXBsZS1lbmNyeXB0ZWQta2V5.ZXhhbXBsZS1pdg.ZXhhbXBsZS1jYXJkLXRva2VuLW5vdC1yZWFs.ZXhhbXBsZS10YWc",
       "customer": {
           "first_name": "John",
           "last_name": "Doe",
           "email": "john.doe@example.com"
       },
       "external_id": "order-2002",
       "nonce": "WFBsWk9HdTJaQTl6eEhHVw",
       "redirect_url": "https://eshop.example.com/payment/redirect",
       "signature": "3a32015e39dd0fd5397b4dd7568dfa0be48be4188766e85efa52a6864e2ea326"
   }'
   ```

   Signature of this request:

   ```text
   Pattern: amount|currency|external_id|nonce|client_secret
   Input:   300|EUR|order-2002|WFBsWk9HdTJaQTl6eEhHVw|q3dpHpYtDrH-KmGD4HMn5OTEx6IsZPBokQ8CqMONWqMSEePWy9bXd3Ua3KvO7f6C
   SHA-256: 3a32015e39dd0fd5397b4dd7568dfa0be48be4188766e85efa52a6864e2ea326
   ```

4. **Redirect the customer to confirm the payment**

   Depending on the amount, a payment with a stored card may go through without 3-D Secure. This is not guaranteed, and 3-D Secure is more likely to be required. Always redirect the customer to `checkout_url` from the response, where they can confirm the payment.

5. **Wait for the webhook**

   After a successful payment, Payout sends `checkout.succeeded`. Handle it as in [Simple payment](https://developers.payout.tech/guides/payment-gateway-use-cases-simple-payment.html#step-7), steps 7 to 9.

## Next steps

- Try the flow in the sandbox with the [test cards](https://developers.payout.tech/guides/payment-gateway-use-cases-simple-payment.html#test-cards).
- To charge a stored card without the customer, see [Recurrent payment](https://developers.payout.tech/guides/payment-gateway-use-cases-recurrent-payment.html).
