App to App integration guide

Prev Next

Setup SDK

ClientFactory used to create Client interface instance with specified parameter.


import android.view.Display 

ClientFactory.bindConfiguration( 

 SDKConfiguration.defaultConfiguration( 

 clientApplicationInfo = PackageInfo( 

 applicationName = applicationInfo.name,  applicationPackage = packageName 

 ) 

 ) 

).bindContext( 

 context = applicationContext 

).bindProtocolConfiguration( 

 RetailerConfiguration(saleID = "Communicator_SALE") ).bindInterceptor( 

 interceptor = { message: DomainMessage > 

 when (message) { 

 / Check message type 

 is SuccessRetailerLoginResponse, 

 is ErrorRetailerLoginResponse, 

 is SuccessRetailerLogoutResponse > { 

 /Handle message 

 } 

 } 

 } 

).bindEventObserver { event: ObservableEvent >

 when (event) { 

 is ObservableEvent.ServerEvent > Logger.d("New server event")  is ObservableEvent.TransactionStateChanged > 

 when (event.state) { 

 is IdleTransactionState > 

bringToForeground(MainActivity :class) 

 else > { 

 / Ignore 

 } 

 } 

 } 

}.build() 

SDKConfiguration stands here forinterprocess communication parameters.

Destination's Application parameters should be specified here. Application's Name and package. 


bindConfiguration( 
 SDKConfiguration.defaultConfiguration( 
 clientApplicationInfo = PackageInfo( 
 applicationName = applicationInfo.name, 
 applicationPackage = packageName 
 ) 
 ) 
) 

ProtocolConfiguration stands for specific protocol parameters.

Our case is Nexo Retailer Protocol v3. Your application's parameters as ECR might be specified here.

bindProtocolConfiguration( 
 RetailerConfiguration(saleID = "Communicator_SALE") 
) 

Interceptor class which will handle all of the responses from Payment Application.

Incoming parameter has generic type DomainMessage all of the messages in app2app communication are subtypes of this class. to specify handling strategy for each response typecheck is recommended. In this example, reaction on SuccessRetailerLoginResponse, ErrorRetailerLoginResponse, SuccessRetailerLogoutResponse is illustrated.

Each operation as Payment/Reversal/Refund etc has it's own message type. It could be found manually through documentation package retailer-protocol.

bindInterceptor( 
 interceptor = { message: DomainMessage > 
 when (message) { 
 / Check message type 
 is SuccessRetailerLoginResponse, 
 is ErrorRetailerLoginResponse,
 is SuccessRetailerLogoutResponse > { 
 /Handle message 
 } 
 } 

Map of requests and responses for main operations

Login

  • Request: RetailerLoginRequest

  • Response: RetailerLoginResponse

  • Response Subtypes:

    • SuccessRetailerLoginResponse

    • FailedRetailerLoginResponse

Payment

  • Request: RetailerPaymentRequest

  • Response:

    • RetailerPaymentResponse

    • RetailerDisplayRequest

  • Response Subtypes:

    • SuccessRetailerPaymentResponse

    • ErrorRetailerPaymentResponse

Payment request is used for Refunds, Pre-Authorisations and Pre-Authorisation Completions as well. There

is no separate subtypes for those operations. DisplayRequest will notify during processing which operation

is being executed.


Abort

  • Request: RetailerAbortRequest

  • Response: RetailerAbortResponse

  • Response Subtypes: ErrorRetailerPaymentResponse

If AbortRequest was sent after payment request started execution, it will be ignored.

Reversal

  • Request: RetailerReversalRequest

  • Response: RetailerReversalResponse

  • Response Subtypes:

    • SuccessRetailerReversalResponse

    • ErrorRetailerReversalResponse

Transaction Status

  • Request: TransactionStatus

  • Response:

    • RetailerTransactionStatusResponse

    • RetailerDisplayRequest

  • Response Subtypes:

    • SuccessRetailerTransactionStatusResponse

    • ErrorRetailerTransactionStatusResponse

EventObserver class

EventObserver class which will handle all of PaymentApplication states changes and events.

Observer receives ObservableEvent instances. There are two subtypes of it:

  1. ObservableEvent.ServerEvent - stands for some events happend in Payment Application

  2. TransactionStateChanged - stands for state changes. For example, when Payment Application starts PaymentProcessing, EventObserver will receive PaymentTransactionState instance. When PaymentProcessing considered finished by Payment Application, EventObserver will receive IdleTransactionState instance. Transitions between states might be recognized through saving previously notified state's instances.

bindEventObserver { event: ObservableEvent
when (event) {
is ObservableEvent.ServerEvent Logger.d("New server event"
is ObservableEvent.TransactionStateChanged
when (event.state) {
is IdleTransactionState
bringToForeground(MainActivity :class
else
Ignor
}
}
}
}

BringToForeground

bringToForeground(MainActivity :class) - is function, responsible for "dragging" to foreground your application after state changes in Payment Application. MainActivity:class is placeholder for your currently running application's activity. If your application is Single-Activity you can don't worry about activity transitions so just provide your Main Activity class as in example.

  • PaymentTransactionSate -> If active/present: switch back to your application during payment authorization.

  • IdleTransactionState -> If active/present: swith back to your application at the end of payment.

For example: You'd like show advertisement in your application or custom transaction details during payment processing instead of Payment Application's spinner. All you have to do to achive it - specify path for PaymentTransactionState like here:

bindEventObserver { event: ObservableEvent
when (event) {
is ObservableEvent.ServerEvent Logger.d("New server event"
is ObservableEvent.TransactionStateChanged
when (event.state) {
is PaymentTransactionState
bringToForeground(MainActivity :class
else
Ignor
}
}
}
}

now, when Payment Processing started in Payment Application your will be brought to foreground. If you also would like to transit to foreground your application after Payment Applications finish transaction, add corresponding path for IdleTransactionState:

bindEventObserver { event: ObservableEvent
when (event) {
is ObservableEvent.ServerEvent Logger.d("New server event"
is ObservableEvent.TransactionStateChanged
when (event.state) {
is IdleTransactionState
bringToForeground(MainActivity :class
is PaymentTransactionState
bringToForeground(MainActivity :class
else
Ignor
}
}
}
}

SDK Usage

Once you've done with SetUp, you can use instance returned by ClientFactory::build function to initiate

communication with Payment Application.

Client interface

It used to send requests and response for those requests will be delivered to previously registered in 1.3

Interceptor.

interface Client {
/**
* Send Login request
suspend fun sendLoginRequest()
/**
* Send Payment request
*
* @param transactionID - identifies transaction, should be unique for each one
* @param saleReferenceId - identification of a Sale global transaction for a s
* @param paymentAmounts - transaction amounts information
suspend fun sendPaymentRequest(
saleReferenceId: String,
transactionID: String,
paymentAmounts: PaymentAmounts,
paymentType: PaymentType
)
/**
* Send Logout request
suspend fun sendLogoutRequest()
/**
* Get last completed in Payment Application transaction status
suspend fun sendTransactionStatusRequest(messageReference:
MessageReference)
/**
* Used for terminal Update/Activation depending on [RetailerAdminExtension.act
suspend fun sendAdminRequest(adminExtension: RetailerAdminExtension)
/**
* Send test connection request
suspend fun sendTestConnectionRequest(
diagnosisRequestArguments:
RetailerMessageArguments.DiagnosisRequestMessageArguments
)
/**
* Reversal request stands for transaction cancellation
* @param poiTransactionId - identifies transaction, should be unique for each
* @param saleReferenceId - identification of a Sale global transaction for a s
* @param transactionData - look at [RetailerMessageArguments.ReversalRequestMe
suspend fun sendReversalRequest(
saleReferenceId: String,
poiTransactionId: String,
transactionData:
RetailerMessageArguments.ReversalRequestMessageArguments.TransactionAmountsData
)
}

Nexo Retailer protocol specificities

Every communication session should start with RetailerLoginRequest - Client::sendLoginRequest. If session was interrupted due to:

  • Payment Application update

  • Payment Application restar

  • Client's (your) application restar

  • Connection between applications was lost

  • RetailerLogoutRequest was sent

New Login procedure should be triggered to instantiate the session. Otherwise requests from your application will be considered unauthorised and will be ignored by Payment Application.