Using iso8583_erl Erlang Library

Using iso8583_erl Erlang Library

i have been working on an iso8583 library and decided to write a post about it.

I have also used the library in three projects over the years so code is production ready and battle tested.

iso8583 is a payment card messaging protocol and in some ways a dsl for describing how to send and receive payment card transactions from a sender to a receiver.

the sender can be an atm,pos device,website,application,etc.. and the receiver an application,card processor like visa,mastercard etc.

The library accepts a specification file which contains info about payment card data for your messages.The specification has info such as header length for various fields,padding info for fields,etc… This info is then used for packing and unpacking the payment card messages.

Library can be used mostly with ascii messages or hex formatted messages.

usage

to use library you can use add the dependancy in mix.exs or rebar.config like below

mix.exs

{:iso8583_erl, "~> 0.4.0"}

rebar.config

{iso8583_erl, "0.4.0"}

quickstart

the library is used by first loading a specification file after which you can pack and unpack data based on the specification file

a sample specification file can be found here

Using erlang code below loading a specification file found in the root directory.

Spec = iso8583_erl:load_specification("custom.cfg"),

if specification file is found in priv directory as is common to erlang, path will be code:priv_dir(iso8583_erl)++"/custom.cfg" and if other path is used for specification, path has be put in there

For adding a message type indicator or mti you can do the following

{ok,First_map} = iso8583_erl:set_mti(maps:new(),<<"0200">>),

For adding payment card fields from 1 to 128 you can do the following

{ok,Second_map} = iso8583_erl:set_field(First_map,3,<<"000102">>), %%Processing code

{ok,Third_map} = iso8583_erl:set_field(Second_map,4,<<"123456789012">>), %%Amount Transaction

{ok,Fourth_map} = iso8583_erl:set_field(Third_map,5,<<"123456789012">>), %%Amount Settlement

As you can probably tell the code updates a map internally.

To set multiple fields you can do this

Map_send_list = iso8583_erl:set_field_list([{mti,<<"0200">>},{3,<<"000102">>},{4,<<"4.5">>},{5,<<"5000">>},{102,<<"123413243">>},{103,<<"12897979987">>}]),

To pack the data so it can be sent to the respondent the following can be done [Mti,Bitmap_final_bit,Fields_list] = iso8583_erl:pack(Map_send_list,Specification)

This packs the message and adds the various headers and paddings for the various fields.It also generates the bitmap for the message.

The result is an iolist which contains the mti,bitmap and the formatted field list.

Usually when using the iso08583 protocol, a size header is appended to the message showing the total size of the message.This is so the receiver can know when processing a message when the whole message has been received.

There are functions in the library iso8583_erl:get_send/2 which calculates the size of the message and zerofills it to the number of bytes which the message size can be so a message with a length of 500 words where the max size is 4 bytes will be 0500

Iso_Message = iso8583_erl:pack(Map_send_list,Specification),

Final_size = iso8583_erl:get_size_send(Iso_Message,Bheader),

%%Bheader is maximum size of header containing message size

Final = [Final_size,Iso_Response], %%appending size of message

ok = gen_tcp:send(Socket,Final), %%sending with socket

To unpack the data on the other side you first get the first n bytes which will have the size of the message. In our case the first n bytes which contain the size of the message is 4 so the size of the message will be in the first 4 bytes.The size will depend on the number of fields and the sizes of the various message fields.

After getting the whole data out at the receiver end and also processing to get the message length out of the mix,you can unpack it by first loading the specification just like in the packing side and then run the unpack command.

unpacking on the receiving side

The unpack command upacks the formatted message based on the specification and then creates a map holding the mti,bitmap, and the various fields all in a map

Specification = iso8583_erl:load_specification("custom.cfg"),

Map_data = iso8583_erl:unpack(Final,Specification)

you can then get the individual fields by pattern matching like so

#{3 => Field_three,4 => Field_four,bit => Bitmap,mti => Mti} = Map_data,

you can also get the various fields by using iso8583_erl:get_field/2 functions.

{ok,Field_four} = iso8583_erl:get_field(4,Map_data)

There is a github project which contains a whole application showing the use of the iso8583_erl library.

Happy hacking and let me know if you see any bugs


Read more