# Adapter scenarios

# Printing Custom Receipt

Business Need : Based on the market and acquirer’s needs, we want to print additional data on the receipt.

To achieve this goal, processorOptions object is used. It is a map of key-value strings and used for various processor specific data including the custom fields to be printed on the receipt.

Poynt terminal application looks for certain keys received in the response message and prints the key and corresponding value on the receipt.

In the following Response Handler Java Script code, the procOpt (an internal variable) is filled with following custom data. Acquirers may decide their own custom data printed on the receipt.

  • Promotional messages
  • Number of installments
  • Cardholder name

And finally TRANSACTION data object is set with the the values with the ones within the procOpt.

POS Terminal application checks certain keywords (“isPrintPromotionalMessage”, “noOfInstallments“, “Cardholder Name“) and then prints them on the receipt.

function responseHandler() {
  //Processor Options bag of Key/Value pairs to return.
  //Most of these are for receipt printing
  var procOpt = $TRANSACTION.getProcessorOptions();
  if (procOpt === null) {
    procOpt = new java.util.HashMap();
  }
  var promoMessageStr = $SELF.getField('hostMessage');
  if (promoMessageStr !== null) {
    procOpt.put("isPrintPromotionalMessage", "true");
    procOpt.put("promotionalMessage", promoMessageStr);
    procOpt.put("isPromotionalMessageDisplayed", "true");
  }
  var installmentData = $SELF.getField('originalData');
  if (installmentData != null && installmentData.length>=3) {
    var noOfInstallmemnts = installmentData.substring(1,3);
    procOpt.put("noOfInstallments",noOfInstallmemnts);
  }
  if ($TRANSACTION.getFundingSource().getCard() !== null &&
      $TRANSACTION.getFundingSource().getCard().getCardHolderFullName() !== null) {
    procOpt.put("Cardholder Name", $TRANSACTION.getFundingSource().getCard().getCardHolderFullName());
  }
  $TRANSACTION.setProcessorOptions(procOpt);
};

# Adding SCA Logic (EU)

Business Need : In Europe, SCA is mandated by regulation. Acquirers send certain SCA soft decline codes to the terminal (INSERT_CARD, ENTER_PIN) and POS terminal prompts user to insert the card or enter the PIN based on these response codes.

To achieve this, Response Handler Java Script code performs following operations :

  • If ReplyCode indicates 1111 (a specific value for ENTER PIN soft decline)

    • Set internal variable (scaResult) to $SCA_ENTER_PIN
  • If ReplyCode indicates 2222 (a specific value for INSERT CAR soft decline)

    • If the transaction is done with a mobile wallet (checkedTag and checkedByte variables)

      • Set internal variable (scaResult) to $SCA_CDCVM
    • else

      • Set internal variable (scaResult) to $SCA_INSERT_CARD

And finally set scaResult in the $PROCESSOR_RESPONSE.

POS terminal gets the $PROCESSOR_RESPONSE, checks the scaResult and perform the defined actions based on this data.

# Setting EMV Data(Auth Message)

Business Need : Brands) have different EMV tags and new tags comes in certain periods. We need to be able to define any EMV tags in the authorization message.

emvData field has following attributes:

Adapter emvdata1

To achieve this goal, there is a WHITELIST function where EMV tags are defined. New tags can easily be added in this list.

The Java script code performs following operations :

var eMode = $TRANSACTION.getFundingSource().getEntryDetails().getEntryMode().name();
console.info ('>>>>>>>>eMode' + eMode)
if (eMode == 'INTEGRATED_CIRCUIT_CARD' || eMode == 'CONTACTLESS_INTEGRATED_CIRCUIT_CARD') {
  var emvData = $TRANSACTION.getFundingSource().getEmvData();
  if (emvData !== null) {
    var WHITELIST = ['0x9F6E', '0x82', '0x95', '0x9A', '0x9C', '0x5F2A', '0x9F02', '0x9F03', '0x9F09', '0x9F1A',
                     '0x9F1E', '0x9F26', '0x9F27', '0x9F33', '0x9F34', '0x9F35', '0x9F36', '0x9F37', '0x9F39',
                     '0x9F41', "0x9F53", '0x84', '0x9F10', '0x5F34', '0x9F1E', '0x9F06', '0x9F07'];
    var tlv = $TLV.make(emvData, WHITELIST);
    return tlv;
  }
}

# Setting EMV Data(Auth Response)

Business Need : EMV data received from the acquirer should be sent to the terminal.

EMV response data includes significant data(Authorization response cryptogram, issuer response code, etc) to successfully complete an EMV transaction.

To achieve this, Response Handler Java Script code performs following operations :

  • If entryMode indicates that it is an EMV transaction

    • Set the $PROCESSOR_RESPONSE data object with the EMV response tags.

POS terminal reaches out the EMV response data within the $PROCESSOR_RESPONSE and performs EMV defined operations to complete the transaction.

//process EMV response
var entryMode = $TRANSACTION.getFundingSource().getEntryDetails().getEntryMode().name();
if (entryMode === 'INTEGRATED_CIRCUIT_CARD' ||
  entryMode === 'CONTACTLESS_INTEGRATED_CIRCUIT_CARD') {
  var emvDataResp = $BINARY.toHexString($SELF.getBinaryField('emvData'));
  var emvData = $TLV.parse(emvDataResp);
  $PROCESSOR_RESPONSE.setEmvTags(emvData);
}

# Setting Processing Code

Business need : We need to set Processing Code field-(3-4) to a certain value in the following 2 cases.

  • EMV card with US common debit AID

  • MSR card with PIN entry

Processing field has following attributes :

Adapter aid

To achieve this, Java Script code performs following operations :

  • if the entry mode is EMV or contactless

    • If value of EMV Tag 84 (AID) is an U.S Common Debit AID

      • Set the Processing Code field (3-4) to the $INT_DEB_CRD_PIN
  • if the entry mode is NOT EMV or contactless

    • If the trnsaction includes PIN data

      • Set the Processing Code field (3-4) to the $INT_DEB_CRD_PIN
function() {
  var txnType = $PC_GOODS_SERVICE;
  if ($TRANSACTION.getAmounts().getCashbackAmount() != null && $TRANSACTION.getAmounts().getCashbackAmount() > 0) {
    txnType = $PC_GOODS_SERVICE_CASHBACK;
  }
  
  var fromAccount = $PC_FROM_CREDIT;
  if ($TRANSACTION.getFundingSource().isDebit() != null && $TRANSACTION.getFundingSource().isDebit()) {
    fromAccount = $PC_FROM_US_DEBIT;
  }
  
  if ($TRANSACTION.getFundingSource().getAccountType() != null && $TRANSACTION.getFundingSource().getAccountType().name() === "EBT") {
    fromAccount = $PC_FROM_EBT;
  }
  
  console.log(txnType + fromAccount + $PC_TO_DEFAULT);
  return txnType + fromAccount + $PC_TO_DEFAULT;
}

# Setting Track2Data

Business Need : Converting Track2 data to fixed length alphanumeric format and add Fs at the end.

Track2 data comes in the TRANSACTION data object in the BINARY format as defined in the attributes below.

Adapter trackdata1

To achieve this, Java Script code performs following operations :

  • If the EntryMode is not KEYED

    • Get the Track2Data from the TRANSACTION object (the path is $TRANSACTION.getFundingSource().getCard().getTrack2data())

    • If the total length of the track2Data is odd

      • Pad “F” character at the end
    • Convert it to String format

function evaluate() {
    //Z-Attribute Format Rules:
    //replace seperatar/delimiter with 'D' if it is '='
    //If total length is still odd, right pad with F
    //HEX encode the whole thing
  if ($TRANSACTION.getFundingSource().getEntryDetails().getEntryMode().name() !== 'KEYED') {
      var track2 = $TRANSACTION.getFundingSource().getCard().getTrack2data();
      track2 = track2.replace(/=/g,'D'); //Replace '=' with 'D'
      var track2Len = track2.length;
    
      if(track2.length % 2 != 0){      // Check if total length of track II is odd
        track2 = track2 + 'F';       // Right pad with 'F'
      }
    
      var newTrack2 = track2Len.toString() + track2;
      return newTrack2;
  }
  return null;
}

# Error Message on Terminal Screen

Business Need : We need to show specific error messages on the terminal screen for certain response codes.

To achieve this, Response Handler Java Script code performs following operations :

  • Define error messages for selected response codes (51 and 55 in this example)

  • If the response code is different than 00

    • Set the $PROCESSOR_RESPONSE.setStatusMessage to the defined error message

      var errorMessageEn = {
        '51': 'PIN Try limit exceeded',
        '55': 'Incorrect PIN'
      }
      
      if ($SELF.getField('responseCode') === '00') {
      
        $PROCESSOR_RESPONSE.setStatus($SUCCESSFUL);
        $PROCESSOR_RESPONSE.setStatusCode('00');
        $PROCESSOR_RESPONSE.setStatusMessage($SELF.getField('authIdResponse'));
      } else {
        if ($SELF.getField('responseCode') && errorMessageEn[$SELF.getField('responseCode')]) {
          $PROCESSOR_RESPONSE.setStatusMessage(errorMessageEn[$SELF.getField('responseCode')]);
        }
        $PROCESSOR_RESPONSE.setStatus($FAILURE);
        $PROCESSOR_RESPONSE.setStatusCode($SELF.getField('responseCode'));
      }
      

Poynt terminal displays the message received in the $PROCESSOR_RESPONSE.StatusMessage

# Entry Mode in the Auth Message

Business Need : Field 22 consists of the 2 sub-fields : First 2 bytes is Entry Mode and last byte is PIN entry capability. The field is defined has following attributes : Field type is Fixed length numeric, Length is 3 and Val Encoding is BCD. The field goes in the position 22 in the authorization message.

Adapter entmode

At the bottom of the field definition screen, a Java script is seen. This Java script gets the Entry Mode in the TRANSACTION data object, performs certain controls and then sets the EntryMode in an authorization message.

The Java script code performs following operations :

  • Gets the entry mode from the TRANSACTION data object

  • Sets the entryMode based on the data in the TRANSACTION data object (First 2 digits)

  • Sets the entryMode to ENTRY_MODE_ICC_FALLBACK_MSR if it is a fallback transaction

  • If the transaction includes encrypted PIN data, then sets the 3th digit of the entryMode to 1 (PIN entered)

  • Returns entryMode

The Adapter Java Script Code :

function() {
  console.log('ENTRY MODE:' + $TRANSACTION.getFundingSource().getEntryDetails().getEntryMode());
  
  var entryMode = $ENTRY_MODE_ICC;
  var canAcceptPin = '1';     //PIN entry capability
  
  switch ($TRANSACTION.getFundingSource().getEntryDetails().getEntryMode().name()) {
    case 'KEYED':
      entryMode = $ENTRY_MODE_MANUAL;
      break;
    case 'TRACK_DATA_FROM_MAGSTRIPE':
      entryMode = $ENTRY_MODE_MSR;
      break;
    case 'CONTACTLESS_MAGSTRIPE':
      entryMode = $ENTRY_MODE_MSR_CL;
      break;
    case 'INTEGRATED_CIRCUIT_CARD':
      entryMode = $ENTRY_MODE_ICC;
      break;
    case 'CONTACTLESS_INTEGRATED_CIRCUIT_CARD':
      entryMode = $ENTRY_MODE_ICC_CL;
      break;
    default:
      entryMode = $ENTRY_MODE_ICC;
  }
  
  if ($TRANSACTION.getFundingSource().getEntryDetails().isIccFallback() != null &&
      $TRANSACTION.getFundingSource().getEntryDetails().isIccFallback()) {
    entryMode = $ENTRY_MODE_ICC_FALLBACK_MSR;
  }
  
  return entryMode + canAcceptPin;
}

# Defining Custom Encoder

Sometimes, acquirers may have custom fields in the payload. In the following example, the payload has 2 bytes of the length (length of the payload) information at the beginning of the message. The following Custom Encoder Java Script adds this 2 byte of the length at the beginning of the message and Custom Decoder removes this length bytes.

Custom Encoder

function encode(data) {
  console.log("Data Length >>>>> " + data.length);
  var edata = new ArrayBuffer(2 + data.length);

  edata[0] = (data.length & 0x0000ff00) >> 8;
  edata[1] = (data.length & 0x000000ff);

  for (var i = 0; i < data.length; i++) {
    edata[i + 2] = data[i];
  }
  
  return Java.to(edata, 'byte[]');
}

Custom Decoder

function decode(data) {
  console.log("Data Length >>>>> " + data.length);
  var ddata = new ArrayBuffer(data.length + 2);

  for (var i = 2; i < data.length; i++) {
    ddata[i - 2] = data[i];
  }
  
  return Java.to(ddata, 'byte[]');
}
Last Updated: 12/15/2020, 10:18:59 AM