Skip to main content

Android Intent SDK

The Stitch Payment App offers merchants the ability to integrate their POS system directly with the Stitch Payment App via an Android Intent SDK.

Stitch Android Intent SDK

Add the Maven Repository and include the dependency:

app/build.gradle.kts
dependencyResolutionManagement {
repositories {
...
maven("https://gitlab.com/api/v4/projects/69499542/packages/maven")
}
}

See required lib versions.

Initiating a Transaction

override fun onCreate(savedInstanceState: Bundle?) {
...
val sale = Sale.Builder(
this,
object : SaleTransactionListener {
override fun onSaleResult(result: SaleResult) {
// handle response, setting a viewModel attribute
}

override fun alertError(error: IntentError) {
// handle error, setting a viewModel attribute
}
},
).build()
...
}

fun onButtonClick() {
val externalPosData = mapOf(
"posEg1" to UUID.randomUUID().toString(),
"posEg2" to Random().nextInt().toString(),
"posEg3" to true.toString(),
)
// the amount is represented in cents, so an amount of 1059 is R10.59
if (cashback) {
sale.startTransactionWithCashback(amount, cashAmount, externalPosData)
} else {
sale.startTransaction(amount, externalPosData)
}
...
}
Context and Listener

The actions have a Builder that require at least the following parameters: context & listener. The context is what Android needs to start the Intent and can be the current Activity, the listener is a callback interface where the library will provide the result or error. The builder should be be created in the onCreate() before, content is rendered, and on a button tap the transaction can be initiated.

Optional parameters
  • externalPosData a map representing key value pairs that'll be echoed in the result and be sent on the webhooks (payment app may add additional keys). Can be used for adding identifiers aiding in matching, like a DB row id or an order number, etc.
  • disableReceiptingOnOutcome disables receipt printing and QR code on the outcome screen.

Voiding a Transaction

override fun onCreate(savedInstanceState: Bundle?) {
...
val voider = VoidTransaction.Builder(
this,
object : VoidTransactionListener {
override fun onVoidResult(result: VoidResult) {
// handle response, setting a viewModel attribute
}

override fun alertError(error: IntentError) {
// handle error, setting a viewModel attribute
}
},
).build()
...
if (TransactionUtil.isVoidable(response)) {
// enable void button
}
...
}

fun onButtonClick() {
voider.voidTransaction(transactionId)
...
}
note

It is the responsibility of the calling app to verify that the user is authorised to perform void actions.

Refunding a Transaction

Type of Refund

Refunds initiated via the Android Intent SDK are processed as a card-present refund. This means the customer must present their physical card at the terminal in-store to complete the refund.

override fun onCreate(savedInstanceState: Bundle?) {
...
val refund = Refund.Builder(
this,
object : RefundTransactionListener {
override fun onRefundResult(result: RefundResult) {
// handle response, setting a viewModel attribute
}

override fun alertError(error: IntentError) {
// handle error, setting a viewModel attribute
}
},
).build()
...
if (TransactionUtil.isRefundable(response)) {
// enable void button
}
...
}

fun onButtonClick() {
// the amount is represented in cents, so an amount of 1059 is R10.59
refund.startRefund(amount, transactionId)
...
}
note

It is the responsibility of the calling app to verify that the user is authorised to perform refund actions.

Bypass PIN entry on the Stitch Payment App

The Stitch Payment App normally requires a PIN to authenticate the user and terminal before a transaction can be initiated. This PIN is also required for void and refund transactions.

However, the Merchant POS App can bypass the manual PIN entry by logging the user in automatically in the background. This approach is recommended when the Merchant POS App has already implemented the necessary permission checks, ensuring security without requiring additional user input on the Stitch Payment App.

override fun onCreate(savedInstanceState: Bundle?) {
...
val login = Login.Builder(
this,
object : LoginListener {
override fun onLoginResult(result: Boolean) {
// handle login success, setting a viewModel attribute
}

override fun alertError(error: IntentError) {
// handle error, setting a viewModel attribute
}
},
).build()
...
}

fun onButtonClick() {
login.login(merchantPin)
...
}
note
merchantPin
  • merchantPin auto login without prompting for the PIN.

Lib Version Mapping

Pay VersionCore Versiondto Versionintent-lib Version
v1.0.0v1.0.01.0.33.0.2
v1.0.1v1.0.11.0.53.0.2
v1.0.2v1.0.21.0.83.0.3

Gradle base config (same for all versions):

app/build.gradle.kts
android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
}

dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
implementation("com.exipay.terminal.modules:dto:<version>")
implementation("com.exipay.terminal.modules:intent-lib:<version>")
}