Saving a payment instrument for future use

In this guide, you will learn how to save a payment instrument to a specific customer and use it when making a payment. This approach gives you the flexibility to avoid managing the payment card data for your customers on your servers and eliminates the necessity to have PCI DSS certification.

You will go through the following steps:

  1. Create a customer
  2. Tokenize a card for a customer
  3. Create a checkout
  4. Complete a checkout with a tokenized card

When you complete these steps, you will have saved a payment instrument for a customer of yours and will have made a payment with the token associated with that payment instrument.

Before you begin

Here are the things that you need in order to complete the steps in this guide:

Steps

1. Create a customer

To create a new customer resource, make a POST request to the https://api.sumup.com/v0.1/customers endpoint.

The request body should be a JSON object that contains a unique identifier for your customer in the customer_id attribute. Optionally, you can include additional personal details for your customer, such as name, contact details, and a postal address. For more information about the request, see the API reference.

Following is a sample request for creating a new customer resource:

curl -X POST \
  https://api.sumup.com/v0.1/customers \
  -H 'Authorization: Bearer $SUMUP_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
        "customer_id": "DC000101",
        "personal_details": {
          "first_name": "Boaty",
          "last_name": "McBoatface",
          "phone": "+497453505382",
          "address": {
            "line1": "See Strasse 40",
            "country": "DE",
            "postal_code": "12345",
            "city": "Frankfurt"
          }
        }
      }'
ctx := context.Background()
client := sumup.NewClient().WithAuth(os.Getenv("SUMUP_API_KEY"))

ptr := func(s string) *string {
	return &s
}

customer, err := client.Customers.Create(ctx, sumup.CreateCustomerBody{
	CustomerId: "DC000101",
	PersonalDetails: &sumup.PersonalDetails{
		Address: &sumup.Address{
			City:       ptr("Frankfurt"),
			Country:    "DE",
			Line1:      ptr("See Strasse 40"),
			PostalCode: ptr("12345"),
		},
		FirstName: ptr("Boaty"),
		LastName:  ptr("McBoatface"),
		Phone:     ptr("+497453505382"),
	},
})
$customersService = $sumup->getCustomerService();
$response = $customersService->create(
    'DC000101',
    [
        'first_name' => 'Dominik',
        'last_name'  => 'Biermann',
        'phone'      => '+497453505382'
    ],
    [
        'line1'       => 'Ollenhauer Str. 60',
        'line2'       => 'Wohnungsnummer 3',
        'country'     => 'Germany',
        'postal_code' => '70437',
        'city'        => 'Stuttgart'
    ]
);

The response contains a JSON body with the details of the created customer resource. As you will notice, there isn't an internal identifier for the customer resource - the primary identifier of the resource is the one you provide in the request. You can use this identifier to perform all necessary operations with this resource.

{
  "customer_id": "DC000101",
  "personal_details": {
    "first_name": "Dominik",
    "last_name": "Biermann",
    "phone": "+497453505382",
    "address": {
      "city": "Stuttgart",
      "country": "Germany",
      "line1": "Ollenhauer Str. 60",
      "line2": "Wohnungsnummer 3",
      "postal_code": "70437"
    }
  }
}

2. Tokenize a payment instrument for a customer

To tokenize a payment instrument and save it for an existing customer, make a POST request to the https://api.sumup.com/v0.1/customers/{customer_id}/payment-instruments endpoint, where the value of the {customer_id} path parameter is the unique identifier of the customer resource.

The request body should be a JSON object with the payment instrument type (card) and the payment card details. For more information about the request body parameters, see the API Reference.

Following is a sample request for tokenizing a card for the customer from Step 1:

curl -X POST \
  https://api.sumup.com/v0.1/customers/DC000101/payment-instruments \
  -H 'Authorization: Basic $SUMUP_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
        "type": "card",
        "card": {
          "name": "Boaty McBoatface",
          "number": "4200000000000042",
          "expiry_month": "12",
          "expiry_year": "23",
          "cvv": "123"
        }
      }'
ctx := context.Background()
client := sumup.NewClient().WithAuth(os.Getenv("SUMUP_API_KEY"))

paymentInstrument, err := client.Customers.CreatePaymentInstrument(ctx, "DC000101", sumup.CreatePaymentInstrumentBody{
	Card: sumup.Card{
		Cvv:         "123",
		ExpiryMonth: "12",
		ExpiryYear:  "23",
		Name:        "Boaty McBoatface",
		Number:      "4200000000000042",
	},
	Type: sumup.CreatePaymentInstrumentBodyTypeCard,
})

The response contains a JSON body with the details of the tokenized card resource. The token attribute serves as the unique identifier of the resource. You need to store it and use it to perform all necessary operations with the saved card, such as processing payments for the saved customer in Step 4.

{
  "token": "0e18b211-b2b6-4ca0-975d-a7768320432d",
  "active": true,
  "type": "card",
  "card": {
    "last_4_digits": "3995",
    "type": "VISA"
  }
}

3. Create a checkout

To create a new checkout resource, make a POST request to the https://api.sumup.com/v0.1/checkouts endpoint.

The request body should be a JSON object with the same minimum details as the checkout you created in the guide for making a payment with a card entered by a customer .

Following is a sample request for creating a new checkout resource:

curl -X POST \
  https://api.sumup.com/v0.1/checkouts \
  -H 'Authorization: Bearer $SUMUP_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
        "checkout_reference": "CO746453",
        "amount": 10,
        "currency": "EUR",
        "pay_to_email": "[email protected]",
        "description": "Sample one-time payment"
      }'
ctx := context.Background()
client := sumup.NewClient().WithAuth(os.Getenv("SUMUP_API_KEY"))

checkout, err := client.Checkouts.Create(ctx, sumup.CreateCheckoutBody{
	Amount:            19,
	CheckoutReference: "CO746453",
	Currency:          "EUR",
	MerchantCode:      "MK0001",
})
$checkoutsService = $sumup->getCheckoutService();
$response = $checkoutsService->create(42.24, 'EUR', 'CO287866', '[email protected]', 'Sample payment for a saved customer');
$checkoutId = $response->getBody()->id;

Again, the response contains a JSON body with the details of the created resource in which the resource identifier is returned in the id attribute (4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2 in the sample response below) and the status attribute shows that the payment for this resource is pending and will be processed when you complete the checkout with the payment instrument details.

{
  "checkout_reference": "CO287866",
  "amount": 42.24,
  "currency": "EUR",
  "pay_to_email": "[email protected]",
  "description": "Sample payment for a saved customer",
  "id": "4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2",
  "status": "PENDING",
  "date": "2018-09-28T13:47:01.832Z",
  "transactions": []
}

4. Complete a checkout with a tokenized card

To complete the checkout and trigger the payment with a tokenized card, make a PUT request to the https://api.sumup.com/v0.1/checkouts/{id} endpoint, where the value of the {id} path parameter is the identifier of the checkout resource.

Similarly to the checkout you completed in the guide for making a payment with a card entered by a customer, the request body should be a JSON object with the payment type (card) but instead of including the payment card details, you need to specify the token of the payment card from Step 2 and the identifier of the customer for whom the card is saved from Step 1. For more information about the request, see the API Reference.

Following is a sample request for completing the checkout from Step 3:

curl -X PUT \
  https://api.sumup.com/v0.1/checkouts/4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2 \
  -H 'Authorization: Bearer $SUMUP_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
        "payment_type": "card",
        "token": "0e18b211-b2b6-4ca0-975d-a7768320432d",
        "customer_id": "DC000101"
      }'
ctx := context.Background()
client := sumup.NewClient().WithAuth(os.Getenv("SUMUP_API_KEY"))

ptr := func(v string) *string {
	return &v
}

checkoutSuccess, err := client.Checkouts.Process(ctx, *checkout.Id, sumup.ProcessCheckoutBody{
	PaymentType: sumup.ProcessCheckoutBodyPaymentTypeCard,
	Token:       ptr("0e18b211-b2b6-4ca0-975d-a7768320432d"),
	CustomerId:  "DC000101",
})
$checkoutsService = $sumup->getCheckoutService();
$response = $checkoutsService->pay('4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2', 'DC000101', '0e18b211-b2b6-4ca0-975d-a7768320432d');
$transactionId = $response->getBody()->transaction_id;

The response contains a JSON body with the details of the processed checkout resource in which the attributes related to the payment outcome are populated:

{
  "checkout_reference": "CO287866",
  "amount": 42.24,
  "currency": "EUR",
  "pay_to_email": "[email protected]",
  "description": "Sample payment for a saved customer",
  "id": "4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2",
  "status": "PAID",
  "date": "2018-09-28T13:57:09.038Z",
  "transaction_code": "TDQ49H22AS",
  "transaction_id": "664200af-2b62-4142-9c73-a2a505310d78",
  "transactions": [
    {
      "id": "664200af-2b62-4142-9c73-a2a505310d78",
      "transaction_code": "TDQ49H22AS",
      "merchant_code": "ME7RMQN3",
      "amount": 42.24,
      "vat_amount": 0,
      "tip_amount": 0,
      "currency": "EUR",
      "timestamp": "2018-09-28T13:58:05.655Z",
      "status": "SUCCESSFUL",
      "payment_type": "RECURRING",
      "entry_mode": "CUSTOMER_ENTRY",
      "installments_count": 1,
      "auth_code": "073660",
      "internal_id": 24118510
    }
  ]
}

Result

You have made a payment with a tokenized card associated with a specific customer saved for a merchant user's account. If the payment is successful, the funds will be transferred to the merchant user according to the configured account settings.