1 - Foreword
XFS4IoT has been identified as a successor to XFS 3.x to meet the following requirements:
- Replace the XFS and J/XFS standards in the marketplace.
- Target industries – Retail Banking.
- Operating System Agnostic and Technology and Language Adaptable.
- Multi-Vendor – Able to run common core high level functionality on multiple vendors hardware, while providing access to finer level device API granularity.
- Flexibility – enabling new hardware topologies, device types and functionality to be rapidly adapted.
- Support end to end application level security.
- Should not prevent the use of a low resource computing environment.
- Provide a good developer experience by providing a well-documented API that is easy to learn, is quick to market and reduces risk by exposing an unambiguous interface.
- Leverage existing standards.
Within the overall requirements specified in the Charter, the opportunity has been taken to solve some of the issues with the 3.x interface while retaining all the same functionality:
- Binary data structures makes adding new functionality difficult due to compatibility issues, leading to multiple redundant versions of the same command appearing in many of the existing device classes. To resolve this, a flexible text based approach has been adopted including the wide use of default parameters.
- Compound devices have been difficult for applications to implement, particularly cash recycling. Addition of other shared functionality such as end to end security would make the use of compound devices more prevalent. Compound devices are removed in XFS4IoT, a single Service can support as many interfaces as required to support its requirements.
Migration from and to 3.x is a major consideration to support adoption of XFS4IoT. While a lot of duplication has been removed (for example the Card Reader interface has fewer commands and events defined than the equivalent 3.x IDC specification), all the same IDC commands and events can be implemented. In some cases, this is achieved by having shared common commands such as Common.Status which replaces all the 3.x WFS_INF_XXX_STATUS commands.
2 - API
This chapter defines the API functionality and messages. It defines the XFS4IoT API including but not limited to:
- System Architecture
- Message Definition
- End to End Security
XFS4IoT defines a system consisting of Services provided by one or more vendors. Each Service can support one or more interfaces as required to meet the requirements of the device or function it supports, so for example a Cash Recycling device will need the following interfaces to supply all the device's functionality:
- Common, which defines functionality common to all devices
- CashManagement, which defines functionality common to all cash handling devices
- CashAcceptor, which defines functionality common to all cash accepting devices
- CashDispenser, which defines functionality common to all cash dispensing devices
- Storage, which defines functionality common to devices which store items
Additional interfaces can be added as required for example KeyManagement to support encryption key management.
The following sections describe how clients and services create connections and send messages to each other.
2.2 - WebSockets Connections
Multiple services can be supplied by multiple vendors. This standard doesn't require coordination between these different vendors, or between the service publishers and the service client. It is possible to operate a system with components from multiple hardware vendors, and with third party applications, without the prior knowledge of any party.
This specification covers an environment using WebSockets (ref. api-3) to communicate between services and applications, either on a single machine or across a network.
This section covers both the process for publishing a service such that it can be discovered, and the discovery process used by the service client.
There is also a clear definition of responsibility for each component in the system, including when there are dependencies between components. There are no shared components required to coordinate the system.
The underlying network can use any protocol that supports WebSockets such as IPv4 or IPv6. Nothing in this document requires any particular underlying protocol.
2.2.1 - Overview
In this standard there are two types of "endpoint"; publisher and service. Each endpoint, of either type, is published by a single software/hardware vendor. A publisher endpoint is used for service discovery, to discover service endpoints. A single service endpoint can expose multiple "services", where each service typically represents a single piece of hardware. A single machine (or a single IP address) may expose multiple publisher and service endpoints from different vendors. A "client" application may consume multiple services from multiple service endpoints on the same machine, or across multiple machines.
On startup of the machine, any software services attempt to claim access to individual network ports using the underlying operating system mechanism. Ports are claimed sequentially from a known sequence. Each port becomes an endpoint that can publish multiple services from a single vendor.
A client application will attempt to connect to each port on a machine in the known sequence to get a list of all active publisher endpoints. For each publisher endpoint it then exchanges JSON messages across WebSockets with URIs using a known format to recover a list of services published by that endpoint. Once it has a full list of services it can use WebSocket connections to communicate with each service to perform whichever actions are required.
2.2.2 - Uniform Resource Identifier (URI)
This section describes the Uniform Resource Identifiers used in XFS4IoT.
2.2.2.1 - URI Format
Communication with service publishers and services will be through distinct URIs which will use the following format:
wss://machinename:portnumber/xfs4iot/v1.0/servicename
This URI consists of the following components:
URI Component | Description |
---|---|
wss:// or ws:// | The protocol id for secure WebSockets. See Network Protocol. |
machinename | The identification of the machine publishing endpoints. See Machine Identification. |
portnumber | The port number discovered through the initial service discovery process - see Port Sequence. |
xfs4iot | A literal string. The inclusion of this part identifies standard XFS4IoT services published on this URI. It allows the possibility of a single vendor publishing standard and non-standard proprietary services on the same port. Any standard service URI will start with this string. Any non-standard service's URI must not start with this string. |
v1.0 | The version of the protocol being used by this service. This may be updated to support services with different protocol versions in future versions of the specification and allows support for multiple versions of the specification on the same machine and endpoint. Note that most future changes to the XFS4IoT specification will be done in a non-breaking, backwards and forwards compatible way. For example, optional fields will be added to JSON messages when required and will have no impact on the protocol. This means that changes to the version field of the URI will be very rare. It will only be changed if there is a breaking, incompatible change or a fundamental change to the API. Because of this there won't be any need for complex version negotiation between the client and the service. The client will simply attempt to open the version of the API that it supports. |
servicename | This will be included in the URI to allow different services to be identified on the same port. Services will normally match individual devices. The exact service name is discovered during service discovery and is vendor dependent. The format of the service name shouldn't be assumed. The only URI that doesn't include a service name is the service discovery URI. |
For example, a service discovery URI might be:
- wss://terminal321.atmnetwork.corporatenet:443/xfs4iot/v1.0
- wss://192.168.21.43:5848/xfs4iot/v1.0
Service URI might be:
- wss://terminal321.atmnetwork.corporatenet:443/xfs4iot/v1.0/maincashdispenser
- wss://192.168.21.43:5848/xfs4iot/v1.0/cardreader1
The URI will be case sensitive and lower case.
2.2.2.2 - Network Protocol
The WebSocket protocol defines two URI schemes, wss and ws that are used for encrypted and unencrypted connections. All connections in XFS4IoT should use the wss scheme using TLS encryption to secure network connections. The only exception will be when the network connection between the client and service can be physically secured, for example inside an ATM enclosure. In that case it will be possible to use clear communication without TLS encryption and it is the responsibility of the hardware vendor to ensure that this is sufficient.
- Encrypted connections are identified by the wss:// protocol specifier.
- Unencrypted connections are identified by the ws:// protocol specifier.
Where TLS is used, the service will be protected by a mutually trusted server side certificate as part of the TLS protocol. This complete certificate chain must be mutually trusted by the client and service.
Establishing and managing the certificates between the service and the client is outside of the scope of this specification but trust must be in place. This might be achieved using a public third party certificate authority that issues TLS certificates. Alternatively it might be achieved using a bank's own internal CA. It shouldn't depend on a private Certificate Authority or certificates issued by a vendor, which might limit access to the service.
A wss connection with invalid certificates will be invalid and will be rejected by both the client and the service.
2.2.2.3 - Machine Identification
Machines publishing services are identified by URIs. Machines exposing endpoints can be identified by an IP address or by a DNS name.
Either the IP address or DNS name for a machine must be known by the client for the client to connect. This would probably be a configuration setting for the application and would need to be known by the organization setting up the application, but this configuration is outside the scope of this document.
2.2.2.4 - Port Sequence
Services will be published on a sequence of IP ports consisting of port 80 or 443 followed by the ports 5846 to 5856 inclusive. Hence the full sequence of ports will be 12 ports as,
80 or 443, 5846, 5847, 5848, ... 5855, 5856
Port 80 will only be used with HTTP/WS. Port 443 will only be used with HTTPS/WSS. All other ports may be used with either or both HTTP/WS and HTTPS/WSS.
Port 80 and 443 are the standard ports for HTTP and HTTPS and have the advantage that they are likely to be open on firewalls. The correct port will be used to match the protocol - 80 for HTTP/WS and 443 for HTTPS/WSS. Other ports are flexible and can be used for either protocol by the Service Publisher.
The port range 5846-5856 is semi-randomly selected in the 'user' range of the port space as defined by ICANN/IANA. This range is currently unassigned by IANA.
2.2.3 - Service Publishing
Service publishers will negotiate access to resources and publish services using the following process.
2.2.3.1 - Free Endpoint Port Discovery
On startup each service publisher must attempt to connect to the first port in the port sequence. It will use the underlying OS and network stack to attempt to bind to this port.
All network access must go through the normal underlying OS mechanism. One service publisher must not block another publisher from accessing the network.
If the underlying OS reports that the port is already in use the service publisher will repeat the same process with the next port in the port sequence. This will be repeated until a port is successfully bound to, or all ports in the sequence have been tried.
If no available port can be found the service publisher will have failed to start. How this failure is handled by the service publisher is undefined.
It's important that a single hardware vendor doesn't use up multiple ports, since this could lead to all the ports being blocked so that other publishers can't get a free port. Therefore any single hardware vendor must publish all services on a single port, determined dynamically as above.
Note: A service publisher will only fail to find a free port if more than 12 different hardware vendors are attempting to publish services from the same machine. This should be unusual.
2.2.3.2 - Handling Incoming Connections
Once a service publisher has successfully bound to a port it must handle connection attempts. It will accept all connections from any clients without filtering attempts. Security around connections will be handled after a connection has been established.
Note: This document does not cover restrictions on connections to services or managing permissions for connections, such as limiting connections to certain machines or sub-nets. This would normally be under the control of the machine deployer and can be controlled through normal firewall settings and network configuration.
Incoming connection attempts will specify a specific URI using the normal WebSocket process. The service publisher will allow connections to valid URIs as defined in this spec and track which URI each connection was made to.
The initial connection will be to the URI wss://machinename:port/xfs4iot/v1.0
. This connection will then be used to
list/discover individual services using the process outlined in
Service Endpoint Discovery.
2.2.4 - Service Discovery
A client application must be able to discover and open a connection to each service that it will use. It does this in two steps; firstly, through publisher endpoint discovery, then through service discovery for each service endpoint. It will do this through the following process.
2.2.4.1 - Publisher Endpoint Discovery
The client will enumerate endpoints by attempting to open a WebSocket connection to the following URL on each port in the Port sequence.
wss://machinename:portnumber/xfs4iot/v1.0
The client will continue to enumerate publisher endpoints by repeating for each port number in the port sequence until all ports have been tried.
The client will also start service endpoint discovery on the open connection. There is no requirement for the order of opening ports and discovering services. All ports connections may be created first followed by service discovery, or port enumeration and service discovery may continue in parallel.
If the connection attempt to any port fails then the application will attempt error handling for network issues, machine powered off, etc. The details of error handling are left up to the client.
2.2.4.2 - Service Endpoint Discovery
Once a connection has been established between the client and each publisher endpoint, the client will discover the services published by sending a service discovery command and receiving messages in the usual way as described in Message Types.
The only command sent to the publisher endpoint will be ServicePublisher.GetServices.
The publisher will acknowledge the command.
The command will be followed by zero or more ServicePublisher.ServiceDetailEvent messages, then complete with a completion message. Each event and the completion message will contain the following payload:
{
"payload": {
"vendorName": "<Name of hardware/software vendor>",
"services": [
{
"serviceURI": "wss://machinename:port/xfs4iot/v1.0/<servicename1>"
},
{
"serviceURI": "wss://machinename:port/xfs4iot/v1.0/<servicename2>"
}
]
}
}
The service endpoint URI will be returned as a serviceURI property.
A publisher service may be designed to send one URI per message, or it may group URI together into a smaller number of messages. The publisher should try and send messages to report on each URI as soon as each URI is known. It's possible a publisher will know the complete set of URI when they're requested and can send them all at once in one or more messages. Alternatively, the URI may not be known straight away, for example if an IP address or port is being dynamically allocated. In that case the publisher service would delay sending events for unknown URI until the full URI is known.
Having each URI reported only once means that a client can connect to each URI reported in events without having to track which URI have already been connected to. This simplifies the client. Alternatively, a client may wait for the completion message and a full set of URI before attempting to connect. This would be simpler to implement but might be slower to start up.
The completion message will contain every URI that the publisher service is aware of.
The publisher service will follow the above process to publish all URI that it's aware of. It will not suppress URI based on device status or service status.
For example, a device might be powered off, in the process of powering on, or powered on but have a hardware fault that makes it impossible to use. In all cases the publisher service will publish the URI anyway. The client can't assume anything about the device based on the URI. It will always need to query the service at the URI for its status to know more.
Events should be sent as soon as a URI is known by the publisher - the event doesn't mean or imply that the URI is currently available or can be connected to - that error handling must be performed by the client.
Note: Even if the publisher service could know that a URI was valid at the time that it sends the event, the client can't know that the URI is still valid when it attempts to use the URI. It could have failed between querying and connecting. So the client has to handle errors, timeouts and retrying when connecting to the URI.
The client may then attempt to open a WebSocket connection to each of the returned URI. The client will handle connection failures and timeouts by repeating the attempts to connect such that the service has a reasonable amount of time to start up.
Each service will endeavor to accept connections as quickly as possible during startup and restarts. Some devices are physically slow to start up, but software should be able to start relatively quickly. So, for example, a cash recycler device might be able to accept a connection within a few seconds of power being applied, but the physical hardware can take several minutes to reset. Once a connection has been accepted a service may continue to report device as starting until the device is physically started and ready. While starting, any command on the connection other than Common.Status will fail with sequenceError.
Each connection will be used to communicate with a single service. The service will then be queried for details about that service, such as the type of service or device that it represents and the messages and interfaces that it supports.
The connection to the service will be kept open for as long as the service is in use. Details of the service lifetime are covered elsewhere.
The returned URI is a full URI including the machine name and port. It is possible that these values will be different to the service discovery URI - each service may be on a different machine, a different IP address, and a different port. The port is also independent of the discovery port range. It can be any port number.
The service URI values will have the same version number as the service discovery URI version number. Different versions of the API will not be mixed.
If a client wants to open multiple different API version numbers then it should perform service discovery against each of the possible version URI strings.
The client may close the publisher connection once it has completed service discovery, or it may keep the connection open. This will have no effect on the behavior of services.
2.3 - Messages
XFS4IoT Services are accessed using messages passed over a WebSocket Interface. The messages are JSON formatted data Ref. api-1 defined using JSON Schema 2020-12 Ref. api-4.
2.3.2 - Header Definition
The headers contains properties common to all messages as well as properties specific to a message type.
Additional properties are not allowed.
Property | Property Type | Required |
---|---|---|
type | string | ✓ |
name | string | ✓ |
version | string | ✓ |
requestId | integer | |
timeout | integer | |
status | string, null | |
completionCode | string, null | |
errorDescription | string, null |
The following example illustrates the header for a Common.Status command message.
{
"header": {
"type": "command",
"name": "Common.Status",
"version": "1.0",
"requestId": 12345,
"timeout": 1000
}
}
2.3.2.4 - requestId Property
Unique request identifier supplied by the client used to correlate the command message with acknowledge, event and completion messages. The client will supply values that are positive, incremental and greater than or equal to 0. The service will check that the requestId does not conflict with a currently executing or queued command request from the same client and return status invalidRequestID if it does.
Unsolicited messages do not have a requestId.
2.3.2.5 - timeout Property
This property is only applicable to command messages.
Timeout in milliseconds for the command to complete. If set to 0, the command will not timeout but can be canceled.
Default: 0
2.3.2.6 - status Property
This property is only applicable to acknowledge messages.
If null the command has been accepted for execution and will complete with a completion message. Otherwise this property can be one of the following values:
invalidMessage
- The JSON in the message is invalid and can't be parsed.invalidRequestID
- The request ID on the command is invalid. This could be because the value is not an integer, has a zero value, or because a command with the same request ID from the same client is already queued or is executing.tooManyRequests
- The service has currently received and queued more requests than it can process.
Default: null
2.3.2.7 - completionCode Property
This property is only applicable to completion messages.
If null the command completed successfully. Otherwise, the property will contain one of the following values:
commandErrorCode
- Check the errorCode property for the command specific error code.canceled
- Canceled using the Common.Cancel command.timeOut
- Timed out after the client specified timeout.deviceNotReady
- The device is not ready or timed out.hardwareError
- An error occurred on the device.internalError
- An internal inconsistency or other unexpected error occurred.invalidCommand
- The command is not supported by the service.invalidRequestID
- The requestId is invalid.unsupportedCommand
- The command is valid for the interface, but is not supported by the service or device.invalidData
- The command message contains invalid data.userError
- The user is preventing proper operation of the device.unsupportedData
- The command message contains data that is valid for the interface command, but is not supported by the service or device.fraudAttempt
- The user is attempting a fraudulent act on the device.sequenceError
- The command request is not valid at this time or in the device's current state.authorizationRequired
- The command request cannot be performed because it requires authorization.noCommandNonce
- The value of the nonce stored in the hardware was cleared, for example by a power failure.invalidToken
- The security token is invalid.invalidTokenNonce
- The value of the nonce in the security token does not match the stored value.invalidTokenHMAC
- The value of the HMAC in the security token is incorrect.invalidTokenFormat
- The token format version value is not recognized, or the token format is somehow invalid.invalidTokenKeyNoValue
- The key used for the HMAC for a token has not been loaded and the token cannot be validated.notEnoughSpace
- There is not enough space on the storage.
If the value is commandErrorCode, the payload errorCode property contains the command specific completion error code.
Default: null
2.3.2.8 - errorDescription Property
This property is only applicable to completion messages for which the completionCode value is neither canceled or timeOut.
If not null, this contains additional vendor dependent information to assist with problem resolution. The format of this string should not be relied on.
Default: null
2.3.3 - Payload Definition
The XFS4IoT interface specifications detail the payload content for the command, event, completion and unsolicited messages.
If not null, the payload cannot be empty. It must contain at least one property.
2.3.3.1 - Additional Properties
It is possible to include additional properties not defined by the specification. This can be useful in some cases and is allowed as long as those additional properties do not impact the proper functioning of the service or client.
For example, it may be useful to include properties with extra debugging information such as human readable error messages or hardware specific error codes.
Any additional property not defined by this specification and not recognized by the Service or the Client will be ignored.
Ignoring an unknown property will have no effect on the standard behavior of the service or client. There will be no requirement to use undefined additional properties.
The service or client may use undefined additional properties for whatever purpose they require. Dependance on undefined additional properties will mean the client or service is non-standard and may impact interoperability.
When non-standard properties are used there is a risk that the same name could be used by different implementations, causing unexpected behaviors. Implementors should reduce the risk of this name clash by using a company name or code as a prefix for the property name. For example, a company called "Acme" might add the "acmeHardwareError" and "acmeLogMessage" properties.
2.4 - Message Types
XFS4IoT supports the following message types.
type | Direction | Description |
---|---|---|
command | client to Service | Message sent to the Service to perform a command. |
acknowledge | Service to client | Message from the Service indicating if the command is valid and queued. |
event | Service to client | Intermediate message from the Service indicating progress of the command. |
completion | Service to client | Message from the Service indicating the command is complete. |
unsolicited | Service to client | Message from the Service unrelated to a command. |
2.4.1 - Command Messages
The start of a command will be initiated by the client with a command message, requesting the service performs the specified action. The message uses the standard header properties with type set to command.
The requestId is given by the client and allows the client to link messages sent in response to the command back to the original command. For example, the completion message for this command will contain the same requestId.
The requestId must be greater than or equal to 1 and incremented between each command, 0 is reserved for unsolicited events. The client is responsible for ensuring that each requestId is unique for a single connection. They do not have to be unique across connections. The request is identified by a combination of the requestId and the connection.
The Service will remember the last requestId and reject any requestId for a new command which is lower or equal to the previous requestId. Other than that the service will not track the requestId.
Examples of commands with payloads are shown in the example sequence.
2.4.2 - Acknowledge Messages
As soon as the service has received and parsed the command message it will send an acknowledge message to indicate that the command message has been received and queued. This will normally include the requestId so that the client can identify which command it relates to (unless an error occurs which prevents the requestId being included). The message uses the standard header properties with type set to acknowledge.
Sending the acknowledge message immediately allows the client to handle network errors and lost messages more quickly. It can set a short timeout and expect to receive the acknowledge within that timeout, and continue with error handling if it does not.
Receiving the acknowledge message does not give any guarantees about what the service will do with the command, or even that it can be executed. Any errors will be reported in the completion message for the command, not in the acknowledge.
If for any reason the service does not accept and queue the command request, the acknowledge message header status property will indicate the reason. When this occurs, the acknowledge message is the final message related to the command request.
Examples of acknowledge messages are shown in the example sequence.
2.4.3 - Event Messages
During the processing of the command the service can send multiple solicited events, as defined in the interface chapters. This is used to inform the client when something significant happens that it may need to react to, like a card being inserted or a key being pressed.
Each solicited event will contain the original requestId in the header, and will only be sent on the connection that the original command was received on, so that individual solicited events can be linked to the original command by the client.
For compatibility with future specification changes, and to permit custom extensions by service implementors, the client should ignore any events that it does not recognize.
Examples of event messages are shown in the example sequence.
2.4.4 - Completion Messages
If a command is accepted, there will be one completion message. If an acknowledge message with an error code is returned to the command message then the command will not be executed, and no completion message will be sent.
The message uses the standard header properties with type set to completion. The completion message will contain the requestId from the original command message, so that the client can link the message back to the command. After the completion message for a command has been sent with a particular requestId, no more messages will be sent with that requestId.
Each completion message will contain as much information as possible to avoid requiring extra events. For example, when a command is used to fetch information from the Service then the information will be included in the completion message. When a command results in particular information, like reading a card, then that information is included in the completion message. The exact information included in each completion message is defined in the interface document that defines that completion message.
Examples of completion messages are shown in the example sequence.
After a command message has been received and associated acknowledge sent, the completion code, either success or an error code, will be included in the completion message for that command. The interface chapter may define command specific error codes that are valid for each completion message. No other error codes will be returned by the service for the completion message.
The completion message payload completionCode property contains one of the values defined in Completion Codes.
When an error occurs, optional vendor specific information may be included in the errorDescription property.
2.4.5 - Unsolicited Event Messages
The Service will also send unsolicited events to the client to signal events that can happen at any time, independent of command handling. These can happen before, during, or after any command handling. The message uses the standard header properties with type set to unsolicited.
To allow clients to react to events quickly, unsolicited messages should be sent as soon as possible. For example, it should avoid queuing events until after the current command has been processed if it does not have to.
Since unsolicited events are not linked to command handling, they do not have a matching requestId. The event header will contain a requestId of 0. Unsolicited events are also broadcast to all clients, on all open connections.
Each interface chapter defines the unsolicited events relevant to the interface.
For compatibility with future specification changes, and to permit custom extensions by service implementors, the client should ignore any events that it does not recognize.
Examples of unsolicited messages are shown in the example sequence.
2.5 - Command Processing
Once a service has been discovered (see Service Endpoint Discovery) and a connection created the client can send command messages to the service. Commands may cause the service to perform actions that are entirely software based, such as returning the current status, or they may cause actions to be performed by hardware, such as opening a shutter.
The sequence of messages passed between the service and the client is the same for all commands, independent of the command or interface being used.
Services may also send unsolicited events directly to the client. This can happen at any time that the service connection is open. This could be during the processing of a command, or between commands.
The following sections provide information on various topics related to command processing:
- Standard command processing flow
- Command queuing
- Commands cancellation
- Example flow
2.5.1 - Standard Sequence
The normal command message sequence will be as follows, note this example has multiple solicited and unsolicited events:
All parts will be passed as standard messages as defined in the Messages section.
2.5.2 - Command Queuing
Some commands can be executed in parallel. For example, a status command that returns the current status can always be executed immediately even if another long running command is being executed. Other commands may be blocked from parallel execution by mechanical or other restraints. For example, it's probably impossible to accept a card and capture a card at the same time on most card readers.
As far as possible, services will attempt to execute commands in parallel. In particular, all commands that simply return information should be executed immediately even if other commands are in progress. It is up to the client to synchronize status information with ongoing actions.
When it's not possible to execute a command immediately then commands will be queued and executed as soon as possible.
The acknowledge message is always sent before the command is queued.
Queued commands will normally be dequeued and executed in the order received. It is valid to execute queued commands in a different order to that received.
If the condition that caused a command to be queued clears, the command nearest the front of the queue that is blocked by that condition will be dequeued and executed ahead of any other commands nearer the front of the queue.
For example, if while idle, an Encrypting Pin Pad service receives the following command requests in the order listed:
The Service executes in parallel the Keyboard.DataEntry and Crypto.CryptoData commands as one uses the Pin Pad and the other uses the encryptor. The Keyboard.PinEntry and Crypto.Digest commands are added to the queue in that order. If the Crypto.CryptoData command completes before the Keyboard.DataEntry command, the service will execute the Crypto.Digest command as the encryptor is available while keeping the Keyboard.PinEntry command on the queue as the Pin Pad is still in use by the Keyboard.DataEntry command.
The order of execution would therefore be:
- Keyboard.DataEntry
- Crypto.CryptoData
- Crypto.Digest
- Keyboard.PinEntry
2.5.3 - Cancelation
A client can use the Common.Cancel command to attempt cancelation of one, multiple or all queued or executing commands at any time.
The Common.Cancel command adheres to the standard command message flow. That is, the Client must assign it a unique requestId when sending the command message, and the service will send both acknowledge and completion messages using that requestId. The Service will not send any event messages related to the Common.Cancel command requestId.
The Common.Cancel command can only be used to cancel requests associated with the client connection on which the command is sent. That is, one client cannot cancel another client's requests.
The Common.Cancel command itself cannot be canceled. Similarly, a requestId that does not match a queued or executing command requestId will have no effect.
The Common.Cancel will complete immediately. It will not wait until the completion messages of the specified request(s) have been sent.
Completion of the Common.Cancel command does not imply when the commands requested to cancel will complete. Nor does it imply those commands will be canceled and complete with completionCode of canceled.
Clients should expect that, at some future point, commands may complete with a completionCode other than canceled. For example, device state prevents the command canceling forcing it to complete as if no cancel request had been received.
The Service will always cancel queued commands which have not started executing.
The Service must send completion messages, for any command requests being canceled, after the completion message for the Common.Cancel command has been sent.
The Client should not attempt to cancel any one requestId more than once as it is the responsibility of the Service to maintain the cancel requested state of a command until the command completes. Sending multiple requests to cancel the same command will have no effect.
2.6 - Message Versions
All messages types are assigned version numbers to enable evolution of individual messages. The major version number of a completion message will always be the same as the major version number of the command message it is associated with, however, the minor version numbers can be different.
If a new version of a command message has a property which has an associated capability property, the service must implement, at a minimum, the version of the Common.Capabilities command that includes the associated capability property. This will allow the client to decide whether to use the command message property and the value it should be set to.
Each release of the specification defines the message version numbers of the command, acknowledge, event, completion and unsolicited messages included in that release of the specification. The specification number is different from the message version numbers. If a message definition does not change from one release of the specification to the next, the message version number will remain the same.
2.6.1 - Version Numbers
Message version numbers have the form X.Y where X and Y are non-negative integers, and do not contain leading zeroes. X is the major version and Y is the minor version. The major and minor version numbers are incremented according to the scope of change described in the following sections.
The major version must be greater than 0. If a minor change is made, the minor version is incremented and the major version remains the same. If a major change is made, the major version is incremented and the minor version is reset to 0. For example, 1.1 -> 1.2 -> ... -> 1.10 -> 2.0.
2.6.1.1 - Major Version Numbers
Major version X (X.y) numbers will be incremented in the specification if any backwards incompatible changes are introduced to the command, event, unsolicited or completion messages. It may also include minor level changes.
Major version increments represent a new command, event or unsolicited message. While there will likely be similarities with the previous major version, this is not guaranteed. It is anticipated that given the flexibility of JSON, major version increments will rarely be required.
Major version increments allow:
- Removal of command message properties.
- Change of definition of command message properties.
- Change of definition of completion message properties.
- Change of definition of event message properties.
- New event messages which cannot be ignored by the client.
2.6.1.2 - Minor Version Numbers
Minor version Y (x.Y) numbers will be incremented in the specification if new, backwards compatible functionality is introduced to the command, event, completion or unsolicited message. It will also be incremented if any message property is marked as deprecated. It may be incremented if substantial new functionality or improvements are introduced where backwards compatibility is maintained.
Minor version increments allow:
- Additional command message properties.
- Additional completion, event and unsolicited message properties.
- New event messages which can be ignored by the client.
Additional command message properties must be optional. If omitted, the command behavior must be as defined in minor version 0 of the major version of the command message. If included, additional properties may change the behavior of the command. Clients that included additional command message properties that change behavior should therefore handle these behavioral changes.
For additional completion, event and unsolicited message properties, clients should expect that new properties may be added and if not required, ignored. That is, clients should not break because they do not recognize additional properties.
2.6.2 - Version Number Selection
Version number selection occurs after a client connection has been established with the service. By default, the service will for each client connection, use the lowest available major version of each message it supports.
The client is responsible for determining version compatibility. If compatible, the client must inform the service of its version requirements. If incompatible, the client must handle the incompatibilities, possibly by not using incompatible commands. If the client cannot handle the incompatibilities then it should close the connection and not use the service.
The following sequence demonstrates use of the Common.Capabilities command to identify the command and event (both event and unsolicited) versions supported by the service, and the client use of the Common.SetVersions command to inform the service of the versions that should be used for the connection on which the command is sent.
2.6.3 - Version Evolution Example
The following table depicts an example evolution of a command, an event and an unsolicited event.
Evolution | command | event | completion | unsolicited |
---|---|---|---|---|
Initial | 1.0 propA |
1.0 propA |
1.0 propA |
1.0 propA |
Minor update - command property added - completion unchanged |
1.1 propA propB |
1.0 propA |
1.0 propA |
1.0 propA |
Minor update - event property added |
1.1 propA propB |
1.1 propA propB |
1.0 propA |
1.0 propA |
Major update - completion property removed - command unchanged - unsolicited property removed - unsolicited property added |
2.0 propA propB |
1.1 propA propB |
2.0 propB |
2.0 propB |
2.6.4 - Extending Enumeration Values
Extending an enumeration value is a breaking change as existing clients will not be coded to handle the new enumeration value. A breaking change to a message requires the message major version number be incremented.
Where possible the specification will avoid breaking changes. To support this, if the additional enumeration value is related to an existing enumeration value:
-
An additional property with name originalNameX will be added to the message definition, where originalName is the original name of the property and X is the next available index. Indices will be non-negative integers and start at 2.
-
The message minor version number will be incremented. This indicates the change is backwards compatible.
-
The original property definition will be set as deprecated indicating it may be removed in a subsequent major revision of the message.
-
Service implementations which implement the message version that defines the additional property will, if the original property is required, always include both originalName and originalNameX properties.
Existing clients will be unaffected by the additional property as the original property will still be included in the message. New or updated clients can be written to use any of the previous related properties. If a client does not have a use for a new enumeration value, it can continue to use one of the previously defined related properties.
For example, if version 1.0 of a message defines a device property with enumeration values:
- online, offline, hardwareError, userError
And a new enumeration value:
- fraudAttempt
Is added which relates to the existing, less specific, userError value, the new enumeration value could be added to the device2 property in minor increment version 1.1 of the message. In this case when reporting the new enumeration value, version 1.1 of the message will include both:
{
"device": "userError",
"device2": "fraudAttempt"
}
2.7 - End to End Security
A key priority for XFS4IoT is to improve security of the entire environment where XFS is used. This means securing not only the interface between the service and the device, or the interface between the client and the service, but providing security all the way from one end of an operation to the other.
For example, during a cash dispense operation, the transaction will first be authorized by an authorizing host which represents the owner of the cash in the device. That host will communicate through various other systems to the client application, the client application will communicate with the XFS4IoT service and the service will finally communicate with the device. Any part of that process is vulnerable to an attack which could lead to the wrong amount of cash being dispensed. XFS4IoT has been designed to block attacks at any point between the authorizing host and the dispenser hardware.
Details of end-to-end (E2E) security are covered in the generic E2E security specification [Ref. api-2] shared between XFS3.x and XFS4IoT. Generic and specific E2E tokens are defined in that specification. The tokens are passed to commands and returned in events which are documented in this specification, such as with CashDispenser.Dispense
There are specific commands to support E2E security which are covered by this specification, including Common.GetCommandNonce and Common.ClearCommandNonce
Not all commands that could require E2E security are currently covered. When E2E security is being enforced by a device, sensitive commands with no token defined will be blocked from executing. This is required to avoid any way of bypassing security. For example, the cash CashDispenser.Dispense command has a token format defined but the CashDispenser.TestCashUnits command does not. For security, CashDispenser. TestCashUnits must be blocked from dispensing cash, otherwise an attacker could simply replace the CashDispenser. Dispense with calls to CashDispenser.TestCashUnits. Restrictions are documented for each affected command.
3 - Service Publisher Interface
This chapter defines the Service Publisher interface functionality and messages.
3.1 - Command Messages
3.1.1 - ServicePublisher.GetServices
Command sent to the service discovery port to identify services exposed by this publisher.
This command can be used while in Vendor Mode.
Command Message
Payload (version 2.0) |
---|
This message does not define any properties. |
Completion Message
Event Messages
4 - Common Interface
This chapter defines the Common interface functionality and messages.
4.1 - Command Messages
4.1.1 - Common.Status
This command is used to obtain the overall status of the Service. The status includes common status information and can include zero or more interface specific status objects, depending on the interfaces the Service supports. It may also return vendor-specific status information.
This command can be used while in Vendor Mode.
Command Message
Payload (version 2.0) |
---|
This message does not define any properties. |
Completion Message
Event Messages
None4.1.2 - Common.Capabilities
This command retrieves the capabilities of the service. It may also return vendor specific capability information.
This command can be used while in Vendor Mode.
Command Message
Payload (version 2.0) |
---|
This message does not define any properties. |