├── .gitignore ├── README.md └── src └── ISO └── iso8583.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | .DS_STORE 3 | 4 | # Package Files # 5 | *.jar 6 | *.war 7 | *.ear 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | iso8583-Java 2 | ============ 3 | 4 | iso8583 Message Pack & Unpack lib for Java. Works well with Android too. 5 | 6 | Supports: 7 | -> Tertiary Bitmap 8 | -> Subfields 9 | 10 | ISO 8583 Financial transaction card originated messages — Interchange message specifications is the International Organization for Standardization standard for systems that exchange electronic transactions made by cardholders using payment cards. 11 | 12 | Check out http://en.wikipedia.org/wiki/ISO_8583 for more information. -------------------------------------------------------------------------------- /src/ISO/iso8583.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Subfields> 3 | * Copyright (C) 2013 Vikrant Labde 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | package ISO; 20 | 21 | import java.io.BufferedOutputStream; 22 | import java.io.IOException; 23 | import java.io.OutputStreamWriter; 24 | import java.net.Socket; 25 | import java.net.UnknownHostException; 26 | import java.util.ArrayList; 27 | import java.util.Collections; 28 | import java.util.HashMap; 29 | import java.util.Iterator; 30 | import java.util.Map; 31 | import java.util.Set; 32 | 33 | 34 | public class iso8583 { 35 | 36 | public static HashMap ISOSCHEMA = new HashMap(); 37 | public static HashMap ISOMESSAGE = new HashMap(); 38 | public static HashMap PARSEDISOMESSAGE = new HashMap(); 39 | public static HashMap> SUBFIELDSMAPPING = new HashMap>(); 40 | public static boolean ISSUBFIELDPARSING = false; 41 | public static String SUBFIELDID = ""; 42 | 43 | /** 44 | * @param args 45 | * @throws Exception 46 | */ 47 | public static void main(String[] args) throws Exception { 48 | 49 | /* 50 | ========== 51 | DATATYPES 52 | ========== 53 | CHAR -> Variable Length String 54 | FCHAR -> Fixed Length String 55 | NUMERIC -> Fixed Lenth Integer 56 | NUM -> Varible Length Number 57 | 58 | */ 59 | 60 | /* isoSchema.put("--->-"); */ 61 | 62 | ISOSCHEMA.put("1","BITMAP"); 63 | ISOSCHEMA.put("4","NUM-2-10-0_0"); 64 | ISOSCHEMA.put("9","NUMERIC-0-8-0_0"); 65 | ISOSCHEMA.put("18","FCHAR-10-10-0_0"); 66 | ISOSCHEMA.put("52","CHAR-2-64-0_0"); 67 | ISOSCHEMA.put("57","CHAR-2-50-0_0"); 68 | ISOSCHEMA.put("58","CHAR-2-99-0_0"); 69 | ISOSCHEMA.put("65","NUMERIC-1-1-0_0"); 70 | ISOSCHEMA.put("100","NUM-2-8-0_0"); 71 | ISOSCHEMA.put("101","CHAR-2-99-0_0"); 72 | ISOSCHEMA.put("114","CHAR-4-9999-1_1"); 73 | ISOSCHEMA.put("114.1","BITMAP"); 74 | ISOSCHEMA.put("114.7","CHAR-2-99-0_0"); 75 | ISOSCHEMA.put("114.10","NUM-2-5-0_0"); 76 | ISOSCHEMA.put("114.23","CHAR-2-20-0_0"); 77 | ISOSCHEMA.put("114.24","CHAR-2-20-0_0"); 78 | ISOSCHEMA.put("114.65","NUMERIC-0-1-0_0"); 79 | ISOSCHEMA.put("114.117","CHAR-2-99-0_0"); 80 | ISOSCHEMA.put("114.150","CHAR-2-99-0_0"); 81 | 82 | ISOSCHEMA.put("120","CHAR-4-9999-1_1"); 83 | ISOSCHEMA.put("120.1","BITMAP"); 84 | ISOSCHEMA.put("120.64","CHAR-2-99-0_0"); 85 | ISOSCHEMA.put("120.120","CHAR-2-99-0_0"); 86 | 87 | ISOSCHEMA.put("130","CHAR-2-90-0_0"); 88 | 89 | 90 | //Packing ISO MESSAGE 91 | HashMap isofields = new HashMap(); 92 | isofields.put("4", "10"); 93 | isofields.put("9", "99999999"); 94 | isofields.put("18", "V"); 95 | isofields.put("100", "3"); 96 | isofields.put("101", "Cuelogic Technologies, India"); 97 | isofields.put("130", "California"); 98 | isofields.put("114.10", "99"); 99 | isofields.put("114.117", "Steve Jobs"); 100 | isofields.put("114.150", "Shravya Vikrant Labde"); 101 | 102 | isofields.put("120.64", "Vikrant Labde is building ISO8583 message library for Sub Fields"); 103 | isofields.put("120.120", "Here parsing one more subfield"); 104 | 105 | 106 | //TESTING: ISOMESSAGE PACKING 107 | String isoMessage = packIsoMsg("1001",isofields); 108 | System.out.println("Packed iso8583 Message: "+isoMessage+"\n"); 109 | 110 | 111 | //Sends data to server 112 | //-------- // networkTransport(isoMessage); 113 | 114 | 115 | //TESTING: ISOMESSAGE UNPACKING 116 | unpackIsoMsg(isoMessage); 117 | 118 | System.out.println("Unpacked iso8583 Message" + PARSEDISOMESSAGE); 119 | 120 | } 121 | 122 | /** 123 | * This method packs the message into ISO8583 standards. 124 | * This method requires HASHMAP representation as an input 125 | * 126 | * @param MTI 127 | * @param isofields 128 | * @return String 129 | * @throws Exception 130 | */ 131 | public static String packIsoMsg(String MTI, HashMap isofields) throws Exception 132 | { 133 | Set set = isofields.entrySet(); 134 | Iterator i = set.iterator(); 135 | ArrayList keys = new ArrayList(); 136 | HashMap> subFiledBitMapHolder = new HashMap>(); 137 | 138 | //Lets start building the ISO Message 139 | ISOMESSAGE.put("MTI", MTI); 140 | 141 | while(i.hasNext()) { 142 | 143 | @SuppressWarnings("rawtypes") 144 | Map.Entry me = (Map.Entry)i.next(); 145 | 146 | String fields = me.getKey().toString(); 147 | 148 | keys.add(fields); 149 | 150 | //Get Schema of fields 151 | String dataType = null; 152 | String fieldLenType = null; 153 | String fieldMaxLen = null; 154 | String subfieldIndicator = null; 155 | String hasSubfield = null; 156 | @SuppressWarnings("unused") 157 | String hasSubfieldBitmap = null; 158 | 159 | String breakFieldForSubField[] = null; 160 | String baseField = null; 161 | Integer subField = null; 162 | 163 | 164 | try{ 165 | breakFieldForSubField = fields.split("[.]"); 166 | baseField = breakFieldForSubField[0].toString(); 167 | subField = Integer.parseInt(breakFieldForSubField[1]); 168 | try{ 169 | subFiledBitMapHolder.get(baseField).add(subField); 170 | } 171 | catch(Exception e) 172 | { 173 | ArrayList arrSubFields = new ArrayList(); 174 | arrSubFields.add(subField); 175 | subFiledBitMapHolder.put(baseField, arrSubFields); 176 | } 177 | 178 | }catch(Exception e) 179 | { 180 | //Nothing to do here 181 | } 182 | 183 | 184 | String schema = ISOSCHEMA.get(fields); 185 | String arrSchema[] = schema.split("-"); 186 | dataType = arrSchema[0]; 187 | fieldLenType = arrSchema[1]; 188 | fieldMaxLen = arrSchema[2]; 189 | subfieldIndicator = arrSchema[3]; 190 | String arrSubField[] = subfieldIndicator.split("_"); 191 | 192 | hasSubfieldBitmap = arrSubField[1]; 193 | 194 | if(dataType.equalsIgnoreCase("NUM") && fieldLenType.equalsIgnoreCase("1")) 195 | { 196 | throw new IOException("Field:" +fields + " has data type NUM is having field-size = 1 in ISOSCHEMA. Try assign NUMERIC data type"); 197 | } 198 | 199 | String fieldVlaue = isofields.get(fields); 200 | Integer fieldLength = fieldVlaue.length(); 201 | 202 | String strfieldLength = fieldLength.toString(); 203 | 204 | if(dataType.equalsIgnoreCase("NUMERIC")) 205 | { 206 | if(Integer.parseInt(fieldMaxLen) >= fieldLength) 207 | { 208 | String newFieldValue = ""; 209 | if (fieldVlaue.equals("")) 210 | { 211 | newFieldValue = String.format("%0"+ fieldMaxLen +"d", 0); 212 | } 213 | else if (fieldLength == Integer.parseInt(fieldMaxLen)) 214 | { 215 | newFieldValue = fieldVlaue; 216 | } 217 | else 218 | { 219 | newFieldValue = String.format("%0"+ fieldMaxLen +"d", Long.parseLong(fieldVlaue)); 220 | } 221 | 222 | ISOMESSAGE.put(fields, newFieldValue); 223 | } 224 | else 225 | { 226 | throw new IOException("Field:"+fields + " Has bigger value. Its set "+fieldMaxLen +" in ISOSCHEMA and you have entered" + fieldLength ); 227 | } 228 | } 229 | else if (dataType.equalsIgnoreCase("CHAR") || dataType.equalsIgnoreCase("NUM")) 230 | { 231 | if(Integer.parseInt(fieldMaxLen) >= fieldLength) //?????????? fieldLength OR fieldMaxLen -- Discuss with Sagar 232 | { 233 | String newFieldLen = String.format("%0"+ fieldLenType +"d", Long.parseLong(strfieldLength)); 234 | 235 | ///// 236 | ISOMESSAGE.put(fields.toString(), newFieldLen + fieldVlaue); 237 | //// 238 | } 239 | else 240 | { 241 | throw new IOException("Field:"+fields + " Has bigger value. Its set "+fieldMaxLen +" in ISOSCHEMA and you have entered" + fieldLength ); 242 | } 243 | } 244 | else if (dataType.equalsIgnoreCase("FCHAR")) 245 | { 246 | if(Integer.parseInt(fieldMaxLen) >= fieldLength) 247 | { 248 | 249 | String newFieldValue = String.format("%-"+ fieldMaxLen +"s", fieldVlaue); 250 | 251 | ///// 252 | ISOMESSAGE.put(fields.toString(), newFieldValue); 253 | //// 254 | } 255 | else 256 | { 257 | throw new IOException("Field:"+fields + " Has bigger value. Its set "+fieldMaxLen +" in ISOSCHEMA and you have entered" + fieldLength ); 258 | } 259 | } 260 | else if (dataType.equalsIgnoreCase("PCHAR")) 261 | { 262 | if(Integer.parseInt(fieldMaxLen) >= fieldLength) 263 | { 264 | String newFieldValue = String.format("%"+ fieldMaxLen +"s", fieldVlaue); 265 | newFieldValue = newFieldValue.replaceAll(" ", "0"); 266 | ///// 267 | ISOMESSAGE.put(fields.toString(), newFieldValue); 268 | //// 269 | } 270 | else 271 | { 272 | throw new IOException("Field:"+fields + " Has bigger value. Its set "+fieldMaxLen +" in ISOSCHEMA and you have entered" + fieldLength ); 273 | } 274 | } 275 | else if (dataType.equalsIgnoreCase("BINARY")) 276 | { 277 | if(Integer.parseInt(fieldMaxLen) >= fieldLength) 278 | { 279 | int bytes = (fieldLength + 1) / 2; // The +1 is so it rounds up 280 | byte b; 281 | StringBuffer sb = new StringBuffer(); 282 | String fPa; 283 | if (fieldLength % 2 == 0) // Even number of chars, so there's no padding at the end 284 | { 285 | for (int iRe = 0; iRe < fieldLength; iRe += 2) 286 | { 287 | fPa = fieldVlaue.substring(iRe, iRe + 2); 288 | sb.append(CtoX(fPa)); 289 | } 290 | } 291 | else // Odd number 292 | { 293 | int iRe; 294 | 295 | fPa = ""; 296 | fPa = fPa + fieldVlaue.charAt(0); 297 | 298 | sb.append(CtoX(fPa)); // Get the first char from the second nibble 299 | for (iRe = 1; iRe < fieldLength; iRe += 2) 300 | { 301 | fPa = fieldVlaue.substring(iRe, iRe + 2); 302 | sb.append(CtoX(fPa)); 303 | } 304 | } 305 | 306 | ///// 307 | ISOMESSAGE.put(fields.toString(), sb.substring(0, sb.length())); 308 | //// 309 | } 310 | else 311 | { 312 | throw new IOException("Field:"+fields + " Has bigger value. Its set "+fieldMaxLen +" in ISOSCHEMA and you have entered" + fieldLength ); 313 | } 314 | } 315 | 316 | } 317 | 318 | //Process Bitmap - Add 1 and 65 number Data Elements 319 | ArrayList finalFields = new ArrayList(); 320 | finalFields = processBitmap(parseFields(keys)); 321 | 322 | //Process Subfield bitmap - Add 1 and 65 for each field that has subfields 323 | processSubFieldBitmap(subFiledBitMapHolder); 324 | 325 | return buildISOMessage(finalFields); 326 | 327 | } 328 | 329 | /** 330 | * This method assembles the entire ISO Message in a String 331 | * @param finalFields 332 | * @return String 333 | * @throws Exception 334 | */ 335 | public static String buildISOMessage(ArrayList finalFields) throws Exception 336 | { 337 | String isoMessage = ISOMESSAGE.get("MTI"); 338 | isoMessage = isoMessage + ISOMESSAGE.get("1"); 339 | 340 | Iterator j = finalFields.iterator(); 341 | while(j.hasNext()) 342 | { 343 | String dataElement = j.next().toString(); 344 | String schema = ISOSCHEMA.get(dataElement); 345 | 346 | try{ 347 | String arrSchema[] = schema.split("-"); 348 | 349 | String fieldLenType = arrSchema[1]; 350 | 351 | String subfieldIndicator = arrSchema[3]; 352 | String arrSubField[] = subfieldIndicator.split("_"); 353 | String hasSubfield = arrSubField[0]; 354 | 355 | if(hasSubfield.equalsIgnoreCase("1")) 356 | { 357 | //Traverse subfields 358 | ArrayList subFields = new ArrayList(); 359 | subFields = SUBFIELDSMAPPING.get(Integer.parseInt(dataElement)); 360 | Iterator i = subFields.iterator(); 361 | String isoSubMessage = ""; 362 | if(!subFields.contains(1)){ 363 | isoSubMessage = isoSubMessage + ISOMESSAGE.get(dataElement + ".1"); 364 | 365 | } 366 | 367 | while(i.hasNext()) 368 | { 369 | String subDataElement = i.next().toString(); 370 | String mainDataElement = dataElement + "." + subDataElement; 371 | isoSubMessage = isoSubMessage + ISOMESSAGE.get(mainDataElement); 372 | } 373 | 374 | 375 | String subMessageLen = String.format("%0"+ fieldLenType +"d", isoSubMessage.length()); 376 | isoMessage = isoMessage + subMessageLen + isoSubMessage; 377 | } 378 | else 379 | { 380 | isoMessage = isoMessage + ISOMESSAGE.get(dataElement); 381 | } 382 | 383 | }catch(Exception e) 384 | { 385 | //System.out.println(" has problem with schema"); 386 | } 387 | } 388 | return isoMessage; 389 | } 390 | 391 | /** 392 | * Create array list of all mail Data Elements that are available. This method is used in method packIsoMsg 393 | * @param fields 394 | * @return ArrayList 395 | * @throws Exception 396 | */ 397 | public static ArrayList parseFields(ArrayList fields) throws Exception 398 | { 399 | 400 | ArrayList newFiledMap = new ArrayList(); 401 | Iterator j = fields.iterator(); 402 | while(j.hasNext()) 403 | { 404 | try{ 405 | String breakFieldForSubField[] = j.next().toString().split("[.]"); 406 | Integer baseField = Integer.parseInt(breakFieldForSubField[0].toString()); 407 | 408 | if(!newFiledMap.contains(baseField)) 409 | { 410 | newFiledMap.add(baseField); 411 | } 412 | }catch(Exception e) 413 | { 414 | Integer keys = Integer.parseInt(j.next().toString()); 415 | newFiledMap.add(keys); 416 | } 417 | } 418 | 419 | //Sort fields in assending order 420 | Collections.sort(newFiledMap); 421 | return newFiledMap; 422 | } 423 | 424 | /** 425 | * This is helper method used in the packIsoMsg method to process BITMAP 426 | * @param fields 427 | * @return Arraylist 428 | * @throws Exception 429 | */ 430 | public static ArrayList processBitmap(ArrayList fields) throws Exception 431 | { 432 | String bitmapType = "primary"; 433 | char[] bitMap; 434 | 435 | //Retrive heighest Data Element from the list 436 | Integer DE = fields.get(fields.size() - 1); 437 | 438 | //Know the type of bitmap (primary, secondary, tertiary 439 | if(DE > 65 && DE <= 128) 440 | { 441 | fields.add(1); //Add 1st Bit for secondary bitmap 442 | bitmapType = "secondary"; 443 | bitMap = new char[16]; 444 | } 445 | else if(DE > 128) 446 | { 447 | fields.add(1); //Add 1st Bit for secondary bitmap 448 | fields.add(65); //Add 65th Bit for tertiary bitmap 449 | ISOMESSAGE.put("65", "1"); 450 | bitmapType = "tertiary"; 451 | bitMap = new char[24]; 452 | 453 | } 454 | else 455 | { 456 | bitmapType = "primary"; 457 | bitMap = new char[8]; 458 | 459 | } 460 | 461 | //Sort ArrayList again 462 | Collections.sort(fields); 463 | 464 | 465 | //Append BITMAP to the message 466 | CalcBitMap(bitMap, fields); 467 | ISOMESSAGE.put("1", String.valueOf(bitMap, 0, bitMap.length)); 468 | 469 | return fields; 470 | } 471 | 472 | 473 | /** 474 | * This is helper method used in the packIsoMsg method. To process SubFields 475 | * @param subFieldMap 476 | * @throws Exception 477 | */ 478 | @SuppressWarnings("unchecked") 479 | public static void processSubFieldBitmap(HashMap> subFieldMap) throws Exception 480 | { 481 | Set set = subFieldMap.entrySet(); 482 | Iterator i = set.iterator(); 483 | char[] bitMap; 484 | while(i.hasNext()) { 485 | 486 | @SuppressWarnings("rawtypes") 487 | Map.Entry me = (Map.Entry)i.next(); 488 | 489 | ArrayList fields = new ArrayList(); 490 | fields = (ArrayList) me.getValue(); 491 | String subFieldId = me.getKey().toString(); 492 | //System.out.println(fields); 493 | 494 | Collections.sort(fields); //Sort the arrayList 495 | 496 | String bitmapType = "primary"; 497 | 498 | //Retrive heighest Data Element from the list 499 | Integer DE = fields.get(fields.size() - 1); 500 | 501 | //Know the type of bitmap (primary, secondary, tertiary 502 | if(DE > 65 && DE <= 128) 503 | { 504 | fields.add(1); //Add 1st Bit for secondary bitmap 505 | bitmapType = "secondary"; 506 | bitMap = new char[16]; 507 | } 508 | else if(DE > 128) 509 | { 510 | fields.add(1); //Add 1st Bit for secondary bitmap 511 | fields.add(65); //Add 65th Bit for tertiary bitmap 512 | ISOMESSAGE.put(subFieldId + ".65", "1"); 513 | bitmapType = "tertiary"; 514 | bitMap = new char[24]; 515 | } 516 | else 517 | { 518 | bitmapType = "primary"; 519 | bitMap = new char[8]; 520 | } 521 | //Sort ArrayList again 522 | Collections.sort(fields); 523 | 524 | //Maintain Subfield Mapping 525 | SUBFIELDSMAPPING.put(Integer.parseInt(subFieldId), fields); 526 | 527 | //Append BITMAP to the message 528 | CalcBitMap(bitMap, fields); 529 | ISOMESSAGE.put(subFieldId+".1", String.valueOf(bitMap, 0, bitMap.length)); 530 | } 531 | } 532 | 533 | /** 534 | * This function uppack/Parse ISO8583 encoded message and stores the output in HASHMAP -> PARSEDISOMESSAGE 535 | * @param isoMessage 536 | * @throws Exception 537 | */ 538 | public static void unpackIsoMsg(String isoMessage) throws Exception 539 | { 540 | String overallBitmap = null; 541 | 542 | String messageAfterBitMap = null; 543 | 544 | if(ISSUBFIELDPARSING == false) 545 | PARSEDISOMESSAGE.put("MTI",isoMessage.substring(0, 4)); 546 | 547 | String priMaryHexBitMap = ""; 548 | if(ISSUBFIELDPARSING == false) 549 | priMaryHexBitMap = isoMessage.substring(4, 12); 550 | else 551 | priMaryHexBitMap = isoMessage.substring(0, 8); 552 | 553 | //Convert BITMAP to Binary 554 | String primaryBitMap = GetBitMap(priMaryHexBitMap ,1); 555 | 556 | overallBitmap = primaryBitMap; 557 | //Check if Secondary bitMap is available or not 558 | Integer firstBit = Integer.parseInt(primaryBitMap.substring(0, 1)); 559 | 560 | //if firstBit = 1 it means secondary bitmap is available 561 | String secondaryHexBitmap = null; 562 | String secondaryBitMap = null; 563 | String tertiaryHexBitmap = null; 564 | String tertiaryBitMap = null; 565 | int bitmaplength = 64; 566 | 567 | if(firstBit > 0) 568 | { 569 | bitmaplength = 128; 570 | if(ISSUBFIELDPARSING == false) 571 | secondaryHexBitmap = isoMessage.substring(12, 20); 572 | else 573 | secondaryHexBitmap = isoMessage.substring(8, 16); 574 | 575 | secondaryBitMap = GetBitMap(secondaryHexBitmap, 1); 576 | overallBitmap = overallBitmap + secondaryBitMap; 577 | //if 65th field is binary then there is a tertiary bitmap 578 | Integer firstBitOfSecBitmap = Integer.parseInt(secondaryBitMap.substring(0, 1)); 579 | if(firstBitOfSecBitmap > 0) 580 | { 581 | bitmaplength = 192; 582 | if(ISSUBFIELDPARSING == false) 583 | tertiaryHexBitmap = isoMessage.substring(20, 28); 584 | else 585 | tertiaryHexBitmap = isoMessage.substring(16, 24); 586 | 587 | tertiaryBitMap = GetBitMap(tertiaryHexBitmap, 1); 588 | overallBitmap = overallBitmap + tertiaryBitMap; 589 | if(ISSUBFIELDPARSING == false) 590 | messageAfterBitMap = isoMessage.substring(28); //After MTI and Primary bitmap 591 | else 592 | messageAfterBitMap = isoMessage.substring(24); //After MTI and Primary bitmap 593 | } 594 | else 595 | { 596 | if(ISSUBFIELDPARSING == false) 597 | messageAfterBitMap = isoMessage.substring(20); //After MTI and Primary bitmap 598 | else 599 | messageAfterBitMap = isoMessage.substring(16); //After MTI and Primary bitmap 600 | } 601 | } 602 | else //Secondary bitmap is not available so remaining message is actual data 603 | { 604 | if(ISSUBFIELDPARSING == false) 605 | messageAfterBitMap = isoMessage.substring(12); //After MTI and Primary bitmap 606 | else 607 | messageAfterBitMap = isoMessage.substring(8); //After MTI and Primary bitmap 608 | } 609 | 610 | //Traverse the overall bitmap string 611 | ArrayList debugList = new ArrayList(); //This is just for debugging purpose 612 | 613 | String remainingMessage = null; 614 | for(int i=0;i 1) //Exclude 1st Field which is reserve for bitmap 630 | { 631 | String schema = null; 632 | try{ 633 | schema = ISOSCHEMA.get(SUBFIELDID+field.toString()); 634 | }catch(Exception e) 635 | { 636 | throw new IOException(field + " has problem with schema."); 637 | } 638 | 639 | try{ 640 | String arrSchema[] = schema.split("-"); 641 | 642 | dataType = arrSchema[0]; 643 | fieldLenType = arrSchema[1]; 644 | fieldMaxLen = arrSchema[2]; 645 | subfieldIndicator = arrSchema[3]; 646 | String arrSubField[] = subfieldIndicator.split("_"); 647 | hasSubfield = arrSubField[0]; 648 | hasSubfieldBitmap = arrSubField[1]; 649 | }catch(Exception e) 650 | { 651 | throw new IOException(field + " has problem with schema."); 652 | } 653 | 654 | if(dataType.equalsIgnoreCase("NUMERIC")) 655 | { 656 | if(remainingMessage == null) 657 | { 658 | String fieldValue = messageAfterBitMap.substring(0,Integer.parseInt(fieldMaxLen)); 659 | 660 | if(fieldValue == null) 661 | { 662 | throw new IOException(field + " Has null or inappropriate value"); 663 | } 664 | 665 | if(hasSubfield.equalsIgnoreCase("1")) 666 | { 667 | ISSUBFIELDPARSING = true; 668 | SUBFIELDID = field+"."; 669 | unpackIsoMsg(fieldValue); 670 | } 671 | else 672 | { 673 | PARSEDISOMESSAGE.put(SUBFIELDID+field.toString(), fieldValue); //Lets start pushing parsed fields into Hash Map 674 | } 675 | remainingMessage = messageAfterBitMap.substring(Integer.parseInt(fieldMaxLen)); 676 | } 677 | else //operation on remainingMessage 678 | { 679 | String fieldValue = remainingMessage.substring(0,Integer.parseInt(fieldMaxLen)); 680 | 681 | if(fieldValue == null) 682 | { 683 | throw new IOException(field + " Has null or inappropriate value"); 684 | } 685 | 686 | if(hasSubfield.equalsIgnoreCase("1")) 687 | { 688 | ISSUBFIELDPARSING = true; 689 | SUBFIELDID = field+"."; 690 | unpackIsoMsg(fieldValue); 691 | } 692 | else 693 | { 694 | PARSEDISOMESSAGE.put(SUBFIELDID+field.toString(), fieldValue); //Lets start pushing parsed fields into Hash Map 695 | } 696 | remainingMessage = remainingMessage.substring(Integer.parseInt(fieldMaxLen)); 697 | } 698 | } 699 | else if(dataType.equalsIgnoreCase("FCHAR")) 700 | { 701 | if(remainingMessage == null) 702 | { 703 | String fieldValue = messageAfterBitMap.substring(0,Integer.parseInt(fieldMaxLen)).trim(); 704 | 705 | if(fieldValue == null) 706 | { 707 | throw new IOException(field + " Has null or inappropriate value"); 708 | } 709 | 710 | if(hasSubfield.equalsIgnoreCase("1")) 711 | { 712 | ISSUBFIELDPARSING = true; 713 | SUBFIELDID = field+"."; 714 | unpackIsoMsg(fieldValue); 715 | } 716 | else 717 | { 718 | PARSEDISOMESSAGE.put(SUBFIELDID+field.toString(), fieldValue); //Lets start pushing parsed fields into Hash Map 719 | } 720 | remainingMessage = messageAfterBitMap.substring(Integer.parseInt(fieldMaxLen)); 721 | } 722 | else //operation on remainingMessage 723 | { 724 | String fieldValue = remainingMessage.substring(0,Integer.parseInt(fieldMaxLen)).trim(); 725 | 726 | if(fieldValue == null) 727 | { 728 | throw new IOException(field + " Has null or inappropriate value"); 729 | } 730 | 731 | if(hasSubfield.equalsIgnoreCase("1")) 732 | { 733 | ISSUBFIELDPARSING = true; 734 | SUBFIELDID = field+"."; 735 | unpackIsoMsg(fieldValue); 736 | } 737 | else 738 | { 739 | PARSEDISOMESSAGE.put(SUBFIELDID+field.toString(), fieldValue); //Lets start pushing parsed fields into Hash Map 740 | } 741 | remainingMessage = remainingMessage.substring(Integer.parseInt(fieldMaxLen)); 742 | } 743 | } 744 | else if(dataType.equalsIgnoreCase("PCHAR")) 745 | { 746 | if(remainingMessage == null) 747 | { 748 | String fieldValue = messageAfterBitMap.substring(0,Integer.parseInt(fieldMaxLen)).replaceFirst("^0+(?!$)", ""); 749 | 750 | if(fieldValue == null) 751 | { 752 | throw new IOException(field + " Has null or inappropriate value"); 753 | } 754 | 755 | if(hasSubfield.equalsIgnoreCase("1")) 756 | { 757 | ISSUBFIELDPARSING = true; 758 | SUBFIELDID = field+"."; 759 | unpackIsoMsg(fieldValue); 760 | } 761 | else 762 | { 763 | PARSEDISOMESSAGE.put(SUBFIELDID+field.toString(), fieldValue); //Lets start pushing parsed fields into Hash Map 764 | } 765 | remainingMessage = messageAfterBitMap.substring(Integer.parseInt(fieldMaxLen)); 766 | } 767 | else //operation on remainingMessage 768 | { 769 | String fieldValue = remainingMessage.substring(0,Integer.parseInt(fieldMaxLen)).replaceFirst("^0+(?!$)", ""); 770 | 771 | if(fieldValue == null) 772 | { 773 | throw new IOException(field + " Has null or inappropriate value"); 774 | } 775 | 776 | if(hasSubfield.equalsIgnoreCase("1")) 777 | { 778 | ISSUBFIELDPARSING = true; 779 | SUBFIELDID = field+"."; 780 | unpackIsoMsg(fieldValue); 781 | } 782 | else 783 | { 784 | PARSEDISOMESSAGE.put(SUBFIELDID+field.toString(), fieldValue); //Lets start pushing parsed fields into Hash Map 785 | } 786 | remainingMessage = remainingMessage.substring(Integer.parseInt(fieldMaxLen)); 787 | } 788 | } 789 | else if(dataType.equalsIgnoreCase("BINARY")) 790 | { 791 | if(remainingMessage == null) 792 | { 793 | String fieldValue = messageAfterBitMap.substring(0,(Integer.parseInt(fieldMaxLen)/2)); 794 | System.out.println(fieldValue); 795 | if(fieldValue == null) 796 | { 797 | throw new IOException(field + " Has null or inappropriate value"); 798 | } 799 | 800 | String originalMsg=""; 801 | for (int x = 0; x < fieldValue.length(); x++) { 802 | int value = (int)fieldValue.charAt(x); 803 | String originalValue = Integer.toHexString(value); 804 | 805 | originalMsg = originalMsg + originalValue; 806 | } 807 | 808 | fieldValue = Integer.toString(Integer.parseInt(originalMsg,16)); 809 | 810 | PARSEDISOMESSAGE.put(SUBFIELDID+field.toString(), fieldValue); //Lets start pushing parsed fields into Hash Map 811 | 812 | remainingMessage = messageAfterBitMap.substring(Integer.parseInt(fieldMaxLen)/2); 813 | } 814 | else //operation on remainingMessage 815 | { 816 | String fieldValue = remainingMessage.substring(0,(Integer.parseInt(fieldMaxLen)/2)); 817 | 818 | if(fieldValue == null) 819 | { 820 | throw new IOException(field + " Has null or inappropriate value"); 821 | } 822 | 823 | String originalMsg=""; 824 | for (int x = 0; x < fieldValue.length(); x++) { 825 | int value = (int)fieldValue.charAt(x); 826 | String originalValue = Integer.toHexString(value); 827 | 828 | originalMsg = originalMsg + originalValue; 829 | } 830 | 831 | fieldValue = Integer.toString(Integer.parseInt(originalMsg,16)); 832 | 833 | PARSEDISOMESSAGE.put(SUBFIELDID+field.toString(), fieldValue); //Lets start pushing parsed fields into Hash Map 834 | remainingMessage = remainingMessage.substring(Integer.parseInt(fieldMaxLen)/2); 835 | } 836 | } 837 | else if(dataType.equalsIgnoreCase("CHAR") || dataType.equalsIgnoreCase("NUM")) 838 | { 839 | if(remainingMessage == null) 840 | { 841 | String fieldlength = messageAfterBitMap.substring(0,Integer.parseInt(fieldLenType)); 842 | remainingMessage = messageAfterBitMap.substring(Integer.parseInt(fieldLenType)); 843 | 844 | String fieldValue = remainingMessage.substring(0,Integer.parseInt(fieldlength)); 845 | if(fieldValue == null) 846 | { 847 | throw new IOException(field + " Has null or inappropriate value"); 848 | } 849 | 850 | if(hasSubfield.equalsIgnoreCase("1")) 851 | { 852 | ISSUBFIELDPARSING = true; 853 | SUBFIELDID = field+"."; 854 | unpackIsoMsg(fieldValue); 855 | } 856 | else 857 | { 858 | PARSEDISOMESSAGE.put(SUBFIELDID+field.toString(), fieldValue); //Lets start pushing parsed fields into Hash Map 859 | } 860 | 861 | remainingMessage = remainingMessage.substring(Integer.parseInt(fieldlength)); 862 | 863 | } 864 | else //operation on remaining message 865 | { 866 | String fieldlength = remainingMessage.substring(0,Integer.parseInt(fieldLenType)); 867 | 868 | remainingMessage = remainingMessage.substring(Integer.parseInt(fieldLenType)); 869 | 870 | String fieldValue = remainingMessage.substring(0,Integer.parseInt(fieldlength)); 871 | if(fieldValue == null) 872 | { 873 | throw new IOException(field + " Has null or inappropriate value"); 874 | } 875 | 876 | if(hasSubfield.equalsIgnoreCase("1")) 877 | { 878 | ISSUBFIELDPARSING = true; 879 | SUBFIELDID = field+"."; 880 | unpackIsoMsg(fieldValue); 881 | } 882 | else 883 | { 884 | PARSEDISOMESSAGE.put(SUBFIELDID+field.toString(), fieldValue); //Lets start pushing parsed fields into Hash Map 885 | } 886 | 887 | remainingMessage = remainingMessage.substring(Integer.parseInt(fieldlength)); 888 | } 889 | } 890 | } 891 | } 892 | } 893 | 894 | ISSUBFIELDPARSING = false; 895 | SUBFIELDID = ""; 896 | 897 | //System.out.println("Parsed Message " + PARSEDISOMESSAGE); 898 | } 899 | 900 | 901 | /** 902 | * This Method generates the binary representation of the BITMAP. 903 | * @input= Arraylist for the subfields present 904 | * @return String containing bitmap msg 905 | * @throws Exception 906 | * 907 | */ 908 | public static String CalcBitMap(char[] bitMap, ArrayList list) throws Exception 909 | { 910 | for(int i=0;i 0) binRes.append('1'); else binRes.append('0'); 944 | if((bin.charAt(iCo) & 64) > 0) binRes.append('1'); else binRes.append('0'); 945 | if((bin.charAt(iCo) & 32) > 0) binRes.append('1'); else binRes.append('0'); 946 | if((bin.charAt(iCo) & 16) > 0) binRes.append('1'); else binRes.append('0'); 947 | if((bin.charAt(iCo) & 8) > 0) binRes.append('1'); else binRes.append('0'); 948 | if((bin.charAt(iCo) & 4) > 0) binRes.append('1'); else binRes.append('0'); 949 | if((bin.charAt(iCo) & 2) > 0) binRes.append('1'); else binRes.append('0'); 950 | if((bin.charAt(iCo) & 1) > 0) binRes.append('1'); else binRes.append('0'); 951 | } 952 | 953 | return binRes.toString(); 954 | } 955 | 956 | 957 | 958 | /** 959 | * Method for Replacing the char in string at provided location 960 | * @input pos-Int position where to replace character 961 | * char-char to be replace at provided pos 962 | * String- s which is to be formated 963 | * 964 | * @return Re-formated String 965 | * 966 | * */ 967 | public static String replaceCharAt(String s, int pos, char c) throws Exception 968 | { 969 | return s.substring(0,pos) + c + s.substring(pos+1); 970 | } 971 | 972 | /** 973 | * Type cast to char data type 974 | * @param x 975 | * @return 976 | */ 977 | public static char CtoX(String x) 978 | { 979 | int r = 0; 980 | r = Integer.parseInt(x,16); 981 | return (char)r; 982 | } 983 | 984 | /** 985 | * This method sends ISO8583 message to server and accepts the response. 986 | * 987 | * @param isoMessage 988 | * @return String 989 | * @throws UnknownHostException 990 | * @throws IOException 991 | */ 992 | public static String networkTransport(String isoMessage) throws UnknownHostException, IOException 993 | { 994 | Socket connection = new Socket("127.1.1.1", 1223); 995 | 996 | BufferedOutputStream bos = new BufferedOutputStream(connection.getOutputStream()); 997 | OutputStreamWriter osw = new OutputStreamWriter(bos); 998 | osw.write(isoMessage+"\n"); 999 | osw.flush(); 1000 | 1001 | byte[] arrOutut = new byte[4096]; 1002 | int count = connection.getInputStream().read(arrOutut, 0, 4096); 1003 | 1004 | String clientRequest = ""; 1005 | for (int outputCount = 0; outputCount < count; outputCount++) 1006 | { 1007 | char response = (char)arrOutut[outputCount]; 1008 | clientRequest = clientRequest + response; 1009 | } 1010 | 1011 | connection.close(); 1012 | 1013 | return clientRequest; 1014 | } 1015 | } 1016 | --------------------------------------------------------------------------------