GPE terminals with AX Retail POS
One of the common tasks when delivering POS solutions to customers is to prepare POS application for card payments. Although there is some support for payment cards in Dynamics AX 2012, it does not fit well with the requirements that most European retailers would put on it. Thus, custom development is inevitable. In this post, I give some guidelines on how to integrate the payment terminals with Dynamics AX 2012 Retail POS. Namely, we successfully integrated Global Payment Europe (GPE) payment terminals with Enterprise POS (Windows Forms version of POS) for Microsoft Dynamics AX 2012 R3 (CU10). However, I believe that the text contains valuable information for other versions of Dynamics AX POS as well, be it Modern POS or Cloud POS in Dynamics AX 2012, Dynamics AX (7) or Dynamics 365 for Operations.
This blog post is for reader who has already some experience with Dynamics AX 2012 enterprise POS development more information is below.
I suppose that the reader has already some experience with Dynamics AX 2012 enterprise POS development. For introductory information, see Extend Point of Sale section at technet. There are also good posts by Erstad Shane or you can have a look at my previous post for a complete POS development scenario.
Card payment process
As already mentioned, standard AX has a support for payment cards. This includes not only AX backend but also POS clients. So, what’s the trouble? The answer lies in the payment process. From the POS point of view, it consists of the following steps:
Payment process in standard AX
- POS user creates a POS order.
- POS user chooses a card payment method in POS application.
- Customer inserts his/her payment card into the payment terminal and enters the PIN (or just places the contactless card near the sensor). The terminal reads the information from the card – at least card number, expiration date and security code – and sends the data back to the POS application. Alternatively, if the payment terminal is out of order, POS user can enter card information manually in POS.
- The POS application then communicates directly with the bank (or card center), sending information about the card and about the order itself.
- The result of the bank transaction is then returned to the POS application.
However, for security reasons, payment terminal providers implement another approach, which is not supported in AX:
Required payment process
- POS user creates a POS order.
- POS user chooses a card payment method in POS application.
- POS application sends information about the order – at least amount and currency – to the payment terminal.
- Customer then checks the amount displayed at the payment terminal, inserts his/her payment card into the payment terminal and enters the PIN. Payment terminal will then send the card data and the order data to the bank.
- The result of the bank transaction is returned to the payment terminal. Subsequently, the payment terminal communicates back to the POS application about the transaction.
From the above we can see that a development is needed in two areas:
- A .NET class library for communication with the payment terminal
- POS application adjustments enabling card payments with the help of the .NET library from previous point
Payment terminal communication library
Development of payment terminal communication library is far beyond the scope of this post. For your imagination – the whole Visual Studio solution contains over 30 files putting it together to more than 3500 source code lines in C#. Therefore, I will give only some basic ideas how to proceed.
First, it is important to find out what does the communication protocol between POS and payment terminal look like. To this end you must contact your payment terminal vendor and get a technical documentation. The communication protocol will most probably consist of two layers – application protocol and transport technology. In my case (GPE), the technology has two variants – you can either communicate over TCP/IP network or by USB serial port. Our customer opted for TCP/IP transfer but the use of USB would not be much different – mainly since the application protocol defined by GPE is the same in both cases.
At high level, the GPE application protocol defines several operations. Here I will concentrate on the bare minimum – the operation “Make payment” that takes in amount, currency code and optionally invoice (receipt) identification as input parameters and then performs the card payment itself. GPE defines few more operations – return, cancel the last operation, perform payment terminal closing etc. – but it would only distract us from the main ideas that are the same regardless of the operation.
Now invoking the make payment operation consists of assembling data payloads correctly and sending them to the payment terminal over TCP/IP or USB. As for the transport part, .NET framework does the most of the job by offering TcpClient and SerialPort classes, respectively. Thus, our main concern is the assembly of the data payloads according to the rules defined in the payment terminal’s documentation. However, there is much more to that – exception handling, asynchronous programming, recovery after operation cancellation and others. This is quite a lot of work to do. Fortunately, in Dynamics AX Retail SDK there are samples where to learn from.
HardwareStation Visual Studio solution contains sample implementation for the Verifone Mx925 payment terminal
Namely, there is a HardwareStation Visual Studio solution that contains sample implementation for the Verifone Mx925 payment terminal. Having had a look at it it turned out that there are many analogies between GPE and Mx925 payment terminals and that a lot of source code for GPE solution can be easily adopted from existing classes. Therefore, let’s delve into the internal structure of the HardwareStation solution a little bit.
The whole solution consists of three projects:
The Application project is an ASP.NET web application. Of main interest for us is the PaymentTerminalController class (in Controllers/PaymentTerminalController.cs). It is an entry point for any operations provided by payment terminals. For our needs, I refactored this class so that it is not bound to ASP.NET. In other words – my PaymentTerminalController class does not extend the ApiController class and its public methods are not decorated by HttpPost attributes.
Next object to look at is the PaymentTerminalManager class in PaymentTerminal / PaymentTerminalManager.cs of the Peripherals project. It just represents an additional level of indirection between PaymentTerminalController and IPaymentDevice interface implementation.
The IPaymentDevice interface defines payment terminal device’s capabilities. Different payment terminals differ by implementing classes – VerifonePaymentDevice in HardwareStation solution or GPEPaymentDevice in my case. Inside VerifonePaymentDevice class you will note the extensive use of the protocol member variable of type IDeviceProtocol, the implementation of which is in the VerifoneDeviceProtocol class. It is exactly the place where the application protocol is defined (in fact it uses several other helper classes to this aim – ProtocolCommands, ProtocolConstants and ProtocolUtilities) and thus where my largest effort was given during GPE payment terminals implementation.
Finally, classes in the PaymentTerminal / Mx925Device / Transport folder contain transport protocol specific logic (e.g. IP address and port number value substitution). This can be seen in TcpTransport class.
Sticking to the HardwareStation internal architecture has one potential advantage – porting to the Modern POS or Cloud POS should be much easier – it suffices to change the PaymentTerminalController class.
Now it is time to connect POS to the .NET assembly and change payment process at POS side. This consists of several steps:
- Add a new button to the screen layout. Bind the button to a blank operation; give it a unique name (“PaymentTerminal”) and setup a payment method code that will be passed in as a parameter for this operation. After synchronizing these changes to the POS application, a new button for payment by card at payment terminal will be available during POS orders processing.
- Create a new class library project PaymentTerminal in the Services solution in the Retail SDK. Add two items to it – BlankOperationsPaymentTerminal class and frmPayPaymentTerminal form.
- Add code to the BlankOperationsPaymentTerminal class. This class implements the IBlankOperations interface and exports it in the sense of dependency injection via MEF:
In the IBlankOperations interface’s BlankOperation method, it is important to check for the actual type of blank operation. If it is PaymentTerminal, then we simply call the PayCard method and mark the operation as handled:
The PayCard method then contains the order payment processing. First it calculates the order. Then a new form is displayed (frmPayPaymentTerminal) that is responsible for the interaction with payment terminal using the communication assembly described above. When the form is closed properly, the order is marked as paid and the tender operation is written to the channel database:
- Add design and code to the frmPayPaymentTerminal form. Its design is very simple – it consists only of a static text telling the user that communication with the payment terminal is going on. Its functionality is concentrated into the OnLoad virtual method – first we create an instance of the PaymentTerminalController class. The code snippet is somewhat simplified. In real life, the configuration is saved in RetailParameters in AX. Next, our MakePayment method is called and the result is saved in the form’s PaymentInfo property. Again, there is much more in the real life implementation – exceptions are caught and logged, a Cancel button is added so that the operation can be cancelled by a POS user etc.
Card payments are a must for each POS implementation. I hope that after reading this post a reader will have an idea of what the payment terminal integration into Dynamics AX Retail POS involves and what skills are needed for its successful implementation.