Hubtel POS SDK Documentation
The Hubtel POS SDK comprises a suite of packages that collectively facilitate point-of-sale terminal transactions on All-In-One
devices.
The SDK is organized in 3 layers. And each layer of the SDK is designed to deliver a unique set of functionalities, ensuring a comprehensive and efficient handling of point-of-sale terminal transactions in the apps requiring these capabilities such as the Bank POS
app.
OBJECTIVES
The primary objective of this SDK is to isolate all Point-Of-Sale (POS) hardware-related functionality, thereby ensuring complete separation from product applications.
Through this segregation, it is hoped that the product team can innovate freely within their product apps, without worrying about the performance of the POS-hardware.
Similarly, the segregation would also encourage research and innovation in the tooling aspect of the project.
FUNCTIONALITY
The Hubtel POS SDK offers two primary functionalities to its dependencies:
- First, process card payments.
- And second, generate receipts for all transactions.
To process card payments, the card must be read, its data extracted, interpreted, and the order processed by the SDK. Rephrased, at the highest level, the SDK primarily handles payment processing. However, beneath this surface, the SDK performs many more tasks.
For receipt generation, the SDK provides a receipt creator that generates any type of printable document, which is then passed to the SDK for printing processing.
SDK LAYERS
As pointed out previously, the Hubtel POS SDK is structured across three layers:
- The PUB-API (Public API)
- The DEV-API (Device API)
- The SHARED-API (Shared Module API)
The PUBLIC API (PUB-API)
The PUB-API
is the hubtel-pos-sdk
module in the Platform-App-Android-Hubtel-Library
project. The module
is a public api that exposes the basic functionalities that are required of the SDK.
Primarily, the module exposes an init()
method, and a PosDevice
property.
The init()
initialises the SDK, it is recommended to invoke this method very early in app startup processes.
The PosDevice
property is appropriately named posDevice
. PosDevice
is an interface that defines a card processor, a printer, serial number and device type.
Each of these shall be discussed in detail in the SHARED-API section of this documentation.
interface PosDevice {
val cardProcessor: POSDeviceProcessor
val cardPrinter: POSPrinter
val serialNumber: String
val deviceType: PosDeviceType
}
The cardProcessor
exposes a start(chargeInfo: ChargeInfo)
, cancel()
methods and cardProcessListener
property.
- The
start()
method initiates and processes payments. - The
cancel()
method terminates all active card transaction processes. - The
cardProcessListener
monitors the progress of the transaction. These events can be monitored to facilitate communication between the SDK and the dependent application. The snippet below illustrates how this property can be utilized:
LaunchedEffect(cardProcessor.cardProcessListener) {
cardProcessor.cardProcessListener.collect { result: CardProcessResult ->
when (result) {
is CardProcessResult.Message -> {
message = result.value
}
is CardProcessResult.BasicInformation -> {
val cardHolderName = result.cardHolderName
val cardNumber = result.maskedCard
val cardExpiryDate = result.expiryDate
val entryMode = result.entryMode
}
is CardProcessResult.PaymentCompleted -> {
val message = "Payment successfully."
}
is CardProcessResult.Error -> {
val errorMessage = result.message
}
is CardProcessResult.Cancel -> {
val message = "User cancelled transaction"
}
is CardProcessResult.OnKeyPressed -> {
val pin = result.data
}
else -> {}
}
}
}
The cardPrinter
, on the other hand, exposes a print(creator: ReceiptCreator)
method that facilitates receipts generation.
The serialNumber
property returns the serial number of the device.
The deviceType
property returns the device on which the SDK is running e.g. JTact
, Z90
, and PAX
. These are enum values defined in PosDeviceType
of the SHARED-Module API
.
Below is a snippet demonstrating how the HubtelPOSKit
can be used to access these methods and properties:
val posDevice = HubtelPOSKit.posDevice
val posDeviceType: PosDeviceType = HubtelPOSKit.posDevice.deviceType
val cardProcessor = posDevice.cardProcessor
val cardPrinter = posDevice.cardPrinter
val serialNumber = posDevice.serialNumber
ADDING A DEVICE TO THE SDK
In addition, the HubtelPOSKit
has a private getCurrentDevice(context: Context): PosDevice
method that takes context and returns a PosDevice.
To add a new device to the SDK, the DEV-API (Device API) must be defined in the devices layer. Next, this getCurrentDevice method should be modified to be able to return the new device. Following are the devices currently defined:
private fun getCurrentDevice(context: Context): PosDevice {
return when (getPOSManufacturer()) {
POSManufacturer.BLU_Z90 -> Z90Device(context)
POSManufacturer.JTACT_V56 -> JTactDevice(context)
else -> error("No supported device found.")
}
}
To add a new device, say, RJ_45
, the method would have to be updated to be like so:
private fun getCurrentDevice(context: Context): PosDevice {
return when (getPOSManufacturer()) {
POSManufacturer.BLU_Z90 -> Z90Device(context)
POSManufacturer.JTACT_V56 -> JTactDevice(context)
POSManufacturer.RJ_45 -> RJ45Device(context)
else -> error("No supported device found.")
}
}
Now, if the SDK is launched on a RJ_45
device, it should run smoothly without any issues.
The SHARED-API (Shared Module API)
The SHARED-API
represents the shared module within the Platform-App-Android-Library project. This module houses the fundamental classes and methods that underpin the APIs for all devices within the library. This section delves into the detailed components of the SHARED-API.
The SHARED-API is structured around several core packages, which include:
card_delegates
(com.hubtel.pos.shared.card_delegates)device
(com.hubtel.pos.shared.device)network
(com.hubtel.pos.shared.network)printer
(com.hubtel.pos.shared.printer)resources
(com.hubtel.pos.shared.resources)utils
(com.hubtel.pos.shared.utils)
The device
Package
The device package encapsulates the definitions for POSDevice
, POSDeviceProcessor
, and POSPrinter
interfaces.
The POSDeviceProcessor
interface outlines two key methods: start(chargeInfo: ChargeInfo)
and cancel()
, along with a property cardProcessListener
of type Flow<CardProcessResult>
.
Within the Device API
, this interface is implemented by specific device classes, which are responsible for tailoring the implementation to the unique characteristics of each device.
Following is an example how a Z90 device would implement this interface:
class Z90Device(private val context: Context) : PosDevice {
private val system by lazy {
DriverManager.getInstance().baseSysDevice
}
override val cardProcessor: POSDeviceProcessor = Z90Processor(context)
override val cardPrinter: POSPrinter = Z90Printer()
override val serialNumber: String
get() = ...
override val deviceType: PosDeviceType
get() = PosDeviceType.Z90
init {
Z90Utils.initZ90Device(context, system)
}
}
The POSDevice interface is a mandatory component of the Device API, and the naming convention for the implementing class typically reflects the device model or name, appended with Device. Examples include Z90Device, JTactDevice, and PAXDevice.
Each device class implementation is anticipated to initialize the device within its constructor, setting properties such as init{}
, serialNumber: String
, deviceType: PosDeviceType
, cardProcessor: POSDeviceProcessor
, and cardPrinter: POSPrinter
.
The PosDeviceType
is a Kotlin enum class that enumerates all the devices compatible with the library.
The deviceType: PosDeviceType
property was introduced upon the request of the Product Team.
enum class PosDeviceType {
Z90,
JTACT,
PAX
}
The POSPrinter interface defines a print(creator: ReceiptCreator)
method that must be implemented by the Device API like so:
class Z90Printer : POSPrinter {
override suspend fun print(creator: ReceiptCreator): Unit =
suspendCoroutine { continuation ->
}
}
class JTactPrinter : POSPrinter {
override suspend fun print(creator: ReceiptCreator): Unit = suspendCoroutine { continuation ->
}
}
The POSManufacturer
enum class serves as a definitive source for identifying the model of a device and its associated list of identifiers, which typically include processor names. This enumeration is instrumental in distinguishing between various device models within the system.
The DeviceUtils file includes a function named getPOSManufacturer()
. This function is pivotal in determining the manufacturer of the device currently in use. When combined with the getCurrentDevice(context: Context)
method from the HubtelPOSKit
, it plays a crucial role in initializing the device with the correct configuration and settings.
CHAT SAMMIAT