Build ISO8583 Message

ISO8583Message.kt

In this class to make ISO8583 Message require data and some params default is null. This class is on project path is utils > ISO8583Message.kt

class ISO8583Message(
    private val transactionType: String?,
    private val cardNumber: String? = null,
    private val operation: String? = null,
    private val amount: String? = null,
    private val additionalAmount: String? = null,
    private val originalAmount: String? = null,
    private val cardEXP: String? = null,
    private val typeA0: String? = "credit_account",
    private val type0X: String? = "more_message_indicator",
    private val track1: String? = null,
    private val track2: String? = null,
    private val tid: String? = null,
    private val mid: String? = null,
    private val nii: String? = null,
    private val stan: Int?,
    private val invoice: Int?,
    private val refNumber: String?,
    private val approveCode: String?,
    private val responseCode: String?,
    private val date: String?,
    private val time: String?,
    private val realm: Realm,
    private val TLV: String? = null
) {
    ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

How to get message

On class have a function to return ISO8583 data on string format.

fun iso8583Payload(): String {
    // Get tpdu
    val tpdu = getTPDU()
    // Get message type
    val messageType = getTransactionMessageType()
    // Get bitmap
    var bitmap = getBitmap()
    // Get data payload
    var data = bitmapElement().toString()

    // Merge data
    val mergeData = tpdu + messageType + bitmap + data
    // Calculate length of message
    val headerLength = payloadLength(mergeData)
    // Return ISO8583 message
    return headerLength + mergeData
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Calculate Payload length

In ISO8583 Message is a first of message should be length of all of message to tell host for valid message is true.

private fun payloadLength(payload: String): String {
    // find Payload length with /2 and change to HEX by 4 characters.
    return (payload.length / 2).toString(16).padStart(4, '0')
}
1
2
3
4

Build payload with bitmap

This function to use for build message by bitmap and loop to call getBitElementDetail function

private fun bitmapElement(): StringBuilder1 {
    // Initail StringBuilder for keep string data
    val payload = StringBuilder1()
    // Loop by bitmap
    getBitmapOperation().bitmaps.forEach {
        // Add string to string builder
        payload.append(getBitElementDetail(it))
    }
    // Return string builder
    return payload
}
1
2
3
4
5
6
7
8
9
10
11

Build payload data

This function use when call from bitmapElement function and return string when build message finished

private fun getBitElementDetail(bit: Int): String {
    // Find bitmap element at current position
    val getBit = isoBitmapEleData.isoBitElement.single { it.bit == bit }
    // Initial return response by string
    val responseData: String
    when (bit) {
        // Bit 2 case
        2 -> {
            // call function checkType and recive data by string
            responseData = checkType(cardNumber, getBit)
        }
        3 -> {
            // check processing code
            var processingCode = ""
            if (getProcessingCodeList().size > 0) {
                getProcessingCodeList().forEach {
                    val currentName = it.lowercase(Locale.getDefault())
                    val getNameOfProcessingCode =
                        if (currentName == "a0" || currentName == "0x") {
                            realm.where<ProcessingCodeRO>().equalTo("name", currentName).findFirst()
                        } else null
                    processingCode += when (currentName) {
                        "a0" -> {
                            getNameOfProcessingCode!!.data.single { data -> data.acc == typeA0 }.code.toString() + "0"
                        }
                        "0x" -> {
                            "0" + getNameOfProcessingCode!!.data.single { data -> data.acc == type0X }.code.toString()
                        }
                        else -> {
                            currentName
                        }
                    }
                }
            } else {
                processingCode = processingCodeReversal!!
            }
            responseData = processingCode
        }
        4 -> {
            val transformAmount =
                amount?.replace(".", "") ?: throw Exception("Amount is invalid")
            responseData = checkType(transformAmount, getBit)
        }
        ...
        
        else -> {
            responseData = "..."
        }
    }
    return responseData
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Last Updated:
Contributors: Supavit Panyafang