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
- Securely retrieve tokenized PCI data
- Avoid direct PCI data handling
- Compatible with standard HTTP libraries and tools
- Pass PCI tokenized authorization payloads to any PSP from a single card vault vendor
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
- Download and store the certificate.
- 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
- Payment Method Token: A Forter-issued PCI token for payment credentials.
- 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:
- Using the Forter Token Directly: This requires including the forter-token header with the token string.
- 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:
- The primary Forter token string forter-token OR forter-token-alias-key and forter-token-alias-value
- The CVC-specific token issued by Forter forter-cvc-token OR forter-cvc-token-alias-key and forter-cvc-token-alias-value
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
- sha256
- sha512
- sha1
- md5
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:
- {{ request-body }} - The full outgoing request body, after detokenization, as a single string.
- {{ http-method }} - The HTTP method used in the request
- {{ http-path }} - The relative path used in the request
- {{ header-name }} - Any header sent along the request can be used to construct the signing payload. The header name must be converted to lowercase.
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 }}",
}
'