Communication Flow
The communication flow between POS Event Stream API and the client application includes the following:
Socket Communication - A Transmission Control Protocol (TCP) socket transmits data from POS Event Stream to the client application.
Message Encryption - Some portions of the request, response, and event messages are encrypted.
Validation - As part of the key exchange process, the client application must send a request to POS API on the same TCP socket to register itself as a client.
Offline Validation - After the validation is complete, POS API stores sufficient information locally so the client can be validated offline, if necessary.
Socket Communication
The IP address and port of the client application must be configured for the site through the Portal. POS API retrieves the socket address and port values from the Portal.
POS Event Stream uses a simple Transmission Control Protocol (TCP) socket to transmit data to the client application. There will be multiple point of sale (POS) terminals at the site and possibly a service to handle orders from external systems, such as kiosks, mobile orders, and web orders. Each of these POS terminals transmits event information to the client application. The client application listens for connection requests from the POS terminals, instead of the client application polling for and connecting to multiple, active POS terminals. The client application must be able to handle multiple, concurrent socket connections, one for each POS terminal, including terminals or services that accept orders from external systems.
POS API creates a new connections to the client’s IP address and port each time it starts or at an interval whenever a client connection is configured, but is not established currently. Each POS application, including services that accept new orders from an outside system such as kiosks, mobile orders, and web orders, creates a separate connection to the client application.
Socket Message Format
Each message sent on the socket consists of two parts: a four-byte value and the request, response, or event data. The first part is a four-byte value with the length of the message buffer that follows. The length value is specified with the least significant byte first with remaining bytes in increasing order of significance, referred to as little endian byte format. The four-byte length value does not include its own length (four). The second part of the socket message is the request, response, or event data. The POS Event Stream request/response/event is formatted as JSON data. The content of each JSON message is described in this documentation.
For example, the following request has 129 bytes of JSON data. The socket message has four bytes of binary data to specify a length of 129 bytes to follow. Decimal value 129 is 0x00000081 in hexadecimal representation.
{"source":"xenial","version":"1.0","msg_id":"ac0701e8-cd5e-4d41-9f33-1e0317568 aab","msg_type":"register_client","msg_resp":"ack"}
The message on the socket will be 81000000 followed by the JSON data. Note the format of the first four bytes for the length of the following data, which has the least significant byte first.
81 00 00 00 7b 22 73 6f 75 72 63 65 22 3a 22 78 65 6e 69 61 ....{"source":"xenia 6c 22 2c 22 76 65 72 73 69 6f 6e 22 3a 22 31 2e 30 22 2c 22 l","version":"1.0"," 6d 73 67 5f 69 64 22 3a 22 61 63 30 37 30 31 65 38 2d 63 64 msg_id":"ac0701e8-cd 35 65 2d 34 64 34 31 2d 39 66 33 33 2d 31 65 30 33 31 37 35 5e-4d41-9f33-1e03175 36 38 61 61 62 22 2c 22 6d 73 67 5f 74 79 70 65 22 3a 22 72 68aab","msg_type":"r 65 67 69 73 74 65 72 5f 63 6c 69 65 6e 74 22 2c 22 6d 73 67 egister_client","msg 5f 72 65 73 70 22 3a 22 61 63 6b 22 7d _resp":"ack"}
The client application should read the first four bytes to get the length of the data to follow, then read only that many bytes from the socket. If all bytes are not yet available, read what is available and wait for more data to arrive, each time reading only as much data as is necessary to read the complete, single message. If more data remains in the socket’s buffer, begin the process again to read the next message. This process handles cases where a single message might be split across multiple network packets and also handles the case where the socket buffer contains multiple messages that are waiting to be read.
For more information, see Requirements.
Message Encryption
Some portions of the request, response, and event messages are encrypted before they are transmitted on the socket connection. The message encryption has the following requirements:
Both POS API and the client application must be able to encrypt and decrypt messages through Advanced Encryption Standard (AES) 256 cryptographic functions.
This AES 256 symmetric cryptography requires that both POS API and the client application use the same encryption key.
POS Event Stream API requires that a new AES 256 Data Encryption Key (DEK) be created each time a new socket connection is established.
This AES 256 DEK, when shared, requires a second cryptographic method, RSA, for the key exchange. As a result, both POS API and the client application have a copy of the same AES 256 DEK.
The AES 256 key must be protected, so it cannot be transmitted on the socket as a clear, unencrypted value.
The AES 256 DEK must first be encrypted using a Key Encrypting Key (KEK) through a method that allows for the other side to decrypt the AES 256 DEK value.
An RSA public/private key scheme is used to safely encrypt and transmit the AES 256 DEK value to the other side.
Each time a new socket connection is established, repeat the following steps to create and exchange keys:
POS API issues a Transmission Control Protocol (TCP) socket connection request to the client application’s IP address and port.
The client application accepts the socket connection request. A socket connection has been established between POS API and the client.
POS API generates a new RSA public/private key pair. This RSA key pair is used as a Key Encrypting Key (KEK).
POS API sends the RSA public key to the client application through the newly established socket connection.
The client application receives the RSA public key and saves it in its memory. There is no need to persist-key the value to long-term storage.
The client application generates a new value to be used as the AES 256 Data Encrypting Key (DEK).
The client application uses the RSA public KEK to encrypt the AES 256 DEK value.
The client application sends the encrypted value to POS API.
POS API receives the key exchange message and decrypts the message content using the RSA private key.
POS API saves the AES 256 DEK received from the client application in memory. There is no need to persist-key the AES 256 value to long-term storage.
Note
If the key or the socket connection is lost, a new key exchange must be performed using these same steps.
Now both the client application and POS API have the same AES 256 DEK. All subsequent traffic on the socket must be encrypted using this AES 256 DEK. POS API will not send event messages to the client application until it has a valid AES 256 DEK.
Validation
As part of the key exchange process, the client application must send a request to POS API on the same Transmission Control Protocol (TCP) socket to register itself as a client. The client application sends a register_client request, which includes the Advanced Encryption Standard (AES) 256 Data Encrypting Key (DEK) and the partner’s integrator key_id and secret_key that were obtained previously from us. Both the key_id and secret_key must be safeguarded and kept confidential to avoid impersonation by unknown actors. It is your responsibility as the the author of the client application to ensure the integrator’s key_id and secret_key are never exposed or stored in such a way that they can be obtained by other parties. The content of the register_client request message element msg_data, just as all other messages, must be encrypted using the AES 256 DEK before transmitting the request on the socket to POS API.
When POS API receives the register_client request, it decrypts the msg_data value using the RSA private key from the first step and uses the integrator’s key_id and secret_key to validate the identity of the client application. This validation step requires POS API to have access to the internet so it can use cloud services to validate the integrator’s values. After successful validation through cloud services, the feed to the client application is enabled.
Offline Validation
When a client application is validated during the register_client operation, POS API stores sufficient information locally. This allows the client to be validated offline should internet access be unavailable the next time validation is required. An example of required validation is when a new socket connection is established. POS API allows offline connection validation for up to 30 days after the previous, successful online validation.