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.
  • timeoutSeconds sets the timeout for card reads (60s if not supplied, must be in the range of 30-300).
  • autoCloseDurationOnOutcome if supplied, the outcome screen will automatically close after the provided number of seconds (ranged between 5 - 90)
  • merchantPin auto login (if required) without prompting for the PIN.

Sale Result

Sale responses have the following format

Base Information

Field PathTypeDescriptionExample / Notes
outcomeOutcomeOutcome of the transaction
posDataMap<String, String>Additional 3rd party meta data to be associated to this transaction.optional
responseTransactionResponseDtoResponse dataoptional
receiptReceiptReceipt infooptional

Outcome

Field PathTypeDescriptionExample / Notes
statusStatusThe status enum, used for logic
detailDetailThe detail, used for display

Detail

Field PathTypeDescriptionExample / Notes
transactionTypeStringThe type of transaction
totalAmountStringThe total amount formatted in transaction currency
saleAmountStringThe sale amount in transaction currencyoptional
cashbackAmountStringThe cashback amount in transaction currencyoptional
outcomeStringThe outcome display text
codeStringThe response code. See REST API for values
descriptionStringThe response code description

Receipt

Field PathTypeDescriptionExample / Notes
dateTimeFormattedStringdate time of transactionformat = yyyy-MM-dd HH:mm
merchantNameStringname of the merchant this terminal is assigned to
transactionTypeStringType of transactions performed.example values: Sale, Refund
statusStringstatus of the transaction.example values: Approved, Declined, Failed, Reversed
totalAmountStringfull amount. This the same amount plus any additional amount e.g. cashback
saleAmountStringsale amount of transaction formated in currency
cashbackAmountStringcashback amount formatted in the currency of the transactionoptional
declinedDetailStringsuccinct description of decline responseoptional: not present for approvals
midStringThe acquiring institution Merchant Identifier (MID) used for this transaction.optional
tidStringThe acquiring institution Terminal Identifier (TID) used for this transaction.optional
schemeStringscheme of the card presentedoptional
aidStringapplication id of the card presentedoptional
cardHolderNameStringcardholder name if present on the cardoptional
applicationNameStringname of the card application usedoptional
authStringThe code issued by the authorizing institution indicating the approval status.optional
tvrStringterminal verification resultsoptional. format: hex
tsiStringtransaction status informationoptional. format: hex
maskedPanStringPAN for presented card masked for security purposesoptional
entryModeStringmethod in which the card was presentedoptional
rrnStringThe RRN (Retrieval Reference Number) submitted to the acquirer for the transactionoptional
cvmStringcardholder verification method usedoptional. example values: no_cvm_required, online_pin, fail_cvm
cardholderReceiptUrlStringURL where the cardholder receipt can be viewed or downloaded.optional
merchantReceiptUrlStringURL where the merchant receipt can be viewed or downloaded.optional

TransactionResponseDto

Field PathTypeDescriptionExample / Notes
transactionIdUUIDThe ExiPay generated transaction ID.
transactionResultTransactionResultThe overall processing result status. Should the result be approved then a follow up confirmation message is required.
originalTransactionIdUUIDThe ExiPay generated transaction ID for the original transaction that this transaction relates to.optional
referenceIdStringThe 3rd party reference ID. Used to more easily identify transactions by a 3rd party. This value must be unique per transaction per terminal.optional
errorMessageStringShould the processing result be a failure or a decline then the error message will contain a description of the error.optional
cardNotPresentRefundableStatusCardNotPresentRefundableStatusIndicates whether or not a card not present refund is possible for this transaction.optional
merchantReceiptUrlStringURL where the merchant receipt can be viewed or downloaded.optional
cardholderReceiptUrlStringURL where the cardholder receipt can be viewed or downloaded.optional
transactionTypeValueWithDescriptionIntegerDetails of the transaction type used to perform the transaction.optional
responseCodeResponseCodeValueWithDescriptionDetails of the response code for the transaction. See REST API for valuesoptional
cardTransactionDataCardTransactionResponseDataThe card transaction response data.optional
voidableUntilTimeOffsetDateTimeThe UTC time that the transaction will be allowed to be voided in ISO 8601 format.optional
transactionTimeOffsetDateTimeThe UTC time the transaction was received by ExiPay in ISO 8601 format.optional
posDataMap<String, String>Additional 3rd party meta data to be associated to this transaction.optional

TransactionResult

ValueDescription
approved_confirmedTransaction was Approved and confirmation sent
authorized_confirmedPre-authorization was Approved and confirmation sent
declinedDeclined
failedFailed
reversedReversed
voidedVoided

other values are not valid for intentapi scenarios

CardTransactionResponseData

Field PathTypeDescriptionExample / Notes
rrnStringThe RRN (Retrieval Reference Number) submitted to the acquirer for the transaction.optional
stanStringThe STAN (System Trace Number) submitted to the acquirer for the transaction.optional
settlementDateLocalDateThe date indicating when the transaction will be settled. Format yyyy-MM-dd.optional
merchantMerchantResponseDataThe merchant data related to the transaction.optional
amountAmountResponseDataAmounts related to the transaction.optional
cardCardResponseDataDetailed card response data for the transaction.optional
midStringThe acquiring institution Merchant Identifier (MID) used for this transaction.optional
tidStringThe acquiring institution Terminal Identifier (TID) used for this transaction.optional
approvalCodeStringThe code issued by the authorizing institution indicating the approval status.optional
cryptogramStringThe response cryptogram for EMV transactions.optional
issuerTerminalDataStringThe issuer response data to return to the terminal.optional

MerchantResponseData

Field PathTypeDescriptionExample / Notes
nameStringThe merchant name.
cityStringThe merchant city.optional
countryCodeStringThe merchant ISO 3166 alpha2 country code. A complete list of country codes can be found here: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2ISO.optional

AmountResponseData

Field PathTypeDescriptionExample / Notes
amountLongThe transaction's amount represented as cents. The total transaction amount including otherAmount for this transaction.
currencyCodeStringThe default ISO 4217 currency code that was used to process the transaction. A complete list of currency codes can be found here: https://en.wikipedia.org/wiki/ISO_4217.
displayValueStringA user friendly formatted amount using the currency symbol and decimal places related to the transaction currency.
otherAmountDisplayValueStringA user friendly formatted other amount using the currency symbol and decimal places related to the transaction currency.
otherAmountLongThe transaction's other amount's represented as cents.optional

CardResponseData

Field PathTypeDescriptionExample / Notes
maskedPanStringMasked PAN (Primary Account Number) of the card.optional
binNumberStringThe card BIN (Bank Identification Number).optional
schemeStringThe card scheme name.optional
cardholderNameStringThe name of the card holder.optional
expiryYearStringThe card expiry year. Format yy.optional
expiryMonthStringThe card expiry month. Format MM.optional
budgetPeriodIntThe number of months the customer has chosen to repay the issuer for the purchase.optional
accountTypeValueWithDescriptionIntegerDetails of the card holder account type.optional
panEntryModeValueWithDescriptionIntegerThe method used on the terminal to perform the transaction.optional
cvmMethodValueWithDescriptionIntegerThe card verification method used on the terminal to perform the transaction.optional
cvmConditionCodeValueWithDescriptionIntegerThe CVM (Card Verification Mode) condition code.optional
cvmRuleResultValueWithDescriptionIntegerThe CVM (Card Verification Mode) rule result.optional
applicationIdStringThe application ID selected for an EMV transaction.optional
applicationNameStringThe textual representation of the application ID for an EMV transaction.optional
terminalVerificationResultStringThe terminal verification result for performing the transaction.optional
transactionStatusInformationStringThe transaction status information (TSI) extracted from EMV tag 0x9B.optional
productTypeStringThe product type of the card.optional
bankNameStringThe name of the bank which has been allocated this BIN range.optional
countryCodeStringThe ISO 3166 alpha-2 country code related to the bank that own the BIN range.optional
aipStringApplication Interchange Profile. Indicates the capabilities of the card to support specific functions in the applicationoptional
aipSupportsCDCVMBooleanIndicates if the aip supports Consumer Device Cardholder Verification Method. CDCVM is a type of Cardholder Verification supported by the card networks when accepting contactless transactions originating from mobile devicesoptional
tokenizedBooleanIndicates if the card pan is a confirmed tokenized PAN, based of a bin lookup.optional
cardHmacStringUnique Stitch card PAN HMAC.optional
cardFingerprintStringUnique Stitch card PAN fingerprint.optional
tokenStringA card token that can be used to initiate follow-up transactions via Stitch Card. A token is only returned for tokenisation-enabled tenants.optional

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.

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.
  • merchantPin auto login (if required) without prompting for the PIN.
  • supervisorPin a PIN to perform privileged actions. If not supplied the UI will prompt for one.

Void Result

Base Information

Field PathTypeDescriptionExample / Notes
successBooleanWas the transaction voided successfully
posDataMap<String, String>Additional 3rd party meta data to be associated to this transaction.optional
responseReversalResponseDtoResponse dataoptional

ReversalResponseDto

Field PathTypeDescriptionExample / Notes
transactionIdjava.util.UUIDThe ExiPay generated transaction ID.
transactionResultTransactionResultThe overall processing result status. Should the result be approved then a follow up confirmation message is required.
originalTransactionIdjava.util.UUIDThe ExiPay generated transaction ID for the original transaction that this transaction relates to.optional
referenceIdStringThe 3rd party reference ID. Used to more easily identify transactions by a 3rd party. This value must be unique per transaction per terminal.optional
errorMessageStringShould the processing result be a failure or a decline then the error message will contain a description of the error.optional
cardNotPresentRefundableStatusCardNotPresentRefundableStatusIndicates whether or not a card not present refund is possible for this transaction.optional
merchantReceiptUrlStringURL where the merchant receipt can be viewed or downloaded.optional
cardholderReceiptUrlStringURL where the cardholder receipt can be viewed or downloaded.optional
responseCodeStringThe response code for the reversal.optional. See REST API for values
posDataMap<String, String>The meta data from the original transaction will be combined with reversal/void meta data (overwrites if same keys used).optional

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.

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.
  • timeoutSeconds sets the timeout for card reads (60s if not supplied, must be in the range of 30-300).
  • autoCloseDurationOnOutcome if supplied, the outcome screen will automatically close after the provided number of seconds (ranged between 5 - 90)
  • merchantPin auto login (if required) without prompting for the PIN.
  • supervisorPin a PIN to perform privileged actions. If not supplied the UI will prompt for one.

Refund Result

The refund response follows the same form as the SaleResult with the addition of the refundBalanceData field in the RefundResponseDto. This contains the current refundable balance of the original transaction as well as a history of all approved refunds that have been submitted against that transaction.

RefundBalanceResponseData

Field PathTypeDescriptionExample / Notes
amountAmountResponseDataThe original transaction amount.optional
balanceAmountResponseDataBalance remaining to be refunded for the original transaction.optional
refundHistoryList<RefundHistoryData>History of all successful refunds performed against the original transaction.optional

RefundHistoryData

Field PathTypeDescriptionExample / Notes
transactionIdUUIDThe ExiPay generated transaction ID for the refund event.optional
referenceIdStringThe 3rd party reference ID. Used to more easily identify transactions by a 3rd party. This value must be unique per transaction per terminal.optional
amountAmountResponseDataAmounts related to the transaction.optional
transactionTimeOffsetDateTimeThe UTC time the transaction was received by ExiPay in ISO 8601 format.optional

Pre-authorization

override fun onCreate(savedInstanceState: Bundle?) {
...
val preauth = PreAuth.Builder(
this,
object : PreAuthTransactionListener {
override fun onAuthResult(result: SaleResult) {
// handle response
}

override fun onError(error: IntentError) {
// handle errors
}
},
).build()
...
}

fun onButtonClick() {
val externalPosData = mapOf(
"posEg1" to UUID.randomUUID().toString()
)
// the amount is represented in cents, so an amount of 1059 is R10.59
preauth.startTransaction(
amount = amount,
externalPosData = externalPosData,
disableReceiptingOnOutcome = false,
timeoutSeconds = 3L
)
...
}
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.
  • timeoutSeconds sets the timeout for card reads (60s if not supplied, must be in the range of 30-300).
  • autoCloseDurationOnOutcome if supplied, the outcome screen will automatically close after the provided number of seconds (ranged between 5 - 90)
  • merchantPin auto login (if required) without prompting for the PIN.

Card Query

Card query is functionality for the capturing of non-payment cards like loyalty cards. When using this feature a secure whitelist of allowed cards must be agreed and configured with stitch

override fun onCreate(savedInstanceState: Bundle?) {
...
val cardQuery = CardQuery.Builder(
this,
object : CardQueryListener {
override fun onCardQueryResult(result: CardQueryResult) {
// handle result
}

override fun onError(error: IntentError) {
// handle error
}

},
).build()
...
}

fun onButtonClick() {
val externalPosData = mapOf(
"posEg1" to UUID.randomUUID().toString()
)
cardQuery.cardQuery(externalPosData = externalPosData)
...
}
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.
  • merchantPin auto login (if required) without prompting for the PIN.

Card Query Result

Base Information

Field PathTypeDescriptionExample / Notes
statusIntStatus code describing the result of the card query operation0 = success, > 0 = online failure, < 0 = local failures
referenceIdStringReference to operation on serveroptional
errorStringDescription of the specific erroroptional: only present if status != 0
successSuccessSuccess resultoptional: only present if status == 0

CardQueryResult.Success

Field PathTypeDescriptionExample / Notes
track1StringTrack1 data if presentoptional. format: ascii
track2StringTrack2 data from cardoptional. format: ascii
panStringPAN extracted from track 2format: ascii

Get app and terminal Info

The Info command gets important info about the Terminal and the Stitch payment apps.

override fun onCreate(savedInstanceState: Bundle?) {
...
val info = Info.Builder(
this,
object : InfoListener {
override fun onInfoResult(result: InfoResult) {
// handle result
}

override fun onError(error: IntentError) {
// handle error
}
},
).build()
...
}

fun onButtonClick() {
info.get()
}

Info Response

Base Information

Field PathTypeDescriptionExample / Notes
manufacturerStringTerminal manufactureroptional. example: Sunmi, Feitian ...
modelStringTerminal modeloptional
serialNumberStringSerial number of terminal deviceoptional
printerBooleanHas the terminal got printer hardwareoptional
currencyCodeIntThe ISO 4217 currency code used to process transactions. A complete list of currency codes can be found here: https://en.wikipedia.org/wiki/ISO_4217optional
versionVersionStitch payment app versionsoptional
paymentMethodSettingsPaymentMethodSettingsAllowed payment methodsoptional
loginRequiredBooleanDo the apps require login to process commands

InfoResult.Version

Field PathTypeDescriptionExample / Notes
coreStringVersion of the Stitch Core appoptional
payStringVersion of the Stitch Pay appoptional

PaymentMethodSettings

Field PathTypeDescriptionExample / Notes
enableCardBooleanAllow customers to pay using a cardoptional
enableMobileMoneyBooleanAllow customers to pay using MobileMoney (MoMo)optional
enablePbbBooleanAllow customers to pay using Pay by Bank (PBB)optional
enablePbcBooleanAllow customers to pay using Pay by Crypto (PBC)optional

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.

Errors

All listeners can return an IntentError for the cases where errors occur outside of the operation of the command sent. For example if the Pay app isnt installed or if the request parameters are invalid.

Intent Error

Base Information

Field PathTypeDescriptionExample / Notes
codeCodeError case
messageStringDescription of error

Code

ValueDescription
APP_NOT_FOUNDPayment Application not found
INVALID_AMOUNTInvalid amount
INVALID_CASHBACK_AMOUNTInvalid cashback amount
INVALID_REQUESTInvalid request data
USER_CANCELLEDOperation cancelled by user
TIMEOUTTimeout
AUTH_FAILEDAuthentication failed
UNKNOWNUnknown error
INVALID_TIMEOUTTimeout supplied is invalid

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
v1.0.6v1.0.61.0.173.0.7
v1.0.7v1.0.71.0.183.0.8

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>")
}