Using the Mobile SDK

Configuration

Before using the SDK, you must first configure it with the following parameters:

  1. The host URL - this is the URL where your IPC instance has been deployed, this URL should contain:
    1. The protocol (wss:// or ws://)
    2. The IP address or domain name (e.g. 192.168.1.32)
    3. The port (e.g. :443)
    4. The context path that the IPC application is running at (e.g. /ipc-app)
  2. The connection timeout - the number of seconds the SDK waits for a process (such as a payment flow) to complete
  3. A POS License Key - a unique token that identifies the POS app, this is generated by IPC when registering the POS app. If your POS app is not yet registered, you can pass null here and refer toRegister your POS instancefor information on how to obtain a POS License Key
  4. A paypoint ID - the ID of the paypoint configured in IPC that you want to target from this mobile device
  5. Optionally, a custom implementation of Logger - this will allow you to customise how you capture logs from the SDK, by default the SDK uses:
    1. Logcat on Android
    2. The Unified Logging System for iOS 10 or above
    3. The debugger console for iOS 9.x
  6. Basic details of your application (Android only) for logging and traceability
Copied!
// Optionally define a custom logger
let logger: Logger? = ...

Configuration.shared.configure(url: "wss://192.168.1.32:443/ipc-app/", // Host URL
                               timeout: 300, // Connection timeout
                               posLicenseKey: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.4Z3CseLRkkmLxat9JI2RYWjHwFSulJQiy8dmiNvdCW4", // POS License Key
                               paypointId: "PAYPOINT_123", // Paypoint ID
                               logger: logger) // Custom logger
// Optionally define a custom logger
val logger: Logger? = ...

Configuration.configure("wss://192.168.1.32:443/ipc-app/", // Host URL
                        300, // Connection timeout
                        "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.4Z3CseLRkkmLxat9JI2RYWjHwFSulJQiy8dmiNvdCW4", // POS License Key
                        "PAYPOINT_123", // Paypoint ID
                        logger, // Custom logger
                        AppDetails("My POS Application", "1.0.0")) // Application details

Registration

Each instance of you POS app must have a unique POS License Key to be able to interact securely with the IPC.

First, request a POS Activation Code from theControl Centre.

Once you have a POS Activation Code, invoke the RegistrationManager.registerPointOfSale method in the SDK to obtain a POS License Key, thenre-configure the SDKwith the POS License Key and store this value to use each time you configure the SDK.

Copied!
let responseReceived = { (response: PosRegistrationResponse) in
    // Re-configure the SDK

    // Store the POS License Key
}

let errorReceived = { (response: UnhandledError) in
    // Handle error
}

let posRegistrationResponseHandler = PosRegistrationResponseHandler(registerPosResponse: responseReceived,
                                                                    errorResponse: errorReceived)

let posRegistrationRequest = PosRegistration(pointOfSale: PointOfSale(id: "D45FGT",
                                                                      reference: "POS123",
                                                                      activationCode: "AV46THTR"))

RegistrationManager.shared.registerPointOfSale(request: posRegistrationRequest,
                                               handler: posRegistrationResponseHandler)
val registrationCallback = object : PosRegistrationCallback() {
    override fun onRegistrationComplete(response: PosRegistrationResponse) {
        // Re-configure the SDK

        // Store the POS License Key
    }

    override fun onError(error: UnhandledError) {
        // Handle error
    }
}

val posRegistrationRequest = PosRegistration(PointOfSale("D45FGT", // Point of Sale ID
                                                         "POS123", // Point of Sale Reference
                                                         "AV46THTR")) // Activation code

RegistrationManagerCompat.registerPointOfSale(Dispatchers.getIO(),
                                              posRegistrationRequest,
                                              registrationCallback)

If you are familar with Kotlin Coroutines, you can use the RegistrationManager class within a CoroutineScope instead of using RegistrationManagerCompat with callbacks.

Payments

Make a payment

The PaymentManager.startPayment method supports all types of payments (sale, pre-auth and refund), and all types of payment instrument; card (including present, not present and keyed) and card tokens.

To make a payment, first define the type of payment to make. The types of payment request are:

  • CardSale
  • CardRefund
  • CardPreAuthSale
  • TokenisedCardSale
  • TokenisedCardRefund
Copied!
let paymentRequest = CardSale(merchantTransactionReference: "12345678AB", // A transaction reference defined by the merchant
                              value: 1099, // The value of the payment, in minor currency units
                              type: .cardPresent) // How the card will be presented
val paymentRequest = CardSale("12345678AB", // A transaction reference defined by the merchant
                              1099, // The value of the payment, in minor currency units
                              CardInteraction.CARD_PRESENT) // How the card will be presented

During the payment flow, a number of real-time responses will be returned to your app by the SDK, these include:

  • Zero or more PaymentNotification - an update on the progress of the payment
  • Zero or more PaymentAction - an action is required to be performed by your app, possible actions are:
    • Perform a voice authorisation - the authorisation code from a voice authorisation must be provided
    • Input a cashback amount - the amount of cashback requested by the customer must be provided
    • Accept/Decline AVS results - confirmation that the AVS results should be accepted must be provided
    • Verify the customer's signature - confirmation that the customer's signature is valid must be provided
  • Two PaymentReceipt - the content of a receipt to be printed, these will be customer and merchant copies
  • One PaymentResult - the final result of the payment, containing the outcome, gateway transaction reference and IDs, and details of the card used
  • Confirmation that the payment flow has completed and no more messages will be received

In the event an action is requested, the payment flow will pause until the action is completed and the requested data is provided to the SDK.

To receive these responses, define a PaymentHandler:

Copied!
let paymentHandler: PaymentResponseHandler

let notificationReceived = { notification in
    // Display the text to the POS operator
}
let receiptReceived = { receipt in
    // Send the receipt content to a printer
}
let resultReceived = { result in
    // Handle the result of the payment, e.g. display on screen, or store the payment data
}
let actionRequired = { action in
    // Perform the action

    // Respond to the action, confirming it is complete with the relevant data
    paymentHandler.sendActionConfirmation(action: actionConfirmation)
}
let paymentComplete = { () in
    // The payment flow has completed, ready to start the next payment
}

let errorReceived = { error in
    // Handle unexpected errors
}

paymentHandler = PaymentResponseHandler(notificationReceived: notificationReceived,
                                        receiptReceived: receiptReceived,
                                        resultReceived: resultReceived,
                                        actionRequired: actionRequired,
                                        paymentComplete: paymentComplete,
                                        errorReceived: errorReceived)
var paymentHandler: PaymentHandler? = null

val notificationReceived = fun (notification: PaymentNotification) {
    // Display the text to the POS operator
}
val receiptReceived = fun (receipt: PaymentReceipt) {
    // Send the receipt content to a printer
}
val resultReceived = fun (result: PaymentResult) {
    // Handle the result of the payment, e.g. display on screen, or store the payment data
}
val actionRequested = fun (action: PaymentActionRequired) {
    // Perform the action

    // Respond to the action
    paymentHandler?.sendActionConfirmation(actionConfirmation)
}
val paymentComplete = fun () {
    // The payment flow has completed, ready to start the next payment
}

paymentHandler = object : PaymentHandler() {
    override fun onEvent(paymentEvent: PaymentEvent) {
        when (paymentEvent) {
            is PaymentNotification -> notificationReceived(paymentEvent)
            is PaymentReceipt -> receiptReceived(paymentEvent)
            is PaymentResult -> resultReceived(paymentEvent)
            is PaymentActionRequired -> actionRequested(paymentEvent)
            is PaymentComplete -> paymentComplete()
        }
    }

    override fun onErrorReceived(error: UnhandledError) {
        // Handle unexpected errors
    }
}

And finally start the payment:

Copied!
PaymentManager.shared.startPayment(request: paymentRequest,
                                   handler: paymentHandler)
PaymentManagerCompat.startPayment(Dispatchers.getIO(),
                                  paymentRequest,
                                  paymentHandler)

If you are familar with Kotlin coroutines, you can use the PaymentManager class within a CoroutineScope instead of using PaymentManagerCompat with callbacks.

Check a card

A check card transaction can be performed using theMake a paymentflow.

To check a card without performing a payment, pass a CheckCard request into the startPayment method, and the following responses will be returned to the PaymentHandler:

  • Zero or more PaymentNotification - an update on the progress of the check
  • One PaymentResult - the details of the card
  • Confirmation that the check card flow has completed and no more messages will be received

To check a card and then proceed with a payment on that card, pass a CheckCardPayment request into the startPayment method, and the following responses will be returned to the PaymentHandler:

  • Zero or more PaymentNotification - an update on the progress of the check
  • One PaymentResult - the details of the card

Once the PaymentResult is received for a check card with payment, you can decide whether to proceed with a payment on that card, or abort the payment.

To proceed to the payment, use the proceedWithPayment method on your PaymentHandler, passing in details of the payment you wish to process.

Copied!
let paymentRequest = CardSale(merchantTransactionReference: "12345678AB", // Confirm the merchant transaction reference used in the check card request
                              value: 1099, // The value of the payment, in minor currency units
                              type: .cardPresent) // How the card will be presented - this must match the type in the check card request

paymentHandler?.proceedWithPayment(paymentRequest)
val paymentRequest = CardSale("12345678AB", // Confirm the merchant transaction reference used in the check card request
                              1099, // The value of the payment, in minor currency units
                              CardInteraction.CARD_PRESENT) // How the card will be presented - this must match the type in the check card request

paymentHandler.proceedWithPayment(paymentRequest)

This will start the payment as instructed, and you will receive the applicable responses to your PaymentHandler for that payment as you would for a normal payment.

To abort the payment, use the abortPayment method on your PaymentHandler, and you will receive confirmation that the check card flow has completed and no more messages will be received.

Copied!
paymentHandler?.abortPayment(PaymentAbort(merchantTransactionReference: "12345679AB")) // Confirm the transaction reference from the original payment request
paymentHandler.abortPayment(PaymentAbort("12345679AB")) // Confirm the transaction reference from the original payment request

Settle a payment

If a pre-auth payment is made using CardPreAuthSale, it must later be settled in order for the funds to be transferred to the merchant.

To settle a pre-auth payment, you must have the gateway transaction reference, card expiry date, and card number returned in the result of the pre-auth payment. Optionally, you can provide a specific amount to settle if you wish to settle less than the previously authorised amount.

During the settlement flow, the following real-time responses will be returned to your app by the SDK:

  • One PaymentResult - the final result of the payment, containing the outcome, gateway transaction reference and IDs, and details of the card used
  • Confirmation that the settlement flow has completed and no more messages will be received

As with making a payment, define a PaymentHandler to receive these responses, then send the settle payment request:

Copied!
let paymentHandler = ...

let settleRequest = CardSettlement(
                      value: 1099, // Settlement value
                      gatewayTransactionReference: "98765-4321-DF", // Gateway transaction reference from the pre-auth payment
                      cardNumber: "123456XXXXXX1234"), // Card number from the pre-auth payment
                      cardExpiryDate: CardDate(month: 12, year: 21)) // Card expiry date from the pre-auth payment

PaymentManager.shared.settlePayment(request: settleRequest,
                                    handler: paymentHandler)
val paymentHandler = ...

val settleRequest = CardSettlement(
                      1099, // Settlement value
                      "98765-4321-DF", // Gateway transaction reference from the pre-auth payment
                      "123456XXXXXX1234" // Card number from the pre-auth payment
                      PaymentCardDate(12, 21)) // Card expiry date from the pre-auth payment

PaymentManagerCompat.settlePayment(Dispatchers.getIO(),
                                   settleRequest,
                                   paymentHandler)

If you are familar with Kotlin Coroutines, you can use the PaymentManager class within a CoroutineScope instead of using PaymentManagerCompat with callbacks.

Cancel a payment

To cancel a previously made card payment, you must have the gateway transaction reference, card expiry date, and card number returned in the result of the payment you wish to cancel.

During the cancel flow, the following real-time responses will be returned to your app by the SDK:

  • Two PaymentReceipt - the content of a receipt to be printed, these will be customer and merchant copies
  • One PaymentResult - the final result of the payment, containing the outcome, gateway transaction reference and IDs, and details of the card used
  • Confirmation that the cancel flow has completed and no more messages will be received

As with making and settling a payment, define a PaymentHandler to receive these responses, then send the cancel payment request:

Copied!
let paymentHandler = ...

let cancelRequest = PaymentCancelRequest(
                      originalGatewayTransactionReference: "98765-4321-DF", // Gateway transaction reference from the payment being cancelled
                      PaymentInstrument(cardExpiryDate: PaymentCardDate(month: 12, year: 21), // Card expiry date from the payment being cancelled
                                        cardNumber: "123456XXXXXX1234")) // Card number from the payment being cancelled

PaymentManager.shared.cancelPayment(request: cancelRequest,
                                    handler: paymentHandler)
val paymentHandler = ...

val cancelRequest = PaymentCancelRequest("98765-4321-DF", // Gateway transaction reference from the payment being cancelled
                                         PaymentInstrument(PaymentCardDate(12, 21), // Card expiry date from the payment being cancelled
                                                           "123456XXXXXX1234")) // Card number from the payment being cancelled

PaymentManagerCompat.cancelPayment(Dispatchers.getIO(),
                                   cancelRequest,
                                   paymentHandler)

If you are familar with Kotlin Coroutines, you can use the PaymentManager class within a CoroutineScope instead of using PaymentManagerCompat with callbacks.

Query the last payment result

To query the result of the last payment, you should pass the merchant transaction reference of the payment.

During the query flow, the following real-time responses will be returned to your app by the SDK:

  • One PaymentResult - the final result of the payment, containing the outcome, gateway transaction reference and IDs, and details of the card used

As with making, settling or cancelling a payment, define a PaymentHandler to receive these responses, then send the query payment request:

Copied!
let paymentHandler = ...

let queryRequest = PaymentResultQuery(merchantTransactionReference: "12345678AB") // Merchant transaction reference from the payment being queried

PaymentManager.shared.queryPayment(request: queryRequest,
                                   handler: paymentHandler)
val paymentHandler = ...

val queryRequest = PaymentResultQuery("12345678AB") // Merchant transaction reference from the payment being queried

PaymentManagerCompat.queryPayment(Dispatchers.getIO(),
                                  queryRequest,
                                  paymentHandler)

If you are familar with Kotlin Coroutines, you can use the PaymentManager class within a CoroutineScope instead of using PaymentManagerCompat with callbacks.

Query the last payment receipt

To query the receipt of the last payment, you should pass the merchant transaction reference of the payment and the type of receipt required.

During the query flow, the following real-time responses will be returned to your app by the SDK:

  • One PaymentReceipt - the content of a receipt to be printed, these will be the customer or merchant copy, depending on your request

As with making, settling or cancelling a payment, define a PaymentHandler to receive these responses, then send the query payment request:

Copied!
let paymentHandler = ...

let queryRequest = PaymentReceiptQuery(
                     merchantTransactionReference: "12345678AB" // Merchant transaction reference from the payment being queried
                     type: .customer) // The type of receipt required

PaymentManager.shared.queryPayment(request: queryRequest,
                                   handler: paymentHandler)
val paymentHandler = ...

val queryRequest = PaymentReceiptQuery(
                     "12345678AB", // Merchant transaction reference from the payment being queried
                     ReceiptType.CUSTOMER) // The type of receipt required

PaymentManagerCompat.queryPayment(Dispatchers.getIO(),
                                  queryRequest,
                                  paymentHandler)

If you are familar with Kotlin Coroutines, you can use the PaymentManager class within a CoroutineScope instead of using PaymentManagerCompat with callbacks.

Monitoring

Query IPC status

At any time, you can query the status of the IPC instance the SDK is connected to to understand if the instance is ready to take a payment.

Copied!
let statusReceived = { status in
  // Check the status of IPC
}

let errorReceived = { error in
  // Handle unexpected errors
}

let statusHandler = StatusMonitorResponseHandler(clientStatusResponse: statusReceived,
                                                 errorReceived: errorReceived)

StatusMonitor.shared.getClientStatus(handler: statusHandler)
val clientStatusCallback = object : ClientStatusCallback() {
    override fun onStatusReceived(paymentClientStatus: PaymentClientStatus) {
        // Check the status of IPC
    }

    override fun onError(error: UnhandledError) {
        // Handle unexpected errors
    }
}

StatusMonitorCompat.getClientStatus(Dispatchers.getIO(),
                                    clientStatusCallback)

If you are familar with Kotlin Coroutines, you can use the StatusMonitor class within a CoroutineScope instead of using StatusMonitorCompat with callbacks.

Query payment device status

At any time, you can query the status of the payment device associated with your paypoint.

Copied!
let statusReceived = { status in
  // Check the status of the payment device
}

let errorReceived = { error in
  // Handle unexpected errors
}

let statusHandler = StatusMonitorResponseHandler(deviceStatusResponse: statusReceived,
                                                 errorReceived: errorReceived)

StatusMonitor.shared.getDeviceStatus(handler: statusHandler)
val deviceStatusCallback = object : DeviceStatusCallback() {
    override fun onStatusReceived(paymentDeviceStatus: PaymentDeviceStatus) {
        // Check the status of the payment device
    }

    override fun onError(error: UnhandledError) {
        // Handle unexpected errors
    }
}

StatusMonitorCompat.getDeviceStatus(Dispatchers.getIO(),
                                    deviceStatusCallback)

If you are familar with Kotlin Coroutines, you can use the StatusMonitor class within a CoroutineScope instead of using StatusMonitorCompat with callbacks.