All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.global.api.gateways.GnapConnector Maven / Gradle / Ivy

There is a newer version: 14.2.3
Show newest version
package com.global.api.gateways;

import com.global.api.builders.AuthorizationBuilder;
import com.global.api.builders.ManagementBuilder;
import com.global.api.builders.TransactionBuilder;
import com.global.api.entities.EncryptionData;
import com.global.api.entities.enums.AccountType;
import com.global.api.network.entities.gnap.*;
import com.global.api.entities.Transaction;
import com.global.api.entities.enums.*;
import com.global.api.entities.exceptions.ApiException;
import com.global.api.entities.exceptions.GatewayException;
import com.global.api.entities.exceptions.GatewayTimeoutException;
import com.global.api.network.enums.gnap.*;
import com.global.api.network.NetworkMessageHeader;
import com.global.api.network.enums.gnap.CardType;
import com.global.api.network.enums.gnap.GnapFIDS;
import com.global.api.network.enums.gnap.LogMessages;
import com.global.api.network.enums.NetworkProcessingFlag;
import com.global.api.network.enums.gnap.TransactionCode;
import com.global.api.paymentMethods.*;
import com.global.api.serviceConfigs.AcceptorConfig;
import com.global.api.serviceConfigs.GatewayConnectorConfig;
import com.global.api.terminals.DeviceMessage;
import com.global.api.terminals.abstractions.IDeviceMessage;
import com.global.api.utils.*;
import org.joda.time.DateTime;

import java.math.BigDecimal;

public class GnapConnector extends GatewayConnectorConfig {
    boolean isCreditCard;
    boolean isDebitCard;
    boolean isEmvDataPresent;
    final String fs = String.valueOf((char) 0x1C);
    final String rs = String.valueOf((char) 0x1E);
    private TransactionCode transCode=null;

    @Override
    public void setTerminalId(String terminalId) {
        this.terminalId = terminalId;
    }
    public NetworkProcessingFlag getProcessingFlag() {
        return processingFlag;
    }

    public void setProcessingFlag(NetworkProcessingFlag processingFlag) {
        this.processingFlag = processingFlag;
    }

    @Override
    public void setAcceptorConfig(AcceptorConfig acceptorConfig) {
        this.acceptorConfig = acceptorConfig;
    }

    public Transaction processAuthorization(AuthorizationBuilder builder) throws ApiException {

        MessageWriter mr = new MessageWriter();
        GnapRequestData reqData = builder.getGnapRequestData();
        GnapMessageHeader header = reqData.getGnapMessageHeader();
        GnapProdSubFids prodSubFids = reqData.getGnapProdSubFids();
        IPaymentMethod paymentMethod = builder.getPaymentMethod();
        CardBrand cardBrand=null;
        OptionalData optionalData = builder.getGnapRequestData().getOptionalData();
        if(header!=null) {
            header.setCurrentDate(DateTime.now().toString("yyMMdd"));
            header.setCurrentTime(DateTime.now().toString("hhmmss"));
        }

        if (paymentMethod != null) {
            cardBrand=GnapUtils.getCardBrand(paymentMethod);
            isCreditCard = paymentMethod.getPaymentMethodType().equals(PaymentMethodType.Credit) ||paymentMethod instanceof Credit;
            isDebitCard = paymentMethod.getPaymentMethodType().equals(PaymentMethodType.Debit) ||paymentMethod instanceof Debit;
        }

        TransactionType transactionType = builder.getTransactionType();
        EmvData tagData = EmvUtils.parseTagData(builder.getTagData(), isEnableLogging());
        isEmvDataPresent = tagData != null;
        setTransactionCodeInHeader(header,builder);
        if(isCreditCard){
            reqData.setCardType(CardType.Credit);
        }else if(isDebitCard){
            reqData.setCardType(CardType.Debit);
        }

        GnapUtils.log("***************Request Header*****************", "*****");
        MessageWriter headerWriter = buildRequestHeader(header, acceptorConfig);
        GnapUtils.log("Final Request Header", new String(headerWriter.toArray()));
        MapGnapFids mapFids = new MapGnapFids(mr);
        mr.addRange(headerWriter.toArray());

        GnapUtils.log("***************Request Fids*****************", "*****");

        //FID_B("Transaction Amount")
            mapFids.addFid(GnapFIDS.FID_B, getTransactionAmount(builder));

        //FID_D("Account Type")
        if(cardBrand!=null) {
            if ((isDebitCard || cardBrand.equals(CardBrand.UnionPay)) && reqData.getAccountType() != null) {
                mapFids.addFid(GnapFIDS.FID_D, accountTypeMapping(reqData.getAccountType()));
            }
        }

        //FID_F("Approval Code")
        if(isEmvDataPresent && tagData.getApprovalCode()!=null){
                mapFids.addFid(GnapFIDS.FID_F, StringUtils.padRight(tagData.getApprovalCode(), 8, ' '));
        }else if (reqData.getApprovalCode() != null) {
            mapFids.addFid(GnapFIDS.FID_F, StringUtils.padRight(reqData.getApprovalCode(), 8, ' '));
        }

        //FID_P("Draft Capture Flag")
        if(cardBrand!=null) {
            mapFids.addFid(GnapFIDS.FID_P, getDraftCapture(cardBrand, transactionType));
        }
        //FID_Q("Echo Data")
        mapFids.addFid(GnapFIDS.FID_Q, reqData.getEchoData());

        //FID_R("Card Type")
        mapFids.addFid(GnapFIDS.FID_R, reqData.getCardType());

        //FID_S("Invoice Number")
        mapFids.addFid(GnapFIDS.FID_S, reqData.getInvoiceNumber());

        //FID_U("Language Code")
        if(paymentMethod instanceof Credit){
            mapFids.addFid(GnapFIDS.FID_U, reqData.getLanguageCode());
        }else if(paymentMethod instanceof Debit && tagData !=null){
            if(tagData.getLanguageCode()!=null) {
                mapFids.addFid(GnapFIDS.FID_U, tagData.getLanguageCode());
            }else{
                mapFids.addFid(GnapFIDS.FID_U, reqData.getLanguageCode());
            }
        }
        //FID_X("ISO Response Code")
        if(isEmvDataPresent && header.getMessageSubType().equals(MessageSubType.StoreAndForwardTransactions)){
            mapFids.addFid(GnapFIDS.FID_U, tagData.getIsoResponseCode());
        }


        //FID_a("Optional Data")
        if(cardBrand!=null && optionalData != null) {
            mapFids.addFid(GnapFIDS.FID_a, optionalData.getOptionalData(transactionType, header.getTransactionCode(), cardBrand, reqData.getCardType()));
        }

        //FID_b("PIN Block")
        if(paymentMethod instanceof IPinProtected) {
            String pinBlock = ((IPinProtected)paymentMethod).getPinBlock();
            if(!StringUtils.isNullOrEmpty(pinBlock)) {
                mapFids.addFid(GnapFIDS.FID_b, pinBlock);
            }
        }

        //FID_d("Retailer ID")
        mapFids.addFid(GnapFIDS.FID_d, reqData.getRetailerID());

        //FID_e("POS Condition Code")
        mapFids.addFid(GnapFIDS.FID_e, reqData.getPosConditionCode());

        //FID_h("Sequence Number")
        if (reqData.getSequenceNumber() != null) {
            mapFids.addFid(GnapFIDS.FID_h, reqData.getSequenceNumber().getValue());
        }

        //FID_p("Paypass Device Type Indicator")
        if(isEmvDataPresent) {
            mapFids.addFid(GnapFIDS.FID_p, tagData.getDeviceTypeIndicator());
        }

        //FID_q("Track 2 Data")
        if(paymentMethod !=null) {
            if (paymentMethod instanceof IEncryptable && acceptorConfig.isSupportsE2EEEncryption()) {
                EncryptionData encryptionData = ((IEncryptable) paymentMethod).getEncryptionData();
                if (encryptionData != null) {
                    mapFids.addFid(GnapFIDS.FID_q, encryptionData.getTrackNumber());
                }
            } else if (paymentMethod instanceof ITrackData) {
                ITrackData card = (ITrackData) paymentMethod;
                    mapFids.addFid(GnapFIDS.FID_q, card.getValue());
            } else if (paymentMethod instanceof ICardData) {
                ICardData card = (ICardData) paymentMethod;
                mapFids.addFid(GnapFIDS.FID_q, getManualTrackData(card.getNumber(), getShortExpiry(card)));
            }
        }

        //FID_t("Global Payments Pinpad serial Number")
        mapFids.addFid(GnapFIDS.FID_t, acceptorConfig.getPinPadSerialNumber());

        //FID_z("Union Pay Indicator")
        if(cardBrand!=null) {
            if (cardBrand.equals(CardBrand.UnionPay))
                mapFids.addFid(GnapFIDS.FID_z, UnionPayIndicator.UnionPayTransaction);
            else
                mapFids.addFid(GnapFIDS.FID_z, UnionPayIndicator.NonUnionPayTransaction);
        }
        //FID_4("Message Reason Codes for Merchant Initiated Transactions")
        mapFids.addFid(GnapFIDS.FID_4, reqData.getMerchantReasonCodes());

        //FID_6("Product Sub-FIDs")
        if (prodSubFids != null) {
            mapFids.addFid(GnapFIDS.FID_6, "");

            //subFID_B("CVV2/CVC2 Value")
            if (prodSubFids.getCvv2Value() != null) {
                mapFids.addSubFid(GnapSubFids.subFID_B, StringUtils.padRight(prodSubFids.getCvv2Value(), 4, ' '));
            }

            //subFID_E("POS Entry Mode")
            if(paymentMethod !=null) {
                if(paymentMethod instanceof ITrackData) {
                    ITrackData card = (ITrackData) paymentMethod;
                    String entryMode = card.getEntryMethod().getValue() + acceptorConfig.getPinCapability().getValue();
                    mapFids.addSubFid(GnapSubFids.subFID_E, entryMode);
                }else if(paymentMethod instanceof  ICardData) {
                    String entryMode = mapEntryMethod(EntryMethod.Manual) + acceptorConfig.getPinCapability().getValue();
                    mapFids.addSubFid(GnapSubFids.subFID_E, entryMode);
                }
            }

            //subFID_H("Card Verification Digits Presence indicator and Result")
            if (isCreditCard && (transactionType.equals(TransactionType.Sale) || transactionType.equals(TransactionType.Auth))
                    && prodSubFids.getCardPresenceIndicator() != null)
                mapFids.addSubFid(GnapSubFids.subFID_H, StringUtils.padRight(prodSubFids.getCardPresenceIndicator().getValue(), 2, ' '));


            //subFID_I("Transaction Currency Code (TCC)")
            if (isEmvDataPresent && tagData.getTransactionCurrencyCode()!=null)
                mapFids.addSubFid(GnapSubFids.subFID_I, tagData.getTransactionCurrencyCode().substring(1));


            if (isEmvDataPresent && !header.getTransactionCode().equals(TransactionCode.TelephoneAuthPurchase)){
                //subFID_O("EMV Request Data")
                mapFids.addSubFid(GnapSubFids.subFID_O, getEmvReqData(tagData));
                //subFID_P("EMV Additional Request Data")
                mapFids.addSubFid(GnapSubFids.subFID_P, getEmvAdditionalReqData(tagData));
            }

            //subFID_S("UnionPay Online PIN DUKPT KSN")
            mapFids.addSubFid(GnapSubFids.subFID_S, prodSubFids.getUnionPayOnlinePINDUKPTKSN());

            //subFID_T("DUKPT KSN")
            if(paymentMethod instanceof IEncryptable && acceptorConfig.isSupportsE2EEEncryption()){
                EncryptionData encryptionData= ((IEncryptable)paymentMethod).getEncryptionData();
                if(encryptionData != null) {
                    mapFids.addSubFid(GnapSubFids.subFID_T,encryptionData.getKsn());
                }
            }

            //subFID_X("Point of Service Data")
            if (prodSubFids.getPointOfServiceData() != null)
                mapFids.add(GnapSubFids.subFID_X, prodSubFids.getPointOfServiceData().getValue());

            //subFID_q("Paywave Form Factor Indicator")
            if (isEmvDataPresent)
                mapFids.addSubFid(GnapSubFids.subFID_q, tagData.getFormFactorIndicator());
        }

        mr.add(ControlCodes.ETX);
        IDeviceMessage buildMessage = new DeviceMessage(mr.toArray());
        GnapUtils.log("Final Request", buildMessage.toString());

        return sendRequest(mr, builder);
    }

    public Transaction manageTransaction(ManagementBuilder builder) throws ApiException {

        MessageWriter mr = new MessageWriter();
        GnapRequestData reqData = builder.getGnapRequestData();
        GnapMessageHeader header = reqData.getGnapMessageHeader();
        GnapProdSubFids prodSubFids = reqData.getGnapProdSubFids();
        IPaymentMethod paymentMethod = builder.getPaymentMethod();
        CardBrand cardBrand=GnapUtils.getCardBrand(paymentMethod);
        TransactionReference reference = null;
        OptionalData optionalData = builder.getGnapRequestData().getOptionalData();
        boolean isInstanceOfReference = false;

        if(header!=null) {
            header.setCurrentDate(DateTime.now().toString("yyMMdd"));
            header.setCurrentTime(DateTime.now().toString("hhmmss"));
        }

        if (paymentMethod instanceof TransactionReference) {
            reference = (TransactionReference) paymentMethod;
            if(reference!=null) {
                paymentMethod = reference.getOriginalPaymentMethod();
            }
            isInstanceOfReference=true;
            cardBrand=GnapUtils.getCardBrand(paymentMethod);
            isCreditCard = paymentMethod.getPaymentMethodType().equals(PaymentMethodType.Credit) ||paymentMethod instanceof Credit;
            isDebitCard = paymentMethod.getPaymentMethodType().equals(PaymentMethodType.Debit) ||paymentMethod instanceof Debit;
        }

        setTransactionCodeInHeader(header,builder);
        TransactionType transactionType = builder.getTransactionType();
        EmvData tagData = EmvUtils.parseTagData(builder.getTagData(), isEnableLogging());
        isEmvDataPresent = tagData != null;

        if(isCreditCard){
            reqData.setCardType(CardType.Credit);
        }else if(isDebitCard){
            reqData.setCardType(CardType.Debit);
        }

        GnapUtils.log("***************Request Header*****************", "*****");
        MessageWriter headerWriter = buildRequestHeader(header, acceptorConfig);
        GnapUtils.log("Final Request Header", new String(headerWriter.toArray()));
        MapGnapFids mapFids = new MapGnapFids(mr);
        mr.addRange(headerWriter.toArray());

        GnapUtils.log("***************Request Fids*****************", "*****");
        if(!transactionType.equals(TransactionType.BatchClose)) {

            //FID_B("Transaction Amount")
            mapFids.addFid(GnapFIDS.FID_B, getTransactionAmount(builder));

            //FID_C("Original Transaction Amount")
            if(reference != null) {
                if (reference.getOriginalApprovedAmount() != reference.getOriginalAmount())
                    mapFids.addFid(GnapFIDS.FID_C, StringUtils.toNumeric(reference.getOriginalApprovedAmount()));
                else if (transactionType.equals(TransactionType.PreAuthCompletion))
                    mapFids.addFid(GnapFIDS.FID_C, StringUtils.toNumeric(reference.getOriginalAmount()));
            }
            //FID_D("Account Type")
            if((isDebitCard || cardBrand.equals(CardBrand.UnionPay)) && reqData.getAccountType()!=null) {
                mapFids.addFid(GnapFIDS.FID_D, accountTypeMapping(reqData.getAccountType()));
            }

            //FID_F("Approval Code")
            if(reference != null) {
                if (isInstanceOfReference && reference.getOriginalProcessingCode() != null && isApprovalCodeValid(cardBrand, transactionType)) {
                    mapFids.addFid(GnapFIDS.FID_F, StringUtils.padRight(reference.getOriginalProcessingCode(), 8, ' '));
                }
            }

            //FID_P("Draft Capture Flag")
            mapFids.addFid(GnapFIDS.FID_P,getDraftCapture(cardBrand,transactionType));

            //FID_Q("Echo Data")
            mapFids.addFid(GnapFIDS.FID_Q, reqData.getEchoData());

            //FID_R("Card Type")
            mapFids.addFid(GnapFIDS.FID_R, reqData.getCardType());

            //FID_S("Invoice Number")
            mapFids.addFid(GnapFIDS.FID_S, reqData.getInvoiceNumber());

            //FID_T("Original Invoice Number")
            if(reference != null) {
                if (isInstanceOfReference && reference.getOriginalInvoiceNumber() != null)
                    mapFids.addFid(GnapFIDS.FID_T, reference.getOriginalInvoiceNumber());
            }
            //FID_U("Language Code")
            if(paymentMethod instanceof Credit){
                mapFids.addFid(GnapFIDS.FID_U, reqData.getLanguageCode());
            }else if(paymentMethod instanceof Debit && tagData !=null){
                if(tagData.getLanguageCode()!=null) {
                    mapFids.addFid(GnapFIDS.FID_U, tagData.getLanguageCode());
                }else{
                    mapFids.addFid(GnapFIDS.FID_U, reqData.getLanguageCode());
                }
            }

        //FID_X("ISO Response Code")
        if (isEmvDataPresent && (transactionType.equals(TransactionType.PreAuthCompletion)||
                header.getMessageSubType().equals(MessageSubType.StoreAndForwardTransactions))){
            mapFids.addFid(GnapFIDS.FID_X, tagData.getIsoResponseCode());
        }

            //FID_a("Optional Data")
            if (optionalData != null)
                mapFids.addFid(GnapFIDS.FID_a, optionalData.getOptionalData(transactionType,header.getTransactionCode(),cardBrand, reqData.getCardType()));

            //FID_b("PIN Block")
            if(paymentMethod instanceof IPinProtected) {
                String pinBlock = ((IPinProtected)paymentMethod).getPinBlock();
                if(!StringUtils.isNullOrEmpty(pinBlock)) {
                    mapFids.addFid(GnapFIDS.FID_b, pinBlock);
                }
            }

            //FID_d("Retailer ID")
            mapFids.addFid(GnapFIDS.FID_d, reqData.getRetailerID());

            //FID_e("POS Condition Code")
            mapFids.addFid(GnapFIDS.FID_e, reqData.getPosConditionCode());

            //FID_h("Sequence Number")
            if (reqData.getSequenceNumber() != null) {
                mapFids.addFid(GnapFIDS.FID_h, reqData.getSequenceNumber().getValue());
            }

            //FID_j("Mastercard Banknet Reference Number, Visa Transaction Identifier or Discover Network Reference ID")
            if(reference != null) {
                if (isInstanceOfReference)
                    mapFids.addFid(GnapFIDS.FID_j, reference.getTransactionIdentifier());
            }
            //FID_m("Day Totals")
            if (reqData.getDayTotals() != null)
                mapFids.addFid(GnapFIDS.FID_m, reqData.getDayTotals().getValue(reqData.getSequenceNumber()));

            //FID_p("Paypass Device Type Indicator")
            if(isEmvDataPresent) {
                mapFids.addFid(GnapFIDS.FID_p, tagData.getDeviceTypeIndicator());
            }

            //FID_q("Track 2 Data")
            if (paymentMethod != null) {
                if(paymentMethod instanceof IEncryptable && acceptorConfig.isSupportsE2EEEncryption()){
                    EncryptionData encryptionData = ((IEncryptable) paymentMethod).getEncryptionData();
                    if (encryptionData != null) {
                        mapFids.addFid(GnapFIDS.FID_q, encryptionData.getTrackNumber());
                    }
                }else {
                    if (paymentMethod instanceof ITrackData) {
                        ITrackData card = (ITrackData) paymentMethod;
                        if (transactionType.equals(TransactionType.PreAuthCompletion) || transactionType.equals(TransactionType.Void)) {
                            if(builder.getAmount().compareTo(BigDecimal.valueOf(0))==0 && cardBrand.equals(CardBrand.UnionPay)){
                                mapFids.addFid(GnapFIDS.FID_q, card.getValue());
                            }else {
                                mapFids.addFid(GnapFIDS.FID_q, getManualTrackData(card.getPan(), card.getExpiry()));
                            }
                        } else {
                                mapFids.addFid(GnapFIDS.FID_q, card.getValue());
                        }
                    } else if (paymentMethod instanceof ICardData) {
                        ICardData card = (ICardData) paymentMethod;
                        mapFids.addFid(GnapFIDS.FID_q, getManualTrackData(card.getNumber(), getShortExpiry(card)));
                    }
                }
            }


        //FID_t("Global Payments Pinpad serial Number")
        mapFids.addFid(GnapFIDS.FID_t, acceptorConfig.getPinPadSerialNumber());

            //FID_z("Union Pay Indicator")
            if (cardBrand.equals(CardBrand.UnionPay))
                mapFids.addFid(GnapFIDS.FID_z,UnionPayIndicator.UnionPayTransaction);
            else
                mapFids.addFid(GnapFIDS.FID_z,UnionPayIndicator.NonUnionPayTransaction);

            //FID_4("Message Reason Codes for Merchant Initiated Transactions")
            mapFids.addFid(GnapFIDS.FID_4, reqData.getMerchantReasonCodes());

            //FID_5("Transaction Info")
            if(reference != null) {
                if (isInstanceOfReference)
                    mapFids.addFid(GnapFIDS.FID_5, reference.getOriginalTransactionInfo());
            }
            //FID_6("Product Sub-FIDs")
            if (prodSubFids != null) {
                mapFids.addFid(GnapFIDS.FID_6, "");

                //subFID_B("CVV2/CVC2 Value")
                if (prodSubFids.getCvv2Value() != null) {
                    mapFids.addSubFid(GnapSubFids.subFID_B, StringUtils.padRight(prodSubFids.getCvv2Value(), 4, ' '));
                }

                //subFID_E("POS Entry Mode")
                if (paymentMethod != null) {
                    if (paymentMethod instanceof ITrackData) {
                        ITrackData card = (ITrackData) paymentMethod;
                        String entryMode = card.getEntryMethod().getValue() + acceptorConfig.getPinCapability().getValue();
                        mapFids.addSubFid(GnapSubFids.subFID_E, entryMode);
                    } else {
                        String entryMode = mapEntryMethod(EntryMethod.Manual) + acceptorConfig.getPinCapability().getValue();
                        mapFids.addSubFid(GnapSubFids.subFID_E, entryMode);
                    }
                }

                //subFID_H("Card Verification Digits Presence indicator and Result")
                if (isCreditCard && (transactionType.equals(TransactionType.Sale) || transactionType.equals(TransactionType.Auth))
                        && prodSubFids.getCardPresenceIndicator() != null)
                    mapFids.addSubFid(GnapSubFids.subFID_H, StringUtils.padRight(prodSubFids.getCardPresenceIndicator().getValue(), 2, ' '));


                //subFID_I("Transaction Currency Code (TCC)")
                if (isEmvDataPresent)
                    mapFids.addSubFid(GnapSubFids.subFID_I, tagData.getTransactionCurrencyCode().substring(1));

                if (isEmvDataPresent) {
                        //subFID_O("EMV Request Data")
                        mapFids.addSubFid(GnapSubFids.subFID_O, getEmvReqData(tagData));
                        //subFID_P("EMV Additional Request Data")
                        mapFids.addSubFid(GnapSubFids.subFID_P, getEmvAdditionalReqData(tagData));
                }

                //subFID_S("UnionPay Online PIN DUKPT KSN")
                mapFids.addSubFid(GnapSubFids.subFID_S, prodSubFids.getUnionPayOnlinePINDUKPTKSN());

                //subFID_T("DUKPT KSN")
                if(paymentMethod instanceof IPinProtected && acceptorConfig.isSupportsE2EEEncryption()){
                    EncryptionData encryptionData= ((IEncryptable)paymentMethod).getEncryptionData();
                    if(encryptionData != null) {
                        mapFids.addSubFid(GnapSubFids.subFID_T,encryptionData.getKsn());
                    }
                }

            //subFID_X("Point of Service Data")
            if(prodSubFids.getPointOfServiceData() != null)
                mapFids.add(GnapSubFids.subFID_X, prodSubFids.getPointOfServiceData().getValue());

                //subFID_q("Paywave Form Factor Indicator")
                if (isEmvDataPresent)
                    mapFids.addSubFid(GnapSubFids.subFID_q, tagData.getFormFactorIndicator());
            }
        }else{
            //FID_U("Language Code")
            mapFids.addFid(GnapFIDS.FID_U, reqData.getLanguageCode());

            //FID_h("Sequence Number")
            if (reqData.getSequenceNumber() != null) {
                mapFids.addFid(GnapFIDS.FID_h, reqData.getSequenceNumber().getValue());
            }

            //FID_m("Day Totals")
            if (reqData.getDayTotals() != null)
                mapFids.addFid(GnapFIDS.FID_m, reqData.getDayTotals().getValue(reqData.getSequenceNumber()));

            //FID_t("Global Payments Pinpad serial Number")
            mapFids.addFid(GnapFIDS.FID_t, acceptorConfig.getPinPadSerialNumber());

        }

        mr.add(ControlCodes.ETX);
        IDeviceMessage buildMessage = new DeviceMessage(mr.toArray());
        GnapUtils.log("Final Request", buildMessage.toString());

        return sendRequest(mr, builder);
    }

    private > Transaction sendRequest(MessageWriter messageData, T builder) throws ApiException {

        try {
            int messageLength = messageData.length();
            GnapUtils.log("Message Length ", String.valueOf(messageLength));
            MessageWriter req = new MessageWriter();
            req.add(messageLength, 2);
            req.addRange(messageData.toArray());
            IDeviceMessage buildMessage = new DeviceMessage(req.toArray());
            GnapUtils.log("Final Request with header and data", buildMessage.toString());
            byte[] responseBuffer = send(buildMessage);
            return mapResponse(responseBuffer, builder);

        } catch (GatewayTimeoutException exc) {
            throw exc;
        } catch (GatewayException exc) {
            throw new GatewayException(exc.getMessage(), exc.getResponseCode(), exc.getResponseText());
        } catch (Exception ex) {
            throw new ApiException(ex.getMessage());
        }

    }

    private > Transaction mapResponse(byte[] buffer, T builder) throws Exception {

        Transaction result = new Transaction();
        String response = new String(buffer);
        GnapUtils.log("Response ", response);
        String header = response.substring(0, 48);
        String data = response.substring(48,response.length()-1);
        TransactionReference reference = new TransactionReference();

        GnapUtils.log("Response Header", header);
        GnapResponse gnapResponse = new GnapResponse();

        GnapMessageHeader gnapMessageHeader = buildResponseHeader(header);
        GnapResponseData gnapResponseData = buildResponseData(data, reference);

        gnapResponse.setGnapMessageHeader(gnapMessageHeader);
        gnapResponse.setGnapResponseData(gnapResponseData);
        result.setGnapResponse(gnapResponse);

        IPaymentMethod paymentMethod = builder.getPaymentMethod();
        if(paymentMethod !=null) {
            if (paymentMethod instanceof TransactionReference) {
                TransactionReference originalReference = (TransactionReference) builder.getPaymentMethod();
                reference.setOriginalPaymentMethod(originalReference.getOriginalPaymentMethod());
            } else {
                reference.setOriginalPaymentMethod(paymentMethod);
                reference.setPaymentMethodType(builder.getPaymentMethod().getPaymentMethodType());
            }
        }
        reference.setOriginalAmount(builder.getAmount());
        reference.setOriginalTransactionType(builder.getTransactionType());
        result.setResponseCode(gnapResponseData.getApprovalCode());
        result.setTransactionReference(reference);
        return result;
    }

    public static  & IStringConstant> T readFidEnum(String value, Class clazz) {
        return ReverseStringEnumMap.parse(value, clazz);
    }

    @Override
    public String serializeRequest(AuthorizationBuilder builder) throws ApiException {
        return null;
    }

    @Override
    public NetworkMessageHeader sendKeepAlive() throws ApiException {
        return null;
    }

    @Override
    public boolean supportsHostedPayments() {
        return false;
    }

    @Override
    public boolean supportsOpenBanking() {
        return false;
    }

    private GnapResponseData buildResponseData(String sData, TransactionReference transactionReference) throws Exception {

        GnapResponseData gnapData = new GnapResponseData();
        GnapProdSubFids gnapProdSubFids = new GnapProdSubFids();

        String fidString = "";
        String subFidString = "";

        if (sData.contains(fs)) {
            fidString = sData.substring(sData.indexOf(fs)).substring(1);
        }

        if (sData.contains(rs)) {
            subFidString = sData.substring(sData.indexOf(rs)).substring(1);
        }
        String[] fidValues = fidString.split(fs);
        String[] subFidValues = subFidString.split(rs);

        GnapUtils.log("*************** Response FIDs *****************", "*****");

        for (String splt : fidValues) {
            if (!(splt.isEmpty())) {
                GnapFIDS gnapFIDS = readFidEnum(String.valueOf(splt.charAt(0)),GnapFIDS.class);
                String fid = splt.substring(1);

                GnapUtils.log("FID : " + gnapFIDS.getValue(),fid);

                switch (gnapFIDS) {

                    //FID_B("Transaction Amount") 
                    case FID_B:
                        gnapData.setTransactionAmount(new BigDecimal(fid));
                        transactionReference.setOriginalApprovedAmount(gnapData.getTransactionAmount());
                        break;

                    // FID_F("Approval Code")
                    case FID_F:
                        transactionReference.setOriginalProcessingCode(fid);
                        gnapData.setApprovalCode(fid);
                        break;

                    //FID_L("Balance Info")
                    case FID_L:
                        BalanceInfo balanceInfo=new BalanceInfo();
                        StringParser sp = new StringParser(fid);
                        balanceInfo.setAccountType1(sp.readString(2));
                        balanceInfo.setAmountType1(GnapConnector.readFidEnum(sp.readString(2),AmountType.class));
                        balanceInfo.setAmountSign1(sp.readString(1));
                        balanceInfo.setCurrencyCode1(sp.readString(3));
                        balanceInfo.setAmount1(new BigDecimal(sp.readString(12)));
                        if(fid.trim().length()>20) {
                            balanceInfo.setAccountType2(sp.readString(2));
                            balanceInfo.setAmountType2(GnapConnector.readFidEnum(sp.readString(2),AmountType.class));
                            balanceInfo.setAmountSign2(sp.readString(1));
                            balanceInfo.setCurrencyCode2(sp.readString(3));
                            balanceInfo.setAmount2(new BigDecimal(sp.readString(12)));
                        }
                        gnapData.setBalanceInfo(balanceInfo);
                        break;

                    // FID_M("PIN Encryption Key")
                    case FID_M:
                        gnapData.setPinEncryptionKey(fid);
                        break;

                    //FID_Q("Echo Data")
                    case FID_Q:
                        gnapData.setEchoData(fid);
                        break;

                    //FID_X("ISO Response Code")
                    case FID_X:
                        transactionReference.setIsoResponseCode(GnapConnector.readFidEnum(fid, ISOResponseCode.class));
                        gnapData.setIsoResponseCode(GnapConnector.readFidEnum(fid, ISOResponseCode.class));
                        if(transactionReference.getIsoResponseCode()!=null && transactionReference.getIsoResponseCode().equals(ISOResponseCode.PartialApproval)){
                            transactionReference.setPartialApproval(true);
                        }
                        break;

                    //FID_g("Response Message")
                    case FID_g:
                        gnapData.setResponseMessage(fid);
                        break;

                    // FID_h("Sequence Number")
                    case FID_h:
                        SequenceNumber sn = new SequenceNumber();
                        sn.setDayCounter(Integer.parseInt(fid.substring(0, 3)));
                        sn.setShiftCounter(Integer.parseInt(fid.substring(3, 6)));
                        sn.setBatchCounter(Integer.parseInt(fid.substring(6, 9)));
                        sn.setSequenceCounter(Integer.parseInt(fid.substring(9, 12)));
                        sn.setIndicator(Integer.parseInt(fid.substring(12)));
                        gnapData.setSequenceNumber(sn);
                        break;

                    //FID_j("Mastercard Banknet Reference Number, Visa Transaction Identifier or Discover Network Reference ID")
                    case FID_j:
                        transactionReference.setTransactionIdentifier(fid);
                        break;

                    //FID_m("Day Totals")
                    case FID_m:
                        GnapBatchTotal batchTotalRes = new GnapBatchTotal();
                        batchTotalRes.setTotalSalesTransaction(Integer.parseInt(fid.substring(6, 10)));
                        batchTotalRes.setSignTotalSale(GnapConnector.readFidEnum(fid.substring(10,11), BatchTotalSign.class));
                        batchTotalRes.setTotalSaleAmount(StringUtils.toString(fid.substring(11, 20), 2));

                        batchTotalRes.setTotalRefundTransaction(Integer.parseInt(fid.substring(20, 24)));
                        batchTotalRes.setSignTotalRefund(GnapConnector.readFidEnum(fid.substring(24,25), BatchTotalSign.class));
                        batchTotalRes.setTotalRefundAmount(StringUtils.toString(fid.substring(26, 34), 2));

                        batchTotalRes.setTotalAdjustmentTransaction(Integer.parseInt(fid.substring(34, 38)));
                        batchTotalRes.setSignTotalAdjustment(GnapConnector.readFidEnum(fid.substring(38,39), BatchTotalSign.class));
                        batchTotalRes.setTotalAdjustmentAmount(StringUtils.toString(fid.substring(39, 47), 2));

                        gnapData.setDayTotals(batchTotalRes);
                        break;

                    //FID_5("Transaction Info")
                    case FID_5:
                        transactionReference.setOriginalTransactionInfo(fid);
                        gnapData.setTransactionInfo(fid);
                        break;

                    //FID_6("Product Sub-FIDs")
                    case FID_6:
                        for (String sf : subFidValues) {
                            GnapSubFids gnapSubFIDS = readFidEnum(String.valueOf(sf.charAt(0)),GnapSubFids.class);
                            String subFid = sf.substring(1);
                            GnapUtils.log("  SUBFID : " + gnapSubFIDS.getValue(), subFid);
                            switch (gnapSubFIDS) {

                                //subFID_E("POS Entry Mode")
                                case subFID_E:
                                    transactionReference.setOriginalPosEntryMode(subFid);
                                    gnapProdSubFids.setPosEntryMode(subFid);
                                    break;

                                //subFID_H("Card Verification Digits Presence indicator and Result")
                                case subFID_H:
                                    gnapProdSubFids.setCardPresenceIndicator(GnapConnector.readFidEnum(subFid, CardIdentifierPresenceIndicator.class));
                                    break;

                                //subFID_I("Transaction Currency Code (TCC)")
                                case subFID_I:
                                    gnapProdSubFids.setTransactionCurrencyCode(subFid);
                                    break;

                                //subFID_Q("EMV Response Data")
                                case subFID_Q:
                                    gnapProdSubFids.setEmvResponseData(subFid);
                                    break;

                                //subFID_R("EMV Additional Response Data")
                                case subFID_R:
                                    gnapProdSubFids.setEmvAdditionalResponseData(subFid);
                                    break;

                                //subFID_W("CAVV/AAV Result Code")
                                case subFID_W:
                                    gnapProdSubFids.setCavvResultCode(subFid);
                                    break;

                            }
                        }
                        break;
                }
            }
        }
        gnapData.setGnapProdSubFids(gnapProdSubFids);
        return gnapData;
    }

    private GnapMessageHeader buildResponseHeader(String header) {
        GnapMessageHeader gnapMessageHeader = new GnapMessageHeader();

        StringParser sp = new StringParser(header);

        gnapMessageHeader.setDeviceType(sp.readString(2));
        gnapMessageHeader.setTransmissionNumber(sp.readString(2));
        gnapMessageHeader.setTerminalId(sp.readString(16));
        sp.readString(6); //Filler
        gnapMessageHeader.setCurrentDate(sp.readString(6));
        gnapMessageHeader.setCurrentTime(sp.readString(6));
        gnapMessageHeader.setMessageType(sp.readStringConstant(1, MessageType.class));
        gnapMessageHeader.setMessageSubType(sp.readStringConstant(1, MessageSubType.class));
        sp.readString(2);
        gnapMessageHeader.setTransactionCode(transCode);
        gnapMessageHeader.setProcessingFlag1(sp.readInt(1));
        gnapMessageHeader.setProcessingFlag2(sp.readInt(1));
        GnapUtils.log("Processing Flag", String.valueOf(gnapMessageHeader.getProcessingFlag2()));
        gnapMessageHeader.setProcessingFlag3(sp.readInt(1));
        gnapMessageHeader.setResponseCode(sp.readString(3));
        GnapUtils.log("Response Code", gnapMessageHeader.getResponseCode());

        return gnapMessageHeader;

    }

    private MessageWriter buildRequestHeader(GnapMessageHeader header, AcceptorConfig config) {
        MapGnapFids mg = new MapGnapFids();
        mg.add(config.getDeviceType());
        mg.add(StringUtils.padLeft(header.getTransmissionNumber(), 2, '0'));
        mg.add(StringUtils.padRight(terminalId, 16, ' '));
        mg.add(StringUtils.padLeft("", 6, ' '));
        mg.add(header.getCurrentDate());
        mg.add(header.getCurrentTime());
        mg.add(LogMessages.MessageType, getMessageType(header));
        mg.add(LogMessages.MessageSubType, header.getMessageSubType().getValue());
        mg.add(LogMessages.TransactionCode, header.getTransactionCode().getValue());
        transCode=header.getTransactionCode();
        mg.add(String.valueOf(header.getProcessingFlag1()));
        if (config.isEmvCapable())
         mg.add(LogMessages.ProcessingFlag2, ProcessingFlag2.EMVCapableDevice.getValue());
        else
            mg.add(LogMessages.ProcessingFlag2,ProcessingFlag2.NonEMVDevice.getValue());
        mg.add(String.valueOf(header.getProcessingFlag3()));
        mg.add(header.getResponseCode());
        return mg.getWriterObject();
    }

    private String getTransactionAmount(T builder) {
        BigDecimal tranAmt = builder.getAmount();
        if (builder.getSurchargeAmount() != null)
            tranAmt = tranAmt.add(builder.getSurchargeAmount());
        else if (builder.getTaxAmount() != null)
            tranAmt = tranAmt.add(builder.getTaxAmount());
        else if (builder.getTipAmount() != null)
            tranAmt = tranAmt.add(builder.getTipAmount());
        else if (builder.getCashBackAmount() != null)
            tranAmt = tranAmt.add(builder.getCashBackAmount());

        return StringUtils.toNumeric(tranAmt);
    }

    private String getEmvReqData(EmvData tagData) {
        StringBuilder sb = new StringBuilder();
        sb.append("01");
        sb.append(tagData.getCryptogramInformationData());
        sb.append(tagData.getTerminalCountryCode().substring(1));
        sb.append(tagData.getEMVTransactionDate());
        sb.append(tagData.getApplicationCryptogram());
        sb.append(tagData.getApplicationInterchangeProfile());
        sb.append(tagData.getApplicationTransactionCounter());
        sb.append(tagData.getUnpredictableNumber());
        sb.append(tagData.getTerminalVerificationResults());
        sb.append(tagData.getEMVTransactionType());
        sb.append(tagData.getTransactionCurrencyCode().substring(1));
        sb.append(tagData.getCryptogramAmount());
        sb.append(tagData.getIssuerApplicationData());
        return sb.toString();
    }

    private String getEmvAdditionalReqData(EmvData tagData) {
        StringBuilder sb = new StringBuilder();
        sb.append("01");
        sb.append(tagData.getCardSequenceNumber());
        sb.append(tagData.getEMVTerminalType());
        sb.append(tagData.getCustomerVerificationResults());
        sb.append(tagData.getApplicationVersionNumber());
        sb.append(tagData.getDedicatedFileName());
        return sb.toString();
    }

    private  String getMessageType(GnapMessageHeader messageHeader)
    {
        if (messageHeader.getTransactionCode().equals(TransactionCode.EndOfBatch) || messageHeader.getTransactionCode().equals(TransactionCode.EndOfPeriod)){
           return MessageType.AdministrativeTransactions.getValue();
        }
        else {
            return MessageType.FinancialTransactions.getValue();
        }
    }

    private String getManualTrackData(String cardNumber,String expiry) {
        StringBuilder sb=new StringBuilder();
        sb.append("M");
        sb.append(cardNumber);
        sb.append("=");
        sb.append(expiry);
        sb.append("0?");
        return sb.toString();
    }

    private String accountTypeMapping(AccountType accountType) {
            if (accountType.equals(AccountType.Checking))
                return GnapAccountType.ChequingAccount.getValue();
            else if (accountType.equals(AccountType.Savings))
                return GnapAccountType.SavingsAccount.getValue();
            else
                return GnapAccountType.DefaultAccountInteracAndUP.getValue();
    }

    private > void setTransactionCodeInHeader(GnapMessageHeader header,T builder) {

        TransactionType transactionType = builder.getTransactionType();
        if(builder instanceof AuthorizationBuilder){
            if(transactionType.equals(TransactionType.Sale)){
                if(header.getTransactionCode()!=null && header.getTransactionCode().equals(TransactionCode.TelephoneAuthPurchase)) {
                    header.setTransactionCode(TransactionCode.TelephoneAuthPurchase);
                } else {
                    header.setTransactionCode(TransactionCode.Purchase);
                }
            }else if(transactionType.equals(TransactionType.Auth)) {
                header.setTransactionCode(TransactionCode.PreAuthorization);
            } else if(transactionType.equals(TransactionType.Refund)){
                header.setTransactionCode(TransactionCode.Return);
            }
        }else if(builder instanceof ManagementBuilder){
            TransactionReference reference =(TransactionReference) builder.getPaymentMethod();
            if(transactionType.equals(TransactionType.BatchClose)) {
                if(((ManagementBuilder)builder).getBatchCloseType().equals(BatchCloseType.Forced)) {
                    header.setTransactionCode(TransactionCode.EndOfBatch);
                } else if(((ManagementBuilder)builder).getBatchCloseType().equals(BatchCloseType.EndOfShift)) {
                    header.setTransactionCode(TransactionCode.EndOfPeriod);
                }
            } else if( (header.getMessageSubType().equals(MessageSubType.StoreAndForwardTransactions)||header.getMessageSubType().equals(MessageSubType.TimeoutReversalStoreAndForwardTransaction))
                    && reference.getOriginalTransactionType().equals(TransactionType.Refund) && transactionType.equals(TransactionType.Void) ){
                header.setTransactionCode(TransactionCode.SAFReturnVoid);
            } else if((header.getMessageSubType().equals(MessageSubType.StoreAndForwardTransactions)||header.getMessageSubType().equals(MessageSubType.TimeoutReversalStoreAndForwardTransaction))
                    && reference.getOriginalTransactionType().equals(TransactionType.Sale)  && transactionType.equals(TransactionType.Void)) {
                header.setTransactionCode(TransactionCode.SAFPurchaseVoid);
            } else if((header.getMessageSubType().equals(MessageSubType.OnlineTransactions)||header.getMessageSubType().equals(MessageSubType.TimeoutReversalOnlineTransaction))
                    && reference.getOriginalTransactionType().equals(TransactionType.Refund)  && transactionType.equals(TransactionType.Void)) {
                header.setTransactionCode(TransactionCode.OnlineReturnVoid);
            }else if((header.getMessageSubType().equals(MessageSubType.OnlineTransactions)||header.getMessageSubType().equals(MessageSubType.TimeoutReversalOnlineTransaction))
                    && reference.getOriginalTransactionType().equals(TransactionType.Sale)  && transactionType.equals(TransactionType.Void)) {
                header.setTransactionCode(TransactionCode.OnlinePurchaseVoid);
            }else if(transactionType.equals(TransactionType.PreAuthCompletion)) {
                header.setTransactionCode(TransactionCode.PreAuthorizationCompletion);
            }
        }
    }

    private String getDraftCapture(CardBrand cardBrand,TransactionType transactionType){
        if(transactionType.equals(TransactionType.Auth) || cardBrand.equals(CardBrand.UnionPay))
            return DraftCaptureFlag.NonDraftCapture.getValue();
        else
            return DraftCaptureFlag.DraftCapture.getValue();
    }

    private String mapEntryMethod(EntryMethod entryMethod){
        if(entryMethod.equals(EntryMethod.Manual)) {
            return "01";
        }
        return null;
    }

    private String getShortExpiry(ICardData card) {
        if(card.getExpMonth() != null && card.getExpYear() != null) {
            return card.getExpYear().toString().substring(2, 4)+StringUtils.padLeft(card.getExpMonth().toString(), 2, '0');
        }
        return null;
    }

    private boolean isApprovalCodeValid(CardBrand cardBrand,TransactionType transactionType){
        if(cardBrand.equals(CardBrand.Interac) && (transactionType.equals(TransactionType.Void) || transactionType.equals(TransactionType.Refund))){
            return false;
        }
        return true;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy