This document serves as a complete reference guide for individuals seeking to utilize the Pine Labs Android PoSlib SDK. Its primary focus is to assist in the acceptance of payments, the processing of transactions, and the seamless return of payment results to the invoking Android application.
The billing system can be integrated Android platform in two different ways:
In both integration approaches, the merchant billing application should use the PoSLib to communicate with the Pine Labs payment application via PoSBridge.
Also Merchant should ensure that PoSBridge is running on the Android payment terminal before initiating any transactions from the billing application.
Following sections provide detailed insights into both Off-Device and On-Device Integration processes.
In this method, the merchant billing application, running on Android devices such as tablets or mobile phones, communicates with the Pine Labs payment application by integrating the Android PoSlib. The Android PoSlib facilitates communication with the Android payment application via PoSBridge.
The merchant billing application needs to integrate PoSlib to communicate with the PoSBridge application through PoSBridge APIs. The message exchange between PoSLib and PoSBridge can occur over IP and Bluetooth (BT).
The following sequence diagram describes the transaction flow:
Merchant Billing Application should integrated PoSLib to perform transactions with Android Payment application
The following features (APIs) are supported by Android PoSLib:
Supported APIs | Functionality / Description |
---|---|
posLibInitialize | This API will Initialize the POS lib. This should be the first API to be called. |
scanOnlinePOSDevice | This API will be used to auto discover/scan for PoS devices on the same network (Wi-Fi). |
scanBTDevice | This API will be used to scan the paired BT device. |
setConfiguration | This API will be used to set the required configuration in PoSlib. |
getConfiguration | This API will be used to get the configuration settings from the PoSlib. |
testTCP | This API will be used to check for a TCP/IP connection. |
testBT | This API will be used to check the BT connection. |
checkBtComStatus | This API will check the BT connectivity status every 30 seconds. |
checkTcpComStatus | This API will check the TCP/IP connectivity status every 30 seconds. |
doTransaction | This API will be used to perform transactions with the Payment application. |
This section describes the pre-requisites and steps to integrate the PoS library with the merchant billing system.
The following section describes the the APIs exposed by PoSLib, and provides sample code snippets.
Note: The sample code snippets provided in this document are currently supported only in Java. These code snippets might have to be customized if you want to test them in Kotlin.
This API will Initialize the PoSlib. This should be the first API to be called
Signature | boolean posLibInitialize(Context context) |
Parameters | context – Application context |
Returns | Success or Failure |
Call-backs | None |
Error Condition | null context |
Initialize PoSLib using the following code:
Java
PosLibManager.getInstance().posLibInitialize(getApplicationContext());
This API will auto-discover the Android payment terminals on the same network where PoSBridge is running and list them.
Signature | public void scanOnlinePOSDevice(ScanDeviceListener scanDeviceListener, Context context ); |
Parameters | scanDeviceListener – Device listener context – Application context |
Returns | None |
Call-backs |
OnSucces( List< DeviceDetails > list) -List of Devices discovered OnFailure(String errorMsg, int errorCode) -Error Message -Error Code |
Error Condition |
Response timeout Device disconnected Parsing error Network down |
Notes | In response devicedetails isBtDevice set to false and btDeviceSsid and btDeviceName will be set to null for scanOnlinePOSDevice API call return |
Java
public class DeviceDetails { private boolean isBtDevice; private String deviceSlNo; private String deviceId; private String deviceIp; private String devicePort; private String btDeviceSsid; private String btDeviceName; } Button buttonScanDeviceViewTcp;// Button for scan online device buttonScanDeviceViewTcp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { showProgress("Searching"); handler.postDelayed(() -> PosLibManager.getInstance().scanOnlinePOSDevice(scanDeviceListener, getApplicationContext()), 1000); } }); ScanDeviceListener scanDeviceListener = new ScanDeviceListener() { @Override public void onSuccess(List<DeviceDetails> list) { //"onSuccess" //Prompt device list and get the selected device from the user } @Override public void onFailure(String errorMsg, int errorCode) { //"on failure" //Handle error message and error code received } };
This API will scan and list the paired BT devices over Bluetooth.
Signature | public void scanBTDevice(ScanDeviceListener scanDeviceListener, Context context); |
Parameters | scanDeviceListener – Device listener context – Application context |
Returns | None |
Call-backs |
OnSucces( List< DeviceDetails > list ) - List of Devices discovered OnFailure(String errorMsg, int errorCode) - Error Message - Error Code |
Error Condition |
• Response timeout • Device disconnected • Parsing error • Network down |
Notes | In response devicedetails isBtDevice set to true and deviceIp,devicePort,deviceSlNo and deviceId will be set to null for scanBTDevice API call return |
Java
Button buttonScanDeviceViewBt; //Button for scan BT devices buttonScanDeviceViewBt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //showDialog(AppSettingActivity.this); showProgress("Searching"); handler.postDelayed(() -> PosLibManager.getInstance().scanBTDevice(scanDeviceListener, getApplicationContext()), 1000); } }); ScanDeviceListener scanDeviceListener = new ScanDeviceListener() { @Override public void onSuccess(List<DeviceDetails> list) { //"onSuccess" //Prompt device list and get the selected device from the user } @Override public void onFailure(String errorMsg, int errorCode) { //"on failure" //Handle error message and error code received } };
This API will set PoS Library configurations related to connectivity, priority settings, and logging options.
Signature | public int setConfiguration(ConfigData configData,Context context); |
Parameters | configData - Configuration Data context – Application context |
Returns | 0 - Success -1 - Failure |
Call-backs | None |
Error Condition |
Invalid IP Invalid port IP or Port not configured PoSLib not initialized |
Java
public class ConfigData { private String tcpIP; private String tcpPort; private String commPortNumber; private String baudRate; private boolean isConnectivityFallBackAllowed; private String btSSID; private String btName; private int commP1;//1=TCPIP , 2=BT ,3=App2App private int commP2;//1=TCPIP , 2=BT ,3=App2App private int commP3;//1=TCPIP , 2=BT ,3=App2App private String connectionMode; private String logPath; private boolean isLogsEnabled; private int logLevel; private int dayToRetainLogs; private int retryCount; private int connectionTimeOut; private boolean isDemoMode; private String cashierID; private String cashierName; private String deviceSlNo; private String deviceId; } private void saveValues() { Log.d(TAG,"Entering saveValues()"); Log.i(TAG,"Saving values to ConfigData..."); ConfigData configData = new ConfigData(); PosLibManager.getInstance().getConfiguration(configData); if (scanDevicetcpIp != null) { configData.setTcpIP(scanDevicetcpIp.getText().toString()); Log.i(TAG,"TCP IP set: " + scanDevicetcpIp.getText().toString()); } if (scanDevicePort != null) { configData.setTcpPort(scanDevicePort.getText().toString()); Log.i(TAG,"TCP Port set: " + scanDevicePort.getText().toString()); } if (scanbtname != null) { configData.setBtName(scanbtname.getText().toString()); Log.i(TAG,"BT Name set: " + scanbtname.getText().toString()); } if (deviceID != null) { configData.setDeviceId(deviceID); Log.i(TAG,"Device Id set: " + deviceID); } if (deviceSlno != null) { configData.setDeviceSlNo(deviceSlno); Log.i(TAG,"Device Sl No set: " + deviceSlno); } if (scanbtssid != null) { configData.setBtSSID(scanbtssid.getText().toString().toUpperCase()); Log.i(TAG,"BT SSID set: " + scanbtssid.getText().toString()); } if (logPathEt.getText().length() > 0) { configData.setLogPath(logPathEt.getText().toString()); Log.i(TAG,"Log Path set: " + logPathEt.getText().toString()); } String logRetainValue = logRetainEt.getText().toString(); if (notNullNotEmpty(logRetainValue)) { configData.setDayToRetainLogs(Integer.parseInt((logRetainValue))); Log.i(TAG,"Day to Retain Logs set: " + logRetainValue); } String logLevelValue = logLevelEt.getText().toString(); if (notNullNotEmpty(logLevelValue)) { configData.setLogLevel(Integer.parseInt(logLevelValue)); Log.i(TAG,"Log Level set: " + logLevelValue); } if (connectionTimeOut.getText().length() > 0) { configData.setConnectionTimeOut(Integer.parseInt(connectionTimeOut.getText().toString())); Log.i(TAG,"Connection timeout set: " + connectionTimeOut.getText().toString()); } if (connectionRetry.getText().length() > 0) { configData.setRetryCount(Integer.parseInt(connectionRetry.getText().toString())); Log.i(TAG,"Connection retry set: " + connectionRetry.getText().toString()); } configData.setConnectivityFallBackAllowed(((CheckBox) findViewById(R.id.connection_FallBack_CheckBox)).isChecked()); if (prioritySpinnerTv.getSelectedItem().toString().contains("TCPIP")) { configData.setCommP1(Constants.TCP_IP); configData.setCommP2(Constants.BT); } else if (prioritySpinnerTv.getSelectedItem().toString().contains("BT")) { configData.setCommP1(Constants.BT); configData.setCommP2(Constants.TCP_IP); } else { configData.setCommP1(Constants.APPTOAPP); } configData.setLogsEnabled(logOptionCheckBox.isChecked()); Log.i(TAG,"Logs Enabled: " + logOptionCheckBox.isChecked()); PosLibManager.getInstance().setConfiguration(configData,this); Log.i(TAG,"Values saved successfully."); Log.d(TAG,"Exiting saveValues()"); }
This API will be used to retrieve PoS Library configurations related to connectivity, priority settings, and logging options.
Signature | int getConfiguration(ConfigData configData) |
Parameters | [out] configData - Configuration Data |
Returns | 0 - Success -1 - Failure |
Call-backs | None |
Error Condition | POS Lib not initialized |
Java
public class ConfigData { private String tcpIP; private String tcpPort; private String commPortNumber; private String baudRate; private boolean isConnectivityFallBackAllowed; private String btSSID; private String btName; private int commP1;//1=TCPIP , 2=BT ,3=App2App private int commP2;//1=TCPIP , 2=BT ,3=App2App private int commP3;//1=TCPIP , 2=BT ,3=App2App private String connectionMode; private String logPath; private boolean isLogsEnabled; private int logLevel; private int dayToRetainLogs; private int retryCount; private int connectionTimeOut; private boolean isDemoMode; private String cashierID; private String cashierName; private String deviceSlNo; private String deviceId; } private void setSettingValues() { ConfigData configData = new ConfigData(); PosLibManager.getInstance().getConfiguration(configData); scanDevicetcpIp.setText(configData.getTcpIP()); scanDevicePort.setText(configData.getTcpPort()); scanbtname.setText(configData.getBtName()); scanbtssid.setText(configData.getBtSSID()); connectionTimeOut.setText(String.valueOf(configData.getConnectionTimeOut())); logOptionCheckBox.setChecked(configData.isLogsEnabled()); if (logOptionCheckBox.isChecked()) { logPathEt.setText(configData.getLogPath()); logRetainEt.setText(String.valueOf(configData.getDayToRetainLogs())); logLevelEt.setText(String.valueOf(configData.getLogLevel())); } connectionRetry.setText(String.valueOf(configData.getRetryCount())); ((CheckBox) findViewById(R.id.connection_FallBack_CheckBox)).setChecked(configData.isConnectivityFallBackAllowed()); if (configData.getCommP1() == Constants.TCP_IP) { prioritySpinnerTv.setSelection(0); } else if (configData.getCommP1() == Constants.BT) { prioritySpinnerTv.setSelection(1); } else { prioritySpinnerTv.setSelection(2); } enableDisableLogOptionComView(configData.isLogsEnabled()); }
This API will verify connectivity between the merchant billing system and the Android payment terminal in IP connectivity mode.
Signature | boolean testTCP(String IP, String port) |
Parameters | IP - Payment terminal IP Port - Payment terminal port |
Returns | true - Success false - Failure |
Call-backs | None |
Java
Button buttonConnectTcp; // Button used to connect IP and port String scanDevicetcpIp; // 192.168.4.62 String scanDevicePort; // 6666 buttonConnectTcp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { showProgress("Connecting"); ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.execute(() -> handleDeviceConnection(PosLibManager.getInstance().testTCP(scanDevicetcpIp.getText().toString(), scanDevicePort.getText().toString()))); executorService.shutdown(); } }); private void handleDeviceConnection(boolean isConnected) { runOnUiThread(() -> { dismissProgress(); if (isConnected) { // "Device Connected!!! } else { //"Failed to Connect" } }); Log.d(TAG,"Exiting connect()"); }
This API will verify connectivity between the merchant billing system and the Android payment terminal in BT connectivity mode.
Signature | boolean testBT(String btSsid) |
Parameters | btSsid - Bluetooth Address |
Returns | true - Success false - Failure |
Call-backs | None |
Java
Button buttonConnectBt; // Button used to connect Bluetooth device String btSsid = null ; // Bluetooth identifier ExecutorService executor = Executors.newSingleThreadExecutor(); btConnectBtn.setOnClickListener(view -> { btConnectBtn.setEnabled(false); String scanBtName = scanbtname.getText().toString().trim(); String scanBtSsid = scanbtssid.getText().toString().trim(); Log.i(TAG,"BT Connect button clicked. Initiating device connection..."); if (scanBtName.isEmpty() || scanBtSsid.isEmpty()) { Log.w(TAG,"Please select a device before connecting."); //Prompt for error message btConnectBtn.setEnabled(true); return; } showProgress("Connecting" executor.execute(() -> { boolean isConnected = PosLibManager.getInstance().testBT(scanBtSsid Handler mainHandler = new Handler(Looper.getMainLooper()); mainHandler.post(() -> { dismissProgress(); if(isConnected){ //"Device Connected" }else{ // "Failed to connect" } btConnectBtn.setEnabled(true); // Re-enable the button }); }); });
Signature | public void checkTcpComStatus(ComEventListener comEventListener, Context context, int timeInterval); |
---|---|
Parameters |
comEventListener - Com Event listener context – Application context timeInterval - The Parameter "timeInterval" is used to specify the time interval for sending health check status requests to the PoSBridge. |
Returns | None |
Call-backs |
eventId = 3000 (TCP Connected and Payment app is Down) eventId = 1000 (TCP Connected and Payment app is Up) eventId = 1001 (TCP Disconnected) eventId = 1002 (TCP Disconnected) eventId = 1003 (TCP Disconnected) |
Java
runOnUiThread(() -> PosLibManager.getInstance().checkTcpComStatus(tcpComEventListener, getApplicationContext(), 30)); ComEventListener tcpComEventListener = eventId -> { Log.d(TAG,"Entering tcpComEventListener()"); Log.i(TAG,"Entering tcpComEventListener on onEvent : " + eventId); switch (eventId) { case 3000: //"TCP Connected and Payment app is down //Status: Inactive break; case 1000: //"TCP Connected and Payment app is UP // Status: Active break; case 1001: case 1002: case 1003: //"TCP Disconnected // Status: Inactive break; default: Log.i(TAG,"Unknown Event ID: " + eventId); break; } };
Signature | public void checkBtComStatus(ComEventListener comEventListener, Context context, int timeInterval); |
---|---|
Parameters |
comEventListener – Com Event listener context – Application context timeInterval - The Parameter "timeInterval" is used to specify the time interval for sending health check status requests to the PoSBridge. |
Returns | None |
Call-backs |
eventId = 3000 (BT Connected and Payment app down) eventId = 2000 (BT Connected and Payment app UP) eventId = 2001 (BT Disconnected) eventId = 2002 (BT Disconnected) |
Java
runOnUiThread(() -> PosLibManager.getInstance().checkBtComStatus(btComEventListener, getApplicationContext(), 30)); ComEventListener btComEventListener = eventId -> { Log.d(TAG,"Entering ComEventListener()"); Log.i(TAG,"Entering comEventListener on onEvent : " + eventId); switch (eventId) { case 3000: //"BT Connected Payment app is down // Status: Inactive break; case 2000: // "BT Connected and Payment app is UP // Status: Active break; case 2001: case 2002: //BT Disconnected // Status: Inactive break; default: Log.i(TAG,"Unknown Event ID: " + eventId); break; } };
This API will be used to perform transactions with Android Payment application.
Signature | public void doTransaction(Context context, String paymentRequest, int transactionType, TransactionListener transactionListener); |
Parameters |
context – Application context |
Returns | None |
Call-backs |
OnSuccess(String paymentResponse) - paymentResponse data for all the supported transaction types OnFailure(String errorMsg, int errorCode) - Error Message - Error Code |
Error Condition |
• Response timeout • Parsing error • BT disconnected • Network down • Comm disconnected |
Java
String paymentRequest = null ; // Requered only for TxnType 6 (payment transaction) paymentRequest = "10000997001D343030312C545831323334353637382C3130313030302C2C2C2C2C2C2CFF"; // sale transaction re-quest paymentRequest = "10000997001D353130312C545831323334353637382C3130313030302C2C2C2C2C2C2CFF"; // Bank EMI transaction request paymentRequest = "10000997001D353030322C545831323334353637382C3130313030302C2C2C2C2C2C2CFF"; // Brand EMI transaction request paymentRequest = "10000997001D353132302C545831323334353637382C3130313030302C2C2C2C2C2C2CFF"; // UPI transaction request int txnType = 6; // Payment transaction new Handler(Looper.getMainLooper()).postDelayed(() -> { ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(() -> PosLibManager. getInstance().doTransaction(MainActivity.this, paymentRequest, TxnType, new TransactionListener() { @Override public void onSuccess(String paymentResponse) { // Success //Convert the payment response from CSV hex string format to byte array format and parse the CSV response. } @Override public void onFailure(String errorMsg, int errorCode) { // Failure //Handle error message and error coded received here } })); executor.shutdown(); }, 100);