App-to-app integration

Connect your Android POS app on the same device as the Peach Payments Payment App using the Intent API library (com.peach:intent_api).

For payment flows (sale, refund, void, recovery), see Terminal integration flows.

Integration modes

ModeWhenHow
Native AndroidKotlin or Java POS appUse builders in com.peach.intentApi.builder
Web POS in WebViewReact or other web UI in your Kotlin shellBridge WebView → Kotlin → Intent API; or use window.FinimoPay in Peach Payments web-wrapper pattern

Amounts are always Long in minor currency units (cents). Sale amount must be > 0.

Installation

Maven repository

Add the Peach Payments GitLab package registry to your project settings.gradle - no access token required:

repositories {
    maven {
        url 'https://gitlab.com/api/v4/projects/61399867/packages/maven'
    }
}

Dependency

dependencies {
    implementation 'com.peach:intent_api:2.0.8'
}

Pin the version Peach Payments confirms for your integration. Refund and void require 2.0.6+.

Architecture

Your POS app
    │
    ├─ Sale / Refund / Void / TransactionLookup builders
    │
    ├─ [binder available] ──► AIDL to Payment App
    │
    └─ [no binder] ──► CommunicationActivity ──► Payment App
            │
            ▼
    ResultObject JSON ──► your listener callback (UI thread)

The Payment App package follows com.finimo.paymentapp (variant suffixes per build).

Kotlin quick start

Sale.Builder(context)
    .amount(1000L)  // R 10.00
    .disableReceiptingOnOutcome(true)
    .setExternalPosData(mapOf("merchantTransactionId" to orderId))
    .setListener(object : SaleTransactionListener {
        override fun alertSaleTransactionResponse(response: PosTransactionSummary) {
            val success = response.isApproved &&
                (response.transactionType == PosTransactionType.SALE ||
                 response.transactionType == PosTransactionType.SALE_WITH_CASHBACK)
        }
        override fun alertError(error: IntentError) { /* see Intent error codes */ }
    })
    .startTransaction()

Implement SaleTransactionListener, RefundTransactionListener, VoidTransactionListener, or TransactionLookupListener depending on the operation.

Java quick start

new Sale.Builder(context)
    .amount(1000L)
    .setExternalPosData(Collections.singletonMap("merchantTransactionId", orderId))
    .setListener(new SaleTransactionListener() {
        @Override
        public void alertSaleTransactionResponse(PosTransactionSummary response) { }
        @Override
        public void alertError(IntentError error) { }
    })
    .startTransaction();

Web POS (Kotlin shell + WebView)

Supported pattern for React or other web clients:

  1. Your Kotlin app hosts a WebView with your POS URL.
  2. Expose a @JavascriptInterface (or replicate the web-wrapper PaymentInterface or FinimoPay bridge).
  3. On payment request from JavaScript, call Intent API builders from Kotlin - do not call the Payment App directly from JavaScript.

In Peach Payments' web-wrapper sample, the bridge object is window.FinimoPay. Older samples may reference PaymentInterface.

JavaScript methodMaps to
FinimoPay.sale(amount, posData)Sale builder
FinimoPay.refund(amount, transactionId)Refund builder
FinimoPay.void(transactionId)Void builder
FinimoPay.lastTransaction()Transaction lookup

Your page implements callbacks (for example, onSaleComplete, onError) registered by the bridge.

Operations

OperationBuilder entryNotes
SaleSale.Builderamount, startTransactionOptional disableReceiptingOnOutcome, redirectText
Sale with cashbackSaleWithCashback.Builderamount + cashbackAmount
RefundRefund.BuilderrefundTransaction(amount, transactionId)transactionId = original sale UUID; use the same terminal as the sale
VoidVoid.BuilderperformVoid(transactionId)Known issue - use a refund instead
Last transactionTransactionLookup.BuilderlastTransactionMost recent transaction where the customer tapped, inserted, or swiped a card
SearchTransactionLookup.BuildersearchTransaction(params)Filter by amount, time, RRN, and so on - use when lastTransaction is not enough
Prepare nextPrepareNextTransaction.BuilderPre-warm Payment App (optional)

Refund and void availability

The original sale and refund must be processed on the same terminal. The Payment App asks for a supervisor PIN and a refund reason. Multiple partial refunds are supported for up to 180 days, provided that their total does not exceed the original sale amount.

Limit access to the supervisor PIN to reduce refund fraud risk.

🚧

Intent-triggered voids have a known issue. Use a refund instead until Peach Payments resolves it.

Builder options (common)

MethodPurpose
setExternalPosData(map)Pass merchantTransactionId and custom fields
disableReceiptingOnOutcome(true)Auto-return to POS after ~10s on outcome screen
redirectText(text)Custom label on outcome close button
setListener(...)Register operation-specific callback

Lookup flags on results

FieldUse
isRefundableShow refund action in POS
isVoidableShow void action in POS

lastTransaction() vs searchTransaction

  • lastTransaction() - returns only the most recent transaction where the customer tapped, inserted, or swiped a card. Attempts where no card details were provided are not returned.
  • searchTransaction - use for broader recovery by amount, date range, RRN, and other supported filters. You cannot search by posData.merchantTransactionId.

If lookup returns an error or no matching successful result, always treat the payment as unsuccessful in your POS - do not mark the order paid.

Callbacks and response models

Listener methodWhen
alertSaleTransactionResponseSale completed
alertRefundTransactionResponseRefund completed
alertVoidResponseVoid completed (VoidResponse)
alertTransactionLookupResponseLookup completed
alertErrorError before or during handoff

PosTransactionSummary (sale/refund) includes transactionId, transactionType, isApproved, transactionResult, posData, rrn, amount.

See Intent API data models for full field tables.

Error codes

See Intent error codes for all IntentErrorCode values and descriptions.

Next steps

  1. Terminal integration flows: end-to-end sale, refund, void, and recovery flows.
  2. Test your integration: Mock Payments App and UAT terminal testing.
  3. Request a UAT account and install the UAT Payment App before terminal testing.

Did this page help you?