Android SDK developer guide

Index

Nexgo Library User Guide

General Library Overview

  • The library is called nexgo_versionNumber-sdk-debug.aar
  • The purpose of the library is to enable transaction execution and provide access to various components of the Nexgo device kernel
  • The library has been tested for devices: N6, N86, UN20
  • The entire library is written in Kotlin – note that this has implications; methods defined as suspend in the library must run in a compatible Coroutine
  • The library we provide includes an internal manufacturer library (nexgo)

Two Main Processes in Transaction Execution

1. EMV Process

This process is executed according to EMV rules and after passing compliant authentication in SHVA. The EMV process is executed according to a combination of various parameters, both parameters related to terminal settings and card settings. The library must provide feedback regarding the entire EMV process (passing compliant messages, providing feedback and instructions if there are errors).

2. Transaction Execution Process

If the EMV process executes “smoothly”, proceed to the transaction execution stage with the clearing company, credit companies, and SHVA. The library must provide feedback on the transaction status upon completion.

Possible Transaction Types

  • Magnetic transaction (including magnetic transaction on a smart card only if there is fallback)
  • EMV transactions with card presentation and card insertion
  • EMV transactions with wallet (phone device, smartwatch, etc.)
  • Phone transactions (manual entry of card details)

Instructions for Programmers

📌 Important: First, you need to integrate the library as part of the libs folder in the project.

The library contains three main objects:


1) nexgoDeviceConfig – Device Initialization

This object was created to perform device initialization (initialization includes receiving parameters and “burning” them into the device).

Available Methods

initDeviceConfiguration

The method must receive as a parameter an object identified with user details (user details are received from Pelcard) and returns a status according to whether the process succeeded or not. It is responsible for receiving configuration files and burning them into the device.

⚠️ Note: Do not perform any transaction until terminal initialization has been completed. It is recommended to perform initialization with each application launch.

resetInitConfiguration

The method is responsible for deleting the parameters burned into the device.

Code Example

private lateinit var nexgoDeviceConfig: NexgoDeviceConfig

override suspend fun initNexgoLibrary(
    terminalNum: String,
    shopNum: String,
    username: String,
    password: String
): Boolean {
    nexgoDeviceConfig = NexgoDeviceConfig(context)
    this.shopNum = shopNum
    libraryAuthDetails = ClientDetails(username, password, terminalNum)
    val res = nexgoDeviceConfig.initDeviceConfiguration(libraryAuthDetails)
    Logg.df("initNexgoLibrary result = $res")
    return res == InitResCode.INIT_SUCCESSFUL
}

2) NexgoDeviceController – Hardware Control

This object was created to enable access to various components of the device such as LEDs, beeper, printer, kiosk mode (screen lock).

You should independently check which methods are exposed to the user and what parameters they receive.

💡 Note on receipt printing: The method receives a pre-defined object which essentially includes parameters received in response to a transaction and must be built independently.

Code Example

override fun getSerialNumber(): String {
    return nexgoDeviceController.getDeviceSerial()
}

override fun makeBeep() {
    nexgoDeviceController.controlBeeper(DeviceBeepLevel.LEVEL_1)
}

override fun setKioskMode(isEnable: Boolean) {
    if(isEnable)
        nexgoDeviceController.enableKioskMode()
    else 
        nexgoDeviceController.disableKioskMode()
}

3) NexgoTransaction – Transaction Processing

The central object responsible for transaction execution. Before explaining it, we’ll cover the listener used to pass messages and events during a transaction.

NexgoLibraryEventsListener

A listener that you must subscribe to in order to receive feedback on various events occurring during the transaction.

For example, PIN code entry events, or receiving continuous messages (messages like insert card, remove card, wait for approval, etc.) are received through the listener.

📡 Event Handling: I take care of providing the events and messages through the listener, but the programmer using the library must find the way to pass and translate the messages and events as desired. The example uses broadcastreceiver.

Listener Implementation Example

init {
    nexgoDeviceController = NexgoDeviceController(context)
    nexgoLibraryEventListener = NexgoLibraryEventsListener(context)
}

class NexgoLibraryEventsListener(private val context: Context): NexgoEventsListener {
    
    init {
        NexgoEventManager.registerListener(eventListener: this)
    }
    
    override fun onEventReceiveTransactionsMessages(msg: String) {
        Logg.df("onEventReceiveTransactionsMessages: $msg")
        onNewTransactionMessage(msg)
    }
    
    override fun onEventPin(pinEvent: PinEvent) {
        Logg.df("onEventPin: ${pinEvent.name}")
        when(pinEvent){
            PinEvent.PIN_FIRST_TIME -> onNewPin(PIN_SCREEN_NAVIGATE)
            PinEvent.PIN_ENTRY_COMPLETED -> onNewPin(PIN_ENTERED_EVENT)
            PinEvent.PIN_ENTRY_DIGIT -> onNewPin(PIN_DIGIT_EVENT)
            PinEvent.PIN_ENTRY_CLEAR -> onNewPin(PIN_CLEAR_DIGITS_EVENT)
            else -> {}
        }
    }
    
    private fun onNewTransactionMessage(msg: String){
        val intent = Intent(action: "common-payment-event")
        intent.putExtra(name: "transaction_message", msg)
        context.sendBroadcast(intent)
    }
    
    private fun onNewPin(pinEvent: String){
        val intent = Intent(action: "common-payment-event")
        intent.putExtra(name: "pin_event", pinEvent)
        context.sendBroadcast(intent)
    }
}

Creating Transaction Object

To perform a transaction, you need to define an object called NexgoDeviceTransaction.

The object must be defined anew for each transaction. This object must receive the activity because there are cases where the library needs to provide UI (for example, for a hybrid card).

transaction = NexgoDeviceTransaction(appContext: getActivity() ?: context)

Transaction Methods

After the object is defined, you can access the various methods related to transaction execution.

The two methods that start the transaction are:

  1. startTransaction
  2. makeManualTransaction

1. startTransaction Method

This method is intended to start a transaction that includes a full EMV process. It receives the user’s identification details (the same details object sent for device initialization), and additionally receives an object that the user must define with transaction details (amount, transaction type, etc.)

From the moment this method is called, the readers are activated and the user can perform a transaction using a physical card (of course, following the messages and events from the listener).

⚠️ New parameter in new versions: If the device works in regular configuration, readCardWithTimeout: Boolean in startTransaction must be false

Cancel Transaction

To cancel the transaction, the user can access an additional method:

cancelTransaction()

Complete J5 Transaction

To complete a J5 transaction, use the function:

completeDebitByUid(
    clientDetails: ClientDetails, 
    uid: String, 
    newAmount: String, 
    newParamX: String, 
    trxId: String
): TransactionResCode

2. makeManualTransaction Method

This method is intended to perform a phone transaction (manual transaction) – it receives the user’s identification details and an additional object that the user must define with the card details parameters.

Handling Transaction Results

After the transaction is completed or canceled (initiated cancellation, or any cancellation by the library due to EMV process or communication issues), the user receives a response.

The returned response is an ENUM value. If the value is:

TransactionResCode.TRANSACTION_OK

This means that the transaction process with the library passed successfully (does NOT mean the transaction was approved!!!!)

If this is the returned value, you can extract using getFinishedTransactionResult() the object containing all the transaction data.

Other ENUM values are left for user handling (cancellation, general error).

Full Transaction Example

override suspend fun sendTransPayment(paymentFull: PaymentFull): PaymentFullRes? {
    makeBeep()
    queryID = paymentFull.queryID
    transaction = NexgoDeviceTransaction(appContext: getActivity() ?: context)
    tranData = PaymentUtil.createNexgoTransaction(paymentFull, shopNum) ?: return null
    val res = transaction?.startTransaction(tranData, libraryAuthDetails)
    Logg.df("sendTransPayment result = $res , nexgo transaction $tranData")
    
    return when (res) {
        TransactionResCode.TRANSACTION_OK -> {
            val tranRes = transaction?.getFinishedTransactionResult()
            val intOt = createIntOt(tranRes)
            receiptData = tranRes?.let { initReceiptData(it) }
            Logg.d("libraryResult: $tranRes")
            PaymentFullRes(
                paymentFull.queryID, 
                intOt, 
                customerRecipt: "", 
                customerReciptDetailed: "", 
                merchantRecipt: ""
            )
        }
        TransactionResCode.TRANSACTION_CANCELED -> {
            PaymentFullRes(
                paymentFull.queryID, 
                IntOt(ashdStatus = CANCELED_BY_USER), 
                customerRecipt: "", 
                customerReciptDetailed: ""
            )
        }
        else -> {
            PaymentFullRes(
                paymentFull.queryID, 
                IntOt(ashdStatus = TRANSACTION_FAILED), 
                customerRecipt: "", 
                customerReciptDetailed: ""
            )
        }
    }
}

Pulse Feature

The library also provides an API through which pulses can be sent from the device.

Through an instance of an object of type NexgoDeviceController, you can access the initPulse method.

The method receives a mode (digit 0 or 1, if something else is sent – there is a default value) and sends a pulse accordingly.

Pulse Example

override fun makePulsesWithGap(startMode: Int, endMode: Int, gap: Long) {
    Logg.d("makePulsesWithGap startMode:$startMode endMode:$endMode gap:$gap")
    nexgoDeviceController.initPulse(startMode)
    try {
        Thread.sleep(gap)
    } catch (e: InterruptedException) {
        throw RuntimeException(e)
    }
    nexgoDeviceController.initPulse(endMode)
}

Reading Magnetic Card Using Track2Reader

Track2Reader is designed to read magnetic card data (2 Track) without performing a full EMV transaction.

Use Cases

  • Tests/diagnostics for magnetic reading
  • Dedicated processes where a full EMV process is not required
  • Collecting 2 Track before another stage in your logic

💡 Important: In any regular payment transaction through startTransaction there is no need to use Track2Reader – the SDK will provide the data automatically.

Class Signature

class Track2Reader(appContext: Context) : OnCardInfoListener {
    suspend fun startReadMag(): MagReadInfo
    fun cancelMagRead()
}

MagReadInfo Result Object

Calling startReadMag() returns an object of type MagReadInfo containing:

  • track2: String? – 2 Track data as read from the device
  • isIcc: Boolean – Does the card contain a chip (useful for fallback decision)
  • status: MagReadStatus – Read status:
    • MAG_READ_SUCCESS – Read succeeded
    • TIMEOUT_MAG – Card not passed in time
    • ERROR_READ_MAG – Read error (incorrect swipe / multiple cards)
    • CANCELED_MAG – Canceled by user

Basic Read Process

  1. Create an instance of Track2Reader with the application’s Context
  2. Call startReadMag() from Coroutine (it’s a suspend function)
  3. Handle the received status
  4. If needed – call cancelMagRead() to cancel

NexgoTransaction Field Reference

This table includes the field name, whether it’s mandatory, its type, default value (if any), and a short description.

Field Mandatory Type Default Description
trxID Yes String Unique transaction ID – mandatory. 10-digit value
shopNumber Yes String Shop number – identifier for the store
amount Yes Long Transaction amount in minor currency units (e.g., agorot for ILS)
cashbackAmount No Long 0 Amount to be returned as cashback. Optional
tranType Yes TranType Transaction type:
1 – Regular Debit
53 – Refund
isPreAuth Yes Boolean Indicates if the transaction is pre-authorization (J5)
creditTerms Yes Int Number of credit terms:
1 – Regular
3 – Direct Debit
6 – Credit
8 – Installments
paymentsNumber No Int 0 Number of installments. Optional
firstPayment No Long 0 First payment amount. Optional. Sent in Cents/Agorot
fixedPayment No Long 0 Fixed payment amount. Optional. Sent in Cents/Agorot
countryCode No String “376” Country code (default is ‘376’)
currencyCode No String “376” Currency code:
376 – Shekel
840 – Dollar
978 – Euro
merchentId No String? “” Merchant ID (nullable). Optional
id No String? “” Optional. Customer ID for manual transaction
notes No String “” Free-text notes for manual transaction. Optional
sapakNum No String “” Supplier number. Optional
tranDate No String? today Transaction date formatted as ‘MMdd’ (default is today)
tranTime No String? now Transaction time formatted as ‘hhmmss’ (default is now)

✅ Summary

This SDK provides a comprehensive solution for integrating Nexgo POS terminals into Android applications. It handles EMV processing, transaction management, and device control, allowing developers to focus on building their business logic and user interface.

No data was found