Amadis

Concert Integration in Arkos SDK

The Arkos next-gen SDK now supports concert protocol. To set the protocol you need to start with the following steps below:

  • You will be provided with these two libraries: concert_library.aar and TCP_socket_library.aar

  • You can refer to the documentation below for the functionalities provided and also the dependencies needed.

  • It is to be noted that these libraries cover IP/Ethernet, WIFI, and Bluetooth compatibility only. RS-232 compatibility will be provided as source code in ArkosPay.

 

ArkosPay currently has a Payment System singleton where the entire application is initialized as a singleton for only one instance to be available throughout the whole app at any time. A new parent, ConcertHandler, has been provided and is responsible for creating the protocol method you want to use.

image-20240911-125618.png

Upon starting Arkospay, you will have no instance of Concert protocol types/methods running. You can navigate to settings → Concert connection types

 

 

image-20240911-130128.png

Choose the type of protocol you want → IP ethernet in this example

 

Upon choosing IP ethernet, a port and protocol version will be prompted. Once confirmed you will return to the idle screen and then your instance will be created.

Now that you have a running instance:

  • You will need to add this in your assets folder, as the specification has a config defined and this file conforms to the configuration specified in the document.

  • You can refer to the IPEthernetHandler.java class how the functions are called and used.

  • A server will automatically start in the background thread and it will automatically listen to incoming connections on the specified port.

  • Once received a listener (callback) runs the parsed message on the UI thread from which the request is executed.

package ca.amadis.arkospay; import android.content.Context; import android.util.Log; import com.preludd.concert_library.Config; import com.preludd.concert_library.ConfigParser; import com.preludd.concert_library.Message; import com.preludd.concert_library.MessageFactory; import com.preludd.tcp_socket_library.TcpSocketServiceManager; import java.io.InputStream; public class IPEthernetHandler extends ConcertHandler { static final private String LOG_TAG = "ConcertHandlerIpEth"; private static IPEthernetHandler instance = null; private MessageFactory messageFactory; private TcpSocketServiceManager tcpSocketServiceManager; private Message parsedMessage; private int headerLength = 2; private IPEthernetHandler(MainActivity activity){ super(activity); Log.i(LOG_TAG, "ConcertHandlerIpEth init"); readConfig(activity); start(activity); Log.i(LOG_TAG, "Starting to listen concert ip ethernet..."); } public static IPEthernetHandler getInstance(MainActivity activity) { if(instance == null){ instance = new IPEthernetHandler(activity); } return instance; } public int getConfig(){ return headerLength; } public void setConfig(int headerLength){ this.headerLength = headerLength; } public void readConfig(Context context){ InputStream inputStream = readAssetsFileAsInputStream(context, "concertConfig.json"); messageFactory = ConfigParser.createFromStream(inputStream); Config config = messageFactory.getConfig(); if(getConfig() == 0){ config.headerLength = 0; messageFactory.setConfig(config); } Log.i(LOG_TAG, "Getting config length ..." + config.headerLength); } public void start(Context context){ tcpSocketServiceManager = TcpSocketServiceManager.getInstance(); tcpSocketServiceManager.setPort(PaymentSystem.getConcertHandler().getPort()); tcpSocketServiceManager.setMaximumMessageLength(2048); tcpSocketServiceManager.startService(context); } public void receive(MessageReceivedCallback callback) { tcpSocketServiceManager = TcpSocketServiceManager.getInstance(); Log.d(LOG_TAG, "Message not received yet..."); tcpSocketServiceManager.setSocketServiceListener(messageReceived -> { if (messageReceived != null) { if(messageFactory != null) { parsedMessage = messageFactory.parseMessage(messageReceived); Log.d(LOG_TAG, parsedMessage.toString()); } String sMessageReceived = bytesToHex(messageReceived); Log.d(LOG_TAG, sMessageReceived); callback.onMessageReceived(true,parsedMessage,sMessageReceived); } else{ callback.onMessageReceived(false,null,null); } }); } @Override public void send(byte[] response) { if(messageFactory != null) { Message message = messageFactory.newMessage(); ConcertHandler concertHandler = PaymentSystem.getConcertHandler(); message.setVersionProtocol(concertHandler.getProtocolVersion()); String actionStatus = convertPaymentResultIDtoProtocolActionStatus(concertHandler.getProtocolActionStatus()); //set the mandatory values message.setTagValue("CJ", concertHandler.getProtocolID()) .setTagValue("AE", actionStatus ) .setTagValue("CA",concertHandler. getProtocolNumber()) .setTagValue("CB", concertHandler.getProtocolAmount()) .setTagValue("CC", "000") .setTagValue("CD", concertHandler.getProtocolActionType()) .setTagValue("CE", concertHandler.getProtocolCurrencyCode()); String convertedResponse = concertHandler.byteArrayToLatinStringEncoding(response); Log.d(LOG_TAG, convertedResponse); // if(concertHandler.isCustomerReceipt() && concertHandler.isMerchantReceipt()){ // message.setTemplateTagValue("ZT","CK","120"); // message.setTemplateTagValue("ZT","AK",convertedResponse); // } else if (concertHandler.isCustomerReceipt()) { // message.setTemplateTagValue("ZT","CK","100"); // message.setTemplateTagValue("ZT","AK",convertedResponse); // } else if (concertHandler.isMerchantReceipt()) { // message.setTemplateTagValue("ZT","CK","110"); // message.setTemplateTagValue("ZT","AK",convertedResponse); // } // else { // message.setTemplateTagValue("ZT","CK","000"); // } byte[] result = message.formMessage(); String formedMessage = bytesToHex(result); Log.d(LOG_TAG, "formedResponse " + formedMessage); tcpSocketServiceManager.respondMessage(result); } } public void stop(Context context){ tcpSocketServiceManager.stopService(context); } }
@Override public void onMessageReceived(boolean success, Message parsedMessage, String hexMessage) { if (success) { Log.d(LOG_TAG, "Message received and processed!"); if (!PaymentSystem.tryAcquire(PaymentSystemLock.Type.CONCERT)) { Log.e(LOG_TAG, "Could not acquire lock"); return; } String protocolVersion = parsedMessage.getTagValue("CZ"); if(protocolVersion != null){ PaymentSystem.getConcertHandler().setProtocolVersion(protocolVersion); Log.d(LOG_TAG, "protocolVersion " + protocolVersion); } String protocolID = parsedMessage.getTagValue("CJ"); if(protocolID != null){ PaymentSystem.getConcertHandler().setProtocolID(protocolID); Log.d(LOG_TAG, "protocolID " + protocolID); } String protocolNumber = parsedMessage.getTagValue("CA"); if(protocolNumber != null){ PaymentSystem.getConcertHandler().setProtocolNumber(protocolNumber); Log.d(LOG_TAG, "protocolNumber " + protocolNumber); } String amount = parsedMessage.getTagValue("CB"); if(amount != null){ Log.d(LOG_TAG, "amount " + amount); PaymentSystem.getConcertHandler().setAmount(Long.parseLong(amount)); PaymentSystem.getConcertHandler().setProtocolAmount(amount); } String currencyCode = parsedMessage.getTagValue("CE"); if(currencyCode != null){ PaymentSystem.getConcertHandler().setProtocolCurrencyCode(currencyCode); Log.d(LOG_TAG, "currencyCode " + currencyCode); } String actionType = parsedMessage.getTagValue("CD"); if(actionType != null){ Log.d(LOG_TAG, "actionType " + actionType); PaymentServiceID serviceID = PaymentSystem.getConcertHandler().concertActionTypeToServiceIDConverter(actionType); PaymentSystem.getConcertHandler().setServiceID(serviceID); PaymentSystem.getConcertHandler().setProtocolActionType(actionType); getActivity().runOnUiThread(() -> { //page 30 de la spec concert 3.2, CD switch (actionType) { case "0": case "1": case "2": case "I" : navigate(R.id.toConcertPayment); break; case "B": // navigate(R.id.receiptConfiguration); break; default: Toast.makeText(getContext(), actionType + "not supported", Toast.LENGTH_LONG).show(); PaymentSystem.release(); break; } }); } if(actionType == null){ PaymentSystem.release(); } } else { Log.d(LOG_TAG, "No message received."); } }

Note: Do not forget to block your UI thread when a valid request is received to prevent your app from doing other tasks on the UI thread simultaneously.

Â