Detokenization Proxy - Overviews

Detokenization Proxy

Overview Overview

The Forter Detokenization Proxy is a forward HTTP proxy designed to facilitate detokenization for merchants interacting with third-party APIs that require sensitive PCI data. This enables you to process transactions securely without handling or storing sensitive cardholder information.

Key Benefits

Proxy Environments Proxy Environments

Sandbox: https://pci-proxy-sandbox.checkouttools.com

Production: https://pci-proxy.checkouttools.com

Authentication Authentication

The Forter Detokenization Proxy requires HTTP Basic Authentication using the proxy-authorization header in the following format:

Node.js

proxy-authorization: Basic TO_BASE64(site_id:site_secret)

The same credentials are used for both the Detokenization Proxy and the Tokenization API.

Trusted CA Certificate Trusted CA Certificate

To establish a secure connection, you must trust Forter’s CA root certificate.

Sandbox Certificate Sandbox Certificate

Text

-----BEGIN CERTIFICATE-----
MIICuDCCAaACCQDx1qoYa/sqhTANBgkqhkiG9w0BAQsFADAeMQswCQYDVQQGEwJJ
TDEPMA0GA1UECgwGRm9ydGVyMB4XDTIyMDgyNTEzMDMyMFoXDTMyMDgyMjEzMDMy
MFowHjELMAkGA1UEBhMCSUwxDzANBgNVBAoMBkZvcnRlcjCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAOSmh9WDhKaceirpwfVbfvpvHIQ0H5TmKZixjrzN
QVGpeXd+e65fPjnDZtXpT06aN2Dqimh9VlEf6WX9E6zxeQZzxkmwUU5rwjWx0HQ2
75RBh9LeRy0xlcF4rPDAaQd74eoQWPPJ+5GBtHjxWEiPAG0wB6yb++D1kDhvT5yXd
8qXqc9GL1HXex4OZexcTr5XJCPfRUZgC/78sF8H0Gg5vwOq8VprN0951TW7W1gHA4
9Hl51alZKv4VUCEhr1FDQfrW6N2IrahYhKYg38P3p+1KfT9N01/qa3yAp2JuDM4Md
EWy/rOCZAVRREGXeH0xrhW5PzUbAD4wMK1zfqKbwa0b2WWsCAwEAATANBgkqhkiG
9w0BAQsFAAOCAQEAqjx8Oas5GLqFH/vb9Hk2Zr9kCxgXm+66wdE+cdfILpFx8J9P
J15aB37SgWk1V+6Ov29Z2znqJx4GOOnJlWLBAZhR9DSJDoDysJtRbrshXbY5U/YS
bh0ESSuAfBiUzQu2cE2DhuLUABvzC789HeFyof16vdNtFIkxPvSJ/aHqemaWHbtO
uS8/RYGmXH0N655p7TZor8FotfVYwqw8iE6Zt/8sUsd6DmBYsgxn3q6HwfzIAc2K
f5vp/750ylKw2Dv2SWJO7OUZ20qIThq6+cJdbvTvrVlEQGVtzEVPKiDgw5dxMPNt
3b8bjmIovuECw7123hwDQRhT2ccqr9Pv+cqZxw==
-----END CERTIFICATE-----

Production Certificate Production Certificate

Text

-----BEGIN CERTIFICATE-----
MIICnjCCAYYCCQCqd/JdClQxIDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQKDAZG
b3J0ZXIwHhcNMjIxMTIxMTMyNDQ4WhcNMjcxMTIwMTMyNDQ4WjARMQ8wDQYDVQQK
DAZGb3J0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4NgIfmQm5
MkADTIxzOcKUAI4+XGBwmLobFQqtMluUn3pe4ChPFOURCbTxReSHZq0ywwFTUT51
ARMh+tsUw+DzbH35T0YTvMXBPFzhikg9uFXUhc9EOn/mFPZxYm15LH78NAKXumPT
+5r0+cg5TbJpPCnVZbXMTyQOcOQGGj4ZSZLF4IjGnQlKrvuA90UQL1PttUd8p6Vg
/8O8vO0IcrsA9QZ7vlJoVxi4JAI8GoMjC0b+8r+fihakQ146RPn9f5ZajpOu83btk
n59nJWjwBG7JQd0gTb+5McywoFSGR+EMAaiMVREK1bGftewjmzuZdxgSecguL/Xy
6qb3EJr8Mtj5AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGCmJlEiQEsBl5cud6I6
112PiJpA1ZK7cjZ+fMPSCH7bDA/gmdc5oNG4Gb4QkBAwsNXpPeySbtkyzCWsGo5iSR
12kfhxrCN/EGyDuwYzM1ceNFUUt+V7TzDnmSTAA5xHCEBuKUE3RQdy+QqlNEwL/faI
133P0TaiojiFypsz04tHAvXAGJzTETSZigzsexSamdUUyCcZIPgiJrXr/oNCKjapXz
14lirDWLLO5HU+wn+ZvOPrkUvRRHvrz/WQKMdqA2IU7OavI0MrRFt/wvw73wOZZhZo
15nWLGh2TlEk6wV+BT9qHZdMv045l9LG9PhnoPCt5k4RDGUs6pRYMzdZq870NHhO9p
16cCY=
-----END CERTIFICATE-----

Setup

  1. Download and store the certificate.
  2. In your HTTP framework, add it as a trusted CA without overriding the default CA list.

Using the Detokenization Proxy Using the Detokenization Proxy

To use the proxy, replace sensitive PCI data in the request payload with placeholders, and include the Forter token in the request header.

Token Types Token Types

  1. Payment Method Token: A Forter-issued PCI token for payment credentials.
  2. CVC-Only Token: A specialized token for periodic CVC authentication.

Required headers Required headers

For Payment Method Tokens

When using a Payment Method Token issued by Forter, you have two integration options:

  1. Using the Forter Token Directly: This requires including the forter-token header with the token string.
  2. Using a Token Alias: If a token alias was previously specified in a /tokenize request to the Forter Tokenization API, you must provide the alias information via the following headers:
    • forter-token-alias-key The alias key assigned in the tokenization request.
    • forter-token-alias-value The corresponding alias value.

For CVC-Only Tokens

When using the CVC-Only Token, the following headers must be included:

Request Placeholders Request Placeholders

Placeholders are strings enclosed in double curly brackets ({{ }}). These placeholders should be inserted into the request payload sent to the Detokenization Proxy to ensure the correct request body format for the final third-party target.

Standard Placeholders Standard Placeholders

Placeholder Description
{{card_number}} The full credit card Primary Account Number (PAN).
{{expiration_m}} The expiration month as a single-digit number (e.g., 8).
{{expiration_mm}} The expiration month as a two-digit number (e.g., 08).
{{expiration_yy}} The expiration year as a two-digit number (e.g., 28).
{{expiration_yyyy}} The expiration year as a four-digit number (e.g., 2028).
{{cvc}} The card’s security code (CVV/CVC). Note: The CVC is only available when using a single-use token.
{{card_holder_name}} The name of the cardholder.
{{card_bin}} The card’s Bank Identification Number (BIN).
{{card_last_four}} The last four digits of the card number.

Network Tokenization Placeholders Network Tokenization Placeholders

Placeholder Description
{{network_token}} The PAN's associated network token.
{{network_token_cryptogram}} A one-time cryptogram used with the network token.
{{network_token_eci}} The network token’s Electronic Commerce Indicator (ECI).
{{network_token_par}} The Payment Account Reference (PAR) associated with the network token.
{{network_token_expiration_m}} The expiration month of the network token as a single-digit number (e.g., 8).
{{network_token_expiration_mm}} The expiration month of the network token as a two-digit number (e.g., 08).
{{network_token_expiration_yy}} The expiration year of the network token as a two-digit number (e.g., 28).
{{network_token_expiration_yyyy}} The expiration year of the network token as a four-digit number (e.g., 2028).

Custom Placeholder Fields Custom Placeholder Fields

Placeholder Description
{{ text_field }} Extra fields from the tokenization API can be included.
Ensure the placeholder name must match the original casing and wording.

Handling Errors Handling Errors

The Detokenization Proxy uses special status codes to distinguish its own errors from third-party API responses.

HTTP Status Code Description
407 Proxy authentication error (check credentials)
502 Network error while reaching the third-party API
555 Token not found
556 Validation error (check inputs)
565 Unexpected internal error
Other Codes Relayed directly from the third-party API

HMAC Request Signing HMAC Request Signing

Some Payment Service Providers (PSPs) require HMAC signing to verify request integrity. Forter supports multiple hashing algorithms and allows you to sign requests seamlessly.

Supported HMAC Algorithms

HMAC Headers

Header Name Description
forter-hmac-algo HMAC algorithm (e.g., sha256)
forter-hmac-target-header Name of the header storing the computed signature
forter-hmac-secret Shared secret for signing
forter-hmac-payload-template Template for the signed payload.

For the forter-hmac-payload-template special placeholder values denoted in curly braces are supported:

PSP specific signing methods

Disclaimer: Payment Service Providers (PSPs) employ various signing algorithms, and we can support a range of them. For assistance with your specific requirements, please reach out to us.

Examples

Sending a request to Forter Sending a request to Forter

Forter's Order API Forter's Order API

Curl

curl'https://api.forter-secure.com/v3/orders/{id}'\
-x https://SITE_ID:TOKENIZATION_SITE_SECRET@pci-proxy-sandbox.checkouttools.com \
 --proxy-header 'forter-token: ftr1df95272f9e204c5791427722cc4ef407'\
--cacert [your CA certificate file path]  \
-X POST \
-H 'Content-type: application/json' \
-H 'x-forter-siteid: SITE_ID' \
-H 'api-version: API_VERSION' \
-H 'authorization: Basic dGVzdDo=' \
--data
{
 "orderId": "2356fdse0rr489",
 "orderType": "WEB",
 "authorizationStep": "PRE_AUTHORIZATION",
 "totalAmount": {
 "amountUSD": "99.95",
 "amountLocalCurrency": "105.55",
 "currency": "CAD",
 "amountMerchantMainCurrency": "125.95",
 "merchantMainCurrency": "EUR"
 },
 "totalDiscount": {
 "couponCodeUsed": "FATHERSDAY2015",
 "discountType": "COUPON"
 },
 "payment": [
 {
 "creditCard": {
 "nameOnCard": "{{ card_holder_name }}",
 "bin": "{{ card_bin }}",
 "lastFourDigits": "{{ card_last_four }}",
 "cardType": "credit",
 "expirationMonth": "{{ expiration_mm }}",
 "expirationYear": "{{ expiration_year }}",
 "fullCreditCard": "{{ card_number }}"
 },
 "billingDetails": {
 "personalDetails": {
 "fullName": "Or Paul",
 "email": "or.paul@gmail.com"
 },
 "phone": [],
 "address": {
 "zip": "90043",
 "address1": "123 17th St",
 "city": "Santa Monica",
 "region": "CA",
 "country": "US"
 }
 },
 "amount": {
 "currency": "EUR",
 "amountLocalCurrency": "90.00",
 "amountUSD": "100.00"
 }
 },
 "primaryRecipient": {
 "personalDetails": {
 "firstName": "John",
 "lastName": "Smith",
 "gender": "MALE",
 "birthdate": "1987-05-22",
 "email": "john_s@test.com"
 },
 "address": {
 "address1": "235 Montgomery st.",
 "address2": "Ste. 1110",
 "zip": "94104",
 "city": "San Francisco",
 "region": "CA",
 "country": "US",
 "company": "Generic Corp. ltd.",
 "savedData": {
 "usedSavedData": true,
 "choseToSaveData": false
 }
 },
 "comments": {
 "userCommentsToMerchant": "Please wrap with care!!",
 "messageToBeneficiary": "Enjoy the gift John!",
 "merchantComments": "Shipping delayed"
 }
 },
 "phoneOrderInformation": {
 "customerWebId": "123456789",
 "callerFirstName": "John",
 "callerLastName": "Smith",
 "callerId": "2121234567",
 "callStartTime": 1412345911,
 "callDuration": 4,
 "remarks": "The customer is buying the product for a friend",
 "merchantAgentData": {
 "merchantAgentName": "John Smith",
 "merchantAgentId": "HG36885TZ"
 }
 },
 "historicalData": {
 "orderStatus": "COMPLETED",
 "merchantOrderStatus": "Shipped",
 "fraud": "FRAUD_CHARGEBACK"
 }
 }
}

Sending a request to a PSP Sending a request to a PSP

Stripe Stripe

Securely paying using a newly collected CVC token

import { HttpsProxyAgent } from "https-proxy-agent";
import url from "url";
import Stripe from "stripe";
import tls from 'tls';

const stripe = Stripe("sk_test_***************");

const secureProxyHttpsAgent = new HttpsProxyAgent("https://pci-proxy-sandbox.checkouttools.com", {
 // Passing the "ca" option will override the default Mozilla trusted CA bundle, so we need to specify it explicitly again.
 ca: [ ...tls.rootCertificates, await fs.readFile('./forter-proxy-ca.pem') ],
 headers: {
 "proxy-authorization": `Basic ${btoa('site_id:site_secret')}`,
 "forter-token": "ftr1df95272f9e204c5791427722cc4ef407",
 },
});

stripe.setHttpAgent(secureProxyHttpsAgent);

const cvcToken = await stripe.tokens.create({
cvc_update: { cvc: "{{ cvc }}" },
});

const paymentIntent = await stripe.paymentIntents.create({
 payment_method: 'abcd',
 customer: '1234',
 amount: 1099,
 currency: 'usd',
 confirmation_method: 'manual',
 confirm: true,
 payment_method_options: { card: { cvc_token: cvcToken } },
});

Worldpay Worldpay

Authorizing a transaction using authorizations API and a token alias

// NOTE: We must trust the require proxy CA certificate. In NodeJS, this can be done in one of two ways:
// 1. Saving the CA certificate to a file, and using the NODE_EXTRA_CA_CERTS environment variable
// e.g.: export NODE_EXTRA_CA_CERTS=[your CA certificate file path]
// 2. Extending NodeJS list of trusted CAs (shown below)
import { HttpsProxyAgent } from "https-proxy-agent";
import url from "url";
import axios from "axios";
import fs from "fs/promises";
import tls from 'tls';

const secureProxyHttpsAgent = new HttpsProxyAgent("https://pci-proxy-sandbox.checkouttools.com", {
 // Passing the "ca" option will override the default Mozilla trusted CA bundle, so we need
to specify it explicitly again.
 ca: [ ...tls.rootCertificates, await fs.readFile('./forter-proxy-ca.pem') ], // Contains Forter's custom CA certificate
 headers: {
 "proxy-authorization": `Basic ${btoa('site_id:site_secret')}`,
 "forter-token-alias-key": "zooz",
 "forter-token-alias-value": "ABCABC123",
 },
});

// Securely calling worldpay's authorizations API
 axios.post(
 "https://try.access.worldpay.com/payments/authorizations",
 `{   
 "transactionReference": "Memory265-13/08/1876",
 "merchant": {
 "entity": "MindPalaceLtd"
 },
 "instruction": {
 "narrative": {
 "line1": "Mind Palace"
 },
 "value": {
 "currency": "GBP",
 "amount": 250
 },
 "paymentInstrument": {
 "type": "card/plain",
 "cardNumber": "{{ card_number }}",
 "cardExpiryDate": {
 "month": {{ expiration_month }},
 "year": {{ expiration_year }}
 }
 }
 }
 }`,
 { httpsAgent: secureProxyHttpsAgent }
 );

Fiserv Fiserv

Calculate a SHA256 hash-based HMAC and store the result in a new header called message-signature:

curl 'https://prod.emea.api.fiservapps.com/sandbox/ipp/payments-gateway/v2/payments/' \
 -x 'https://SITE_ID:TOKENIZATION_SITE_SECRET@pci-proxy-sandbox.checkouttools.com'\
 --proxy-header 'forter-token: ftr1df95272f9e204c5791427722cc4ef407'\
 -X POST \
 -H 'Content-type: application/json'\
 -H 'client-request-id: 123456'\
 -H 'api-key: FISERV_API_KEY'\
 -H 'timestamp: 655846200000'\
 -H 'forter-hmac-target-header: message-signature'\
 -H 'forter-hmac-algo: sha256'\
 -H 'forter-hmac-secret: signing-secret'\
 -H 'forter-hmac-payload-template: {{ api-key }}{{ client-request-id }}{{ timestamp }}{{ request-body }}'\
 -d '
 {   
 fullCreditCard: "{{ card_number }}",
 nameOnCard: "{{ card_holder_name }}",
 expirationMM: "{{ expiration_mm }}",
 expirationYY: "{{ expiration_yy }}",
 }
'