iso8583

package module
v0.21.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 12, 2024 License: Apache-2.0 Imports: 18 Imported by: 7

README

Moov Banner Logo

Project Documentation · Community · Blog

GoDoc Build Status Coverage Status Go Report Card Repo Size Apache 2 License Slack Channel GitHub Stars Twitter

moov-io/iso8583

Moov's mission is to give developers an easy way to create and integrate bank processing into their own software products. Our open source projects are each focused on solving a single responsibility in financial services and designed around performance, scalability, and ease of use.

ISO8583 implements an ISO 8583 message reader and writer in Go. ISO 8583 is an international standard for card-originated financial transaction messages that defines both message format and communication flow. It's used by major card networks around the globe including Visa, Mastercard, and Verve. The standard supports card purchases, withdrawals, deposits, refunds, reversals, balance inquiries, inter-account transfers, administrative messages, secure key exchanges, and more.

Table of contents

Project status

Moov ISO8583 is a Go package that's been thoroughly tested and trusted in the real world. The project has proven its reliability and robustness in real-world, high-stakes scenarios. Please let us know if you encounter any missing feature/bugs/unclear documentation by opening up an issue. Thanks!

Go library

This project uses Go Modules. See Golang's install instructions for help in setting up Go. You can download the source code and we offer tagged and released versions as well. We highly recommend you use a tagged release for production.

Go version support policy

Always up-to-date, never left behind

While we strive to embrace the latest language enhancements, we also appreciate the need for a certain degree of backward compatibility. We understand that not everyone can update to the latest version immediately. Our philosophy is to move forward and embrace the new, but without leaving anyone immediately behind.

Which versions do we support now?

As of today, we are supporting the following versions as referenced in the setup-go action step:

  • stable (which points to the current Go version)
  • oldstable (which points to the previous Go version)

The setup-go action automatically manages versioning, allowing us to always stay aligned with the latest and preceding Go releases.

What does this mean for you?

Whenever a new version of Go is released, we will update our systems and ensure that our project remains fully compatible with it. At the same time, we will continue to support the previous version. However, once a new version is released, the 'previous previous' version will no longer be officially supported.

Continuous integration

To ensure our promise of support for these versions, we've configured our GitHub CI actions to test our code with both the current and previous versions of Go. This means you can feel confident that the project will work as expected if you're using either of these versions.

Installation
go get github.com/moov-io/iso8583

How to

Define your specification

Currently, we have defined the following ISO 8583 specifications:

  • Spec87ASCII - 1987 version of the spec with ASCII encoding
  • Spec87Hex - 1987 version of the spec with Hex encoding

Spec87ASCII is suitable for the majority of use cases. Simply instantiate a new message using specs.Spec87ASCII:

isomessage := iso8583.NewMessage(specs.Spec87ASCII)

If this spec does not meet your needs, we encourage you to modify it or create your own using the information below.

First, you need to define the format of the message fields that are described in your ISO8583 specification. Each data field has a type and its own spec. You can create a NewBitmap, NewString, or NewNumeric field. Each individual field spec consists of a few elements:

Element Notes Example
Length Maximum length of field (bytes, characters or digits), for both fixed and variable lengths. 10
Description Describes what the data field holds. "Primary Account Number"
Enc Sets the encoding type (ASCII, Hex, Binary, BCD, LBCD, EBCDIC). encoding.ASCII
Pref Sets the encoding (ASCII, Hex, Binary, BCD, EBCDIC) of the field length and its type as fixed or variable (Fixed, L, LL, LLL, LLLL). The number of 'L's corresponds to the number of digits in a variable length. prefix.ASCII.Fixed
Pad (optional) Sets padding direction and type. padding.Left('0')

While some ISO8583 specifications do not have field 0 and field 1, we use them for MTI and Bitmap. Because technically speaking, they are just regular fields. We use field specs to describe MTI and Bitmap too. We currently use the String field for MTI, while we have a separate Bitmap field for the bitmap.

The following example creates a full specification with three individual fields (excluding MTI and Bitmap):

spec := &iso8583.MessageSpec{
	Fields: map[int]field.Field{
		0: field.NewString(&field.Spec{
			Length:      4,
			Description: "Message Type Indicator",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		1: field.NewBitmap(&field.Spec{
			Description: "Bitmap",
			Enc:         encoding.Hex,
			Pref:        prefix.Hex.Fixed,
		}),

		// Message fields:
		2: field.NewString(&field.Spec{
			Length:      19,
			Description: "Primary Account Number",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LL,
		}),
		3: field.NewNumeric(&field.Spec{
			Length:      6,
			Description: "Processing Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
			Pad:         padding.Left('0'),
		}),
		4: field.NewString(&field.Spec{
			Length:      12,
			Description: "Transaction Amount",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
			Pad:         padding.Left('0'),
		}),
	},
}

The following example creates a full specification with three individual fields (excluding MTI and Bitmap). It differs from the example above, by showing the expandability of the bitmap field. This is useful for specs that define both a primary and secondary bitmap.

spec := &iso8583.MessageSpec{
	Fields: map[int]field.Field{
		0: field.NewString(&field.Spec{
			Length:      4,
			Description: "Message Type Indicator",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		1: field.NewBitmap(&field.Spec{
			Description: "Bitmap",
			Enc:         encoding.Hex,
			Pref:        prefix.Hex.Fixed,
		}),

		// Message fields:
		2: field.NewString(&field.Spec{
			Length:      19,
			Description: "Primary Account Number",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LL,
		}),
		3: field.NewNumeric(&field.Spec{
			Length:      6,
			Description: "Processing Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
			Pad:         padding.Left('0'),
		}),
		4: field.NewString(&field.Spec{
			Length:      12,
			Description: "Transaction Amount",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
			Pad:         padding.Left('0'),
		}),
        // Pulled from the 1993 spec
        67: field.NewNumeric(&field.Spec{
            Length: 2,
            Description: "Extended Payment Data",
            Enc: encoding.ASCII,
            Pref: prefix.ASCII.Fixed,
            Pad: padding.Left('0'),
        }),
	},
}
Build and pack the message

After the specification is defined, you can build a message. Having a binary representation of your message that's packed according to the provided spec lets you send it directly to a payment system!

Notice in the examples below, you do not need to set the bitmap value manually, as it is automatically generated for you during packing.

Setting values of individual fields

If you need to set few fields, you can easily set them using message.Field(id, string) or message.BinaryField(id, []byte) like this:

// create message with defined spec
message := NewMessage(spec)

// set message type indicator at field 0
message.MTI("0100")

// set all message fields you need as strings

err := message.Field(2, "4242424242424242")
// handle error

err = message.Field(3, "123456")
// handle error

err = message.Field(4, "100")
// handle error

// generate binary representation of the message into rawMessage
rawMessage, err := message.Pack()

// now you can send rawMessage over the wire

Working with individual fields is limited to two types: string or []byte. Underlying field converts the input into its own type. If it fails, then error is returned.

Setting values using data struct

Accessing individual fields is handy when you want to get value of one or two fields. When you need to access a lot of them and you want to work with field types, using structs with message.Marshal(data) is more convenient.

First, you need to define a struct with fields you want to set. Fields should correspond to the spec field types. Here is an example:

// list fields you want to set, add `index` tag with field index or tag (for
// composite subfields) use the same types from message specification
type NetworkManagementRequest struct {
	MTI                  *field.String `index:"0"`
	TransmissionDateTime *field.String `index:"7"`
	STAN                 *field.String `index:"11"`
	InformationCode      *field.String `index:"70"`
}

message := NewMessage(spec)

// now, pass data with fields into the message
err := message.Marshal(&NetworkManagementRequest{
	MTI:                  field.NewStringValue("0800"),
	TransmissionDateTime: field.NewStringValue(time.Now().UTC().Format("060102150405")),
	STAN:                 field.NewStringValue("000001"),
	InformationCode:      field.NewStringValue("001"),
})

// pack the message and send it to your provider
requestMessage, err := message.Pack()
Parse the message and access the data

When you have a binary (packed) message and you know the specification it follows, you can unpack it and access the data. Again, you have two options for data access: access individual fields or populate struct with message field values.

Getting values of individual fields

You can access values of individual fields using message.GetString(id), message.GetBytes(id) like this:

message := NewMessage(spec)
message.Unpack(rawMessage)

mti, err := message.GetMTI() // MTI: 0100
// handle error

pan, err := message.GetString(2) // Card number: 4242424242424242
// handle error

processingCode, err := message.GetString(3) // Processing code: 123456
// handle error

amount, err := message.GetString(4) // Transaction amount: 100
// handle error

Again, you are limited to a string or a []byte types when you get values of individual fields.

Getting values using data struct

To get values of multiple fields with their types just pass a pointer to a struct for the data you want into message.Unmarshal(data) like this:

// list fields you want to set, add `index` tag with field index or tag (for
// composite subfields) use the same types from message specification
type NetworkManagementRequest struct {
	MTI                  *field.String `index:"0"`
	TransmissionDateTime *field.String `index:"7"`
	STAN                 *field.String `index:"11"`
	InformationCode      *field.String `index:"70"`
}

message := NewMessage(spec)
// let's unpack binary message
err := message.Unpack(rawMessage)
// handle error

// create pointer to empty struct
data := &NetworkManagementRequest{}

// get field values into data struct
err = message.Unmarshal(data)
// handle error

// now you can access field values
data.MTI.Value() // "0100"
data.TransmissionDateTime.Value() // "220102103212"
data.STAN.Value() // "000001"
data.InformationCode.Value() // "001"

For complete code samples please check ./message_test.go.

Inspect message fields

There is a Describe function in the package that displays all message fields in a human-readable way. Here is an example of how you can print message fields with their values to STDOUT:

// print message to os.Stdout
iso8583.Describe(message, os.Stdout)

and it will produce the following output:

MTI........................................: 0100
Bitmap.....................................: 000000000000000000000000000000000000000000000000
Bitmap bits................................: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
F000 Message Type Indicator................: 0100
F002 Primary Account Number................: 4242****4242
F003 Processing Code.......................: 123456
F004 Transaction Amount....................: 100
F020 PAN Extended Country Code.............: 4242****4242
F035 Track 2 Data..........................: 4000****0506=2512111123400001230
F036 Track 3 Data..........................: 011234****3445=724724000000000****00300XXXX020200099010=********************==1=100000000000000000**
F045 Track 1 Data..........................: B4815****1896^YATES/EUGENE L^^^356858      00998000000
F052 PIN Data..............................: 12****78
F055 ICC Data – EMV Having Multiple Tags...: ICC  ... Tags

by default, we apply iso8583.DefaultFilters to mask the values of the fields with sensitive data. You can define your filter functions and redact specific fields like this:

filterAll = func(in string, data field.Field) string {
	runesInString := utf8.RuneCountInString(in)

	return strings.Repeat("*", runesInString)
}

// filter only value of the field 2
iso8583.Describe(message, os.Stdout, filterAll(2, filterAll))

// outputs:
// F002 Primary Account Number................: ************

If you want to view unfiltered values, you can use no-op filters iso8583.DoNotFilterFields that we defined:

// display unfiltered field values
iso8583.Describe(message, os.Stdout, DoNotFilterFields()...)
JSON encoding

You can serialize message into JSON format:

message := iso8583.NewMessage(spec)
message.MTI("0100")
message.Field(2, "4242424242424242")
message.Field(3, "123456")
message.Field(4, "100")

jsonMessage, err := json.Marshal(message)

it will produce the following JSON (bitmap is not included, as it's only used to unpack message from the binary representation):

{
   "0":"0100",
   "2":"4242424242424242",
   "3":123456,
   "4":"100"
}

Also, you can unmarshal JSON into iso8583.Message:

input := `{"0":"0100","2":"4242424242424242","4":"100"}`

message := NewMessage(spec)
if err := json.Unmarshal([]byte(input), message); err != nil {
    // handle err
}

// access indidual fields or using struct
Network Header

All messages between the client/server (ISO host and endpoint) have a message length header. It can be a 4 bytes ASCII or 2 bytes BCD encoded length. We provide a network.Header interface to simplify the reading and writing of the network header.

Following network headers are supported:

  • Binary2Bytes - message length encoded in 2 bytes, e.g, {0x00 0x73} for 115 bytes of the message
  • ASCII4Bytes - message length encoded in 4 bytes ASCII, e.g., 0115 for 115 bytes of the message
  • BCD2Bytes - message length encoded in 2 bytes BCD, e.g, {0x01, 0x15} for 115 bytes of the message
  • VMLH (Visa Message Length Header) - message length encoded in 2 bytes + 2 reserved bytes

You can read network header from the network connection like this:

header := network.NewBCD2BytesHeader()
_, err := header.ReadFrom(conn)
if err != nil {
	// handle error
}

// Make a buffer to hold message
buf := make([]byte, header.Length())
// Read the incoming message into the buffer.
read, err := io.ReadFull(conn, buf)
if err != nil {
	// handle error
}
if reqLen != header.Length() {
	// handle error
}

message := iso8583.NewMessage(specs.Spec87ASCII)
message.Unpack(buf)

Here is an example of how to write network header into network connection:

header := network.NewBCD2BytesHeader()
packed, err := message.Pack()
if err != nil {
	// handle error
}
header.SetLength(len(packed))
_, err = header.WriteTo(conn)
if err != nil {
	// handle error
}
n, err := conn.Write(packed)
if err != nil {
	// handle error
}

CLI

CLI suports following command:

  • display to display ISO8583 message in a human-readable format
Installation

iso8583 CLI is available as downloadable binaries from the releases page for MacOS, Windows and Linux.

Here is an example how to install MacOS version:

wget -O ./iso8583 https://github.com/moov-io/iso8583/releases/download/v0.4.6/iso8583_0.4.6_darwin_amd64 && chmod +x ./iso8583

Now you can run CLI:

➜ ./iso8583
Work seamlessly with ISO 8583 from the command line.

Usage:
  iso8583 <command> [flags]

Available commands:
  describe: display ISO 8583 file in a human-readable format
Display

To display ISO8583 message in a human-readable format

Example:

➜ ./bin/iso8583 describe msg.bin
MTI........................................: 0100
Bitmap.....................................: 000000000000000000000000000000000000000000000000
Bitmap bits................................: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
F000 Message Type Indicator................: 0100
F002 Primary Account Number................: 4242****4242
F003 Processing Code.......................: 123456
F004 Transaction Amount....................: 100
F020 PAN Extended Country Code.............: 4242****4242
F035 Track 2 Data..........................: 4000****0506=2512111123400001230
F036 Track 3 Data..........................: 011234****3445=724724000000000****00300XXXX020200099010=********************==1=100000000000000000**
F045 Track 1 Data..........................: B4815****1896^YATES/EUGENE L^^^356858      00998000000
F052 PIN Data..............................: 12****78
F055 ICC Data – EMV Having Multiple Tags...: ICC  ... Tags

You can specify which of the built-in specs to use to the describe message via the spec flag:

➜ ./bin/iso8583 describe -spec spec87ascii msg.bin

You can also define your spec in JSON format and describe message using the spec file with spec-file flag:

➜ ./bin/iso8583 describe -spec-file ./examples/specs/spec87ascii.json msg.bin

Please, check the example of the JSON spec file spec87ascii.json.

Learn about ISO 8583

Getting help

channel info
Project Documentation Our project documentation available online.
Twitter @moov You can follow Moov.io's Twitter feed to get updates on our project(s). You can also tweet us questions or just share blogs or stories.
GitHub Issue If you are able to reproduce a problem please open a GitHub Issue under the specific project that caused the error.
moov-io slack Join our slack channel (#iso8583) to have an interactive discussion about the development of the project.

Contributing

While Spec87ASCII is appropriate for most users, we hope to see improvements and variations of this specification for different systems by the community. Please do not hesitate to contribute issues, questions, or PRs to cover new use cases. Tests are also appreciated if possible!

Please review our Contributing guide and Code of Conduct to get started! Check out our issues for first time contributors for something to help out with.

This project uses Go Modules and Go v1.18 or newer. See Golang's install instructions for help setting up Go. You can download the source code and we offer tagged and released versions as well. We highly recommend you use a tagged release for production.

As part of Moov's initiative to offer open source fintech infrastructure, we have a large collection of active projects you may find useful:

  • Moov ACH provides ACH file generation and parsing, supporting all Standard Entry Codes for the primary method of money movement throughout the United States.

  • Moov Watchman offers search functions over numerous trade sanction lists from the United States and European Union.

  • Moov Fed implements utility services for searching the United States Federal Reserve System such as ABA routing numbers, financial institution name lookup, and FedACH and Fedwire routing information.

  • Moov Wire implements an interface to write files for the Fedwire Funds Service, a real-time gross settlement funds transfer system operated by the United States Federal Reserve Banks.

  • Moov ImageCashLetter implements Image Cash Letter (ICL) files used for Check21, X.9 or check truncation files for exchange and remote deposit in the U.S.

  • Moov Metro2 provides a way to easily read, create, and validate Metro 2 format, which is used for consumer credit history reporting by the United States credit bureaus.

License

Apache License 2.0 - See LICENSE for details.

Documentation

Overview

Version will be automatically set during the build

Index

Constants

This section is empty.

Variables

View Source
var DefaultFilters = func() []FieldFilter {
	filters := []FieldFilter{
		FilterField("2", PANFilter),
		FilterField("20", PANFilter),
		FilterField("35", Track2Filter),
		FilterField("36", Track3Filter),
		FilterField("45", Track1Filter),
		FilterField("52", PINFilter),
		FilterField("55", EMVFilter),
	}
	return filters
}
View Source
var DoNotFilterFields = func() []FieldFilter {
	filters := []FieldFilter{
		FilterField("-1", NoOpFilter),
	}
	return filters
}
View Source
var EMVFilter = func(in string, data field.Field) string {
	if utf8.RuneCountInString(in) < emvFirstIndex+emvLastIndex {
		return in
	}

	return in[0:emvFirstIndex] + emvPattern + in[len(in)-emvLastIndex:]
}
View Source
var NoOpFilter = func(in string, data field.Field) string {
	return in
}
View Source
var PANFilter = func(in string, data field.Field) string {
	if utf8.RuneCountInString(in) < panFistIndex+panLastIndex {
		return in
	}
	return in[0:panFistIndex] + panPattern + in[len(in)-panLastIndex:]
}
View Source
var PINFilter = func(in string, data field.Field) string {
	if utf8.RuneCountInString(in) < pinFirstIndex+pinLastIndex {
		return in
	}
	return in[0:pinFirstIndex] + pinPattern + in[len(in)-pinLastIndex:]
}
View Source
var Track1Filter = func(in string, data field.Field) string {
	track := field.Track1{}
	if err := newTrackData(data, &track); err != nil {
		return in
	}

	track.PrimaryAccountNumber = PANFilter(track.PrimaryAccountNumber, nil)
	return getTrackDataString(in, &track)
}
View Source
var Track2Filter = func(in string, data field.Field) string {
	track := field.Track2{}
	if err := newTrackData(data, &track); err != nil {
		return in
	}

	track.PrimaryAccountNumber = PANFilter(track.PrimaryAccountNumber, nil)
	return getTrackDataString(in, &track)
}
View Source
var Track3Filter = func(in string, data field.Field) string {
	track := field.Track3{}
	if err := newTrackData(data, &track); err != nil {
		return in
	}
	track.PrimaryAccountNumber = PANFilter(track.PrimaryAccountNumber, nil)

	return getTrackDataString(in, &track)
}
View Source
var Version string

Functions

func Describe added in v0.11.0

func Describe(message *Message, w io.Writer, filters ...FieldFilter) error

func DescribeFieldContainer added in v0.18.0

func DescribeFieldContainer(container FieldContainer, w io.Writer, filters ...FieldFilter) error

DescribeFieldContainer describes the FieldContainer (e.g. Wrapped Message or CompositeField)

Types

type ContainerWithBitmap added in v0.18.0

type ContainerWithBitmap interface {
	Bitmap() *field.Bitmap
}

type FieldContainer added in v0.18.0

type FieldContainer interface {
	GetSubfields() map[string]field.Field
}

FieldContainer should be implemented by the type to be described we use GetSubfields() as a common method to get subfields while Message doesn't implement FieldContainer interface directly we use MessageWrapper to wrap Message and implement FieldContainer

type FieldFilter added in v0.14.0

type FieldFilter func(fieldFilters map[string]FilterFunc)

func FilterField added in v0.14.0

func FilterField(id string, filterFn FilterFunc) FieldFilter

type FilterFunc added in v0.14.0

type FilterFunc func(in string, data field.Field) string

type Message

type Message struct {
	// contains filtered or unexported fields
}

func NewMessage

func NewMessage(spec *MessageSpec) *Message

func (*Message) BinaryField added in v0.0.2

func (m *Message) BinaryField(id int, val []byte) error

func (*Message) Bitmap added in v0.0.2

func (m *Message) Bitmap() *field.Bitmap

func (*Message) Clone added in v0.8.0

func (m *Message) Clone() (*Message, error)

Clone clones the message by creating a new message from the binary representation of the original message

func (*Message) Field added in v0.0.2

func (m *Message) Field(id int, val string) error

func (*Message) GetBytes added in v0.0.2

func (m *Message) GetBytes(id int) ([]byte, error)

func (*Message) GetField added in v0.4.1

func (m *Message) GetField(id int) field.Field

func (*Message) GetFields added in v0.4.1

func (m *Message) GetFields() map[int]field.Field

Fields returns the map of the set fields

func (*Message) GetMTI added in v0.0.2

func (m *Message) GetMTI() (string, error)

func (*Message) GetSpec added in v0.4.8

func (m *Message) GetSpec() *MessageSpec

func (*Message) GetString added in v0.0.2

func (m *Message) GetString(id int) (string, error)

func (*Message) MTI added in v0.0.2

func (m *Message) MTI(val string)

func (*Message) Marshal added in v0.10.0

func (m *Message) Marshal(v interface{}) error

Marshal populates message fields with v struct field values. It traverses through the message fields and calls Unmarshal(...) on them setting the v If v is not a struct or not a pointer to struct then it returns error.

func (*Message) MarshalJSON added in v0.3.3

func (m *Message) MarshalJSON() ([]byte, error)

func (*Message) Pack added in v0.0.2

func (m *Message) Pack() ([]byte, error)

Pack locks the message, packs its fields, and then unlocks it. If any errors are encountered during packing, they will be wrapped in a *PackError before being returned.

func (*Message) SetData added in v0.0.2

func (m *Message) SetData(data interface{}) error

Deprecated. Use Marshal instead.

func (*Message) Unmarshal added in v0.10.0

func (m *Message) Unmarshal(v interface{}) error

Unmarshal populates v struct fields with message field values. It traverses through the message fields and calls Unmarshal(...) on them setting the v If v is nil or not a pointer it returns error.

func (*Message) UnmarshalJSON added in v0.6.1

func (m *Message) UnmarshalJSON(b []byte) error

func (*Message) Unpack added in v0.0.2

func (m *Message) Unpack(src []byte) error

Unpack unpacks the message from the given byte slice or returns an error which is of type *UnpackError and contains the raw message

type MessageSpec added in v0.0.2

type MessageSpec struct {
	Name   string
	Fields map[int]field.Field
}
var Spec87 *MessageSpec = &MessageSpec{
	Name: "ISO 8583 v1987 ASCII",
	Fields: map[int]field.Field{
		0: field.NewString(&field.Spec{
			Length:      4,
			Description: "Message Type Indicator",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		1: field.NewBitmap(&field.Spec{
			Length:      8,
			Description: "Bitmap",
			Enc:         encoding.BytesToASCIIHex,
			Pref:        prefix.Hex.Fixed,
		}),
		2: field.NewString(&field.Spec{
			Length:      19,
			Description: "Primary Account Number",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LL,
		}),
		3: field.NewNumeric(&field.Spec{
			Length:      6,
			Description: "Processing Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		4: field.NewString(&field.Spec{
			Length:      12,
			Description: "Transaction Amount",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
			Pad:         padding.Left('0'),
		}),
		5: field.NewString(&field.Spec{
			Length:      12,
			Description: "Settlement Amount",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
			Pad:         padding.Left('0'),
		}),
		6: field.NewString(&field.Spec{
			Length:      12,
			Description: "Billing Amount",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
			Pad:         padding.Left('0'),
		}),
		7: field.NewString(&field.Spec{
			Length:      10,
			Description: "Transmission Date & Time",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		8: field.NewString(&field.Spec{
			Length:      8,
			Description: "Billing Fee Amount",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		9: field.NewString(&field.Spec{
			Length:      8,
			Description: "Settlement Conversion Rate",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		10: field.NewString(&field.Spec{
			Length:      8,
			Description: "Cardholder Billing Conversion Rate",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		11: field.NewString(&field.Spec{
			Length:      6,
			Description: "Systems Trace Audit Number (STAN)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		12: field.NewString(&field.Spec{
			Length:      6,
			Description: "Local Transaction Time",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		13: field.NewString(&field.Spec{
			Length:      4,
			Description: "Local Transaction Date",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		14: field.NewString(&field.Spec{
			Length:      4,
			Description: "Expiration Date",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		15: field.NewString(&field.Spec{
			Length:      4,
			Description: "Settlement Date",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		16: field.NewString(&field.Spec{
			Length:      4,
			Description: "Currency Conversion Date",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		17: field.NewString(&field.Spec{
			Length:      4,
			Description: "Capture Date",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		18: field.NewString(&field.Spec{
			Length:      4,
			Description: "Merchant Type",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		19: field.NewString(&field.Spec{
			Length:      3,
			Description: "Acquiring Institution Country Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		20: field.NewString(&field.Spec{
			Length:      3,
			Description: "PAN Extended Country Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		21: field.NewString(&field.Spec{
			Length:      3,
			Description: "Forwarding Institution Country Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		22: field.NewString(&field.Spec{
			Length:      3,
			Description: "Point of Sale (POS) Entry Mode",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		23: field.NewString(&field.Spec{
			Length:      3,
			Description: "Card Sequence Number (CSN)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		24: field.NewString(&field.Spec{
			Length:      3,
			Description: "Function Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		25: field.NewString(&field.Spec{
			Length:      2,
			Description: "Point of Service Condition Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		26: field.NewString(&field.Spec{
			Length:      2,
			Description: "Point of Service PIN Capture Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		27: field.NewString(&field.Spec{
			Length:      1,
			Description: "Authorizing Identification Response Length",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		28: field.NewString(&field.Spec{
			Length:      9,
			Description: "Transaction Fee Amount",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		29: field.NewString(&field.Spec{
			Length:      9,
			Description: "Settlement Fee Amount",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		30: field.NewString(&field.Spec{
			Length:      9,
			Description: "Transaction Processing Fee Amount",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		31: field.NewString(&field.Spec{
			Length:      9,
			Description: "Settlement Processing Fee Amount",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		32: field.NewString(&field.Spec{
			Length:      11,
			Description: "Acquiring Institution Identification Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LL,
		}),
		33: field.NewString(&field.Spec{
			Length:      11,
			Description: "Forwarding Institution Identification Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LL,
		}),
		34: field.NewString(&field.Spec{
			Length:      28,
			Description: "Extended Primary Account Number",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LL,
		}),
		35: field.NewString(&field.Spec{
			Length:      37,
			Description: "Track 2 Data",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LL,
		}),
		36: field.NewString(&field.Spec{
			Length:      104,
			Description: "Track 3 Data",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		37: field.NewString(&field.Spec{
			Length:      12,
			Description: "Retrieval Reference Number",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		38: field.NewString(&field.Spec{
			Length:      6,
			Description: "Authorization Identification Response",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		39: field.NewString(&field.Spec{
			Length:      2,
			Description: "Response Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		40: field.NewString(&field.Spec{
			Length:      3,
			Description: "Service Restriction Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		41: field.NewString(&field.Spec{
			Length:      8,
			Description: "Card Acceptor Terminal Identification",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		42: field.NewString(&field.Spec{
			Length:      15,
			Description: "Card Acceptor Identification Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		43: field.NewString(&field.Spec{
			Length:      40,
			Description: "Card Acceptor Name/Location",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		44: field.NewString(&field.Spec{
			Length:      99,
			Description: "Additional Data",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LL,
		}),
		45: field.NewString(&field.Spec{
			Length:      76,
			Description: "Track 1 Data",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LL,
		}),
		46: field.NewString(&field.Spec{
			Length:      999,
			Description: "Additional data (ISO)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		47: field.NewString(&field.Spec{
			Length:      999,
			Description: "Additional data (National)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		48: field.NewString(&field.Spec{
			Length:      999,
			Description: "Additional data (Private)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		49: field.NewString(&field.Spec{
			Length:      3,
			Description: "Transaction Currency Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		50: field.NewString(&field.Spec{
			Length:      3,
			Description: "Settlement Currency Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		51: field.NewString(&field.Spec{
			Length:      3,
			Description: "Cardholder Billing Currency Code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		52: field.NewString(&field.Spec{
			Length:      8,
			Description: "PIN Data",
			Enc:         encoding.BytesToASCIIHex,
			Pref:        prefix.Hex.Fixed,
		}),
		53: field.NewString(&field.Spec{
			Length:      16,
			Description: "Security Related Control Information",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		54: field.NewString(&field.Spec{
			Length:      120,
			Description: "Additional Amounts",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		55: field.NewString(&field.Spec{
			Length:      999,
			Description: "ICC Data – EMV Having Multiple Tags",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		56: field.NewString(&field.Spec{
			Length:      999,
			Description: "Reserved (ISO)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		57: field.NewString(&field.Spec{
			Length:      999,
			Description: "Reserved (National)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		58: field.NewString(&field.Spec{
			Length:      999,
			Description: "Reserved (National)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		59: field.NewString(&field.Spec{
			Length:      999,
			Description: "Reserved (National)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		60: field.NewString(&field.Spec{
			Length:      999,
			Description: "Reserved (National)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		61: field.NewString(&field.Spec{
			Length:      999,
			Description: "Reserved (Private)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		62: field.NewString(&field.Spec{
			Length:      999,
			Description: "Reserved (Private)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		63: field.NewString(&field.Spec{
			Length:      999,
			Description: "Reserved (Private)",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.LLL,
		}),
		64: field.NewString(&field.Spec{
			Length:      8,
			Description: "Message Authentication Code (MAC)",
			Enc:         encoding.BytesToASCIIHex,
			Pref:        prefix.Hex.Fixed,
		}),
		70: field.NewString(&field.Spec{
			Length:      3,
			Description: "Network management information code",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
		90: field.NewString(&field.Spec{
			Length:      42,
			Description: "Original Data Elements",
			Enc:         encoding.ASCII,
			Pref:        prefix.ASCII.Fixed,
		}),
	},
}

keep it here for a little while for compatibility all new specs and updates to Spec87 should go to ./specs

func (*MessageSpec) CreateMessageFields added in v0.0.2

func (s *MessageSpec) CreateMessageFields() map[int]field.Field

Creates a map with new instances of Fields (Field interface) based on the field type in MessageSpec.

func (*MessageSpec) Validate added in v0.19.3

func (s *MessageSpec) Validate() error

Validate checks if the MessageSpec is valid.

type MessageWrapper added in v0.18.0

type MessageWrapper struct {
	*Message
}

MessageWrapper implements FieldContainer interface for the iso8583.Message as currently it has GetFields() and not GetSubfields and it returns map[int]field.Field (key is int, not string)

func (*MessageWrapper) GetSubfields added in v0.18.0

func (m *MessageWrapper) GetSubfields() map[string]field.Field

type MesssageTypeIndicator added in v0.4.10

type MesssageTypeIndicator string

MesssageTypeIndicator message type indicator is a four-digit numeric field which indicates the overall function of the ISO 8583:1987 message

const (
	// AuthorizationRequest is a request from a point-of-sale terminal for authorization for a cardholder purchase
	AuthorizationRequest MesssageTypeIndicator = "0100"

	// AuthorizationResponse is a request response to a point-of-sale terminal for authorization for a cardholder purchase
	AuthorizationResponse MesssageTypeIndicator = "0110"

	// AuthorizationAdvice is when the point-of-sale device breaks down and you have to sign a voucher
	AuthorizationAdvice MesssageTypeIndicator = "0120"

	// AuthorizationAdviceRepeat used to repeat if the advice times out
	AuthorizationAdviceRepeat MesssageTypeIndicator = "0121"

	// IssuerResponseToAuthorizationAdvice is a confirmation of receipt of authorization advice
	IssuerResponseToAuthorizationAdvice MesssageTypeIndicator = "0130"

	// AuthorizationPositiveAcknowledgement indicates that an Authorization Response was received
	AuthorizationPositiveAcknowledgement MesssageTypeIndicator = "0180"

	// AuthorizationNegativeAcknowledgement indicates that an Authorization Response or Reversal Response was late or invalid
	AuthorizationNegativeAcknowledgement MesssageTypeIndicator = "0190"

	// AcquirerFinancialRequest is a request for funds, typically from an ATM or pinned point-of-sale device
	AcquirerFinancialRequest MesssageTypeIndicator = "0200"

	// IssuerResponseToFinancialRequest is a issuer response to request for funds
	IssuerResponseToFinancialRequest MesssageTypeIndicator = "0210"

	// AcquirerFinancialAdvice is used to complete transaction initiated with authorization request. e.g. Checkout at a hotel.
	AcquirerFinancialAdvice MesssageTypeIndicator = "0220"

	// AcquirerFinancialAdviceRepeat is used if the advice times out
	AcquirerFinancialAdviceRepeat MesssageTypeIndicator = "0221"

	// IssuerResponseToFinancialAdvice is a confirmation of receipt of financial advice
	IssuerResponseToFinancialAdvice MesssageTypeIndicator = "0230"

	// BatchUpload is a file update/transfer advice
	BatchUpload MesssageTypeIndicator = "0320"

	// BatchUploadResponse is a file update/transfer advice response
	BatchUploadResponse MesssageTypeIndicator = "0330"

	// AcquirerReversalRequest is used to reverse a transaction
	AcquirerReversalRequest MesssageTypeIndicator = "0400"

	// AcquirerReversalResponse is a response to a reversal request
	AcquirerReversalResponse MesssageTypeIndicator = "0410"

	// AcquirerReversalAdvice
	AcquirerReversalAdvice MesssageTypeIndicator = "0420"

	// AcquirerReversalAdviceResponse
	AcquirerReversalAdviceResponse MesssageTypeIndicator = "0430"

	// BatchSettlementResponse is a card acceptor reconciliation request response
	BatchSettlementResponse MesssageTypeIndicator = "0510"

	// AdministrativeRequest is a message delivering administrative data, often free-form and potentially indicating a failure message
	AdministrativeRequest MesssageTypeIndicator = "0600"

	// AdministrativeResponse is a response to an administrative request
	AdministrativeResponse MesssageTypeIndicator = "0610"

	// AdministrativeAdvice is an administrative request with stronger delivery guarantees
	AdministrativeAdvice MesssageTypeIndicator = "0620"

	// AdministrativeAdviceResponse is a response to an administrative advice
	AdministrativeAdviceResponse MesssageTypeIndicator = "0630"

	// NetworkManagementRequest is used in hypercom terminals initialize request. Echo test, logon, logoff etc
	NetworkManagementRequest MesssageTypeIndicator = "0800"

	// NetworkManagementResponse is a hypercom terminals initialize response. Echo test, logon, logoff etc.
	NetworkManagementResponse MesssageTypeIndicator = "0810"

	// NetworkManagementAdvice is a key change
	NetworkManagementAdvice MesssageTypeIndicator = "0820"
)

type PackError added in v0.18.3

type PackError struct {
	Err error
}

func (*PackError) Error added in v0.18.3

func (e *PackError) Error() string

func (*PackError) Unwrap added in v0.18.3

func (e *PackError) Unwrap() error

type UnpackError added in v0.18.3

type UnpackError struct {
	Err        error
	FieldID    string
	RawMessage []byte
}

UnpackError returns error with possibility to access RawMessage when connection failed to unpack message

func (*UnpackError) Error added in v0.18.3

func (e *UnpackError) Error() string

func (*UnpackError) Unwrap added in v0.18.3

func (e *UnpackError) Unwrap() error

Directories

Path Synopsis
cmd
examples
exp
emv
test

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL