Detokenization Proxy
The Forter Detokenization Proxy allows merchants to pass Forter PCI tokenized payloads to any PSP.
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 merchants 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
- Sandbox: https://pci-proxy-sandbox.checkouttools.com
- Production: https://pci-proxy.checkouttools.com
Authentication
The Forter Detokenization Proxy requires HTTP Basic Authentication using the proxy-authorization
header in the following format:
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
To establish a secure connection, merchants must trust Forter’s CA root certificate.
Sandbox Certificate
-----BEGIN CERTIFICATE-----
MIICuDCCAaACCQDx1qoYa/sqhTANBgkqhkiG9w0BAQsFADAeMQswCQYDVQQGEwJJ
TDEPMA0GA1UECgwGRm9ydGVyMB4XDTIyMDgyNTEzMDMyMFoXDTMyMDgyMjEzMDMy
MFowHjELMAkGA1UEBhMCSUwxDzANBgNVBAoMBkZvcnRlcjCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAOSmh9WDhKaceirpwfVbfvpvHIQ0H5TmKZixjrzN
QVGpeXd+e65fPjnDZtXpT06aN2Dqimh9VlEf6WX9E6zxeQZzxkmwUU5rwjWx0HQ2
5RBh9LeRy0xlcF4rPDAaQd74eoQWPPJ+5GBtHjxWEiPAG0wB6yb++D1kDhvT5yXd
qXqc9GL1HXex4OZexcTr5XJCPfRUZgC/78sF8H0Gg5vwOq8VprN0951TW7W1gHA4
Hl51alZKv4VUCEhr1FDQfrW6N2IrahYhKYg38P3p+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
-----BEGIN CERTIFICATE-----
MIICnjCCAYYCCQCqd/JdClQxIDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQKDAZG
b3J0ZXIwHhcNMjIxMTIxMTMyNDQ4WhcNMjcxMTIwMTMyNDQ4WjARMQ8wDQYDVQQK
DAZGb3J0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4NgIfmQm5
MkADTIxzOcKUAI4+XGBwmLobFQqtMluUn3pe4ChPFOURCbTxReSHZq0ywwFTUT51
ARMh+tsUw+DzbH35T0YTvMXBPFzhikg9uFXUhc9EOn/mFPZxYm15LH78NAKXumPT
+5r0+cg5TbJpPCnVZbXMTyQOcOQGGj4ZSZLF4IjGnQlKrvuA90UQL1PttUd8p6Vg
/O8vO0IcrsA9QZ7vlJoVxi4JAI8GoMjC0b+8r+fihakQ146RPn9f5ZajpOu83btk
n59nJWjwBG7JQd0gTb+5McywoFSGR+EMAaiMVREK1bGftewjmzuZdxgSecguL/Xy
6qb3EJr8Mtj5AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGCmJlEiQEsBl5cud6I6
2PiJpA1ZK7cjZ+fMPSCH7bDA/gmdc5oNG4Gb4QkBAwsNXpPeySbtkyzCWsGo5iSR
kfhxrCN/EGyDuwYzM1ceNFUUt+V7TzDnmSTAA5xHCEBuKUE3RQdy+QqlNEwL/faI
3P0TaiojiFypsz04tHAvXAGJzTETSZigzsexSamdUUyCcZIPgiJrXr/oNCKjapXz
lirDWLLO5HU+wn+ZvOPrkUvRRHvrz/WQKMdqA2IU7OavI0MrRFt/wvw73wOZZhZo
nWLGh2TlEk6wV+BT9qHZdMv045l9LG9PhnoPCt5k4RDGUs6pRYMzdZq870NHhO9p
cCY=
-----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
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
- Payment Method Token - A Forter-issued PCI token for payment credentials.
- CVC-Only Token - A specialized token for periodic CVC authentication.
Required headers
For Payment Method Tokens
When using a Payment Method Token issued by Forter, merchants 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, merchants 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:
forter-token
– The primary Forter token string.forter-cvc-token
– The CVC-specific token issued by Forter.
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
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
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
Placeholder | Description |
---|---|
| Extra fields from the tokenization API can be included. Ensure the placeholder name must match the original casing and wording. |
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
Some Payment Service Providers (PSPs) require HMAC signing to verify request integrity. Forter supports multiple hashing algorithms and allows merchants 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.
To implement signing for Ixopay, include the following header: Forter-Ixopay-Signature: SHARED_IXOPAY_KEY
This will generate X-Signature
and Date
headers in the proxied request to Ixopay.
Examples
Sending a request to Forter
Forter's Order API Integration
orders API
curl 'https://api.forter-secure.com/v3/orders/{id}' \
-x https://SITE_ID:[email protected] \
--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": "[email protected]"
},
"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": "[email protected]"
},
"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
Stripe
Securely paying using a newly collected CVC token(Node.js)
// 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 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
Authorizing a transaction using authorizations api and a token alias(Node.js)
// 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",
// Note: we are using a stringified payload as worldpay uses integers to represent dates which becomes
// invalid JSON when replaced with our placeholders
`{
"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
Calculate a SHA256 hash based HMAC and store the result in a new header called message-signature:(cURL)
curl 'https://prod.emea.api.fiservapps.com/sandbox/ipp/payments-gateway/v2/payments/' \
-x 'https://SITE_ID:[email protected]' \
--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 }}",
}'
Updated 10 days ago