Network Protocol
Network Protocol
Revision history
Version Issue date Author Notes
Summary
1 INTRODUCTION.......................................................................................................................................................... 4
Objective
This document explains how VSAM sends transaction data for the server and also how VLIB synchronizes the
unified list.
1 Introduction
The VSAM chip is a security module with several technologies inside. For public transport its main use is to
guarantee security and cryptographic performance of contactless payments. It can be used to enhance closed-
loop solutions security, allow EMV transactions, ABT and QrCode payments.
The VLIB is a terminal resident software library developed by Planeta for both new or existing close-loop
applications to support additional transactions such as EMV, or QR-code. VLIB is written in C and works on
GNU/Linux, Windows, and Android. It can be also ported to other systems by implementing an OS adaptation
layer.
When VSAM is activated to do a transaction by VLIB it will use the command multiplexer to send several types
of requests to the validator, among them are contactless APDU commands, deny list check and transaction
data for server clearing. This document describes the protocol that VSAM uses for sending this data out and
what type of answer it expects. The data is sent in binary to reduce package length and due to APDU length
constraints. VLIB also uses the same protocol to synchronize data with the server, this is related to updating
the lists and configuration files. The protocol data can then be encapsulated into other application level
protocols like HTTP as detailed later at this document.
The transmission type is related to the way the request data is encoded, it is followed by the command type.
The transmission type values are characters defined as:
‘A’ = Plain data transmission: The request data is the final data and no changes were made to it.
‘D’ = Encrypted data transmission: The request data is encrypted using AES with a 128-bit key
configured in the VSAM/VLIB, the server must known this key to decrypt and use the data. Only the
request data is encrypted, the transmission type and command type are always plain. Since AES is
used the request data is always rounded to 16 bytes with zeros.
‘0’ = TRANSACTION SUBMISSION: A completed EMV transaction with Offline Data Authentication
(ODA) check. The operation may have finished either in success or error to be stored in the server and
in successful cases can be used for clearing. Used on both async and synchronous transactions.
Code: MOP Network Command Protocol
‘1’ = LISTS/TABLES UPDATE: Request used by VLIB to update its list and configuration files.
‘2’ = Safe deposit request: Similar to request ‘0’ only sent on successful transactions and always
synchronous. Used by the server to request a money reserve from the issuer.
‘3’ = QR Code use: Sent with QR code data so the server can check for valid information.
‘4’ = SUPER TAP: A synchronous operation used to recover debts of user on public transport
operations. This feature is disabled by default.
‘5’ = SUPER AVR: A synchronous operation used on public transport operations when the passenger is
using the system for the first time. This operation does an account verification check (AVR) at the
issuer to identify if the card is valid. This feature is disabled by default.
‘6’ = ONLINE NON-ODA CARDS: Similar to ‘0’ but for cards that don’t support the Offline Data
Authentication (ODA). These types of cards can’t be used on public transport since they are essentially
online only. This operation is only used for retail operations.
‘7’ = COMBO FIRST TRANSACTION: Used on sync operations when the transaction was configured to
read more than one application from the EMV card. For example a card that has both debit and credit
applications will have both data read and the first (determined by the card priority indicator) will be
sent for the server for clearing. If it fails the next application will be sent as command type ‘8’.
‘8’ = COMBO FINAL TRANSACTION: When the command ‘7’ fails and there is another application to try
clearing VLIB will use command ‘8’.
‘9’ = LOG ONLY TRANSACTION: This command happens when COMBO is being used and the there are
2 applications and the first operation with command ‘7’ worked with success, so instead of sending the
second operation with code ‘8’ the code ‘9’ is used just so the server can log the transaction but never
attempt to clear it.
‘A’ = VDT TICKET: Similar to ‘0’ but the EMV media has a VDT (Visa Digital Ticketing) ticket so tag 9F6A
will be present in the request data together with other EMV tags.
‘B’ = ABT TRANSACTION: A transaction that identifies a previously registered account in the server
side, can be used in both sync and async modes.
When the transaction is configured in the VSAM to use TEST mode the command type used in the process for
the transaction command will be different. So the server don’t interpret it as a real transaction. This also forces
specific code in the server to deal with this transactions ensuring that they will never be treated as a real
production transaction. For example, instead of receiving the command and type “A0” the server will receive
“AV”. Or instead of “D6” it will be “Db”.
The following table shows the above codes with their respective test counterpart. The values are show in char
and hexadecimal. See Appendix C – Test operation conversion for source code to convert this table.
‘0’ ‘1’ ‘2’ ‘3’ ‘4’ ‘5’ ‘6’ ‘7’ ‘8’ ‘9’ ‘A’ ‘B’
0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x41 0x42
‘V’ ‘W’ ‘X’ ‘Y’ ‘Z’ ‘a’ ‘b’ ‘c’ ‘d’ ‘e’ ‘f’ ‘g’
Code: MOP Network Command Protocol
0x56 0x57 0x58 0x59 0x5A 0x61 0x62 0x63 0x64 0x65 0x66 0x67
More detailed information about the requests are present in the following chapters.
Responses are prefixed by two bytes that define the size of the data in little endian. The size is followed by the
response data. Example of response:
10 00 81 00 FF 6D 51 72 32 4A 81 00 00 00 74 C1 1E C8
In this example the first 2 bytes are “10 00”, so 16 bytes. The maximum packet size would be “FFFF” or 65.535
bytes. Although the protocol allows there is no response messages smaller than 16 bytes.
Code: MOP Network Command Protocol
The transaction data format is formed by a 16 bytes token followed by 16 bytes of PAN HASH and the tag data.
The transaction token is unique on the system, its 16 bytes represent the following fields:
struct TRANSACTION_TOKEN
{
unsigned char ATC_SAM[3];
unsigned char UID_SAM[5];
unsigned char DATE_TIME[4];
unsigned char CRC[4];
};
ATC_SAM: A transaction counter in little endian format, if the byte[2] is 0xFF than the transaction
finished in error and the error is defined by byte[0]. For example: 0800FF means “transaction finished
in error 0x08”. The last good transaction counter number is FFFFFE which is the number 16,711,679.
DATE_TIME: A compressed format for date and time represented in 32 bits, explanation at chapter
2.2.
CRC: The whole packet CRC including the transmission type and command. The CRC usage will be
described later at chapter 2.4.
The following field is the PAN HASH. If PAN HASH has more than 16 bytes the remaining part of the data will be
present in the tag 1F40 inside the tag data part.
The data is a TLV (tag length value) set of tags, the format and type is defined by the EMV standard. In general
the tag can have one or more bytes and the size is usually only one byte long but can also be expanded. To
determine if a tag is 2 bytes long the first byte will have bits lowest 5 bits set (0x1F), example:
Tag 9F33 has 2 bytes since the byte 0x9F has the bits 0x1F set.
To determine if the size has more than 1 byte the highest bit will be set (0x80). The tag 57 holds the DUKPT
encrypted data, more on that at chapter 2.3.
Code: MOP Network Command Protocol
Extra zeros may be added at the end of the tag dat to ensure a multiple of 16 bytes for when encryption is
used. When making a parser ensure that it stops at the first tag identified as value zero. Which EMV tags are
going to be used for each card brand is defined by the acquirer and set inside SAM kernel configuration.
41 30 0C 00 00 00 60 21 61 73 52 4B 33 2B F6 A6 F7 9B B5 59 02 CE 04 49 A3 34 34 FC B0 96 69 DA 33 9A 57 22 FF FF
AA AA AA 2C 2E 60 00 0C 3F C6 F1 FF 2D 24 53 5E CE 6D 6A A8 07 C7 78 FF 39 98 F6 05 10 F6 74 E2 DF 7E 05 00 00 00
00 00 5A 08 46 20 68 AA AA AA 93 78 5F 34 01 00 5F 24 03 22 02 28 9F 26 08 B7 2A 5F 95 5B 80 1F 7C 9F 27 01 80 9F
36 02 00 7B 9F 37 04 AD F2 AE 7F 9F 69 07 01 E6 E2 2F D6 28 40 9F 7C 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 82 02 20 00 9F 10 07 06 01 0A 03 A0 20 00 9F 6E 04 18 80 00 00 9F 02 06 00 00 00 00 00 00 9F 03
06 00 00 00 00 00 00 95 05 00 00 00 00 00 9A 03 21 10 20 9C 01 00 9F 1A 02 00 76 5F 2A 02 09 86 9F 39 01 07 DF 17
01 08 4F 07 A0 00 00 00 03 10 10 9F 09 02 00 02 9F 1E 08 58 43 4C 00 60 21 61 73 9F 33 03 00 08 08 9F 34 03 1F 03
02 9F 35 01 22 9F 41 04 00 00 00 12 DF 4F 11 82 9D 49 4A AE 53 9D D1 37 0E 27 17 A1 86 24 81 00 50 0B 56 49 53 41
20 43 52 45 44 49 54 00 00 00 00 00 00 00 00 00 00 00
The first byte is the transmission type, 0x41 is ‘A’. The second byte is the command type, 0x30 is ‘0’. Following
there is the 16 byte token in yellow and then the 16 byte PAN HASH in gray, after that there is all tag data
alternating colors for each TLV item. See chapter 10 for a text parsing of an EMV transaction tag data.
YYYYYYY: 7 bits to represent the year. Range 0 to 127, only used up to 99. Add 2000.
MMMM: 4 bits for the month. Range 0 to 15, only used from 0 to 11. Add one for calendar month.
DDDDD: 5 bits for month day. Range 0 to 31, only used from 0 to 30. Add 1 for calendar month day.
hhhhh: 5 bits for hour. Range 0 to 31, only used from 0 to 23.
mmmmmm: 6 bits for minutes. Range 0 to 63, only used from 0 to 59.
sssss: 5 bits for seconds. Range 0 to 31, only used from 0 to 29. The value is multiplied by 2 so there is
never an odd number of seconds.
An example of compressed date (always in little endian): 1D AD 33 2B (to convert the bytes to number use
them reversed like 0x2B33AD1D).
The function to pack / unpack the date is defined at Appendix B – Unpack VSAM date.
It is also possible to retrieve the transaction date and time if the EMV tags 9A (date) and 9F21 (time) are
enabled for the specific brand.
Code: MOP Network Command Protocol
VSAM can be configured to output the encrypted data in many different formats to support different acquirers
like BCD or ASCII for encoding and raw tag 57 contents or TLV like data with multiple tags. The first 10 bytes of
the tag will be the KSN (Key Serial Number) and the rest of the data is the encrypted data. The following
chapters shows different ways to encrypt the sensitive data from the same card.
For an example showing the steps of the DUKPT decryption see Appendix D – DUKPT operation steps. The BDK
(Base Derivation Key) for all examples below is 00112233445566778899AABBCCDDEEFF (3DES) with zeroed IV.
The value in yellow is the KSN, the rest of the value is the data. If we decrypt that using the key mentioned
above we will have:
4984536234915804D27072060000098790770FFFFFFFFFFF
The format of the EMV tag 57 is to have all data encoded in BCD with a ‘D’ separating the date from PAN. It is
possible to see the card PAN, the date in YYMM format (June 2027) and the service code 206. The remaining
data is part of the discretionary data and the padding for block size as required by the 3DES encryption.
Decrypted data with the same values highlighted previously and showing the first byte as the number of
nibbles. This mode is used when the acquirer requires the use of the complete discretionary data instead of
just the PAN and date. So it knows exactly where the data ends and padding starts.
374984536234915804D27072060000098790770FFFFFFFFF
374984536234915804D27072060000098790770FFFFFFFFF //37 nibbles painted in green
Result after decryption shows the TLV data followed by random padding. There are 3 tags: 57, 59 (date in
YYMM format) and 5A.
57134984536234915804D27072060000098790770F590227075A084984536234915804002F3A214E
Code: MOP Network Command Protocol
Another TLV example with tag 5F24 instead of 59. The difference is that 5F24 has the format YYMMDD.
57134984536234915804D27072060000098790770F5F24032707315A084984536234915804316C56
2.3.4 Multi-DUKPT
It is also able to output the same data encrypted for different acquirers. When using multi-acquirer data
generation the tag 57 will have the first configured acquirer and also there will be the tags 1F5X to represent
the DUKPT data for different acquirer formats. The tags 1F50 to 1F57 define the index of the acquirer and the
tags 1F58 to 1F5F define the data. 1F50 is the acquirer index for 1F58 data, 1F51 is for 1F59 and so on. The list
of acquirer indexes is:
For example, data where we have DUKPT for both Cielo (0x03) and Granito (0x04) aside from tag 57 for other
acquirer could look like:
1F 50 01 03 1F 58 22 FF FF AA BB CC 2C 2E 60 00 01 D8 63 78 CB 20 B4 75 F8 84 98 D3 3B 18 3D 00 AA B1 0D B2 97 80
78 BA 58 1F 51 01 04 1F 59 22 FF FF CC DD EE 2C 2E 60 00 01 43 41 1D 9A E1 00 B6 23 4F D2 61 AD 47 52 FC F2 5B 19
32 EC 1E 02 9A D2
The tag 1F50 has value 0x03 and the data is on tag 1F58, followed by tag 1F51 with value 0x04 and the tag
data on tag 1F59.
41 30 01 00 00 00 60 21 61 73 C3 53 33 2B 70 21 93 73 7D BC 05 66 B6 F6 72 8D 2F 1D D9 A5 C3 43 81 24 1F 50 01 03
1F 58 22 FF FF 98 76 54 2C 2E 60 00 01 D8 63 78 CB 20 B4 75 F8 84 98 D3 3B 18 3D 00 AA B1 0D B2 97 80 78 BA 58 1F
51 01 04 1F 59 22 FF FF F9 99 99 2C 2E 60 00 01 43 41 1D 9A E1 00 B6 23 4F D2 61 AD 47 52 FC F2 5B 19 32 EC 1E 02
9A D2 DF 7E 05 00 00 00 00 00 5A 08 46 20 68 AA AA AA 93 78 5F 34 01 00 5F 24 03 22 02 28 9F 26 08 16 44 86 0E 57
62 97 30 9F 27 01 80 9F 36 02 00 7C 9F 37 04 54 84 8C 0C 9F 69 07 01 D4 51 C1 47 28 40 9F 7C 14 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 82 02 20 00 9F 10 07 06 01 0A 03 A0 20 00 9F 6E 04 18 80 00 00 9F 02 06
00 00 00 00 00 00 9F 03 06 00 00 00 00 00 00 95 05 00 00 00 00 00 9A 03 21 10 20 9C 01 00 9F 1A 02 00 76 5F 2A 02
09 86 9F 39 01 07 DF 17 01 08 4F 07 A0 00 00 00 03 10 10 9F 09 02 00 02 9F 1E 08 58 43 4C 00 60 21 61 73 9F 33 03
00 08 08 9F 34 03 1F 03 02 9F 35 01 22 9F 41 04 00 00 00 01 DF 4F 11 83 9C 25 7B 3F E5 44 EC 02 88 3B 31 F8 73 44
4C 00 50 0B 56 49 53 41 20 43 52 45 44 49 54 00 00 00 00 00 00 00 00 00 00 00 00 00
Code: MOP Network Command Protocol
To calculate the CRC the place where the value is be filled with zeros and then calculated (packet trimmed to
reduce repetition):
41 30 01 00 00 00 60 21 61 73 C3 53 33 2B 00 00 00 00 7D BC 05 66 B6 F6 72 8D 2F 1D D9 A5 C3 43 81 24 1F 50 01 03
1F 58 22 FF FF 98 76 54 2C 2E 60 00 01 D8 63 78 CB 20 B4 75 F8 84 98 .. 44 49 54 00 00 00 00 00 00 00 00 00 00 00
00 00
The result will be 70 21 93 73, it will then be placed where we have the zeros above resulting in the final
package. Source code at Appendix A – CRC function.
Note that depending on the endianness of the hardware the output of the CRC function may have to be
reversed byte by byte to match the CRC value.
The transaction response is made of 16 bytes, there may be an additional receipt for the transaction. The
mandatory format is:
struct TRANSACTION_REPLY
{
unsigned char ATC_SAM[3];
unsigned char UID_SAM[5];
unsigned char STATUS[4];
unsigned char RFU[4];
};
The receipt data comes after this struct if it exists, there is an example late in this chapter.
The first 2 fields (ATC_SAM and UID_SAM) are a copy of the request fields. The status field has the following
bytes:
-- Success
-- Error cases
◦ 0x85: Passed OK but was on server DENY list (unsync validator list).
◦ 0x86: Denied on validator but was UNKNOWN on server (unsync validator list).
[2]: Pending list ride, used to force VLIB to request sync of lists, each bit represents one thing:
Bits not documented for STATUS bytes and RFU field must be zero.
10 00 83 00 FF 00 60 21 61 73 83 00 10 00 00 00 00 00
First 2 bytes are the size of the response in little endian format. The value “10 00” means 16 bytes. Followed
by the format described above. The status byte[0] is 0x83 (description in the list of Error Cases above) and
status byte[2] is telling VLIB to force an update of the unified list.
The format of the receipt is application defined, VLIB will only store and return it to the application on request.
Complete example of transaction response with a sample JSON receipt:
B0 00 83 00 FF 00 60 21 61 73 02 00 00 00 00 00 00 00 7B 20 22 61 75 74 68 54 79 70 65 22 3A 20 22 74 69 63 6B 65
74 22 2C 20 22 61 75 74 68 43 6F 64 65 22 3A 20 22 31 36 38 31 36 39 32 37 37 37 22 2C 20 22 74 72 61 6E 73 55 73
6E 22 3A 20 22 38 34 36 39 33 30 38 38 36 22 2C 20 22 61 63 71 75 69 72 65 72 4E 61 6D 65 22 3A 20 22 70 69 2D 73
65 72 76 65 72 22 2C 20 22 61 63 71 75 69 72 65 72 54 69 6D 65 22 3A 20 22 33 22 2C 20 22 6D 65 73 73 61 67 65 22
3A 20 22 50 53 50 3A 20 49 6E 76 61 6C 69 64 20 72 65 71 75 65 73 74 22 20 7D
In this case there are 0xB0 bytes (176), the status byte[0] is 0x02 and the receipt in ASCII will read (bytes 0x7B
and 0x7D marked):
{
Code: MOP Network Command Protocol
"authType": "ticket",
"authCode": "1681692777",
"transUsn": "846930886",
"acquirerName": "pi-server",
"acquirerTime": "3",
"message": "Transaction Success"
}
Code: MOP Network Command Protocol
3 List requests
List requests are used to fill the device side deny list. VLIB will periodically request the deny list from the server
or will force a request if the last transaction data synchronization reply requested to do so.
The list is indexed by a PAN HASH that is based in the EMV media PAN and is safe to store as it is not
reversible. During the transaction the VSAM will calculate the PAN HASH and request VLIB to check its status.
The command type will be ‘1’ as explained at chapter 1.1. VLIB will regularly request list updates, the interval is
defined in its configuration. As explained at chapter 2.5 a transaction response may also force a list update.
Request structure:
struct REQUEST_TOKEN
{
unsigned char ATC_REQ[3];
unsigned char UID_SAM[5];
unsigned char DATE_TIME[4];
unsigned char CRC[4];
};
struct LIST_REQUEST
{
unsigned char LIST_ID[2];
unsigned char TABLE_REQUEST_CONTROL[8];
};
The transaction token is the same as described in the chapter 2. The only difference is that ATC_REQ is a
sequential number set by VLIB itself and not VSAM, this number should not be used by any means on the
server side since it resets at every VLIB startup. Please check chapter 2.1 for the description of the
REQUEST_TOKEN structure.
0x1919: Config file update request. This operation may not be supported by the PSP.
The request control is a 8 byte value that is sent by the server as a pointer to the current list index. In the first
time VLIB starts and initialize an empty list it will send a zeroed value to the server. The server will then send
items and update the request control in the response. Next time VLIB contacts the server it will send the new
request control and so on until the server decides the list is synchronized but not sending any new items. This
control number has no meaning for VLIB, it will store and use whatever was sent from the server after the first
zeroed request.
01 00 00 00 60 21 61 73 1D AD 33 2B 42 D8 04 A1 18 18 F9 B6 70 61 00 00 00 00
In this example the yellow part tells the list type is 1818 and the request control is the green bytes.
Code: MOP Network Command Protocol
44 31 17 08 5E DA 89 57 46 E4 F2 CF AB AE 89 E3 25 E0 CE 5F 5B 76 EA EE 3D D6 27 5E CE 84 7E 55 E0 49
//Decrypted (starting from byte[2], transmission type and command type are skipped)
-- -- 01 00 00 00 5D 6E CF B8 A0 7C 0E 2D 24 23 08 50 18 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00
As long as there are items to synchronize VLIB will keep creating new requests until the server replies without
items. The server may reply up to 90 items with 16 bytes PAN HASH or 60 items for 32 bytes PAN HASH, when
using HTTP this limit is specified by VLIB using an specific parameter described at chapter 4.
struct PSP_LISTCFG_REPLY
{
struct REQUEST_TOKEN token; /**< The token returned with the same format from request. */
u8 NEW_REQUEST_CONTROL; /**< The request control number for next requests of the list delta. */
}
struct PSP_UNIFIED_ITEM
{
u1 ACTION; /**< 'I' to Add, 'U' to Update, 'D' to Delete. */
u1 PAN_HASH[PAN_HASH_SIZE]; /**< The PAN HASH that references an EMV media based in its PAN. */
u1 entry_id; /**< A numeric counter for the item position inside the reply. */
u1 pan_status[8]; /**< Each byte represents one application to accept or decline. */
u1 rfu2;
u1 rfu3[6];
};
Each operation can represent an item to be added/updated or removed. There is no difference between Insert
and Update in the point of view of VLIB. This is defined by the ACTION parameter and the valid values are ‘I’,
‘U’ and ‘D’.
The item can identify up to 8 different applications inside the same media. This was developed to countries
where the same EMV media has multiple applications for the same brand, for example cards that have both
debit and credit features at the same time. The order of applications come from the media itself, so if the first
application defined by the card priority is debit this will be represented by the pan_status[0]. This is the list of
possible status:
0x00 – Unknown. When this state is used the VSAM will authorize the transaction unless Super AVR is
enabled. When Super AVR is enabled a synchronous online attempt will be made to check the card at
the PSP. This is the default state used if the PAN HASH is not registered in the list.
0x01 – OK. This means the media is fine and must be accepted.
Code: MOP Network Command Protocol
0x02 – Temporary deny. In this state VSAM will deny the card unless Super TAP is enabled. When
Super TAP is enabled a synchronous online attempt will be made so the server can recover a previous
debit that is currently pending for this card.
If the target country for the operation does not have cards with support for multiple applications only the first
position of the pan_status will be used.
This is an example of 2 calls to synchronize 15 items, first 10 and them more 5 items, the PAN HASH is 16 bytes
long. First request with zero request control code:
41 31 01 00 00 00 5D 6E CF B8 77 91 0F 2D B5 44 BE F9 18 18 00 00 00 00 00 00 00 00
Server returns the new request control and 10 items, the new request control is marked in yellow. All items
are marked as ‘I’. The first entry has pan_status 0x00 while the second one has status 0x03. The packet size is
62 01 which is 0x162 from little endian so 354 bytes.
62 01 01 00 00 00 5D 6E CF B8 00 00 00 00 07 F2 9E F5 00 00 00 00 00 00 00 01 49 01 00 00 00 00 00 00 00 C4 C4 C4
C4 C4 C4 C4 C4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 02 00 00 00 00 00 00 00 C4 C4 C4 C4 C4 C4 C4 C4
00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 03 00 00 00 00 00 00 00 C4 C4 C4 C4 C4 C4 C4 C4 00 03 00 00 00
00 00 00 00 00 00 00 00 00 00 00 49 04 00 00 00 00 00 00 00 C4 C4 C4 C4 C4 C4 C4 C4 00 02 00 00 00 00 00 00 00 00
00 00 00 00 00 00 49 05 00 00 00 00 00 00 00 C4 C4 C4 C4 C4 C4 C4 C4 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00
00 49 06 00 00 00 00 00 00 00 C4 C4 C4 C4 C4 C4 C4 C4 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 07 00 00
00 00 00 00 00 C4 C4 C4 C4 C4 C4 C4 C4 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 08 00 00 00 00 00 00 00
C4 C4 C4 C4 C4 C4 C4 C4 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 09 00 00 00 00 00 00 00 C4 C4 C4 C4 C4
C4 C4 C4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 0A 00 00 00 00 00 00 00 C4 C4 C4 C4 C4 C4 C4 C4 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00
In the next call VLIB will request with the new request control:
02 00 00 00 5D 6E CF B8 77 91 0F 2D DB 99 EE 7C 18 18 00 00 00 00 00 00 00 01
BD 00 02 00 00 00 5D 6E CF B8 00 00 00 00 43 0B 11 E5 00 00 00 00 00 00 00 02 49 0B 00 00 00 00 00 00 00 C4 C4 C4
C4 C4 C4 C4 C4 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 0C 00 00 00 00 00 00 00 C4 C4 C4 C4 C4 C4 C4 C4
00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 0D 00 00 00 00 00 00 00 C4 C4 C4 C4 C4 C4 C4 C4 00 01 00 00 00
00 00 00 00 00 00 00 00 00 00 00 49 0E 00 00 00 00 00 00 00 C4 C4 C4 C4 C4 C4 C4 C4 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 49 0F 00 00 00 00 00 00 00 C4 C4 C4 C4 C4 C4 C4 C4 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00
00
03 00 00 00 5D 6E CF B8 77 91 0F 2D F6 6E FA 02 18 18 00 00 00 00 00 00 00 02
And the empty result telling the operation is over from the server, same request control number repeated.
18 00 03 00 00 00 5D 6E CF B8 00 00 00 00 FD EE 9C BE 00 00 00 00 00 00 00 02
Code: MOP Network Command Protocol
4 HTTP encapsulation
It is not mandatory but it is a common practice to use HTTP for communication between the device and the
server. In this case what is done is to encode the packet data using base64 to avoid problems with binary data
and to send to server using a GET call. In the same way the server will encode the data before replying.
The transmission type and command type are not encoded together with the rest of the data as they are in
ASCII encoding by definition.
The default endpoint that VLIB attempts to access in the server is /VrdyServiceF. All data will be passed inside
the parameter tag.
/VrdyServiceF?tag=A1AQAAAF1uz7g6mw8tZyS0ghgYAAAAAAAAAAA%3D&app=UXVpY2stUGktMC42LjU%3D&
data=eyJhcHBOYW1lIjoiRGVtbyIsImFwcFZlcnNpb24iOiIxLjAuMCIsImNhdGVnb3J5IjoiMCIsImxvY2FsSWQiOiIxIiwic2VyaWFsTnVtYmVyI
joiMDAwMDAwMDEiLCJ0ZXJtaW5hbElkIjoiMDAwMDAwMDEiLCJkaXJlY3Rpb24iOiIxIn0K&
req_limit=90&
step=1&
In this example we can see the tag parameter starting with A1 (transmission type ‘A’, command type ‘1’). If we
decode the following data using base64 the result will be:
01 00 00 00 5D 6E CF B8 3A 9B 0F 2D 67 24 B4 82 18 18 00 00 00 00 00 00 00 00
There are also other parameters that VLIB will send by default, if the application has data to send it will be
inside the data parameter also in base64, in this case the example has a JSON object:
{"appName":"Demo","appVersion":"1.0.0","category":"0","localId":"1","serialNumber":"00000001","terminalId":"000000
01","direction":"1"}
The format and data inside this parameter is defined between application and server. VLIB will only carry the
information to send in the requests. It can be filled with information to identify the device at server side, for
example.
The req_limit tells the server the limit of items it must return and the step parameter is only meant to tell the
server how many calls VLIB has done so far in this synchronization sprint.
The whole reply is encoded using base64. An example of an empty list result encoded in base64 as a reply to
the device:
GAADAAAAXW7PuAAAAAAT4P2SAAAAAAAAAAA=
Decoded:
18 00 03 00 00 00 5D 6E CF B8 00 00 00 00 13 E0 FD 92 00 00 00 00 00 00 00 00
VLIB will respect the server HTTP Connection parameter, when enabled for Keep-Alive at server side it
improves the performance of list synchronization as it allows several HTTP calls over the same TCP connection.
VLIB also supports HTTPS if GnuTLS or libSSL are present at the host device.
Code: MOP Network Command Protocol
The PHP sample uses the PHP inner HTTP server support, so it simplifies the development reducing the need to
a full fledged HTTP server. It is able to receive the transaction data, dump it and reply accordingly.
The Javascript sample uses NodeJS features to create an HTTP server and does the same thing as the PHP
server.
The PHP and Javascript samples are meant as starting point to make a new server side integration.
Code: MOP Network Command Protocol
unsigned long CRC32(unsigned char *buf, int size, int reverse, unsigned long crc)
{
while (size--)
crc = CRC32_TABLE[(crc ^ *buf++) & 0xFF] ^ (crc >> 8);
return reverse ? (crc ^ ~0U) : crc;
}
PHP language:
Javascript language:
const CRC32_TABLE =
[
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832,
0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa,
0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e,
0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2,
0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6,
0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e,
0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12,
0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76,
0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda,
0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82,
0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6,
0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a,
0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e,
0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
];
#define DATE_TIME_4SAM(Y, M, D, h, m, s) (((Y % 100) << 25) + (((M - 1) % 12) << 21) + (((D - 1) % 31) << 16) +
((h % 24) << 11) + ((m % 60) << 5) + ((s % 60) / 2))
DATA FFFF001122B14F000001AE472C4D841DFC6201D69078E6752D48E203D492F9744729
BDK 00112233445566778899AABBCCDDEEFF
KSN FFFF001122B14F000001
IPEK 74D43CAA5724E37D71F35F63FEE1F51A
PEK 2D222679F7B6F5E56A9F40BDC989D6EE
SKEY 0E102552BDD32E91899E519787458FD2
INPUT AE472C4D841DFC6201D69078E6752D48E203D492F9744729
/VrdyServiceF?tag=A6AgAAaTVGYkXxnA8td%2FnI2fcVy4hyPBvIzE%2FkLIuGO3pXIv%2F%2F%2BZmZzEigAAK
%2F8RPTKfSIK4LIzRPODEHE8EWouBjCojvffgYBAQAAAABaCEEjRKqqqgIAXzQBAV8kAyISMZ8mCFV1QmNsDqlhnycBgJ82AgAbnzcES6IUdIICAAC
fEAcGAREDoAAAn24EIHAAAJ8CBgAAAAAAAJ8DBgAAAAAAAJUFAAAAAACaAyIJFpwBAJ8aAgB2XyoCCYafOQEH3xcBCE8HoAAAAAMQEJ8JAgACnx4IA
AAAAAAAAACfMwMACAifNAMfAwKfNQEln0EEAAAAAt9PEVFGKnjrhr7goZctLU2Qg70AUAlWSVNBIFRFU1QAAAAAAAAAAAAAAAAA&app=UXVpY2stUG
ktMC42LjU
%3D&data=eyJhcHBOYW1lIjoiRGVtbyIsImFwcFZlcnNpb24iOiIxLjAuMCIsImNhdGVnb3J5IjoiMCIsImxvY2FsSWQiOiIxIiwic2VyaWFsTnVtY
mVyIjoiMDAwMDAwMDEiLCJ0ZXJtaW5hbElkIjoiMDAwMDAwMDEiLCJkaXJlY3Rpb24iOiIxIn0K&log=32gE4wAAAN9pBCX7JGPfawwxLjIuMi1nbG
9iYWzfXgQAAAAA318EAAAAAN9qAjgU320LTm92IDEyIDIwMTnfbggyMzoxMDoxOd9vCFhDTABdbs%2B4&step=0&
Base64 decoded (marked the first 32 bytes for receipt and PAN HASH):
02 00 00 69 35 46 62 45 F1 9C 0F 2D 77 F9 C8 D9 F7 15 CB 88 72 3C 1B C8 CC 4F E4 2C 8B 86 3B 7A 57 22 FF FF F9 99
99 CC 48 A0 00 02 BF F1 13 D3 29 F4 88 2B 82 C8 CD 13 CE 0C 41 C4 F0 45 A8 B8 18 C2 A2 3B DF 7E 06 01 01 00 00 00
00 5A 08 41 23 44 AA AA AA 02 00 5F 34 01 01 5F 24 03 22 12 31 9F 26 08 55 75 42 63 6C 0E A9 61 9F 27 01 80 9F 36
02 00 1B 9F 37 04 4B A2 14 74 82 02 00 00 9F 10 07 06 01 11 03 A0 00 00 9F 6E 04 20 70 00 00 9F 02 06 00 00 00 00
00 00 9F 03 06 00 00 00 00 00 00 95 05 00 00 00 00 00 9A 03 22 09 16 9C 01 00 9F 1A 02 00 76 5F 2A 02 09 86 9F 39
01 07 DF 17 01 08 4F 07 A0 00 00 00 03 10 10 9F 09 02 00 02 9F 1E 08 00 00 00 00 00 00 00 00 9F 33 03 00 08 08 9F
34 03 1F 03 02 9F 35 01 25 9F 41 04 00 00 00 02 DF 4F 11 51 46 2A 78 EB 86 BE E0 A1 97 2D 2D 4D 90 83 BD 00 50 09
56 49 53 41 20 54 45 53 54 00 00 00 00 00 00 00 00 00 00 00 00 00
Starting from the first tag this is the parsing of all EMV tags: