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.
Upon starting Arkospay, you will have no instance of Concert protocol types/methods running. You can navigate to settings → Concert connection types
Â
Â
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.
Â