Skip to main content

Channels (Server side)

Channels are a flexible way to add the PCI Proxy as a man in the middle between your backend software and third party software such as a PMS and a Booking engine. In this way you can safely receive and send sensitive credit card information.

info

Channels are configured by your developer team using our REST API.

Attributes

A channel always consists of following attributes:

FIELD NAMEAVAILABLE VALUESDESCRIPTION
endpointEndpoint to or from which the body is transmitted
actiontokenize, detokenizeSpecifies wether the card data is masked or unmasked.
directionpull, pushIndicates wether the payload body that has to be processed is pushed to the channel or fetched from the channel
contentTypejson,xmlFormatting of the payload body from which the data has to be extracted for the tokenization or detokenization process.
encodingutf8, ascii, utf16le, ucs2, base64, latin1Encoding of the payload body
fieldMappingIndicates the PCI proxy how the data is to be extracted from the body

A fieldMapping consists of following fields:

FIELD NAMEDESCRIPTION
referenceOptional. This can be used to associate the card data to a reference of your software. Such as a booking id.
panCard humber or the card token.
cardHolderName of the card holder.
expiryExpiry date of the card. Valid formats are MM-YYYY, MM-YY, YYYY-MM, YY-MM, MM/YYYY, YYYY/MM, MM/YY, YY/MM, MMYY. If expiry date is split in two separate fields use expiryMonth and expiryYear instead.
expiryMonthUsed if expiry date of card is split in two fields.
expiryYearUsed if expiry date of card is split in two fields.
cardCVVCard CVV number

The field mapping is specified as XPATH or JSONPATH attributes depending on the contentType of the body. To get a better understanding of these query languages please visit XPATH and JSONPATH resources.

info

In order to test your XPATH expressions we recommend this Online XPATH test tool. For testing your JSONPATH expressions we recommend this Online JSONPATH test tool.

When to use each channel configuration

The main difference between the channel configurations are the direction and the action fields. To make it clearer, let's see some real world scenarios:

PUSH + TOKENIZATION

PUSH + TOKENIZATION

You are a PMS and a channel mannager sends new bookings over to your backend sofware (e.g.: SOAP API). These bookings include sensitive payment card data which you do not want to store directly on your database but instead delegate this to the secure PROXY PCI vault.

In this case you would have to create a PUSH + TOKENIZATION channel. On the endpoint field you will add your SOAP API entry point (e.g.: http://somehost.com/xmlsoapinterface).

Once you have created the channel using the PROXY PCI REST API you can then updated the channel manager configuration and replace your endpoint with the channel invocation endpoint (e.g.: https://pci-proxy-api.paynopain.com/production/channel/1df28290-f3cd-411f-9f5f-6b844fe6aaa4/invoke).

By this the channel mannager will invoke the PROXY PCI which then does it's magic and finally forwards the bookings to your configured endpoint having replaced all the card pan's with a token version of it. This token can then be stored by you and use it for issuing a payment or forwarding it to another third party.

PULL + TOKENIZATION

PULL + TOKENIZATION

You are a PMS, but you still need the bookings from a channel mannager. But in this case the channel manager is not sending the data over to you. You are the one that initiates a request to the channel manager and then the channel manager replies with the latest bookings.

In this case you need a PULL + TOKENIZATION channel where the endpoint attribute of the channel is the channel mannagers API endpoint. You can then initiate your request to the channel invocation endpoint, then the PROXY PCI will fetch the new bookins from the channel mannager API endpoint, do it's magic, and reply with the new bookings.

info

The PROXY PCI channel invocation method forwards all QUERY and HTTP HEADERS to the configured endpoint.

PUSH + DETOKENIZATION

PUSH + DETOKENIZATION

In this case we want to send our collected card pan data to a third party PAYMENT GATEWAY for payment processing. The PAYMENT GATEWAY offers and endpoint for this where you have to send the card details in their specified JSON format. In this scenario we'll be needing a PUSH + DETOKENIZATION channel. The endpoint of the channel will be the PAYMENT GATEWAY API endpoint. You will be sending the card details, except for the card pan, to the PROXY PCI channel invocation endpoint and the PROXY PCI will replace the card token with the actual card pan.

PULL + DETOKENIZATION

PULL + DETOKENIZATION

In this final use case you're a channel manager and have collected card details of a future guest using the javascipt client side library. So now a PCI compliant PMS system want's to download the full card details from your channel manager. In this case you'd just configure a PULL + DETOKENIZATION channel. In the endpoint attribute you'll specify your API endpoint and provide the resulting PROXY PCI invocation endpoint to the PMS system, which then initiates the request. We will forward the request yo your API and you respond with the booking. We will replace the card token with the actual pan and reply this to the PMS.

danger

When using DETOKENIZATION action, the PROXY PCI will only replace the card token with the actual card pan. All other fields have to be provided in the payload as they are. You can safely store the expiry date and card holder by yourself.

Examples

For your better understanding we have prepared some working channels for you to invoke. There is one JSON PUSH tokenization endpoint and one XML PUSH detokenization examples for you to try.

JSON example

JSON example
{
"bookings": [
{
"id": "BK-213123",
"room_category": "VIP",
"facility_id": 1,
"payment_data": {
"card": {
"pan": "4442330588722461",
"cvv": "123",
"expiry": "12/21",
"holder": "John Doe"
}
}
},
{
"id": "BK-3213123",
"room_category": "VIP",
"facility_id": 1,
"payment_data": {
"card": {
"pan": "4701731341611394",
"expiry": "06-2025",
"holder": "Patma Patill"
}
}
}
]
}

FIELD MAPPING

FIELD NAMEVALUE
reference$.bookings[*].id
cardHolder$.bookings[*].payment_data.card.holder
expiry$.bookings[*].payment_data.card.expiry
pan$.bookings[*].payment_data.card.pan
cardCVV$.bookings[*].payment_data.card.cvv

WORKING CHANNEL EXAMPLE

We have configured a channel with this exact field mapping. This is the exact channel configuration:

{
"action": "tokenize",
"direction": "push",
"endpoint": "https://pciproxypnp.free.beeceptor.com/push/json/tokenize",
"contentType": "json",
"fieldMapping": {
"reference": "$.bookings[*].id",
"cardHolder": "$.bookings[*].payment_data.card.holder",
"expiry": "$.bookings[*].payment_data.card.expiry",
"pan": "$.bookings[*].payment_data.card.pan"
},
"encoding": "utf8"
}

This means that if invoked, the transmitted body will be analysed and the mapped fields will be extracted and vaulted. Then the pan is replaced with a token version of it. Finally the new body is forwarded to the provided endpoint, including all the original headers and query parameters which where sent to the channel's endpoint.

Go ahead and visit https://beeceptor.com/console/pciproxypnp and leave the page open. Then issue the following curl command:

curl -X POST \
https://pci-proxy-api.paynopain.com/sandbox/channel/1df28290-f3cd-411f-9f5f-6b844fe6aaa4/invoke \
-H 'Content-Type: application/json' \
-H 'SomeCustomeHeader: SayHello!' \
--data '{"bookings":[{"id":"BK-213123","room_category":"VIP","facility_id":1,"payment_data":{"card":{"pan":"4442330588722461","expiry":"12/21","holder":"John Doe"}}},{"id":"BK-3213123","room_category":"VIP","facility_id":1,"payment_data":{"card":{"pan":"4701731341611394","expiry":"06-2025","holder":"Patma Patill"}}}]}'

After executing the command you should see the request on the beeceptor console. Feel free to inspect the received body and check the pan field of the card object.

XML example

XML example
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ota="http://www.opentravel.org OTA/2003/05">
<SOAP-ENV:Header>
<wsse:Security xmlns="http://schemas.xmlsoap.org/soap/envelope/" mustUnderstand="1">
<wsse:UsernameToken>
<wsse:Username>::someUsername</wsse:Username>
<wsse:Password>::somePassword::</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ota:OTA_HotelResNotifRQ>
<ota:HotelReservations>
<ota:HotelReservation CreateDateTime="2018-10-03T19:08:23.000+02:00" LastModifyDateTime="2018-10-03T19:08:23.000+02:00" ResStatus="Commit">
<ota:UniqueID ID="M5304934-86503" Type="14"/>
<ota:ResGlobalInfo>
<ota:TimeSpan Duration="3" End="2018-10-24" Start="2018-10-21"/>
<ota:Guarantee>
<ota:GuaranteesAccepted>
<ota:GuaranteeAccepted>
<ota:PaymentCard CardCode="335" CardCVV="123" CardNumber="A27BEC4A-C3EF-4A45-A6B9-1485BA596625" ExpireDate="08-2022">
<ota:CardHolderName>John Doe</ota:CardHolderName>
</ota:PaymentCard>
</ota:GuaranteeAccepted>
</ota:GuaranteesAccepted>
</ota:Guarantee>
</ota:ResGlobalInfo>
</ota:HotelReservation>
</ota:HotelReservations>
</ota:OTA_HotelResNotifRQ>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
info

This payload was partially extracted from the Siteminder channel manager.

Namespaces

danger

Understanding how xpath and namespaces work is crucial for the XML field mapping.

Prefix Namespaces

A namespace is composed of a name and a URI specification. The scope of the prefix-namespace mapping is that of the element that the namespace declaration occurs on as well as all its children.

<bk:bookstore xmlns:bk="urn:xmlns:25hoursaday-com:bookstore">
<bk:book>
<bk:title>Lord of the Rings</bk:title>
<bk:author>J.R.R. Tolkien</bk:author>
<inv:inventory status="in-stock" isbn="0345340426"
xmlns:inv="urn:xmlns:25hoursaday-com:inventory-tracking" />
</bk:book>
</bk:bookstore>

Example: //bk:author

Undeclared namespaces

If an element has blank namespace (xmlns="") then it is a undeclared namespace and any children element without a prefix namespace is associated to that undeclared namespace.

<bookstore xmlns="urn:xmlns:25hoursaday-com:bookstore">
<book xmlns="">
<title>Lord of the Rings</title>
<author>J.R.R. Tolkien</author>
<inv:inventory status="in-stock" isbn="0345340426"
xmlns:inv="urn:xmlns:25hoursaday-com:inventory-tracking" />
</book>
</bookstore>

Example: //title

Field mapping

FIELD NAMEVALUE
reference//ota:UniqueID/@ID
cardHolder//ota:CardHolderName
expiry//ota:PaymentCard/@ExpireDate
pan//ota:PaymentCard/@CardNumber
cardCVV//ota:PaymentCard/@CardCVV

We have configured a channel with this exact field mapping. This is the exact channel configuration:

{
"action": "detokenize",
"direction": "push",
"endpoint": "https://pciproxypnp.free.beeceptor.com/push/xml/detokenize",
"contentType": "xml",
"fieldMapping": {
"reference": "//ota:UniqueID/@ID",
"cardHolder": "//ota:CardHolderName",
"expiry": "//ota:PaymentCard/@ExpireDate",
"pan": "//ota:PaymentCard/@CardNumber",
"cardCVV": "//ota:PaymentCard/@CardCVV"
},
"encoding": "utf8"
}

This means that if invoked, the transmitted body will be analysed and the mapped fields will be extracted and vaulted. Then the pan is replaced with a token version of it. Finally the new body is forwarded to the provided endpoint, including all the original headers and query parameters which where sent to the channel's endpoint.

Go ahead and visit https://beeceptor.com/console/pciproxypnp and leave the page open. Then issue the following curl command:

curl -X POST \
https://pci-proxy-api.paynopain.com/sandbox/channel/da3e2c5b-8e3d-44f3-a56e-0491b949d7f7/invoke \
-H 'Content-Type: application/xml' \
-H 'SomeCustomeHeader: SayHello!' \
--data '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ota="http://www.opentravel.org OTA/2003/05"><SOAP-ENV:Header><wsse:Security xmlns="http://schemas.xmlsoap.org/soap/envelope/" mustUnderstand="1"><wsse:UsernameToken><wsse:Username>::someUsername</wsse:Username><wsse:Password>::somePassword::</wsse:Password></wsse:UsernameToken></wsse:Security></SOAP-ENV:Header><SOAP-ENV:Body><ota:OTA_HotelResNotifRQ><ota:HotelReservations><ota:HotelReservation CreateDateTime="2018-10-03T19:08:23.000+02:00" LastModifyDateTime="2018-10-03T19:08:23.000+02:00" ResStatus="Commit"><ota:UniqueID ID="M5304934-86503" Type="14"/><ota:ResGlobalInfo><ota:TimeSpan Duration="3" End="2018-10-24" Start="2018-10-21"/><ota:Guarantee><ota:GuaranteesAccepted><ota:GuaranteeAccepted><ota:PaymentCard CardCode="335" CardNumber="A27BEC4A-C3EF-4A45-A6B9-1485BA596625" ExpireDate="08-2022"><ota:CardHolderName>John Doe</ota:CardHolderName></ota:PaymentCard></ota:GuaranteeAccepted></ota:GuaranteesAccepted></ota:Guarantee></ota:ResGlobalInfo></ota:HotelReservation></ota:HotelReservations></ota:OTA_HotelResNotifRQ></SOAP-ENV:Body></SOAP-ENV:Envelope>'

After executing the command you should see the request on the beeceptor console. Feel free to inspect the received body and check the pan field of the card object.