Proxy payment instruments

Payrails Vault is a key module of our system and works in conjunction with our Payments and Ledger services to help you accept and optimize your payments smoothly.

However, every service at Payrails can be used standalone to adapt to our merchant's use cases. This guide explains how to use the instruments and tokens stored in our Vault with your own Payment service so that your infrastructure is never exposed to sensitive data.

We call this feature Vault Proxy because our Payrails Vault stands between your backend and the PSP or third-party service that will receive the sensitive data. When receiving your request, we replace certain placeholders in the request body with the sensitive information stored in our vault before sending it to the provider. When they respond, we remove the sensitive information and send the response back to you.

Usually, this feature would be used for executing payment authorization requests, but depending on the external provider, it may be that they also require receiving the card in a separate endpoint. For example, Mangopay requires you to first store the card and then execute the payment with their card identifier, so you would use our Proxy only on the first call.

The following is a high-level sequence diagram of the interaction between the services.

Creating Providers

Before being able to use the /proxy endpoint, you have to inform Payrails about the provider with whom you want to exchange information.

We need to start by checking their PCI certification to receive full PANs securely. To ensure everyone's security and compliance, Payrails must perform certain checks on the provider before sending card data. After the security checks, we're ready to configure the provider on our system. For example, we need to know which endpoint in the provider itself we need to call on your behalf (providerUrl) and the credentials we need to use for authentication (providerConfig).

After Payrails is done checking their compliance, we will provide you with a providerId that identifies the Provider in our system, and a providerConfigId, which contains your specific credentials to call them. You will need both for executing Proxy requests.

Executing Proxy requests

After the provider is created and configured, you can use the VaultProxy endpoint to send your instruments to the provider.

The following are some examples of some well-known providers and how you should map the card data using our instruments.

{
  "paymentInstrumentId": "eeaac45c-f032-49bc-a8c5-ec99d79b74e2",
  "providerConfigId": "d9699acd-9361-4e11-8d06-b30f41fc6210",
  "url" : "https://checkout-test.adyen.com/v69/payments",
  "headers": {
    "x-API-key": "YOUR_API_KEY"
  },
  "body": {
    "amount": {
      "currency": "USD",
      "value": 1000
    },
    "reference": "your-order-number",
    "paymentMethod": {
      "type": "scheme",
      "number": "{{cardNumber}}",
      "expiryMonth": "{{cardExpiryMonth}}",
      "expiryYear": "{{cardExpiryYear}}",
      "cvc": "{{cardSecurityCode}}",
      "holderName": "{{cardHolderName}}"
    },
    "returnUrl": "https://your-company.com/...",
    "merchantAccount": "YOUR_MERCHANT_ACCOUNT"
  }
}
{
  "paymentInstrumentId": "eeaac45c-f032-49bc-a8c5-ec99d79b74e2",
  "providerConfigId": "d9699acd-9361-4e11-8d06-b30f41fc6210",
  "url" : "https://checkout-test.adyen.com/v69/payments",
  "headers": {
    "x-API-key": "YOUR_API_KEY"
  },
  "body": {
    "amount": 1000,
    "currency": "USD",
    "reference": "some_reference",
    "source": {
      "type": "card",
      "number": "{{cardNumber}}",
      "expiry_month": "{{cardExpiryMonth}}",
      "expiry_year": "{{cardExpiryYear}}",
      "cvv": "{{cardSecurityCode}}",
      "name": "{{cardHolderName}}"
    },
    "payment_type": "Regular",
    "authorization_type": "Final",
    "capture": true,
    "processing_channel_id": "pc_xxxxxxxxxxx",
    "risk": {
      "enabled": false
    },
    "merchant_initiated": true
  }
}
{
  "paymentInstrumentId": "eeaac45c-f032-49bc-a8c5-ec99d79b74e2",
  "providerConfigId": "d9699acd-9361-4e11-8d06-b30f41fc6210",
  "url" : "https://pci.mangopay.com/pci/v2.01/YOUR_CLIENT_ID/payins/card/direct/raw",
  "headers": {},
  "body": {
    "Tag": "Custom meta",
    "AuthorId": "205062273",
    "DebitedFunds": {
      "Currency": "EUR",
      "Amount": 5000
    },
    "SecureModeReturnURL": "https://mangopay.com/docs/please-ignore",
    "Culture": "EN",
    "BrowserInfo": {
      "AcceptHeader": "text/html, application/xhtml+xml, application/xml;q=0.9, /;q=0.8",
      "JavaEnabled": true,
      "Language": "en-EN",
      "ColorDepth": 4,
      "ScreenHeight": 1800,
      "ScreenWidth": 400,
      "TimeZoneOffset": 60,
      "UserAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",
      "JavascriptEnabled": true
    },
    "IpAddress": "b02a:7967:ecc2:d827:cdd0:67d3:6d2f:4fef",
    "Billing": {
      "FirstName": "Alex",
      "LastName": "Smith",
      "Address": {
        "AddressLine1": "100 rue Rivoli",
        "AddressLine2": null,
        "City": "Paris",
        "Region": "Ile-de-France",
        "PostalCode": "75001",
        "Country": "FR"
      }
    },
    "Shipping": {
      "FirstName": "Alex",
      "LastName": "Smith",
      "Address": {
        "AddressLine1": "100 rue Rivoli",
        "AddressLine2": null,
        "City": "Paris",
        "Region": "Ile-de-France",
        "PostalCode": "75001",
        "Country": "FR"
      }
    },
    "Card":{
      "Number":"{{cardNumber}}",
      "ExpirationDate":"{{cardExpiryMonth}}{{cardExpiryYear2Digits}}",
      "CVX":"{{cardSecurityCode}}"
    },
    "CardType":"CB_VISA_MASTERCARD"
  }
}

Variable substitution

Fields of the format {{key}} will be replaced by data contained in your Payrails Payment Instrument.

The following fields are currently supported:

  • {{cardNumber}}: Card number
  • {{cardHolderName}}: Card holder name
  • {{cardSecurityCode}}: Card security code (CVV, CVC, or several other names)
  • {{cardExpiryMonth}} or {{MM}}: Card expiry month
  • {{cardExpiryYear}} or {{YYYY}}: Card expiry year
  • {{cardExpiryYear2Digits}} or {{YY}}: Card expiry year last 2 digits

If the key is not present, the data will be sent "as is" to the Payment Provider.

❗️

With great power comes great responsibility

This feature gives you absolute control on what is sent to the Provider. Make sure you sanitize and validate your requests to avoid risk of exposing sensitive information in a field that is not protected.

For example, if you put the variable {{cardNumber}} in a field that the Provider shows in their Portal (like an order description, cart item name, etc.), then you would be exposing the customer's card number to your support team.

Override card security code

According to PCI DSS rules, we can only retain the card security code during a payment authorization. This means that when including the {{cardSecurityCode}} in your request body, you need to be sure that the value is still available in our Vault.

If the card was initially stored with the correct authorization flags, you should not need the security code to authorize a payment. However, we provide this option in case you have one of the following use cases:

  • you want to ask for the security code to prevent fraud due to account takeover attacks
  • you are required by a Provider to include this field even if the card is already stored

Our VaultProxy endpoint has an optional parameter called encryptedSecurityCode that allows you to override the stored value (if any) of the {{cardSecurityCode}} variable in the body you intend to send to your Provider.

To obtain the value of the encryptedSecurityCode, you can use our client-side SDK function called encryptCardData. Check the documentation for it here.