---
title: "Two-Step Payment"
source_url: https://docs.rapyd.net/en/two-step-payment-369200.html
lang: en
---

# Two-Step Payment

Authorize a card and capture funds after the order is completed.

You may prefer getting a card authorization while the customer's order on your website is being assembled, or processed. Two-Step Payment first authorizes the card, and when the order is shipped, you ask Rapyd to [capture](https://docs.rapyd.net/en/glossary.md#UUID-945d98cf-adae-e1cf-2606-c7fae8b4a7e1_capture "Capture") the payment.

> **Note:**
>
> Only clients with [PCI-DSS](https://docs.rapyd.net/en/glossary.md#UUID-945d98cf-adae-e1cf-2606-c7fae8b4a7e1_dss "Payment Card Industry Data Security Standard") certification can handle personal identifying information for cards. This method is available to merchants who have signed a special agreement with Rapyd.

### Card Authorization and Capture Workflow

Finding the specific payment methods you'll accept and the corresponding required fields that customers fill out is described under How it Works.

### Step 1: Customer Purchases Goods

![customer-purchase-goods.jpg](image/img-91a57c61acc4bf4b58ae7133615c8b1f.jpg)

1. Using your website or app, a customer adds furniture to the shopping cart and checks out.
2. Your website displays available payment methods.
3. The customer selects 'card'.
4. Your website requests card details.
5. The customer provides the details and clicks **Pay Now**.

### Step 2: Authorizing the Card Payment

![authorize-payment.jpg](image/img-e3ed0ccf5a7aa77fe38b8ef795d1d10a.jpg)

1. Your website back end asks Rapyd for card authorization.
2. Rapyd processes the authorization request and returns a confirmation and payment ID.
3. You notify the customer that the purchase succeeded.

### Step 3: Capturing the Card Payment

![capture-payment.jpg](image/img-362f3f6a92cc96baf0483fab2f5cad33.jpg)

1. You prepare and pack your product for delivery.
2. Your website back end asks Rapyd to capture the payment, specifying the Payment ID.
3. Rapyd processes the capture request and returns the updated transaction status.

### Two-Step Card Payment Message Sequences

The message sequence diagrams below describe how information is exchanged between Rapyd, the merchant, and the card network.

Two-Step Card Payment

![payment-with-late-capture---success.svg](image/img-45fdadff50af0b7e73eac5ca1f6f2dc7.svg)

### How Two-Step Payment Works

Decide which payment methods you will accept, so that your customer can specify their payment methods on your payment page.

### Find Available Payment Methods

Use [List Payment Methods by Country](https://docs.rapyd.net/en/list-payment-methods-by-country.md "List Payment Methods by Country") with the following parameters:

- US and USD is displayed as an example for country and currency.

Description of Query Parameters

| Query Parameter | Description |
| --- | --- |
| country | Enter **US** as the country code. |
| currency | Enter **USD** as the currency code. |

### Find Required Fields for the Payment Method

- Determine the fields that are required for the payment method as described in [Get Payment Method Required Fields](https://docs.rapyd.net/en/get-payment-method-required-fields.md "Get Payment Method Required Fields").

### Create a Wallet

- Create a company wallet. Run [Create Wallet](https://docs.rapyd.net/en/create-wallet.md "Create Wallet"). Use the ID you get in the response. For more information, see [Creating a Rapyd Wallet](https://docs.rapyd.net/en/creating-a-rapyd-wallet.md "Creating a Rapyd Wallet") .

### Requesting Payment Authorization

When your customer pays for the furniture, you request a card authorization for the 115.65 USD (U.S. Dollars) payment.

For that, you'll use [Create Payment](https://docs.rapyd.net/en/create-payment.md "Create Payment") with the following parameters:

Description of Body Parameters

| Body Parameter | Description |
| --- | --- |
| amount | Enter **115.65** as the payment amount. |
| currency | Enter **USD** as the currency code. |
| capture | Enter **false** as the value. This tells Rapyd to create only a card authorization. The authorized payment will be captured at a later time. |
| ewallet | Enter the wallet 'id' that you received when you created Four Star Furniture's company wallet in your sandbox. For purposes of this use case lesson, we are using **ewallet_8915a7fdeff7be5b7c1a7fa5f0b81414**, which is the wallet ID we created in our sandbox. |
| payment_method | Enter a 'payment_method' object with the following fields:  - `type` - Enter the payment method type you want to use for your test. For purposes of this use case lesson, we are using **us_debit_visa_card** . - `fields` - Enter an object that contains all required fields, as shown in the response when you ran [Get Payment Method Required Fields](https://docs.rapyd.net/en/get-payment-method-required-fields.md "Get Payment Method Required Fields"). For purposes of this use case lesson, we are using the fields required for us_debit_visa_card. |

### Create Payment Request

You ask Rapyd to process the customer's 115.65 USD (U.S. Dollars) payment as a card authorization.

- - Request

    - ```
      // Request URL: POST https://sandboxapi.rapyd.net/v1/payments

      // Message body: 
      {
              "amount": 115.65,
              "currency": "USD",
              "payment_method": {
                      "type": "us_debit_visa_card",
                      "fields": {
                              "number": "4111111111111111",
                              "expiration_month": "10",
                              "expiration_year": "25",
                              "cvv": "123",
                              "name": "Test User"
                      }
              },
              "ewallet": "ewallet_8915a7fdeff7be5b7c1a7fa5f0b81414",
              "capture": false
      }
      ```
- - .NET Core

    - ```
      using System;
      using System.Text.Json;

      namespace RapydApiRequestSample
      {
          class Program
          {
              static void Main(string[] args)
              {
                  try
                  {
                      var requestObj = new
                      {
                          amount = 115.65,
                          capture = false,
                          currency = "USD",
                          ewallet = "ewallet_8915a7fdeff7be5b7c1a7fa5f0b81414",
                          payment_method = new
                          {
                              type = "us_visa_card",
                              fields = new
                              {
                                  number = "4111111111111111",
                                  expiration_month = "10",
                                  expiration_year = "25",
                                  cvv = "123",
                                  name = "John Doe",
                              }
                          },
                      };

                      string request = JsonSerializer.Serialize(requestObj);

                      string result = RapydApiRequestSample.Utilities.MakeRequest("POST", "/v1/payments", request);

                      Console.WriteLine(result);
                  }
                  catch (Exception e)
                  {
                      Console.WriteLine("Error completing request: " + e.Message);
                  }
              }
          }
      }
      ```
- - JavaScript

    - ```
      const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest;

      async function main() {
        try {
          const body = {
            amount: 115.65,
            currency: 'USD',
            payment_method: {
              type: 'us_visa_card',
              fields: {
                number: '4111111111111111',
                expiration_month: '10',
                expiration_year: '20',
                cvv: '123',
                name: 'John Doe'
              }
            },
            ewallet: 'ewallet_8915a7fdeff7be5b7c1a7fa5f0b81414',
            capture: false
          };
          const result = await makeRequest('POST', '/v1/payments', body);

          console.log(result);
        } catch (error) {
          console.error('Error completing request', error);
        }
      }
      ```
- - PHP

    - ```
      <?php
      $path = $_SERVER['DOCUMENT_ROOT'];
      $path .= "/<path-to-your-utility-file>/utilities.php";
      include($path);

      $body = [
          "amount" => "115.65",
          "currency" => "USD",
          "ewallet" => "ewallet_8915a7fdeff7be5b7c1a7fa5f0b81414",
          "payment_method" => [
              "type" => "us_visa_card"
          ]
      ];

      try {
          $object = make_request('post', '/v1/payments', $body);
          var_dump($object);
      } catch (Exception $e) {
          echo "Error: $e";
      }
      ?>
      ```
- - Python

    - ```
      from pprint import pprint

      from utilities import make_request

      payment_body = {
          "amount": 115.65,
          "currency": "USD",
          "payment_method": {
              "type": "us_visa_card",
              "fields": {
                  "number": "4111111111111111",
                  "expiration_month": "10",
                  "expiration_year": "25",
                  "cvv": "123",
                  "name": "John Doe"
              }
          },
          "ewallet": "ewallet_452c8cd682f347b4abee9bbee04eac03",
          "capture": False
      }

      create_payment_response = make_request(method='post',
                                             path='/v1/payments',
                                             body=payment_body)
      pprint(create_payment_response)
      ```

### Create Payment Response

Let's take a look at the response.

- - Response

    - ```
      {
          "status": {
              "error_code": "",
              "status": "SUCCESS",
              "message": "",
              "response_code": "",
              "operation_id": "7b0f7ce9-ed39-4eb5-ae1d-4210ad865072"
          },
          "data": {
              "id": "payment_fc109dbe553a223401d86156e3adea8c",
              "amount": 0,
              "original_amount": 115.65,
              "is_partial": false,
              "currency_code": "USD",
              "country_code": "us",
              "status": "ACT",
              "description": "",
              "merchant_reference_id": "",
              "customer_token": "cus_bd1338e2b5980deb6e3eae9eb785fdce",
              "payment_method": "card_164f3fd242091eba09f4b8c1f4a75597",
              "expiration": 0,
              "captured": false,

       //     ...         

              "paid": false,
              "paid_at": 0,

       //     ...         

              "ewallet_id": "ewallet_8915a7fdeff7be5b7c1a7fa5f0b81414",
              "ewallets": [
                  {
                      "ewallet_id": "ewallet_8915a7fdeff7be5b7c1a7fa5f0b81414",
                      "amount": 115.65,
                      "percent": 100,
                      "refunded_amount": 0
                  }
              ],
              "payment_method_options": {},
              "payment_method_type": "us_debit_visa_card",
              "payment_method_type_category": "card",

       //     ...         

          }
      }
      ```

The `data` section of this response shows:

- The payment `id` is **payment_fc109dbe553a223401d86156e3adea8c**. When you run this example in your own sandbox, you will get a different ID, which you will need for a later step in this use case.
- `amount` is  **0**, which indicates that no money has actually been received yet.
- `original_amount` is **115.65**
- `currency_code` is **USD**
- The `status` is  **ACT** (active). This indicates that the payment has not yet been captured.
- The `customer_token` is **cus_bd1338e2b5980deb6e3eae9eb785fdce**, which is a unique customer ID for this transaction only. Since the request did not specify an existing customer saved in the system, the customer is treated as a guest customer.
- The `payment_method` is a unique payment method ID for this transaction only.
- `captured` is  **false** because this is a card authorization only.

### Capturing the Payment

You have prepared and packed your sold order. Before you ship it, you want to capture the card payment that was authorized previously.

For that, you'll use [Capture Payment](https://docs.rapyd.net/en/capture-payment.md "Capture Payment") with the following parameters:

Description of Path Parameters

| Path Parameter | Description |
| --- | --- |
| payment | Enter the payment 'id' that you received when you created the payment in your sandbox. For purposes of this use case lesson, we are using  **payment_fc109dbe553a223401d86156e3adea8c**, which is the payment ID we created in our sandbox. |

Description of Body Parameters

| Body Parameter | Description |
| --- | --- |
| amount | Enter **115.65** as the payment amount. |

Because you are capturing the whole amount that was previously authorized, the `amount` parameter is optional.

### Capture Payment Request

You ask Rapyd to capture all of your customer's 115.65 USD (U.S. Dollars) payment.

- - Request

    - ```
      // Request URL: POST https://sandboxapi.rapyd.net/v1/payments/payment_fc109dbe553a223401d86156e3adea8c/capture

      // Message body: 
      {
         "amount": 115.65
      }
      ```
- - .NET Core

    - ```
      using System;
      using System.Text.Json;

      namespace RapydApiRequestSample
      {
          class Program
          {
              static void Main(string[] args)
              {
                  try
                  {
                      string payment = "payment_9d59d89e3ce3519647f0d22f5d37e23c";

                      var requestObj = new
                      {
                          amount = 115.65,
                      };

                      string request = JsonSerializer.Serialize(requestObj);

                      string result = RapydApiRequestSample.Utilities.MakeRequest("POST", $"/v1/payments/{payment}/capture", request);

                      Console.WriteLine(result);
                  }
                  catch (Exception e)
                  {
                      Console.WriteLine("Error completing request: " + e.Message);
                  }
              }
          }
      }
      ```
- - JavaScript

    - ```
      const makeRequest = require('<path-to-your-utility-file>/utilities').makeRequest;

      async function main() {
        try {
          const body = {
            amount: 115.65
          };
          const result = await makeRequest(
            'POST',
            '/v1/payments/payment_fc109dbe553a223401d86156e3adea8c/capture',
            body
          );

          console.log(result);
        } catch (error) {
          console.error('Error completing request', error);
        }
      }
      ```
- - PHP

    - ```
      <?php
      $path = $_SERVER['DOCUMENT_ROOT'];
      $path .= "/<path-to-your-utility-file>/utilities.php";
      include($path);

      try {
          $capturePayment = make_request('post', '/v1/payments/payment_fc109dbe553a223401d86156e3adea8c');
          var_dump($capturePayment);
      } catch (Exception $e) {
          echo "Error: $e";
      }
      ?>
      ```
- - Python

    - ```
      from pprint import pprint

      from utilities import make_request

      capture_payment_body = {
          "amount": 115.65
      }
      capture_payment_response = make_request(method='post',
                                              path='/v1/payments/payment_fc109dbe553a223401d86156e3adea8c/capture',
                                              body=capture_payment_body)

      pprint(capture_payment_response)
      ```

### Capture Payment Response

Let's take a look at the response.

- - Response

    - ```
      {
          "status": {
              "error_code": "",
              "status": "SUCCESS",
              "message": "",
              "response_code": "",
              "operation_id": "8053816d-3d99-47cd-a216-ccc35e38ccce"
          },
          "data": {
              "id": "payment_fc109dbe553a223401d86156e3adea8c",
              "amount": 115.65,
              "original_amount": 115.65,
              "is_partial": false,
              "currency_code": "USD",
              "country_code": "us",
              "status": "CLO",
              "description": "",
              "merchant_reference_id": "",
              "customer_token": "cus_bd1338e2b5980deb6e3eae9eb785fdce",
              "payment_method": "card_164f3fd242091eba09f4b8c1f4a75597",
              "expiration": 0,
              "captured": true,

       //     ...         

              "paid": true,
              "paid_at": 1590485097,

       //     ...         

              "ewallet_id": "ewallet_8915a7fdeff7be5b7c1a7fa5f0b81414",
              "ewallets": [
                  {
                      "ewallet_id": "ewallet_8915a7fdeff7be5b7c1a7fa5f0b81414",
                      "amount": 115.65,
                      "percent": 100,
                      "refunded_amount": 0
                  }
              ],
              "payment_method_options": {},
              "payment_method_type": "us_debit_visa_card",
              "payment_method_type_category": "card",

       //     ...         

          }
      }
      ```

The `data` section of this response shows that the `status` has changed to **CLO** (closed) and the `amount` has changed to the full amount of the purchase.
