Duplicate Transaction

Pax POSLink for Semi-Integrated processing

Introduction

EMV (Europay, MasterCard, and Visa) is a set of standards for the use of payment chip cards (those with an embedded microprocessor). The microprocessor within a payment chip card provides strong security features and other capabilities not possible with traditional magnetic stripe cards.

Prior to October of 2015, most counterfeit card fraud that occurred at business’ in-store locations, liability was with the card issuers. Since October 2015 that liability has shifted to the merchants in certain cases unless they have replaced or upgraded their card acceptance and processing systems to use chip-enabled devices and applications to process payment transactions.

Background

Chip-enabled credit (and debit) cards have been issued by almost every card issuer in the United States and they have become very common. It used to be a card with a magnetic stripe that you could swipe to process. Chip-Enabled cards require special hardware for card reading and transaction verification.

I developed multiple point of sale systems for both retail and restaurant and was among the first developers to fully integrate PAX S300 pin pads into .NET applications.

I will show methods that allow you to process a credit card, adjust the transaction amount, void a transaction and finally close a batch.

Using POSLink

In order to use this code, you will not have PAX POSLink API. Visit the PAX website and apply for an account and you will receive a copy of POSLink class.

I walk you through the following steps:

  1. Communication settings
  2. Log management
  3. Payment request and payment response
  4. Batch request and response

1- Set Communication Parameters

POSLink class communicates with the Pin pad (or credit card terminal) via:

  1. Ethernet
  2. RS232
  3. Bluetooth

Let’s start by CommSetting class and its constructor:

Communication settings are stored in commsetting.ini.

commsetting.ini has the following structure:

[COMMUNICATE]

PORT=10009

IP=10.1.10.4

SERIALPORT=COM1

TIMEOUT=30000

CommType=TCP

public void SaveSettings()
        {
                POSLink.PosLink cg = new POSLink.PosLink();
                CommSetting commSetting = new CommSetting();
            try
            {
                commSetting.CommType = "TCP";
                commSetting.TimeOut = "60000";
                commSetting.SerialPort = "COM1";
                commSetting.DestIP = "10.1.10.4";
                commSetting.DestPort = "10009";
                commSetting.saveFile();

//save the setting into file, therefore other classes will use the setting communication
                cg.CommSetting = commSetting;
            }
            catch (Exception e)
            {
                MessageBox.Show("{0} Exception caught.", e.ToString());
            }
        }

2- Set Log Management Parameters

The log management parameters are stored in LogSetting.ini . We manage LogSetting.ini with LogManagement class:

[LOGSETTING]

LOGSWITCH=1  (1: ON 0: OFF)

LOGFILEPATH= (Log file location)

LOGFILENAME= (Log file name)

LOGDAYS=30

LOGLEVEL=1 (1: Debug 0: Error)

POSLink.PosLink paxProcess = new PosLink();
POSLink.PaymentRequest paxRequest = new PaymentRequest();
//Initialize PaymentRequest
paxRequest.TenderType = 1;
paxRequest.TransType = 2;
            paxRequest.ECRRefNum= txtInv.Text;
            payAmount = Math.Round(Decimal.Parse(txtPayment.Text) * 100, 0);
            paxRequest.Amount = payAmount.ToString();
            paxRequest.InvNum = txtInv.Text;
            paxProcess.PaymentRequest = paxRequest;

3 – PaymentRequest and PaymentResponse

PaymentRequest () Initializes a PaymentRequest object. This constructor has several properties but we need to values for the followings:

  1. TenderType

ALL = 0

CREDIT = 1

DEBIT = 2

  • TransType

AUTH =1 Verify/Authorize a transaction. Do not put add it to the batch.

SALE = 2 To make a purchase with a card or e-check/ACH with a check. Adds the transaction to the current open batch.

RETURN = 3 Returns transaction amount to the card.

VOID = 4 Void/Reverse a transaction while still in an unsettled batch.

  • ECRRefNum

This is a unique code on the ECR side. for instance, you can use an invoice number.

POSLink.PosLink paxProcess = new PosLink();

POSLink.PaymentRequest paxRequest = new PaymentRequest();

//Initialize PaymentRequest

paxRequest.TenderType = 1;

paxRequest.TransType = 2;

            paxRequest.ECRRefNum= txtInv.Text;

            payAmount = Math.Round(Decimal.Parse(txtPayment.Text) * 100, 0);

            paxRequest.Amount = payAmount.ToString();

            paxRequest.InvNum = txtInv.Text;

            paxProcess.PaymentRequest = paxRequest;

4- PaymentResponse Class

This class with its paymentresponse() constructor provides us with returned values from the PAX terminal after a transaction has been commenced by paymentrequest() constructor:

ResultCode : This is the transaction’s result code.

Now we can build our method to use all of the above and process a SALE transaction:

private void ProcessCredit()
        {
            POSLink.PosLink paxProcess = new PosLink();
            POSLink.PaymentRequest paxRequest = new PaymentRequest();
            CommSetting paxSettings = new CommSetting();
            POSLink.LogManagement paxLog = new LogManagement();
            IniParser.FileIniDataParser paxParser = new FileIniDataParser();
            var parser = new FileIniDataParser();
            IniData data = parser.ReadFile("commsetting.ini");
            decimal payAmount;
            string cardLast4;
            string cardName;
            string payRef;
            string payAuth;

            //Initialize Settings
            paxSettings.DestIP = data["COMMUNICATE"]["IP"];
            paxSettings.CommType = data["COMMUNICATE"]["CommType"];
            paxSettings.DestPort = data["COMMUNICATE"]["PORT"];
            paxSettings.TimeOut = data["COMMUNICATE"]["TIMEOUT"];
            paxProcess.CommSetting = paxSettings;
            //Initialize PaymentRequest
            paxRequest.TenderType = 1;
            paxRequest.TransType = 2;
            paxRequest.ECRRefNum= txtInv.Text;
            payAmount = Math.Round(Decimal.Parse(txtPayment.Text) * 100, 0);
            paxRequest.Amount = payAmount.ToString();
            paxRequest.InvNum = txtInv.Text;
            paxProcess.PaymentRequest = paxRequest;
            //Initialize log management
            paxLog.LogSwitchMode = true;
            paxLog.LogLevel = 1;
            paxLog.LogFilePath = Application.LocalUserAppDataPath; 
            paxProcess.LogManageMent = paxLog;
            //Launch it
            ProcessTransResult  result = paxProcess.ProcessTrans();

            if (result.Code == POSLink.ProcessTransResultCode.OK)
            {
                POSLink.PaymentResponse paymentResponse = paxProcess.PaymentResponse;
                if (paymentResponse != null && paymentResponse.ResultCode != null)
                {
                 
                    lblMsg.Text =  paymentResponse.ResultTxt;
                    cardLast4 = paymentResponse.BogusAccountNum;
                    payAuth = paymentResponse.AuthCode;
                    payRef = paymentResponse.RefNum;
                }
                else
                {
                    MessageBox.Show("Unknown error: paxProcess.PaymentResponse is null.");
                }
                RegisterCard();
            }
            else if (result.Code == POSLink.ProcessTransResultCode.TimeOut)
            {
                lblMsg.Text = "Action Timeout.";
            }
            else
            {
                lblMsg.Text = result.Msg;
            }
            this.Focus();
          
        }

5- BatchRequest Class

BatchRequest() constructor initializes a BatchRequest object.

The only required property is the TransType:

BATCHCLOSE = 1 – Closes the currently open batch.

FORCEBATCHCLOSE = 2 – Force closes the currently open batch, if supported by the host.

BATCHCLEAR = 3 – Clears the local database on the PAX device.

POSLink.PosLink paxProcess = new PosLink();
POSLink.BatchRequest paxBatch = new BatchRequest();
//Initialize Batch
paxBatch.TransType = 1; ‘ Close the current batch
paxBatch.EDCType = 0; ‘Close all transaction types (Credit, debit,..)
paxProcess.BatchRequest = paxBatch;
//Launch it
           ProcessTransResult result = paxProcess.ProcessTrans();
            
            if (result.Code == POSLink.ProcessTransResultCode.OK)
            {
                BatchResponse r = paxProcess.BatchResponse;
                lblMsg.Text = r.ResultTxt;
            }
            else if (result.Code == POSLink.ProcessTransResultCode.TimeOut)
            {
                lblMsg.Text = "Action Timeout.";
            }
            else
            {
                lblMsg.Text = result.Msg;
            }

Integration into PAX payment terminals is relatively simple and you can activate more options, such contactless payments, which enables ApplePay and other payment types.

I believe life is too short to ignore learning a programming language!

Kourosh

Your Header Sidebar area is currently empty. Hurry up and add some widgets.