Quickstart: Card Payments

📘

This guide assumes a basic understanding of PPRO's API core objects and common functionality.

PPRO's APIs provide access to payment products across the globe, covering both local payment methods and card products. This guide focuses on the technical integration for processing card payments.

💡

Sandbox vs. Live APIs

Live API: <https://api.eu.ppro.com>

Sandbox API: <https://api.sandbox.eu.ppro.com>

Our card offering API includes the following features and flows:

  1. One-Step payment - Payment Charge is created with authorization and capture in one single request.
  2. Multi-Step payment - Payment Charge is initialised for authorization and 1 or more (multi partial capture) subsequent requests are expected to capture the payment.
  3. Recurring payments - Payment Agreement is created with either LINK_ONLY or LINK_AND_PAY mode and subsequent recurring Payment Charges can be created under the created Agreement reusing its Payment Instrument (card details).
  4. Validate a Card - The Payment Instrument created associated to a card can be validated to improve sales attempt successful rate (aka zero value auth for Cards) either when creating a Payment Agreement or standalone by interacting directly with the payment instrument.
  5. 3DS
    1. External Authorization - Payment Charge is created with previous 3DS authorization results in the payload so PPRO forwards to the provider
    2. PPRO Authorization (Not supported yet)
  6. Reading the Payment Charge to confirm its current status.
  7. (Partially) Refund the Payment Charge, if needed

1. One-step Payment

Essentially you perform One-Step payment by adding "autoCapture":true to the Payment Charge creation request as bellow:

You create a Payment Charge by issuing a POST request to the/v1/payment-charges endpoint, full API reference can be found here.

Make a one-step card payment

Request

POST v1/payment-charges/

{
  "paymentMethod": "CARD",
  "paymentDescriptor": "PPRO test CP dev team",
  "merchantPaymentChargeReference": "MTR12345678",
  "autoCapture": true,
  "instrument": {
    "type": "RAW_CARD",
    "details": {
      "brand": "VISA",
      "number": "4111111111111111",
      "cvv": "123",
      "holderName": "John Smith",
      "expiryMonth": 1,
      "expiryYear": 2024
    }
  },
  "amount": {
    "value": 1000,
    "currency": "BRL"
  },
  "consumer": {
    "name": "John Smith",
    "country": "BR",
    "taxIdentification": "12345678909"
  }
}

Response

{
    "id": "charge_wQM59vfK5ZoteCHPWmGJE",
    "paymentMethod": "CARD",
    "paymentMedium": "ECOMMERCE",
    "scheduleType": "UNSCHEDULED",
    "instrumentId": "instr_oX4NDzo0KX5zCzCsRq2vN",
    "currency": "BRL",
    "paymentDescriptor": "PPRO test CP dev team",
    "status": "CAPTURED",
    "consumer": {
        "name": "John Smith",
        "taxIdentification": "12345678909"
    },
    "authorizations": [
        {
            "id": "authz_Tk9xjlDqKPdLRgrpohfiD",
            "amount": 1000,
            "status": "AUTHORIZED",
            "merchantPaymentChargeReference": "MTR12345678",
            "createdAt": "2023-08-23T12:09:16.415Z",
            "updatedAt": "2023-08-23T12:09:16.415Z"
        }
    ],
    "captures": [
        {
            "id": "capture_SZ9nJhaXFdK6pLOgN96XW",
            "amount": 1000,
            "status": "CAPTURED",
            "merchantCaptureReference": "MTR12345678",
            "createdAt": "2023-08-23T12:09:16.415Z",
            "updatedAt": "2023-08-23T12:09:16.415Z"
        }
    ],
    "refunds": [],
    "voids": [],
    "createdAt": "2023-08-23T12:09:14.526Z",
    "updatedAt": "2023-08-23T12:09:16.415Z"
    }
}

2. Multi-step Payment

Unlike the One-Step example request above, by adding "autoCapture"="false" or omitting it, the Payment Charge creation follows its standard flow which is getting the payment authorized first and in subsequent requests to capture part of or the whole amount previously authorized.

You can find how to capture a payment charge here

3. Recurring Payments

You can find the recurring PPRO's API info here, for cards specifically, the same concept is followed and you should be able either link and pay and link only with the request example bellow.

Note that unlike the other payment methods, these agreement requests should be sent to our PCI host:

Create a Payment Agreement for cards - LINK ONLY

In this example you register your card payment instrument for a later charge.

Request

POST /v1/payment-agreements/

{
  "paymentMethod": "CARD",
  "description": "PPRO",
  "instrument": {
    "type": "RAW_CARD",
    "details": {
      "brand": "VISA",
      "number": "4111111111111111",
      "cvv": "123",
      "holderName": "John Smith",
      "expiryMonth": 1,
      "expiryYear": 2024
  }
}

Response

{
    "id": "agr_PtAFI2GfLYMhav47h31CI",
    "status": "ACTIVE",
    "description": "PPRO",
    "paymentMethod": "CARD",
    "instrumentId": "instr_CT2ljxNmm6OOQAOdPSMA8",
    "history": [
        {
            "id": "ahist_sIVu9Hve6aN1nUq8JYaLt",
            "status": "ACTIVE",
            "createdAt": "2023-08-23T14:54:19.864Z"
        }
    ],
    "createdAt": "2023-08-23T14:54:19.745Z",
    "updatedAt": "2023-08-23T14:54:19.863Z"
}

Create a Payment Agreement for cards - LINK AND PAY

In this example you register your card payment instrument and perform the first payment charge in one step.

Request

POST /v1/payment-agreements/

{
  "paymentMethod": "CARD",
  "description": "PPRO",
  "instrument": {
    "type": "RAW_CARD",
    "details": {
      "brand": "VISA",
      "number": "4111111111111111",
      "cvv": "123",
      "holderName": "John Smith",
      "expiryMonth": 1,
      "expiryYear": 2024
  },
  "initialPaymentCharge": {
    "paymentDescriptor": "Link and Pay initial charge",
    "merchantPaymentChargeReference": "MTR12345678",
    "amount": {
        "value": 10000,
        "currency": "BRL"
    }
  }
}

Response

{
    "id": "agr_6eNKvtgd81ckLmlh1asm2",
    "status": "CAPTURED",
    "description": "PPRO",
    "paymentMethod": "CARD",
    "amount": {
        "value": 1000,
        "currency": "EUR"
    },
    "instrumentId": "instr_OlnxxCOalfGsRum8m33mo",
    "consumer": {
        "name": "ABC"
    },
    "history": [
        {
            "id": "ahist_ae3WMlHVhfutHpxVq2ZQ6",
            "status": "AUTHENTICATION_PENDING",
            "createdAt": "2023-08-23T16:42:57.888Z"
        }
    ],
    "initialPaymentChargeId": "charge_MGjEXKdhpnblaHeY9qAvU",
    "createdAt": "2023-08-23T16:42:57.575Z",
    "updatedAt": "2023-08-23T16:42:57.888Z"
}

4. Validate a Card

Before using a card to attempt a payment, or saving it as the default instrument for a series of recurring charges, merchants may want to validate that the card details are valid and that authorizations are possible. A common way to do this is through zero-value authorizations. PPRO can simplify this step for you by taking care of zero-auth in the background, before the instrument is created and stored.

To use this instrument validation feature, just add the "validate" node to the instrument object when creating an agreement or payment charge. This will trigger card validation (aka zero-auth-value) prior to saving the instrument and attempting the requested operation.

  • validate.currency must be included in validate. This field determines which currency we use for the zero-value auth.

Create a Payment Agreement with card validation

Request

POST /v1/payment-agreements/

{
    "paymentMethod": "CARD",
    "description": "subscription",
    "startDate": "2023-03-26T20:24:27+00:00",
    "frequency": {
        "type": "MONTHLY"
    },
    "instrument": {
        "type": "RAW_CARD",
        "validate": {
            "currency": "BRL"
        },
        "details": {
            "brand": "VISA",
            "number": "4111111111111111",
            "cvv": "123",
            "holderName": "John Smith",
            "expiryMonth": 12,
            "expiryYear": 2023
        }
    },
    "consumer": {
        "name": "John Smith",
        "country": "BR"
    }
}

Response

{
    "id": "agr_VgEBeWxNu2Vyyo6FyWkSP",
    "status": "ACTIVE",
    "description": "subscription",
    "paymentMethod": "CARD",
    "frequency": {
        "type": "MONTHLY",
        "interval": 1
    },
    "startDate": "2023-03-26T20:24:27Z",
    "instrumentId": "instr_cFBjegcOCDZRZmW8hGNaM",
    "consumer": {
        "name": "John Smith",
        "country": "BR"
    },
    "history": [
        {
            "id": "ahist_A3FIK08zwCA5DWgI71rqi",
            "status": "ACTIVE",
            "createdAt": "2023-11-24T11:21:42.822Z"
        }
    ],
    "createdAt": "2023-11-24T11:21:42.822Z",
    "updatedAt": "2023-11-24T11:21:42.822Z"
}

If the consumer is just saving their card details without making a payment / buying a subscription, you can also use the validate node in a standalone instrument creation request.

Create a Payment Instrument with card validation

Request

POST /v1/payment-instruments/:

{
  "type": "RAW_CARD",
  "validate": {
    "currency":"BRL"
  },
  "details": {
    "brand": "VISA",
    "number": "4111111111111111",
    "cvv": "123",
    "holderName": "John Smith",
    "expiryMonth": 1,
    "expiryYear": 2024
}

Response

{
    "id": "instr_jQzVJK0ZWmx6z2xCTOAf9",
    "details": {
        "brand": "VISA",
        "bin": "411111",
        "last4Digits": "1111",
        "expiryMonth":1,
        "expiryYear": 2024,
        "holderName": "John Smith",
        "panAlias": "ppro_khNy1rGvb",
        "cvvAlias": "ppro_5AsWpq3Wh",
        "isCvvPresent": true
    },
    "type": "CARD_PPRO_VAULTED"
}

5. 3DS

Make a one-step Payment with External 3DS Authorization

Request

POST /v1/payment-charges/

{
  "paymentMethod": "CARD",
  "paymentDescriptor": "PPRO test CP dev team",
  "merchantPaymentChargeReference": "MTR12345678",
  "autoCapture": true,
  "instrument": {
    "type": "RAW_CARD",
    "details": {
      "brand": "VISA",
      "number": "4111111111111111",
      "cvv": "123",
      "holderName": "John Smith",
      "expiryMonth": 1,
      "expiryYear": 2024
  },
  "amount": {
    "value": 1000,
    "currency": "BRL"
  },
  "consumer": {
    "name": "John Smith",
    "taxIdentification": "12345678909"
  },
  "authenticationSettings": [{
    "type": "EXTERNAL_3DS",
    "settings" : {
      "authenticationStatus" : "SUCCESS",
      "authenticationValue" : "e3f7a0c2-fff8-4fb8-afab-dbae6e17c9cc",
      "eci" : "01",
      "version" : "2.0.0",
      "externalId" : "a7fe5eae-d5bb-4f57-a946-2125c3c32801",
      "challenge" : {
        "preference": "NO_CHALLENGE_REQUESTED",
        "outcome":"FRICTIONLESS",
        "exemptionReason": "LOW_VALUE"
      }
    }
  }]
}

Response

{
    "id": "charge_wQM59vfK5ZoteCHPWmGJE",
    "paymentMethod": "CARD",
    "paymentMedium": "ECOMMERCE",
    "scheduleType": "UNSCHEDULED",
    "instrumentId": "instr_oX4NDzo0KX5zCzCsRq2vN",
    "currency": "BRL",
    "paymentDescriptor": "PPRO test CP dev team",
    "status": "CAPTURED",
    "consumer": {
        "name": "John Smith",
        "taxIdentification": "12345678909"
    },
    "authorizations": [
        {
            "id": "authz_Tk9xjlDqKPdLRgrpohfiD",
            "amount": 1000,
            "status": "AUTHORIZED",
            "merchantPaymentChargeReference": "MTR12345678",
            "createdAt": "2023-08-23T12:09:16.415Z",
            "updatedAt": "2023-08-23T12:09:16.415Z"
        }
    ],
    "captures": [
        {
            "id": "capture_SZ9nJhaXFdK6pLOgN96XW",
            "amount": 1000,
            "status": "CAPTURED",
            "merchantCaptureReference": "MTR12345678",
            "createdAt": "2023-08-23T12:09:16.415Z",
            "updatedAt": "2023-08-23T12:09:16.415Z"
        }
    ],
    "refunds": [],
    "voids": [],
    "createdAt": "2023-08-23T12:09:14.526Z",
    "updatedAt": "2023-08-23T12:09:16.415Z"
    }
}