Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Secondary bitmaps and a parsing fix #12

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public BaseMessageClassBuilder(String version, String messageClass)
public ISOMessage build() throws ISOException {

ISOMessage finalMessage = new ISOMessage();
finalMessage.setMessage(buildBuffer(true),this.header != null);
finalMessage.setMessage(buildBuffer(),this.header != null);

//clear();

Expand All @@ -56,23 +56,33 @@ private void clear()
dataElements = new TreeMap<>();
}

private byte[] buildBuffer(boolean generateBitmap)
{
private byte[] buildBuffer() throws ISOException {
FixedBitSet primaryBitmap = new FixedBitSet(64);
FixedBitSet secondaryBitmap = new FixedBitSet(64);
ByteArray dataBuffer = new ByteArray();

for(Map.Entry<Integer, byte[]> elem : dataElements.entrySet()) {
if(generateBitmap)
if(elem.getKey()>64) {
secondaryBitmap.flip(elem.getKey() - 65);

setField(FIELDS.F1_Bitmap, StringUtil.hexStringToByteArray(secondaryBitmap.toHexString()));
}
}

for(Map.Entry<Integer, byte[]> elem : dataElements.entrySet()) {
if(elem.getKey()<=64)
primaryBitmap.flip(elem.getKey() - 1);
}

for(Map.Entry<Integer, byte[]> elem : dataElements.entrySet()) {
dataBuffer.append(elem.getValue());
}

if(generateBitmap)
dataBuffer.prepend(StringUtil.hexStringToByteArray(primaryBitmap.toHexString()));
dataBuffer.prepend(StringUtil.hexStringToByteArray(primaryBitmap.toHexString()));

dataBuffer.prepend(StringUtil.hexStringToByteArray((version + messageClass + messageFunction + messageOrigin)));

if(header!=null && generateBitmap)
if(header!=null)
dataBuffer.prepend(StringUtil.hexStringToByteArray(header));

return dataBuffer.array();
Expand Down Expand Up @@ -202,6 +212,7 @@ public DataElement<T> setField(int no, String value) throws ISOException {
public DataElement<T> setField(FIELDS field, String value) throws ISOException {
switch (field.getType())
{
case "a|n":
case "n":
setField(field,StringUtil.hexStringToByteArray(value),value.length());
break;
Expand All @@ -218,7 +229,7 @@ public DataElement<T> generateMac(ISOMacGenerator generator) throws ISOExceptio

if(generator != null)
{
byte[] mac = generator.generate(buildBuffer(true));
byte[] mac = generator.generate(buildBuffer());
if(mac != null)
setField(FIELDS.F64_MAC,mac);
else
Expand Down
38 changes: 23 additions & 15 deletions src/main/java/com/imohsenb/ISO8583/entities/ISOMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,22 @@ private void parseHeader() {
}

private void parseBody() {
FixedBitSet pb = new FixedBitSet(64);
pb.fromHexString(StringUtil.fromByteArray(primaryBitmap));
int offset = 10;
FixedBitSet primaryBitmap = new FixedBitSet(64);
primaryBitmap.fromHexString(StringUtil.fromByteArray(this.primaryBitmap));
int byteOffset = 10;

for (int o : pb.getIndexes()) {
byteOffset = readFields(primaryBitmap, byteOffset, 0);

FIELDS field = FIELDS.valueOf(o);
byte [] secondaryBitmapBytes = getField(FIELDS.F1_Bitmap);
if(secondaryBitmapBytes != null) {
FixedBitSet secondaryBitmap = new FixedBitSet(64).fromHexString(StringUtil.fromByteArray(secondaryBitmapBytes));
readFields(secondaryBitmap, byteOffset, 64);
}
}

private int readFields(FixedBitSet bitmap, int byteOffset, int fieldOffset) {
for (int fieldIndex : bitmap.getIndexes()) {
FIELDS field = FIELDS.valueOf(fieldIndex+fieldOffset);

if (field.isFixed()) {
int len = field.getLength();
Expand All @@ -216,15 +225,14 @@ private void parseBody() {
if (len % 2 != 0)
len++;
len = len / 2;
addElement(field, Arrays.copyOfRange(body, offset, offset + len));
addElement(field, Arrays.copyOfRange(body, byteOffset, byteOffset + len));
break;
default:
addElement(field, Arrays.copyOfRange(body, offset, offset + len));
addElement(field, Arrays.copyOfRange(body, byteOffset, byteOffset + len));
break;
}
offset += len;
byteOffset += len;
} else {

int formatLength = 1;
switch (field.getFormat()) {
case "LL":
Expand All @@ -236,22 +244,22 @@ private void parseBody() {
}

int flen = Integer.valueOf(
StringUtil.fromByteArray(Arrays.copyOfRange(body, offset, offset + formatLength)));
StringUtil.fromByteArray(Arrays.copyOfRange(body, byteOffset, byteOffset + formatLength)));

switch (field.getType()) {
case "z":
case "n":
flen /= 2;
flen = flen / 2 + flen % 2;
}

offset = offset + formatLength;
byteOffset = byteOffset + formatLength;

addElement(field, Arrays.copyOfRange(body, offset, offset + flen));
addElement(field, Arrays.copyOfRange(body, byteOffset, byteOffset + flen));

offset += flen;
byteOffset += flen;
}

}
return byteOffset;
}

private void addElement(FIELDS field, byte[] data) {
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/com/imohsenb/ISO8583/enums/FIELDS.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/
public enum FIELDS {
// |Field title |no |type |len |fixed |format|
F1_Bitmap (1, "b", 64, true, null),
F1_Bitmap (1, "b", 8, true, null),
F2_PAN (2, "n", 19, false, "LL"),
F3_ProcessCode (3, "n", 6, true, null),
F4_AmountTransaction (4, "n", 12, true, null),
Expand Down Expand Up @@ -71,7 +71,8 @@ public enum FIELDS {
F61_Reserved_Private (61, "ans", 999, false, "LLL"),
F62_Reserved_Private (62, "ans", 999, false, "LLL"),
F63_Reserved_Private (63, "ans", 999, false, "LLL"),
F64_MAC (64, "b", 16, true, null);
F64_MAC (64, "b", 16, true, null),
F70_Network_Management_Code (70, "n", 3, true, null);



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.imohsenb.ISO8583.enums.MESSAGE_ORIGIN;
import com.imohsenb.ISO8583.enums.VERSION;
import com.imohsenb.ISO8583.exceptions.ISOException;
import com.imohsenb.ISO8583.utils.StringUtil;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -93,4 +94,18 @@ public void OddPanShouldHaveCorrectLengthPrefixAndPaddingChar() throws Exception
System.out.println(isoMessage.toString());
assertThat(isoMessage.toString()).isEqualTo("080060000000000000001901234567890123456789920000");
}
}

@Test
public void AMessageWithASecondaryBitmapIsFormattedCorrectly() throws ISOException {
ISOMessage isoMessage = ISOMessageBuilder.Packer(VERSION.V1987)
.networkManagement()
.setLeftPadding((byte) 0x0)
.mti(MESSAGE_FUNCTION.Request, MESSAGE_ORIGIN.Acquirer)
.processCode("123456")
.setField(FIELDS.F70_Network_Management_Code, "310")
.build();
System.out.println(isoMessage.toString());
assertThat(isoMessage.toString()).isEqualTo("0800A00000000000000004000000000000001234560310");
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.imohsenb.ISO8583.builders;

import com.imohsenb.ISO8583.entities.ISOMessage;
import com.imohsenb.ISO8583.enums.FIELDS;
import com.imohsenb.ISO8583.exceptions.ISOException;
import com.imohsenb.ISO8583.utils.StringUtil;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class ISOMessageParseTest {
@Test
public void anEvenLengthPanIsParsedCorrectly() throws Exception {
ISOMessage isoMessage = new ISOMessage();
isoMessage.setMessage(StringUtil.hexStringToByteArray("08006000000000000000161234567890123456920000"), false);

assertThat(isoMessage.getField(FIELDS.F2_PAN)).isEqualTo(StringUtil.hexStringToByteArray("1234567890123456"));
}

@Test
public void anOddLengthPanIsParsedCorrectly() throws Exception {
ISOMessage isoMessage = new ISOMessage();
isoMessage.setMessage(StringUtil.hexStringToByteArray("080060000000000000001901234567890123456789920000"), false);

assertThat(isoMessage.getField(FIELDS.F2_PAN)).isEqualTo(StringUtil.hexStringToByteArray("01234567890123456789"));
}

@Test
public void anExtendedFieldIsReadCorrectly() throws ISOException {
ISOMessage isoMessage = new ISOMessage();
isoMessage.setMessage(StringUtil.hexStringToByteArray("0800A00000000000000004000000000000001234560310"), false);

assertThat(isoMessage.getField(FIELDS.F70_Network_Management_Code)).isEqualTo(StringUtil.hexStringToByteArray("0310"));
}
}