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
VoidVoid.BuilderperformVoid(transactionId)Returns VoidResponse
Last transactionTransactionLookup.BuilderlastTransactionReturns only the most recent transaction where the customer tapped a card - not pre-tap errors or cancels
SearchTransactionLookup.BuildersearchTransaction(params)Filter by amount, time, RRN, and so on - use when lastTransaction is not enough
Prepare nextPrepareNextTransaction.BuilderPre-warm Payment App (optional)

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 a card. Attempts that errored before card presentment are not returned.
  • searchTransaction - use for broader recovery (amount, date range, RRN, and so on) when lastTransaction() does not match your open order.

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.