PayPlugNexo is an SDK that allows Android/iOS sale systems to easily interact with PAYPLUG Terminals.
The sale system and the POS Terminals must be able to communicate through the local network. The PayPlugNexo SDK send request to the terminal’s IP address.
API
PayPlugNexo
This class is the entry point to the SDK. It exposes the main methods to perform payment transactions between the sale terminal and the POI terminal. To get an instance of PayplugNexo, you have to use PayPlugNexoProvider.getPayPlugNexo(settings, appContext, payPlugNexoHandler). It takes the following parameters:
These class methods are invoked from background threads. You shouldn't have to handle that on your side.
This class contains the following methods:
Login
This method allows the sale system to send a login request to the POI terminal. A login is a prerequisite for a payment request. This method has one parameter.
This method tries to abort a payment request to the POI terminal. This method has a required parameter:
Parameter
Type
Purpose
abortReason
String
The reason of cancellation.
AbortReversal
This method tries to abort a reversal request to the POI terminal. This method has a required parameter:
Parameter
Type
Purpose
abortReason
String
The reason of cancellation.
Logout
This method has no parameters and will send a logout request to the terminal. When there are no more operations in progress, a logout must be performed.
PayPlugNexoSettings
This class contains the main settings to instantiate the PayPlugNexo. The primary constructor has these parameters:
Parameter
Type
Purpose
serviceId
String
The identifier of a message pair that processes a transaction.
saleId
String
The identifier of a sale system or a sale terminal for the Sale to POI protocol.
operatorId
String
The identifier of the cashier or operator.
poiId
String
The identifier of a POI system or a POI terminal for the Sale to POI protocol.
isAutoLogin
Boolean
Indicates if session must be open again as soon as possible when session is lost due an error.
The version of the Nexo protocol you want to use, default is 3. For the moment only the version 3 is available.
manufacturerId
String
The identifier of the manufacturer.
applicationName
String
The name of the software product.
softwareVersion
String
The version of the software product.
certificationCode
String
The certification code of the software thatf manages the Sale to POI protocol.
The class also contains constants representing the default values for some settings. The secondary constructor requires only the five first parameters and uses the default values for the others.
PayPlugNexoHandler
This interface contains all the callbacks which called by the SDK. The client must implement them to handle each request.
Note
The callbacks are invoked on the main thread.
This interface has these methods:
onLoginSuccess
This callback is triggered when the login method is complete successfully. This method has one parameter:
If the request couldn't be made, it contains the error otherwise it is null.
onPaymentAborted
This callback is triggered when the abortPayment method is complete. This method has two parameters:
Parameter
Type
Purpose
isSuccessful
Boolean
Is true if the request was successfully sent and false otherwise.
CAUTION: This is not a confirmation of the correct cancellation of the payment, because it should arrive via onPaymentCompleted with an ErrorCondition of type Aborted.
If the request couldn't be made, it contains the error otherwise it is null.
onReversalAborted
This callback is triggered when the abortReversal method is complete. This method has two parameters:
Parameter
Type
Purpose
isSuccessful
Boolean
Is true if the request was successfully sent and false otherwise.
CAUTION: This is not a confirmation of the correct cancellation of the reversal, because it should arrive via onReversalCompleted with an ErrorCondition of type Aborted.
If the request couldn't be made, it contains the error otherwise it is null.
NetworkAddress
Represent POI host info used to connect to it:
Parameter
Type
Purpose
hostname
String
The IP address of the POI system.
port
Int
The port of the POI system.
PayPlugNexoCurrency
An enumeration representing the currencies supported by the POI system. Only EUR is currently available. Each currency has a parameter:
Parameter
Type
Purpose
decimalsProportion
Integer
The proportion of decimals of the specified currency. For example, the EUR has 2 decimals so it's 100. YEN has 0 decimals so it's 1.
PayPlugNexoLang
An enumeration representing the languages supported by the POI system. It allows the choice of the cashier language when the POI displays a message. Current supported languages are: FR, EN, IT, ES
NexoResponseResult
An enumeration representing the request status:
Value
Purpose
SUCCESS
Processing OK. Information related to the result of the processing is contained in other parts of the response message.
FAILURE
Processing of the request fails for various reasons. Some further processing according to the type of requested service, the context of the process, and some additional precision about the failure notified in the ErrorCondition data element.
PARTIAL
The transaction has been processed successfully, but the success is not complete (e.g. only a partial amount is available for the payment, the format to be displayed is not supported and was replaced by a default format).
This object has a method fromString(name) which returns the NexoResponseResult enum value or null if not found.
ErrorCondition
An enumeration representing the ErrorCondition of the NexoSale documentation. The condition which returned an error during the request:
Value
Purpose
Aborted
The sale system sent an Abort request message before the end of the Payment request processing. The POI has aborted the payment transaction, and sends the Payment response message with this ErrorCondition, to report the result of the aborted payment.
Busy
There are transactions in progress in the POI terminal or the sale terminal.
Cancel
The user has aborted the transaction on the Customer interface (e.g. the POI terminal keyboard), because he does not want to continue the payment (e.g., problem of PIN remembering, chooses another payment mean, stop the purchase on a vending machine).
DeviceOut
The POI element cannot start the payment transaction, because of a temporary error on a device (e.g. printer without paper).
InProgress
The transaction is still in progress and then the command cannot be processed.
InsertedCard
The Input Device requested a NotifyCardInputFlag and the Customer inserts a card in the card reader without answering the Input command. The POI has aborted the Input command processing, and answers this ErrorCondition value in the Input response message.
InvalidCard
The card entered by the Customer cannot be processed by the POI because this card is not configured in the system.
LoggedOut
The sale terminal has never sent a Login message request since the last Logout message sending or the start-up of the POI terminal. This is the typical error after a crash of the POI terminal or the POI system.
MessageFormat
Standard message format errors. These are permanent errors, which have to be resolved without any other attempt.
NotAllowed
The Payment request is received during a Device dialogue or another Service dialogue.
NotFound
The resource(Transaction, Message, Reconciliation...) is not stored in the POI system.
PaymentRestriction
The Customer has used a card restricted on the products the card may pay. Some of the items provided in the SaleItem of the request are product than the card cannot pay.
Refusal
The transaction is refused by the payment Acquirer or the rules associated to the card. The cashier has not forced the transaction, and the payment cannot be repeated. A specific message is normally displayed to the Customer and the cashier if they are presents, the information below could be logged for further information.
UnavailableDevice
The hardware is not available (absent, not configured...).
UnavailableService
The service is not available (not implemented, not configured, protocol version too old...).
UnreachableHost
Acquirer or any host is unreachable or has not answered to an online request, so is considered as temporary unavailable. Depending on the Sale context, the request could be repeated (to be compared with "Refusal").
WrongPIN
The user has entered the PIN on the PED keyboard and the verification fails.
Other
An error unrelated to any of the previous cases.
This object has a method fromString(name) which returns the ErrorCondition enum value or null if not found.
ErrorEvent
An enumeration representing the errors that may occur during the request between the sale system and the POI system:
Value
Purpose
PARSE
A parsing error occurs when a parser faces an error.
IO
An IO error can occur during a TCP/IP request.
NOT_CONNECTED
This error occurs when the client tries to send a request without connection.
Qualification
An enumeration representing the display message qualification :
Value
Purpose
POIREPLICATION
Replication of messages on terminal
STATUS
Message indicating a status info
ERROR
Message indicating that on error occurred
OutputFormat
An enumeration representing the format of messages received by the display request :
Value
Purpose
PREDEFINED_CONTENT
Received message is an Integer identifier that can be used to match with locale translated resource
TEXT
Received message is a text (String)
NexoResponse
An abstract class representing a Nexo Response. It contains these properties:
If output format is OutputFormat.Text, contains related text
predefinedContentId
String (optional)
If output format is OutputFormat.PrefefinedContent, contains related id of text
Android
Notes
In order to use this library, the project's min SDK version must be 21 or above.
This is a Kotlin code sample. Java can also be used.
Getting started with PayPlugNexo is very straightforward. This integration guide provides detailed steps in Kotlin to integrate the PayPlugNexo SDK and proceed to a payment in an Android native application.
onConnectionCompleted has been removed since connect() has been removed. Use onLoginSuccess() and onLoginFailed()
onDisconnectionCompleted has been removed since disconnect() has been removed. Use onLogoutCompleted()
onLoginCompleted has been replaced by onLoginSuccess() and onLoginFailed()
onError has been removed. Important errors are throw to associated action callback (onPaymentCompleted, onRefundCompleted,...)
onSessionLost has been added. It indicates when session is ended between cash register and terminals. If auto-reconnection is enabled, connection will be reestablished automatically as soon as possible.
Integration
To add the library, there are three steps:
Add the payplugnexo.aar to the libs directory in your project root directory.
In the project level build.gradle, add the libs directory to the repositories in the allprojects section:
In your Activity or Fragment, you need to declare a PayPlugNexo variable:
private lateinit var payPlugNexo: PayPlugNexo
Afterwards, initialize payPlugNexo in the onCreate method.
To get an instance of PayplugNexo, you have to use PayPlugNexoProvider.getPayPlugNexo(settings, applicationContext, payPlugNexoHandler).
To do this, three parameters PayPlugNexoSettings, AppContext and PayPlugNexoHandler must be provided. The latest represents the callbacks invoked when a request is complete.
val settings = PayPlugNexoSettings(serviceId = "5629", saleId = "saleA", operatorId = "operatorA", poiId = "poiId", isAutoLogin = true)
payPlugNexo = PayPlugNexoProvider.getPayPlugNexo(settings = settings, applicationContext = AppContext(this.applicationContext), object: PayPlugNexoHandler {
override fun onLoginSuccess(loginNexoResponse: LoginNexoResponse) {
// TODO: Write your code here
}
override fun onLoginFailed() {
// TODO: Write your code here
}
override fun onLogoutCompleted(logoutNexoResponse: LogoutNexoResponse?, error: ErrorEvent?) {
// TODO: Write your code here
}
override fun onPaymentCompleted(paymentNexoResponse: PaymentNexoResponse?, error: ErrorEvent?) {
// TODO: Write your code here
}
override fun onRefundCompleted(paymentNexoResponse: PaymentNexoResponse?, error: ErrorEvent?) {
// TODO: Write your code here
}
override fun onReversalCompleted(reversalNexoResponse: ReversalNexoResponse?, error: ErrorEvent?) {
// TODO: Write your code here
}
override fun onPaymentAborted(isSuccessful: Boolean, error: ErrorEvent?) {
// TODO: Write your code here
}
override fun onReversalAborted(isSuccessful: Boolean, error: ErrorEvent?) {
// TODO: Write your code here
}
override fun onDisplayRequest(displayNexoResponse: DisplayNexoResponse?,error: ErrorEvent?) {
// TODO: Write your code here
}
override fun onSessionLost() {
// TODO: Write your code here
}
})
Login
The client can send a login request to make payments. The login method should be called.
findViewById<Button>(R.id.login).setOnClickListener {
payPlugNexo.login(NetworkAddress(hostname = "X.X.X.X"))
// if you want to use network discovery and don't specify IP address, you can use "login" method like this (require payment app 1.4.0 or above)
// payPlugNexo.login(null)
}
The related callbacks are onLoginSuccess and onLoginFailed
override fun onLoginSuccess(loginNexoResponse: LoginNexoResponse) {
// Success login, can do payments now
}
override fun onLoginFailed() {
// Failure during login
}
App2App
To use this mechanism (switching between Payment App and local Retail App automatically) you must use 127.0.0.1 IP address
Payment
Note
The currency used in this sample is EURO.
The amount value is retrieved from the EditText, then it converted to cents by multiplying by 100 (e.g. 5.00 € equals 500).
Afterwards the pay method will be called.
If you copy this code, please mind to update the transactionId parameter below.
findViewById<Button>(R.id.payment).setOnClickListener {
val amount = findViewById(R.id.amount).toString().toDoubleOrNull()
if (doubleValue != null && doubleValue > 0) {
val amountInCents = (doubleValue * 100).toInt()
payPlugNexo.pay("TEST1234", amountInCents)
}
}
The related callback is onPaymentCompleted.
override fun onPaymentCompleted(paymentNexoResponse: PaymentNexoResponse?, error: ErrorEvent?) {
val status = paymentNexoResponse?.result == NexoResponseResult.SUCCESS
Log.d("Payment", if (status) "succeeded" else "failed")
}
Refund
Note
The currency used in this sample is EURO.
The amount value is retrieved from the EditText, then it converted to cents by multiplying by 100 (e.g. 5.00 € equals 500).
Afterwards the refund method will be called.
If you copy this code, please mind to update the transactionId parameter below.
findViewById<Button>(R.id.payment).setOnClickListener {
val amount = findViewById(R.id.amount).toString().toDoubleOrNull()
if (doubleValue != null && doubleValue > 0) {
val amountInCents = (doubleValue * 100).toInt()
payPlugNexo.refund("TEST1234", amountInCents)
}
}
The related callback is onRefundCompleted.
override fun onRefundCompleted(paymentNexoResponse: PaymentNexoResponse?, error: ErrorEvent?) {
val status = paymentNexoResponse?.result == NexoResponseResult.SUCCESS
Log.d("Refund", if (status) "succeeded" else "failed")
}
Reverse
To cancel a transaction, you need to use the reverse method.
A transaction can be cancelled only before reconciliation
If you copy this code, please mind to update the transactionId parameter below.
override fun onReversalCompleted(reversalNexoResponse: ReversalNexoResponse?, error: ErrorEvent?) {
val status = reversalNexoResponse?.result == NexoResponseResult.SUCCESS
Log.d("Reversal", if (status) "succeeded" else "failed")
}
AbortPayment
To try to abort a payment, use the abortPayment method.
CAUTION: The boolean returned by this method is not a confirmation of the correct cancellation of a payment, it should arrive via onPaymentCompleted with an ErrorCondition of type Aborted.
override fun onPaymentAborted(isSuccessful: Boolean?, error: ErrorEvent?) {
Log.d("Payment Aborted", if (isSuccessful) "succeeded" else "failed")
}
AbortReversal
To try to abort a reversal, use the AbortReversal method.
CAUTION: The boolean returned by this method is not a confirmation of the correct cancellation of a reversal, it should arrive via onReversalCompleted with an ErrorCondition of type Aborted.
override fun onLogoutCompleted(logoutNexoResponse: LogoutNexoResponse?, error: ErrorEvent?) {
val status = logoutNexoResponse?.result == NexoResponseResult.SUCCESS
Log.d("Logout", if (status) "succeeded" else "failed")
}
iOS
Notes
Xcode 11 and above is required to integrate the framework.
This is a swift code sample. Objectif-c could also be used.
Getting started with PayPlugNexo is very straightforward. This integration guide provides detailed steps in Swift to integrate the PayPlugNexo SDK and proceed to a payment in an iOS native application.
onConnectionCompleted has been removed since connect() has been removed. Use onLoginSuccess() and onLoginFailed()
onDisconnectionCompleted has been removed since disconnect() has been removed. Use onLogoutCompleted()
onLoginCompleted has been replaced by onLoginSuccess() and onLoginFailed()
onError has been removed. Important errors are throw to associated action callback (onPaymentCompleted, onRefundCompleted,...)
onSessionLost has been added. It indicates when session is ended between cash register and terminals. If auto-reconnection is enabled, connection will be reestablished automatically as soon as possible.
Integration
Add PayPlugNexo.xcframework in the appropriate target (Targets > General > Frameworks, Libraries and Embedded Content).
Configuration
You need to import PayPlugNexo in your ViewController and then associate it to a variable.
import PayPlugNexo
private var payPlugNexo: PayPlugNexo!
To get an instance of PayplugNexo, you have to use PayPlugNexoProvider.shared.getPayPlugNexo(settings, applicationContext, payPlugNexoHandler) to instantiate it on your viewDidLoad :
You also need to configure a PayPlugNexoHandler protocol as parameter. For example by integrating it via the ViewController:
class ViewController: UIViewController, PayPlugNexoHandler {
private var payPlugNexo: PayPlugNexo!
override func viewDidLoad() {
super.viewDidLoad()
let settings = PayPlugNexoSettings(
serviceId: "6676", saleId: "SaleA", operatorId: "operatorA", poiId: "poiId", isAutoLogin: true
)
payPlugNexo = PayPlugNexoProvider.shared.getPayPlugNexo(settings: settings, applicationContext: AppContext(), payPlugNexoHandler: self)
}
func onLoginSucess(loginNexoResponse: LoginNexoResponse) {
// TODO: Write your code here
}
func onLoginFailed() {
// TODO: Write your code here
}
func onLogoutCompleted(logoutNexoResponse: LogoutNexoResponse?, error: ErrorEvent?) {
// TODO: Write your code here
}
func onPaymentCompleted(paymentNexoResponse: PaymentNexoResponse?, error: ErrorEvent?) {
// TODO: Write your code here
}
fun onRefundCompleted(paymentNexoResponse: PaymentNexoResponse?, error: ErrorEvent?) {
// TODO: Write your code here
}
fun onReversalCompleted(reversalNexoResponse: ReversalNexoResponse?, error: ErrorEvent?) {
// TODO: Write your code here
}
fun onPaymentAborted(isSuccessful: Boolean, error: ErrorEvent?) {
// TODO: Write your code here
}
fun onReversalAborted(isSuccessful: Boolean, error: ErrorEvent?) {
// TODO: Write your code here
}
func onDisplayRequest(displayNexoResponse: DisplayNexoResponse?, error: ErrorEvent?) {
// TODO: Write your code here
}
fun onSessionLost() {
// TODO: Write your code here
}
}
To use auto-login functionality and login function without specifiying IP address, a local network discovery need to be performed. For that, a user permission is needed to access to local network.
Add following code in Info.plist :
<key>NSLocalNetworkUsageDescription</key>
<string>REPLACE THIS MESSAGE TO INDICATE WHY PERMISSION IS REQUIRED</string>
<key>NSBonjourServices</key>
<array>
<string>_payplug_retailer_poi._tcp</string>
</array>
Login
The client can send a login request to make payments. The login method should be called.
@IBAction func LoginTouchUp(_ sender: Any) {
payPlugNexo.login(NetworkAddress(hostname = "X.X.X.X"))
// if you want to use network discovery and don't specify IP address, you can use "login" method like this (require payment app 1.4.0 or above)
// payPlugNexo.login(nil)
}
The related callbacks are onLoginSuccess and onLoginFailed.
func onLoginSuccess(loginNexoResponse: LoginNexoResponse) {
// Success login, can do payments now
}
func onLoginFailed() {
// // Failure during login
}
Payment
Note
The currency used in this sample is EURO.
The amount value is retrieved from the EditText, then it converted to cents by multiplying by 100 (e.g. 5.00 € equals 500). Afterwards the pay method will be called.
If you copy this code, please mind to update the transactionId parameter below.
@IBAction func PayTouchUp(_ sender: Any) {
guard let amount = (amountTextField.text as NSString?)?.doubleValue else {
return
}
let transactionId = NSUUID().uuidString
payPlugNexo.pay(transactionId: transactionId, amount: Int32(amount * 100))
}
The amount value is retrieved from the EditText, then it converted to cents by multiplying by 100 (e.g. 5.00 € equals 500). Afterwards the refund method will be called.
If you copy this code, please mind to update the transactionId parameter below.
@IBAction func RefundTouchUp(_ sender: Any) {
guard let amount = (amountTextField.text as NSString?)?.doubleValue else {
return
}
let transactionId = NSUUID().uuidString
payPlugNexo.refund(transactionId: transactionId, amount: Int32(amount * 100))
}
To try to abort a payment, use the abortPayment method.
CAUTION: The boolean returned by this method is not a confirmation of the correct cancellation of a payment, it should arrive via onPaymentCompleted with an ErrorCondition of type Aborted.
@IBAction func AbortPaymentTouchUp(_ sender: Any) {
payPlugNexo.abortPayment(abortReason: "My reason")
}
To try to abort a reversal, use the AbortReversal method.
CAUTION: The boolean returned by this method is not a confirmation of the correct cancellation of a reversal, it should arrive via onReversalCompleted with an ErrorCondition of type Aborted.
@IBAction func AbortReversalTouchUp(_ sender: Any) {
payPlugNexo.abortReversal(abortReason: "My reason")
}