001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.iso; 020 021import java.io.PrintStream; 022 023import org.jpos.util.Loggeable; 024 025/** 026 * Represents POS Data Code flags as defined in jPOS/jCard specifications, 027 * encoding reading method, verification method, POS environment, and security characteristics. 028 */ 029@SuppressWarnings("unused") 030public class PosDataCode extends PosFlags implements Loggeable { 031 /** 032 * Enumeration of card/data reading methods used at the POS terminal. 033 */ 034 public enum ReadingMethod implements Flag { 035 /** Reading method is unknown. */ 036 UNKNOWN (1, "Unknown"), 037 /** Contactless reading (e.g. RFID); information not taken from card. */ 038 CONTACTLESS (1 << 1, "Information not taken from card"), // i.e.: RFID 039 /** Physical entry (e.g. manual entry or OCR). */ 040 PHYSICAL (1 << 2, "Physical entry"), // i.e.: Manual Entry or OCR 041 /** Bar code reading. */ 042 BARCODE (1 << 3, "Bar code"), 043 /** Magnetic stripe reading. */ 044 MAGNETIC_STRIPE (1 << 4, "Magnetic Stripe"), 045 /** ICC (chip) reading. */ 046 ICC (1 << 5, "ICC"), 047 /** Data on file (no card present). */ 048 DATA_ON_FILE (1 << 6, "Data on file"), 049 /** ICC was read but the read failed. */ 050 ICC_FAILED (1 << 11, "ICC read but failed"), 051 /** Magnetic stripe was read but the read failed. */ 052 MAGNETIC_STRIPE_FAILED (1 << 12, "Magnetic Stripe read but failed"), 053 /** Fallback from preferred reading method. */ 054 FALLBACK (1 << 13, "Fallback"), 055 /** Track 1 data is present (jCard private field). */ 056 TRACK1_PRESENT (1 << 27, "Track1 data present"), // jCard private field 057 /** Track 2 data is present (jCard private field). */ 058 TRACK2_PRESENT (1 << 28, "Track2 data present"); // jCard private field 059 060 /** Integer bitmask value for this reading method. */ 061 private int val; 062 /** Human-readable description of this reading method. */ 063 private String description; 064 ReadingMethod (int val, String description) { 065 this.val = val; 066 this.description = description; 067 } 068 /** {@inheritDoc} */ 069 public int intValue() { 070 return val; 071 } 072 /** {@inheritDoc} */ 073 public String toString () { 074 return description; 075 } 076 077 /** Bit offset within the PosDataCode byte array for reading method flags. */ 078 public static int OFFSET = 0; 079 /** {@inheritDoc} */ 080 @Override 081 public int getOffset() { 082 return OFFSET; 083 } 084 } 085 086 /** 087 * Enumeration of cardholder verification methods used at the POS terminal. 088 */ 089 public enum VerificationMethod implements Flag { 090 /** Verification method is unknown. */ 091 UNKNOWN (1, "Unknown"), 092 /** No verification performed. */ 093 NONE (1 << 1, "None"), 094 /** Cardholder verified by manual signature. */ 095 MANUAL_SIGNATURE (1 << 2, "Manual signature"), 096 /** Cardholder verified by online PIN. */ 097 ONLINE_PIN (1 << 3, "Online PIN"), 098 /** Cardholder verified by offline PIN in clear. */ 099 OFFLINE_PIN_IN_CLEAR (1 << 4, "Offline PIN in clear"), 100 /** Cardholder verified by offline encrypted PIN. */ 101 OFFLINE_PIN_ENCRYPTED (1 << 5, "Offline PIN encrypted"), 102 /** Cardholder verified by offline digitized signature analysis. */ 103 OFFLINE_DIGITIZED_SIGNATURE_ANALYSIS (1 << 6, "Offline digitized signature analysis"), 104 /** Cardholder verified by offline biometrics. */ 105 OFFLINE_BIOMETRICS (1 << 7, "Offline biometrics"), 106 /** Cardholder verified by offline manual verification. */ 107 OFFLINE_MANUAL_VERIFICATION (1 << 8, "Offline manual verification"), 108 /** Cardholder verified by offline biographics. */ 109 OFFLINE_BIOGRAPHICS (1 << 9, "Offline biographics"), 110 /** Cardholder verified by account-based digital signature. */ 111 ACCOUNT_BASED_DIGITAL_SIGNATURE (1 << 10, "Account based digital signature"), 112 /** Cardholder verified by public key-based digital signature. */ 113 PUBLIC_KEY_BASED_DIGITAL_SIGNATURE (1 << 11, "Public key based digital signature"); 114 115 /** Integer bitmask value for this verification method. */ 116 private int val; 117 /** Human-readable description of this verification method. */ 118 private String description; 119 VerificationMethod (int val, String description) { 120 this.val = val; 121 this.description = description; 122 } 123 /** {@inheritDoc} */ 124 public int intValue() { 125 return val; 126 } 127 /** {@inheritDoc} */ 128 public String toString () { 129 return description; 130 } 131 132 /** Bit offset within the PosDataCode byte array for verification method flags. */ 133 public static int OFFSET = 4; 134 /** {@inheritDoc} */ 135 @Override 136 public int getOffset() { 137 return OFFSET; 138 } 139 } 140 141 /** 142 * Enumeration of POS terminal environment types. 143 */ 144 public enum POSEnvironment implements Flag { 145 /** POS environment is unknown. */ 146 UNKNOWN (1, "Unknown"), 147 /** Attended POS terminal. */ 148 ATTENDED (1 << 1, "Attended POS"), 149 /** Unattended POS terminal, details unknown. */ 150 UNATTENDED (1 << 2, "Unattended, details unknown"), 151 /** Mail order / telephone order transaction. */ 152 MOTO (1 << 3, "Mail order / telephone order"), 153 /** E-Commerce transaction. */ 154 E_COMMERCE (1 << 4, "E-Commerce"), 155 /** M-Commerce (mobile commerce) transaction. */ 156 M_COMMERCE (1 << 5, "M-Commerce"), 157 /** Recurring transaction. */ 158 RECURRING (1 << 6, "Recurring transaction"), 159 /** Transaction using stored cardholder details. */ 160 STORED_DETAILS (1 << 7, "Stored details"), 161 /** Cardholder Activated Terminal. */ 162 CAT (1 << 8, "Cardholder Activated Terminal"), 163 /** ATM located on bank premises. */ 164 ATM_ON_BANK (1 << 9, "ATM on bank premises"), 165 /** ATM located off bank premises. */ 166 ATM_OFF_BANK (1 << 10, "ATM off bank premises"), 167 /** Deferred transaction. */ 168 DEFERRED_TRANSACTION (1 << 11, "Deferred transaction"), 169 /** Installment transaction. */ 170 INSTALLMENT_TRANSACTION (1 << 12, "Installment transaction"); 171 172 /** Integer bitmask value for this POS environment. */ 173 private int val; 174 /** Human-readable description of this POS environment. */ 175 private String description; 176 POSEnvironment (int val, String description) { 177 this.val = val; 178 this.description = description; 179 } 180 /** {@inheritDoc} */ 181 public int intValue() { 182 return val; 183 } 184 /** {@inheritDoc} */ 185 public String toString () { 186 return description; 187 } 188 189 190 /** Bit offset within the PosDataCode byte array for POS environment flags. */ 191 public static int OFFSET = 8; 192 /** {@inheritDoc} */ 193 @Override 194 public int getOffset() { 195 return OFFSET; 196 } 197 } 198 199 /** 200 * Enumeration of security characteristics for the transaction channel. 201 */ 202 public enum SecurityCharacteristic implements Flag { 203 /** Security characteristic is unknown. */ 204 UNKNOWN (1, "Unknown"), 205 /** Transaction carried over a private network. */ 206 PRIVATE_NETWORK (1 << 1, "Private network"), 207 /** Transaction carried over an open network (Internet). */ 208 OPEN_NETWORK (1 << 2, "Open network (Internet)"), 209 /** Channel-level MACing applied. */ 210 CHANNEL_MACING (1 << 3, "Channel MACing"), 211 /** Pass-through MACing applied. */ 212 PASS_THROUGH_MACING (1 << 4, "Pass through MACing"), 213 /** Channel-level encryption applied. */ 214 CHANNEL_ENCRYPTION (1 << 5, "Channel encryption"), 215 /** End-to-end encryption applied. */ 216 END_TO_END_ENCRYPTION (1 << 6, "End-to-end encryption"), 217 /** Private algorithm encryption applied. */ 218 PRIVATE_ALG_ENCRYPTION (1 << 7, "Private algorithm encryption"), 219 /** PKI encryption applied. */ 220 PKI_ENCRYPTION (1 << 8, "PKI encryption"), 221 /** Private algorithm MACing applied. */ 222 PRIVATE_ALG_MACING (1 << 9, "Private algorithm MACing"), 223 /** Standard algorithm MACing applied. */ 224 STD_ALG_MACING (1 << 10, "Standard algorithm MACing"), 225 /** Cardholder-managed end-to-end encryption applied. */ 226 CARDHOLDER_MANAGED_END_TO_END_ENCRYPTION (1 << 11, "Cardholder managed end-to-end encryption"), 227 /** Cardholder-managed point-to-point encryption applied. */ 228 CARDHOLDER_MANAGED_POINT_TO_POINT_ENCRYPTION (1 << 12, "Cardholder managed point-to-point encryption"), 229 /** Merchant-managed end-to-end encryption applied. */ 230 MERCHANT_MANAGED_END_TO_END_ENCRYPTION (1 << 13, "Merchant managed end-to-end encryption"), 231 /** Merchant-managed point-to-point encryption applied. */ 232 MERCHANT_MANAGED_POINT_TO_POINT_ENCRYPTION (1 << 14, "Merchant managed point-to-point encryption"), 233 /** Acquirer-managed end-to-end encryption applied. */ 234 ACQUIRER_MANAGED_END_TO_END_ENCRYPTION (1 << 15, "Acquirer managed end-to-end-encryption"), 235 /** Acquirer-managed point-to-point encryption applied. */ 236 ACQUIRER_MANAGED_POINT_TO_POINT_ENCRYPTION (1 << 16, "Acquirer managed point-to-point encryption"); 237 238 /** Integer bitmask value for this security characteristic. */ 239 private int val; 240 /** Human-readable description of this security characteristic. */ 241 private String description; 242 SecurityCharacteristic (int val, String description) { 243 this.val = val; 244 this.description = description; 245 } 246 /** {@inheritDoc} */ 247 public int intValue() { 248 return val; 249 } 250 /** {@inheritDoc} */ 251 public String toString () { 252 return description; 253 } 254 255 /** Bit offset within the PosDataCode byte array for security characteristic flags. */ 256 public static int OFFSET = 12; 257 /** {@inheritDoc} */ 258 @Override 259 public int getOffset() { 260 return OFFSET; 261 } 262 } 263 264 /** Raw 16-byte array holding the four groups of POS data code flags. */ 265 private byte[] b = new byte[16]; 266 267 /** Default constructor. */ 268 public PosDataCode() { 269 } 270 271 /** 272 * Constructs a PosDataCode with the given flag integers for each category. 273 * 274 * @param readingMethod bitmask of {@link ReadingMethod} values 275 * @param verificationMethod bitmask of {@link VerificationMethod} values 276 * @param posEnvironment bitmask of {@link POSEnvironment} values 277 * @param securityCharacteristic bitmask of {@link SecurityCharacteristic} values 278 */ 279 public PosDataCode ( 280 int readingMethod, 281 int verificationMethod, 282 int posEnvironment, 283 int securityCharacteristic) 284 { 285 super(); 286 287 b[0] = (byte) readingMethod; 288 b[1] = (byte) (readingMethod >>> 8); 289 b[2] = (byte) (readingMethod >>> 16); 290 b[3] = (byte) (readingMethod >>> 24); 291 292 b[4] = (byte) verificationMethod; 293 b[5] = (byte) (verificationMethod >>> 8); 294 b[6] = (byte) (verificationMethod >>> 16); 295 b[7] = (byte) (verificationMethod >>> 24); 296 297 b[8] = (byte) posEnvironment; 298 b[9] = (byte) (posEnvironment >>> 8); 299 b[10] = (byte) (posEnvironment >>> 16); 300 b[11] = (byte) (posEnvironment >>> 24); 301 302 b[12] = (byte) securityCharacteristic; 303 b[13] = (byte) (securityCharacteristic >>> 8); 304 b[14] = (byte) (securityCharacteristic >>> 16); 305 b[15] = (byte) (securityCharacteristic >>> 24); 306 } 307 308 /** 309 * Constructs a PosDataCode from a raw byte array. 310 * 311 * @param b source byte array (up to 16 bytes are copied) 312 */ 313 private PosDataCode (byte[] b) { 314 if (b != null) { 315 // will always use our own internal copy of array 316 int copyLen= Math.min(b.length, 16); 317 System.arraycopy(b, 0, this.b, 0, copyLen); 318 } 319 } 320 321 /** 322 * Returns {@code true} if all specified reading method bits are set. 323 * 324 * @param readingMethods bitmask of reading methods to test 325 * @return {@code true} if all specified bits are set 326 */ 327 public boolean hasReadingMethods (int readingMethods) { 328 int i = b[3] << 24 | b[2] << 16 & 0xFF0000 | b[1] << 8 & 0xFF00 | b[0] & 0xFF ; 329 return (i & readingMethods) == readingMethods; 330 } 331 332 /** 333 * Returns {@code true} if the given reading method is set. 334 * 335 * @param method the {@link ReadingMethod} to test 336 * @return {@code true} if the reading method bit is set 337 */ 338 public boolean hasReadingMethod (ReadingMethod method) { 339 return hasReadingMethods (method.intValue()); 340 } 341 342 /** 343 * Returns {@code true} if all specified verification method bits are set. 344 * 345 * @param verificationMethods bitmask of verification methods to test 346 * @return {@code true} if all specified bits are set 347 */ 348 public boolean hasVerificationMethods (int verificationMethods) { 349 int i = b[7] << 24 | b[6] << 16 & 0xFF0000 | b[5] << 8 & 0xFF00 | b[4] & 0xFF; 350 return (i & verificationMethods) == verificationMethods; 351 } 352 353 /** 354 * Returns {@code true} if the given verification method is set. 355 * 356 * @param method the {@link VerificationMethod} to test 357 * @return {@code true} if the verification method bit is set 358 */ 359 public boolean hasVerificationMethod (VerificationMethod method) { 360 return hasVerificationMethods(method.intValue()); 361 } 362 363 /** 364 * Returns {@code true} if all specified POS environment bits are set. 365 * 366 * @param posEnvironments bitmask of POS environments to test 367 * @return {@code true} if all specified bits are set 368 */ 369 public boolean hasPosEnvironments (int posEnvironments) { 370 int i = b[11] << 24 | b[10] << 16 & 0xFF0000 | b[9] << 8 & 0xFF00 | b[8] & 0xFF; 371 return (i & posEnvironments) == posEnvironments; 372 } 373 374 /** 375 * Returns {@code true} if the given POS environment is set. 376 * 377 * @param method the {@link POSEnvironment} to test 378 * @return {@code true} if the POS environment bit is set 379 */ 380 public boolean hasPosEnvironment (POSEnvironment method) { 381 return hasPosEnvironments(method.intValue()); 382 } 383 384 /** 385 * Returns {@code true} if all specified security characteristic bits are set. 386 * 387 * @param securityCharacteristics bitmask of security characteristics to test 388 * @return {@code true} if all specified bits are set 389 */ 390 public boolean hasSecurityCharacteristics (int securityCharacteristics) { 391 int i = b[15] << 24 | b[14] << 16 & 0xFF0000 | b[13] << 8 & 0xFF00 | b[12] & 0xFF; 392 return (i & securityCharacteristics) == securityCharacteristics; 393 } 394 395 /** 396 * Returns {@code true} if the given security characteristic is set. 397 * 398 * @param characteristic the {@link SecurityCharacteristic} to test 399 * @return {@code true} if the security characteristic bit is set 400 */ 401 public boolean hasSecurityCharacteristic (SecurityCharacteristic characteristic) { 402 return hasSecurityCharacteristics(characteristic.intValue()); 403 } 404 405 /** 406 * Returns the raw 16-byte representation of this PosDataCode. 407 * 408 * @return byte array holding all POS data code flags 409 */ 410 public byte[] getBytes() { 411 return b; 412 } 413 414 /** 415 * Returns {@code true} if the transaction used an EMV (ICC or contactless) reading method. 416 * 417 * @return {@code true} if ICC or contactless reading method is set 418 */ 419 public boolean isEMV() { 420 return hasReadingMethod(ReadingMethod.ICC) || hasReadingMethod(ReadingMethod.CONTACTLESS); 421 } 422 423 /** 424 * Returns {@code true} if the transaction used manual (physical) entry. 425 * 426 * @return {@code true} if physical reading method is set 427 */ 428 public boolean isManualEntry() { 429 return hasReadingMethod(ReadingMethod.PHYSICAL); 430 } 431 432 /** 433 * Returns {@code true} if the transaction used magnetic stripe reading. 434 * 435 * @return {@code true} if magnetic stripe reading method is set 436 */ 437 public boolean isSwiped() { 438 return hasReadingMethod(ReadingMethod.MAGNETIC_STRIPE); 439 } 440 441 /** 442 * Returns {@code true} if the transaction is a recurring transaction. 443 * 444 * @return {@code true} if the recurring POS environment flag is set 445 */ 446 public boolean isRecurring() { 447 return hasPosEnvironment(POSEnvironment.RECURRING); 448 } 449 450 /** 451 * Returns {@code true} if the transaction is an e-commerce transaction. 452 * 453 * @return {@code true} if the e-commerce POS environment flag is set 454 */ 455 public boolean isECommerce() { 456 return hasPosEnvironment(POSEnvironment.E_COMMERCE); 457 } 458 459 /** 460 * Returns {@code true} if the card was not physically present (e-commerce, manual entry, or recurring). 461 * 462 * @return {@code true} if card-not-present conditions are detected 463 */ 464 public boolean isCardNotPresent() { 465 return isECommerce() || isManualEntry() || isRecurring(); 466 } 467 468 /** {@inheritDoc} */ 469 public String toString() { 470 return super.toString() + "[" + ISOUtil.hexString (getBytes())+ "]"; 471 } 472 473 /** 474 * Creates a PosDataCode instance from a raw byte array. 475 * 476 * @param b source byte array 477 * @return a new {@link PosDataCode} initialized from {@code b} 478 */ 479 public static PosDataCode valueOf (byte[] b) { 480 return new PosDataCode(b); // we create new objects for now, but may return cached instances in the future 481 } 482 483 /** 484 * Dumps a human-readable representation of this PosDataCode to the given stream. 485 * 486 * @param p the output stream 487 * @param indent indentation prefix string 488 */ 489 public void dump(PrintStream p, String indent) { 490 String inner = indent + " "; 491 StringBuilder sb = new StringBuilder(); 492 p.printf("%s<pdc value='%s'>%s%n", indent, ISOUtil.hexString(getBytes()), sb.toString()); 493 for (ReadingMethod m : ReadingMethod.values()) { 494 if (hasReadingMethod(m)) { 495 if (sb.length() > 0) 496 sb.append(','); 497 sb.append(m.name()); 498 } 499 } 500 p.printf ("%srm: %s%n", inner, sb.toString()); 501 sb = new StringBuilder(); 502 for (VerificationMethod m : VerificationMethod.values()) { 503 if (hasVerificationMethod(m)) { 504 if (sb.length() > 0) 505 sb.append(','); 506 sb.append(m.name()); 507 } 508 } 509 p.printf ("%svm: %s%n", inner, sb.toString()); 510 sb = new StringBuilder(); 511 for (POSEnvironment m : POSEnvironment.values()) { 512 if (hasPosEnvironment(m)) { 513 if (sb.length() > 0) 514 sb.append(','); 515 sb.append(m.name()); 516 } 517 } 518 p.printf ("%spe: %s%n", inner, sb.toString()); 519 sb = new StringBuilder(); 520 for (SecurityCharacteristic m : SecurityCharacteristic.values()) { 521 if (hasSecurityCharacteristic(m)) { 522 if (sb.length() > 0) 523 sb.append(','); 524 sb.append(m.name()); 525 } 526 } 527 p.printf ("%ssc: %s%n", inner, sb.toString()); 528 p.println("</pdc>"); 529 } 530 531 /** 532 * Sets or clears one or more reading methods. 533 * 534 * @param value {@code true} to set, {@code false} to clear 535 * @param methods the reading methods to modify 536 */ 537 public void setReadingMethods(boolean value, ReadingMethod ... methods ){ 538 setFlags(value, methods); 539 } 540 541 /** 542 * Clears one or more reading methods. 543 * 544 * @param methods the reading methods to clear 545 */ 546 public void unsetReadingMethods(ReadingMethod ... methods ) { 547 setReadingMethods(false, methods); 548 } 549 550 /** 551 * Sets one or more reading methods. 552 * 553 * @param methods the reading methods to set 554 */ 555 public void setReadingMethods(ReadingMethod ... methods ) { 556 setReadingMethods(true, methods); 557 } 558 559 /** 560 * Sets or clears one or more verification methods. 561 * 562 * @param value {@code true} to set, {@code false} to clear 563 * @param methods the verification methods to modify 564 */ 565 public void setVerificationMethods(boolean value, VerificationMethod ... methods ){ 566 setFlags(value, methods); 567 } 568 569 /** 570 * Clears one or more verification methods. 571 * 572 * @param methods the verification methods to clear 573 */ 574 public void unsetVerificationMethods(VerificationMethod ... methods){ 575 setVerificationMethods(false, methods); 576 } 577 578 /** 579 * Sets one or more verification methods. 580 * 581 * @param methods the verification methods to set 582 */ 583 public void setVerificationMethods(VerificationMethod ... methods){ 584 setVerificationMethods(true, methods); 585 } 586 587 /** 588 * Sets or clears one or more POS environment flags. 589 * 590 * @param value {@code true} to set, {@code false} to clear 591 * @param envs the POS environments to modify 592 */ 593 public void setPOSEnvironments(boolean value, POSEnvironment ... envs){ 594 setFlags(value, envs); 595 } 596 597 /** 598 * Clears one or more POS environment flags. 599 * 600 * @param envs the POS environments to clear 601 */ 602 public void unsetPOSEnvironments(POSEnvironment ... envs){ 603 setPOSEnvironments(false, envs); 604 } 605 606 /** 607 * Sets one or more POS environment flags. 608 * 609 * @param envs the POS environments to set 610 */ 611 public void setPOSEnvironments(POSEnvironment ... envs){ 612 setPOSEnvironments(true, envs); 613 } 614 615 /** 616 * Sets or clears one or more security characteristic flags. 617 * 618 * @param value {@code true} to set, {@code false} to clear 619 * @param securityCharacteristics the security characteristics to modify 620 */ 621 public void setSecurityCharacteristics(boolean value, SecurityCharacteristic ... securityCharacteristics){ 622 setFlags(value, securityCharacteristics); 623 } 624 625 /** 626 * Clears one or more security characteristic flags. 627 * 628 * @param envs the security characteristics to clear 629 */ 630 public void unsetSecurityCharacteristics(SecurityCharacteristic ... envs){ 631 setSecurityCharacteristics(false, envs); 632 } 633 634 /** 635 * Sets one or more security characteristic flags. 636 * 637 * @param envs the security characteristics to set 638 */ 639 public void setSecurityCharacteristics(SecurityCharacteristic ... envs){ 640 setSecurityCharacteristics(true, envs); 641 } 642 643 644}