【问题标题】:Invalid ISO 8583 HeaderISO 8583 标头无效
【发布时间】:2019-05-13 09:35:21
【问题描述】:

我正在尝试解析 ISO 8583 消息并获取各个数据元素。 下面的代码我已经尝试过了

ISOResponse.java

public class ISOResponse {
private static final String TAG = "ISOResponse";
private static final String ISOResponseMessage = "60010203040210303800000E8002000000000000000031000046741306511212383334363133303034363734313330363534303036323730353532340012910A59218CDAFBBCD2520014";

public void parseISO8583(final Context context) throws ParseException, IOException {

    MessageFactory<IsoMessage> messageFactory = new MessageFactory<IsoMessage>();

    if (1 == 0) {
        ConfigParser.configureFromDefault(messageFactory);
    } else {

        PrintLog.log(TAG, "Messagefactory is done");

        InputStream inputData = context.getResources().openRawResource(R.raw.j8583_config);

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputData));

        ConfigParser.configureFromReader(messageFactory, bufferedReader);

    }

    messageFactory.setIgnoreLastMissingField(true);
    IsoMessage isoMessage = messageFactory.parseMessage(ISOResponseMessage.getBytes(),10);
    if (isoMessage != null) {
        PrintLog.log(TAG, "Message type: %04x%n" + isoMessage.getType());
        PrintLog.log(TAG, "FIELD TYPE VALUE");
        for (int i = 2; i <= 64; i++) {
            IsoValue<?> f = isoMessage.getField(i);
            if (f != null) {
                PrintLog.log(TAG, "%5d %-6s [" + i + f.getType());
                PrintLog.log(TAG, f.toString());
                PrintLog.log(TAG, "" + ']');
            }
        }
    }
}
}

j8583_config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE j8583-config PUBLIC "-//J8583//DTD CONFIG 1.0//EN"
"http://j8583.sourceforge.net/j8583.dtd">
<j8583-config>
<!-- This is a test config file -->

<!-- These are the ISO headers to be prepended to the message types specified -->
<header type="0800"/>

<template type="0280">
    <field num="3" type="NUMERIC" length="2">99</field>
</template>

<!-- The server example uses this to read the requests -->
<parse type="0200">
    <field num="3" type="NUMERIC" length="6" />
    <field num="4" type="AMOUNT" />
    <field num="7" type="DATE10" />
    <field num="11" type="NUMERIC" length="6" />
    <field num="12" type="TIME" />
    <field num="13" type="DATE4" />
    <field num="15" type="DATE4" />
    <field num="17" type="DATE_EXP" />
    <field num="32" type="LLVAR" />
    <field num="35" type="LLVAR" />
    <field num="37" type="NUMERIC" length="12" />
    <field num="41" type="ALPHA" length="16" />
    <field num="43" type="ALPHA" length="40" />
    <field num="48" type="LLLVAR" />
    <field num="49" type="ALPHA" length="3" />
    <field num="60" type="LLLVAR" />
    <field num="61" type="LLLVAR" />
    <field num="100" type="LLVAR" />
    <field num="102" type="LLVAR" />
</parse>


<!-- The client example uses this to read the responses -->
<parse type="0210">
    <field num="3" type="NUMERIC" length="6" />
    <field num="4" type="AMOUNT" length="12" />
    <field num="11" type="NUMERIC" length="6" />
    <field num="12" type="TIME" length="6" />
    <field num="13" type="DATE4" length="4" />
    <field num="37" type="NUMERIC" length="12" />
    <field num="38" type="NUMERIC" length="6" />
    <field num="39" type="NUMERIC" length="2" />
    <field num="41" type="ALPHA" length="8" />
    <field num="55" type="LLLVAR" length="255" />
</parse>

<!-- this is for binary tests (message encoding AND fields) -->
<parse type="0600">
    <field num="4" type="AMOUNT" />
    <field num="7" type="DATE10" />
    <field num="11" type="NUMERIC" length="6" />
    <field num="41" type="BINARY" length="8" />
    <field num="42" type="BINARY" length="4" />
    <field num="43" type="ALPHA" length="40" />
    <field num="62" type="LLBIN" />
    <field num="63" type="LLBIN" />
    <field num="64" type="LLLBIN" />
    <field num="65" type="LLLBIN" />
    <field num="102" type="LLLVAR" />
</parse>

<parse type="0800">
    <field num="3" type="ALPHA" length="6"/>
    <field num="12" type="DATE4" length="14"/>
    <field num="17" type="DATE4" length="8"/>
    <field num="11" type="NUMERIC" length="6"/>
    <field num="41" type="LLVAR" length="16"/>
</parse>

<parse type="0810" extends="0800">
    <field num="17" type="exclude"/>
    <field num="39" type="ALPHA" length="2"/>
</parse>

<parse type="0201">
    <field num="3" type="NUMERIC" length="19" />
</parse>
<parse type="0202">
    <field num="3" type="NUMERIC" length="22" />
</parse>
<parse type="0280">
    <field num="3" type="NUMERIC" length="2" />
</parse>

在这之后我的代码抛出了一个

无效的 ISO 8583 标头

异常。我尝试在isoMessage 中删除标头数据并使标头长度为0,但仍然给出相同的异常。

谁能帮我找出代码中的错误。 提前致谢。

【问题讨论】:

    标签: java android iso8583


    【解决方案1】:

    我尝试解析你的消息,我得到了这个:

    <parse header="6001020304" type="0210" bitmap="303800000E800200">
        <field num="3" type="NUMERIC"  length="6"  value="000000" />
        <field num="4" type="AMOUNT"   length="12" value="000000003100" />
        <field num="11" type="NUMERIC" length="6"  value="004674" />
        <field num="12" type="TIME"    length="6"  value="130651" />
        <field num="13" type="DATE4"   length="4"  value="121238" />
        <field num="37" type="NUMERIC" length="12" value="346130046741" />
        <field num="38" type="NUMERIC" length="6"  value="306540" />
        <field num="39" type="NUMERIC" length="2"  value="06" />
        <field num="41" type="ALPHA"   length="8"  value="2705524\0" />
        <field num="55" type="LLLVAR"  length="12" value="910A59218CDAFBBCD2520014" />
    </parse>
    

    您的消息头长度似乎是 14,包括 MTI(或 10 没有 MTI

    【讨论】:

    • 我发现了这个问题,这是因为配置文件。我从配置文件中删除了“
      ”,它起作用了。谢谢你的尝试。
    【解决方案2】:

    我建议使用另一种方法来打包和解包消息。 iso-8583-packer 允许您将消息解包到以下字段

    <f>
        <f name="Header" val="6001020304" valHex="6001020304"/>
        <f name="MTI" val="0210" valHex="0210"/>
        <f name="Bitmap" bitmapHex="303800000E800200" bitSet="{3, 4, 11, 12, 13, 37, 38, 39, 41, 55}">
            <f name="ProcessingCode" fieldNum="3" val="000000" valHex="000000"/>
            <f name="Amount" fieldNum="4" val="000000003100" valHex="000000003100"/>
            <f name="SystemTraceAuditNumber" fieldNum="11" val="004674" valHex="004674"/>
            <f name="LocalTransactionTimeHHMMSS" fieldNum="12" val="130651" valHex="130651"/>
            <f name="LocalTransactionDateMMDD" fieldNum="13" val="1212" valHex="1212"/>
            <f name="PosNumber" fieldNum="37" val="8346130046741" valHex="38333436...36373431"/>
            <f name="ApprovalCode" fieldNum="38" val="306540" valHex="333036353430"/>
            <f name="ActionCode" fieldNum="39" val="06" valHex="3036"/>
            <f name="TerminalId" fieldNum="41" val="2705524" valHex="32373035353234"/>
            <f name="EMV" fieldNum="55" val="910A59218CDAFBBCD2520014" lenHex="0012" valHex="910A5921...D2520014"/>
        </f>
    </f>
    

    消息有如下定义

    <f type="MSG">
        <f type="VAL" name="Header" bodyPacker="LiteralBodyPacker" len="5"/>
        <f type="VAL" name="MTI" bodyPacker="BcdBodyPacker" len="2"/>
        <f type="BIT_SET" name="Bitmap" bitMapPacker="IfbBitmapPacker">
            <f type="VAL" fieldNum="3" name="ProcessingCode" bodyPacker="HexBodyPacker" len="3"/>
            <f type="VAL" fieldNum="4" name="Amount" bodyPacker="BcdBodyPacker" len="6"/>
            <f type="VAL" fieldNum="11" name="SystemTraceAuditNumber" bodyPacker="BcdBodyPacker" len="3"/>
            <f type="VAL" fieldNum="12" name="LocalTransactionTimeHHMMSS" bodyPacker="BcdBodyPacker" len="3"/>
            <f type="VAL" fieldNum="13" name="LocalTransactionDateMMDD" bodyPacker="BcdBodyPacker" len="2"/>
            <f type="VAL" fieldNum="37" name="PosNumber" bodyPacker="AsciiBodyPacker" len="13"/>
            <f type="VAL" fieldNum="38" name="ApprovalCode" bodyPacker="AsciiBodyPacker" len="6"/>
            <f type="VAL" fieldNum="39" name="ActionCode" bodyPacker="AsciiBodyPacker" len="2"/>
            <f type="VAL" fieldNum="41" name="TerminalId" bodyPacker="AsciiBodyPacker" len="7"/>
            <f type="LEN_VAL" fieldNum="55" name="EMV" lengthPacker="BcdLengthPacker" bodyPacker="HexBodyPacker"/>
        </f>
    </f>
    

    整个示例位于GitHub。 注意:我是iso-8583-packer Java 库的作者。

    【讨论】:

      【解决方案3】:

      我知道这是一个老问题,但我最近在使用这个库时遇到了类似的问题,只是想分享这个解决方案,以便它可以帮助其他人。 j8583 config.xml 由两部分组成,用于构建 iso 消息的标记和用于从字符串中解包消息的标记。其中每一个都有子元素字段、类型和子元素 num、type 和 length,用于定义每个 iso 8583 字段。根据经验,使用 j8583 解析 iso 消息的最佳方法是使用位图并生成配置文件,然后设置消息工厂。配置 XML 在 j8583.dtd 中导入一组定义的值并用作父标签,此文件存储在服务器中,因此您需要互联网在运行时下载它或自己下载并作为 SYSTEM 导入,如果您是使用 android 或应用程序在与互联网通信时遇到问题,最好将这些定义添加到 [] 中,而不是使用 PUBLIC -path 在这里查看更多信息https://www.w3schools.com/xml/xml_dtd.asp。同样重要的是,在解析响应时,不要在响应字符串消息中包含其总长度(前 4 个字符)或 tdpu 标头(之后的 10 个字符)。

      构建响应消息配置文件

      private void setResponseFactory(String responseMessage) throws IOException {
      
          Log.i(TAG, "in setResponseFactory");
      
          StringBuilder xmlParser = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                  "<!DOCTYPE j8583-config [\n<!ELEMENT j8583-config ( header*, template*, parse* ) >\n" +
                  "\n" +
                  "<!ELEMENT header ( #PCDATA ) >\n" +
                  "<!ATTLIST header type NMTOKEN #REQUIRED >\n" +
                  "<!ATTLIST header ref NMTOKEN #IMPLIED >\n" +
                  "<!ATTLIST header binary ( true | false ) #IMPLIED >\n" +
                  "\n" +
                  "<!ELEMENT template ( field* ) >\n" +
                  "<!ATTLIST template type NMTOKEN #REQUIRED >\n" +
                  "<!ATTLIST template extends NMTOKEN #IMPLIED >\n" +
                  "\n" +
                  "<!ELEMENT parse ( field* ) >\n" +
                  "<!ATTLIST parse type NMTOKEN #REQUIRED >\n" +
                  "<!ATTLIST parse extends NMTOKEN #IMPLIED >\n" +
                  "\n" +
                  "<!ELEMENT field ( #PCDATA|field )* >\n" +
                  "<!ATTLIST field num NMTOKEN #REQUIRED >\n" +
                  "<!ATTLIST field length NMTOKEN #IMPLIED >\n" +
                  "<!ATTLIST field tz NMTOKEN #IMPLIED >\n" +
                  "<!ATTLIST field type ( ALPHA | NUMERIC | AMOUNT | DATE4 | DATE6 | DATE10 | DATE12 | DATE14 | DATE_EXP | TIME | LLVAR | LLLVAR | LLLLVAR | BINARY | LLBIN | LLLBIN | LLLLBIN | LLBCDBIN | LLLBCDBIN | LLLLBCDBIN | exclude) #REQUIRED >\n]>\n\n\t\t<!-- This file is generated at runtime, for iso message parsing (unpacking), response message types are request type + 10 -->\n\n");
      
          String messageType = responseMessage.substring(0, 4); // response message type 0210 - sale, 0230 - advice ect...
      
          Log.i(TAG, "response message type " + messageType);
          Log.i(TAG, "hex bitmap " + responseMessage.substring(4, 20));
          String bitmap =   new BigInteger(responseMessage.substring(4, 20), 16).toString(2);
      
          int length = 64 - bitmap.length();
          char[] padArray = new char[length];
          Arrays.fill(padArray, '0');
          String padString = new String(padArray);
          bitmap = padString + bitmap; // padd bitmap with zeros to the left
      
          Log.i(TAG, "response bitmap " + bitmap);
      
          HashMap<Integer, Pair<IsoType, Integer>> config = new HashMap<>(); // iso response field dictionary
      
          config.put(Field_Indexes.PRIMARY_ACCOUNT_NUMBER, new Pair<>(IsoType.LLBIN, 0));
          config.put(Field_Indexes.PROCESS_CODE, new Pair<>(IsoType.NUMERIC, 6));
          config.put(Field_Indexes.TRANSACTION_AMOUNT, new Pair<>(IsoType.NUMERIC, 12));
          config.put(Field_Indexes.TRACE_AUDIT_NUMBER, new Pair<>(IsoType.NUMERIC, 6));
          config.put(Field_Indexes.LOCAL_TRANSMISSION_TIME, new Pair<>(IsoType.NUMERIC, 6));
          config.put(Field_Indexes.LOCAL_TRANSMISSION_DATE, new Pair<>(IsoType.NUMERIC, 4));
          config.put(Field_Indexes.POS_ENTRY_MODE, new Pair<>(IsoType.NUMERIC, 4));
          config.put(Field_Indexes.NETWORK_INTERNATIONAL_IDENTIFIER, new Pair<>(IsoType.NUMERIC, 4));
          config.put(Field_Indexes.POS_CONDITION_CODE, new Pair<>(IsoType.NUMERIC, 2));
          config.put(Field_Indexes.RETRIEVAL_REFERENCE_NUMBER, new Pair<>(IsoType.BINARY, 12));
          config.put(Field_Indexes.AUTHORIZATION_IDENTIFICATION_RESPONSE, new Pair<>(IsoType.BINARY, 6));
          config.put(Field_Indexes.RESPONSE_CODE, new Pair<>(IsoType.BINARY, 2));
          config.put(Field_Indexes.CARD_ACCEPTOR_TERMINAL_IDENTIFICATION, new Pair<>(IsoType.BINARY, 8));
          config.put(Field_Indexes.ICC_DATA, new Pair<>(IsoType.LLLLBCDBIN, 0));
          config.put(Field_Indexes.RN_FIELD_60, new Pair<>(IsoType.LLLLBIN, 0));
          config.put(Field_Indexes.RP_FIELD_63, new Pair<>(IsoType.LLLLBCDBIN, 0));
          config.put(Field_Indexes.MESSAGE_AUTHENTICATION_CODE_64, new Pair(IsoType.BINARY, 16));
      
          xmlParser.append("<j8583-config>\n\t\t<parse type=\"" + messageType + "\">");
      
          for(int i = 1; i<= 64; i++) // first bitmap if you are using secondary bitmap change to 128 instead of 64
              if(bitmap.charAt(i - 1) == '1')
                  xmlParser.append("\n\t\t\t<field num=\"" + i + "\" type=\"" + config.get(i).first.toString() + "\""
                          + ((config.get(i).second > 0) ? " length=\"" + config.get(i).second + "\" ": "")  + "/>");
      
      
          xmlParser.append("\n\t\t</parse>\n</j8583-config>");
          wrtieFileOnInternalStorage(xmlParser.toString());
      
          File root = new File(StateMachine.mContext.get().getFilesDir(),"response");
          File file = new File(root, "isoresponse.xml");
      
         responseFactory = ConfigParser.createFromClasspathConfig(file.getCanonicalPath());
      }
      

      调用消息解析器

          public static void main (String[] args){
              setResponseFactory(responseMessage);
              responseFactory.setUseBinaryMessages(false);
      
              Log.i(TAG, "in analize response");
      
              HashMap<Integer, String> isoResponseData = SimpleParser.unpackIsoMessage(responseFactory, responseMessage); // remove tag, tdpu header and trailing 0
      }
      

      使用简单解析器https://github.com/SergeyZyazyulkin/j8583/blob/master/src/main/java/com/solab/iso8583/util/SimpleParser.java实际解包

          public static HashMap<Integer, String> unpackIsoMessage(MessageFactory mf, String message) throws UnsupportedEncodingException, ParseException {
      
              HashMap<Integer, String> messageValues = new HashMap<>();
              Log.i(TAG, "message: " + message);
      
              if (message != null && message.length() > 0) {
                  IsoMessage m = mf.parseMessage(message.getBytes(), 0);
                  if (m != null) {
                      for (int i = 2; i <= 128; i++) {
                          IsoValue<?> f = m.getField(i);
                          if (f != null) {
      
                              Log.i(TAG, "f value class name " + f.getValue().getClass().getSimpleName());
      
                              if(f.getValue().getClass() == byte[].class)
                                  messageValues.put(i, HexCodec.hexEncode((byte[])f.getValue(), 0, ((byte[]) f.getValue()).length));
      
                              else if(f.getValue().getClass().getSimpleName().equals("Long")){
                                  messageValues.put(i, f.getValue() + "");
                              }
      
                              else
                                  messageValues.put(i, (String) f.getValue());
      
                              Log.i(TAG, "iso value index " + i + " value " + messageValues.get(i));
                          }
                      }
                  }
              }
      
              return messageValues;
          }
      }
      

      其他资源 http://j8583.sourceforge.net/xmlconf.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-18
        • 2020-11-29
        • 2018-09-03
        • 2015-05-04
        • 2012-04-25
        • 2019-02-11
        • 2015-01-30
        相关资源
        最近更新 更多