|
|
|
@@ -2,143 +2,153 @@
|
|
|
|
|
ISO8583
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
Introduction to ISO8583
|
|
|
|
|
Introducción al protocolo ISO8583
|
|
|
|
|
|
|
|
|
|
The specification is available at iso.org and it's gotten really complicated; this is just an introduction
|
|
|
|
|
to the generalities of the specification. There is actually a
|
|
|
|
|
{{{http://en.wikipedia.org/wiki/ISO_8583}really good article}} on Wikipedia covering the whole spec and its
|
|
|
|
|
different versions.
|
|
|
|
|
La especificación completa está disponible en el sitio iso.org y es bastante complicada; esta es únicamente
|
|
|
|
|
una introducción muy simple a las generalidades del protocolo. Wikipedia tiene un
|
|
|
|
|
{{{http://en.wikipedia.org/wiki/ISO_8583}artículo bastante completo}} que abarca la especificación completa
|
|
|
|
|
en sus distintas versiones.
|
|
|
|
|
|
|
|
|
|
* Data types
|
|
|
|
|
* Tipos de datos
|
|
|
|
|
|
|
|
|
|
ISO 8583 specifies a lot of data types, the most common of which are implemented directly in j8583 through
|
|
|
|
|
the <<<IsoType>>> enum. Here is a table of the most common ISO types and their j8583 counterpart:
|
|
|
|
|
ISO 8583 especifica muchos tipos de datos, de los cuales se eligieron los más comunes para ser implementados
|
|
|
|
|
en j8583 por medio del enum <<<IsoType>>>. A continuación se presenta una tabla con los tipos ISO más comunes
|
|
|
|
|
y su contraparte en j8583:
|
|
|
|
|
|
|
|
|
|
*--------------*----------------*-----------------+
|
|
|
|
|
| <<ISO type>> | <<j8583 type>> | <<Description >> |
|
|
|
|
|
| <<Tipo ISO>> | <<Tipo j8583>> | <<Descripción>> |
|
|
|
|
|
*--------------*----------------*-----------------+
|
|
|
|
|
| Numeric | NUMERIC | Fixed-width numeric values, padded with zeroes to the left.|
|
|
|
|
|
| Numérico | NUMERIC | Valores numéricos de longitud fija, rellenos con ceros a la izquierda.
|
|
|
|
|
*--------------*----------------*-----------------+
|
|
|
|
|
| Alphanumeric | ALPHA | Fixed-width alphanumeric values, padded with spaces to the right.|
|
|
|
|
|
| Alfanumérico | ALPHA | Valores alfanuméricos de longitud fija, rellenos con espacios a la derecha.
|
|
|
|
|
*--------------*----------------*-----------------+
|
|
|
|
|
| Date | DATE10 | Date in format mmddHHMMSS, fixed width of 10. |
|
|
|
|
|
| Fecha | DATE10 | Fecha en formato mmddHHMMSS, con longitud fija de 10.
|
|
|
|
|
*--------------*----------------*-----------------+
|
|
|
|
|
| Date | DATE4 | Date in format mmdd, fixed width of 4. |
|
|
|
|
|
| Fecha | DATE4 | Fecha en formato mmdd, con longitud fija de 4.
|
|
|
|
|
*--------------*----------------*-----------------+
|
|
|
|
|
| Expiration Date | DATE_EXP | Date in format yymm, fixed width of 4. Used for credit card expiration dates. |
|
|
|
|
|
| Fecha de expiración | DATE_EXP | Fecha en formato aamm, con longitud fija de 4. Se usa por ejemplo para fechas de expiración de tarjetas de crédito.
|
|
|
|
|
*--------------*----------------*-----------------+
|
|
|
|
|
| Time | TIME | Time of day in format HHMMSS, fixed width of 6. |
|
|
|
|
|
| Hora | TIME | Hora del día en formato HHMMSS, con longitud fija de 6. |
|
|
|
|
|
*--------------*----------------*-----------------+
|
|
|
|
|
| Amount | AMOUNT | Currency amount, a positive number expressed in cents, with a fixed width of 4. For example one dollar is encoded as 000000000100 |
|
|
|
|
|
| Monto | AMOUNT | Monto en alguna moneda, expresado en centavos, con una longitud fija de 12. Por ejemplo un dólar se codifica como 000000000100
|
|
|
|
|
*--------------*----------------*-----------------+
|
|
|
|
|
| LLVAR | LLVAR | Variable-width alphanumeric value, up to 99 characters long. The length of the value is encoded in the first 2 characters of the value, for example "HEY" is encoded as 03HEY |
|
|
|
|
|
| LLVAR | LLVAR | Valor alfanumérico de longitud variable, hasta 99 caracteres. La longitud del valor se codifica en los dos primeros caracteres del valor; por ejemplo "HOLA" se codifica como 04HOLA
|
|
|
|
|
*--------------*----------------*-----------------+
|
|
|
|
|
| LLLVAR | LLLVAR | Variable-width alphanumeric value, up to 999 characters long. The length of the value is encoded in the first 3 characters of the value, for example "HEY" is encoded as 003HEY |
|
|
|
|
|
| LLLVAR | LLLVAR | Valor alfanumérico de longitud variable, hasta 999 caracteres. La longitud del valor se codifica en los dos primeros caracteres del valor; por ejemplo "HOLA" se codifica como 004HOLA
|
|
|
|
|
*--------------*----------------*-----------------+
|
|
|
|
|
ISO 8583 types and their corresponding j8583 types
|
|
|
|
|
Tipos de ISO8583 y sus contrapartes en j8583
|
|
|
|
|
|
|
|
|
|
* Common scenarios
|
|
|
|
|
* Escenarios típicos
|
|
|
|
|
|
|
|
|
|
ISO8583 implementations can vary a lot, depending on the provider, and the type of products and transactions it
|
|
|
|
|
is being used for; but there are certain fields which are almost always used in a very similar manner. I will
|
|
|
|
|
describe those here. <<DISCLAIMER:>> This is only something I have learned from experience, and I must say
|
|
|
|
|
my experience has been rather limited to mobile carrier providers. Here I focus more on the field number and
|
|
|
|
|
type, rather on the usage of the field itself.
|
|
|
|
|
Las implementaciones de ISO8583 pueden variar mucho dependiendo del proveedor, así como de los productos o
|
|
|
|
|
servicios manejados y las transacciones que se van a procesar, pero casi siempre hay ciertos campos que se
|
|
|
|
|
utilizan de la misma manera. A continuación se describen estos campos. <<ADVERTENCIA:>> Esto es algo que he
|
|
|
|
|
aprendido únicamente por experiencia, la cual ha sido limitada principalmente a proveedores de telefonía celular.
|
|
|
|
|
Aquí me enfoco más a describir un campo por su tipo y número, más que el uso que se le pueda dar.
|
|
|
|
|
|
|
|
|
|
** Message types
|
|
|
|
|
** Tipos de mensaje
|
|
|
|
|
|
|
|
|
|
These are some of the most common message types. There is some logic to this, if you look at the message types
|
|
|
|
|
as 2-byte hex values: The first byte states the type of operation: 02 are payments, 04 reversals, 08 tests;
|
|
|
|
|
the second byte indicates if it's a request or a response. And sometimes repeated requests should end in 1
|
|
|
|
|
instead of 0, for example reversals are 0400 the first time but 0401 the next time you send them.
|
|
|
|
|
Estos son algunos de los tipos de mensaje más común. Estos tipos siguen cierta lógica, si se les ve como
|
|
|
|
|
valores de 2 bytes; el primer byte indica el tipo de operación: 02 son pagos, 04 son reversos, 08 son pruebas;
|
|
|
|
|
el segundo byte indica si es una petición o una respuesta. Y en ocasiones, los reenvíos de peticiones deben
|
|
|
|
|
terminar en 1 en vez de 0, por ejemplo un reverso se envía por primera vez como 0400 pero en ocasiones
|
|
|
|
|
subsecuentes se debe reenviar como 0401.
|
|
|
|
|
|
|
|
|
|
*------:--+
|
|
|
|
|
| 0200 | A payment or sale request.
|
|
|
|
|
| 0200 | Una petición de pago o venta.
|
|
|
|
|
*------:--+
|
|
|
|
|
| 0210 | A payment or sale response.
|
|
|
|
|
| 0210 | Una respuesta de pago o venta.
|
|
|
|
|
*------:--+
|
|
|
|
|
| 0400 | A reversal request (to undo a previous 0200 operation).
|
|
|
|
|
| 0400 | Petición de reverso (para revertir una operación 0200 previa).
|
|
|
|
|
*------:--+
|
|
|
|
|
| 0410 | A reversal response.
|
|
|
|
|
| 0410 | Respuesta de reverso.
|
|
|
|
|
*------:--+
|
|
|
|
|
| 0600 | A query (to check the status of a previous operation, or check an account's balance, etc).
|
|
|
|
|
| 0600 | Una consulta (por ejemplo de saldo o de una operación previa).
|
|
|
|
|
*------:--+
|
|
|
|
|
| 0610 | A query response.
|
|
|
|
|
| 0610 | Respuesta de consulta.
|
|
|
|
|
*------:--+
|
|
|
|
|
| 0800 | An echo request (just to keep the connection alive and make sure the other side is responsive).
|
|
|
|
|
| 0800 | Petición de eco (para mantener viva una conexión y asegurarse que el otro lado de la conexión sigue respondiendo).
|
|
|
|
|
*------:--+
|
|
|
|
|
| 0810 | An echo response.
|
|
|
|
|
| 0810 | Respuesta de eco.
|
|
|
|
|
*------:--+
|
|
|
|
|
|
|
|
|
|
Some implementations require you to send 0400 for a reversal when you only have the request (so in case of
|
|
|
|
|
timeout you use 0400) and 0420 when you did get the response (so in case of some other error in your system).
|
|
|
|
|
Algunas implementaciones requieren que se envíe 0400 cuando solamente se tiene la petición 0200 sin haber obtenido
|
|
|
|
|
respuesta (en caso de expirar el tiempo de espera para el 0210), y enviar 0420 cuando ya se obtuvo respuesta
|
|
|
|
|
(en caso de que ocurra algún otro error en el sistema, después de recibir el 0210).
|
|
|
|
|
|
|
|
|
|
** Common fields
|
|
|
|
|
** Campos comunes
|
|
|
|
|
|
|
|
|
|
[Field 3] Operation code, NUMERIC of length 6.
|
|
|
|
|
[Field 3] Código de operación, NUMERIC de longitud 6.
|
|
|
|
|
|
|
|
|
|
[Field 4] Amount, AMOUNT.
|
|
|
|
|
[Field 4] Monto, tipo AMOUNT.
|
|
|
|
|
|
|
|
|
|
[Field 7] Date, DATE10.
|
|
|
|
|
[Field 7] Fecha de la transacción, tipo DATE10.
|
|
|
|
|
|
|
|
|
|
[Field 11] Trace, NUMERIC of length 6.
|
|
|
|
|
[Field 11] Número de trace, NUMERIC de longitud 6.
|
|
|
|
|
|
|
|
|
|
[Field 17] Transaction date, DATE4.
|
|
|
|
|
[Field 17] Fecha de la transacción, tipo DATE4.
|
|
|
|
|
|
|
|
|
|
[Field 37] Reference number, NUMERIC of length 12.
|
|
|
|
|
[Field 37] Número de referencia, NUMERIC de longitud 12.
|
|
|
|
|
|
|
|
|
|
[Field 38] Confirmation number, NUMERIC of length 6.
|
|
|
|
|
[Field 38] Número de confirmación, NUMERIC de longitud 6.
|
|
|
|
|
|
|
|
|
|
[Field 39] Response code, NUMERIC of length 2.
|
|
|
|
|
[Field 39] Código de respuesta, NUMERIC de longitud 2.
|
|
|
|
|
|
|
|
|
|
[Field 41] Terminal ID, ALPHA of length 8 or 16.
|
|
|
|
|
[Field 41] Identificador de la terminal de venta, ALPHA de longitud 8 ó 16.
|
|
|
|
|
|
|
|
|
|
[Field 49] Currency, NUMERIC of length 3. See the {{{http://en.wikipedia.org/wiki/ISO_4217}ISO 4217}} table of currencies.
|
|
|
|
|
[Field 49] Código de moneda, NUMERIC de longitud 3. Ver la tabla de códigos {{{http://es.wikipedia.org/wiki/ISO_4217}ISO 4217}}.
|
|
|
|
|
|
|
|
|
|
[Field 128] MAC (Message Authentication Code). Usually ALPHA or NUMERIC of length 16.
|
|
|
|
|
[Field 128] MAC (Código de autenticación de mensaje). Generalmente ALPHA o NUMERIC de longitud 16.
|
|
|
|
|
[]
|
|
|
|
|
|
|
|
|
|
** Asynchronous transmission and reception
|
|
|
|
|
** Transmisión y recepción asíncrona
|
|
|
|
|
|
|
|
|
|
When communicating two systems with ISO8583, usually the communication is asynchronous and all messages are
|
|
|
|
|
handled through a single connection. Between a terminal and a bigger system the communication will be synchronous.
|
|
|
|
|
Cuando se comunican dos sistemas con ISO8583, generalmente la comunicación es asíncrona y todos los mensajes
|
|
|
|
|
se manejan por una misma conexión. Entre una terminal y un sistema de mayor tamaño, la comunicación suele ser
|
|
|
|
|
síncrona.
|
|
|
|
|
|
|
|
|
|
In asynchronous communications, the client can send any number of requests to the server, and the server may
|
|
|
|
|
respond to those requests in a different order in which they were sent. This is why the trace number (field 11)
|
|
|
|
|
is very important and should not be reused; if the client sends requests with traces 123000, 123001 and 123002,
|
|
|
|
|
the server may send back first 123001, then 123002, then 123000. The client will know which response corresponds
|
|
|
|
|
to which request by checking the trace of the responses.
|
|
|
|
|
En la comunicación asíncrona, el cliente puede enviar cualquier cantidad de peticiones al servidor, y el servidor
|
|
|
|
|
puede enviar las respuestas en un orden distinto. Es por esto que el número de traza (campo 11) es tan importante
|
|
|
|
|
y no se debe repetir en periodos cortos de tiempo; si el cliente envía peticiones con trazas 123000, 123001 y
|
|
|
|
|
123002, el server puede contestar primero la 123001, luego 123002, y finalmente la 123000. El cliente sabrá
|
|
|
|
|
a qué petición corresponde cada respuesta por medio del número de traza.
|
|
|
|
|
|
|
|
|
|
The messages can vary in length depending on the message type and the fields it contains. The protocol was
|
|
|
|
|
designed so that a message can be read in parts; first the message type, then the primary bitmap, and from there
|
|
|
|
|
the rest of the fields (secondary bitmap included) can be read and processed one by one. This is very convenient
|
|
|
|
|
for small devices like POS terminals, but is not very efficient in larger systems with a high transaction volume.
|
|
|
|
|
In these cases, the sender first encodes the whole message, measures it, and sends the length as a 2- or 4-byte
|
|
|
|
|
unsigned integer (most significant bit first). This way the receiver knows to read 2 or 4 bytes, interpret them
|
|
|
|
|
as an unsigned integer, and read those many bytes to get an ISO message. Using 2 bytes allows for messages of up
|
|
|
|
|
to 65535 bytes, and 4 bytes allows for 2.14 million bytes long, which is a bit of overkill, given that a message
|
|
|
|
|
can be as long as 127290 bytes, if it's encoded in ASCII and has 127 LLLVAR fields each with 999 characters.
|
|
|
|
|
Los mensajes pueden variar en su longitud según el tipo de mensaje y los campos que contenga. El protocolo fue
|
|
|
|
|
diseñado de modo que un mensaje se pueda leer en partes; primero el tipo de mensaje, luego el bitmap primario,
|
|
|
|
|
y a partir de ahí se leerá cada campo que indique el bitmap, uno por uno. Esto es muy conveniente para
|
|
|
|
|
dispositivos pequeños con poca memoria, como terminales de punto de venta, pero no es muy eficiente en sistemas
|
|
|
|
|
grandes que procesan un gran volumen de operaciones. En estos casos, generalmente se envía primero un encabezado
|
|
|
|
|
de longitud indicando el tamaño del mensaje como un entero sin signo de 2 ó 4 bytes (con el bit más significativo
|
|
|
|
|
primero). De esta forma, el receptor siempre lee primero 2 ó 4 bytes, los interpreta como un entero sin signo
|
|
|
|
|
y después lee tantos bytes como indique ese encabezado, para convertir esa trama en un IsoMessage. Un encabezado
|
|
|
|
|
de 2 bytes permite mensajes hasta de 65535 bytes, mientras que un encabezado de 4 bytes permite mensajes de
|
|
|
|
|
2147 millones de bytes, lo cual es más que suficiente, dado que un mensaje puede medir hasta 127290 bytes,
|
|
|
|
|
si se codifica en ASCII y tiene 127 campos tipo LLLVAR cada uno con 999 caracteres.
|
|
|
|
|
|
|
|
|
|
*** Message terminator
|
|
|
|
|
*** Terminador de mensaje
|
|
|
|
|
|
|
|
|
|
The length header that is sent before a message is very useful to separate the reading operation from the parsing
|
|
|
|
|
of the message; you can dedicate a thread to read from a socket, and put those buffers on a queue where another
|
|
|
|
|
thread parses them. However, a length header only says how many bytes to read and so the reader must read all
|
|
|
|
|
those bytes, but what if the message is invalid because it is <longer> than the length says? To avoid this error,
|
|
|
|
|
some systems use a message terminator. This is just a character that must be found at the end of every message.
|
|
|
|
|
If messages are encoded as text, a common terminator is ASCII 0x03. The terminator may or may not be counted
|
|
|
|
|
as part of the message, that depends on the implementation. You can specify the terminator via the <<<etx>>>
|
|
|
|
|
property of an IsoMessage, of preferably in the MessageFactory so that all new messages already will have the
|
|
|
|
|
property set. To keep the messages from using a terminator, set <<<etx>>> to -1.
|
|
|
|
|
El encabezado de longitud que se envía antes de un mensaje es muy útil para separar la operación de lectura
|
|
|
|
|
de la operación de procesamiento del mensaje; se puede dedicar un hilo a leer de un socket y encolar esas
|
|
|
|
|
tramas para que otro hilo las convierta en IsoMessages. Sin embargo, el encabezado de longitud únicamente indica
|
|
|
|
|
cuántos bytes hay que leer, para que el receptor sepa que tiene que recibir al menos ese número de bytes, pero
|
|
|
|
|
¿qué pasa si el mensaje en realidad es <más largo> de lo que dice la longitud? Habrá problemas leyendo el
|
|
|
|
|
siguiente mensaje. Para evitar este error, algunos sistemas implementa un terminador de mensaje, que es
|
|
|
|
|
simplemente un caracter que va al final de cada mensaje. Si los mensajes se codifican como texto, un terminador
|
|
|
|
|
común es ASCII 0x03. El terminador puede ser contado como parte del mensaje (incluido en el encabezado de
|
|
|
|
|
longitud) o ser contado aparte, depende de la implementación. Se puede especificar el terminador en la propiedad
|
|
|
|
|
<<<etx>>> de un IsoMessage, y también en la misma propiedad de la MessageFactory para que todos los mensajes
|
|
|
|
|
creados por la fábrica ya contengan el terminador y lo incluyan al generar sus tramas. Para no utilizar un
|
|
|
|
|
terminador, se debe indicar -1 en el <<<etx>>> (este es el valor por defecto).
|
|
|
|
|
|
|
|
|
|
** Binary encoding
|
|
|
|
|
** Codificación binaria
|
|
|
|
|
|
|
|
|
|
Many ISO8583 implementations use plain text for the messages (even if the length header is binary). But some
|
|
|
|
|
implementations encode the messages as binary. The main differences are that the message type is only 2 bytes
|
|
|
|
|
long instead of 4 (the ASCII version is actually a hex representation of the message type), the bitmap is not
|
|
|
|
|
hex-encoded, so it's only 8 bytes long; and all numeric values (including date/time fields) are encoded using
|
|
|
|
|
{{{http://en.wikipedia.org/wiki/Binary-coded_decimal}BCD}} (including the headers for LLVAR and LLLVAR fields).
|
|
|
|
|
Muchas implementaciones de ISO8583 utilizan texto simple para los mensajes (aunque el encabezado de longitud
|
|
|
|
|
sea binario). Pero algunas implementaciones codifican sus mensajes en binario. Entre las diferencias
|
|
|
|
|
principales tenemos que el tipo de mensaje es de 2 bytes en vez de 4 (la versión ASCII de hecho es una
|
|
|
|
|
representación de texto hexadecimal el tipo de mensaje), el bitmap no viene codificado en hexadecimal por lo
|
|
|
|
|
que mide sólo 8 bytes; y todos los valores numéricos (incluyendo campos tipo fecha/hora) se codifican usando
|
|
|
|
|
{{{http://es.wikipedia.org/wiki/Binary-coded_decimal}BCD}} (incluyendo los encabezados de campos LLVAR y LLLVAR).
|
|
|
|
|
|
|
|
|
|
You can encode messages in binary by setting the <<<binary>>> property of IsoMessages, or in the MessageFactory
|
|
|
|
|
directly by setting the <<<useBinaryMessages>>> so that it gets set on all new messages. It must be set in
|
|
|
|
|
the MessageFactory if you want it to parse binary messages.
|
|
|
|
|
Se pueden codificar un mensaje en formato binario activando la propiedad <<<binary>>> de un IsoMessage, o la
|
|
|
|
|
propiedad <<<useBinaryMessages>>> de la MessageFactory, para afectar los mensajes creados a partir de ese momento.
|
|
|
|
|
Además para poder leer mensajes en formato binario se debe activar la propiedad en la MessageFactory.
|
|
|
|
|