Payonclick Developer Docs
v1

Android SDK Integration

Add the Payonclick Micro ATM SDK to your Android app, launch it with the values from POST /ext/v1/matm/transactions and report what it returns.


The card and the PIN never touch your server or ours: the Payonclick Micro ATM SDK pairs with the Bluetooth card reader, reads the card, takes the PIN on the reader and talks to the bank network itself. Your app does three things around it — ask your server to start the transaction, open the SDK with the values it returns, and send the SDK’s result back.

1
Your server
POST /ext/v1/matm/transactions (signed with your API key — never call the API from the phone). Pass data.sdk and data.reference_id to your app.
2
Your app
PayonclickMatm.createIntent(context, sdk, deviceId) and launch it.
3
The outlet
The customer inserts, swipes or taps the card on the reader and enters the PIN.
4
Your app → your server
PayonclickMatm.parseResult(...), then send result.toReportJson() to POST /ext/v1/matm/transaction/{reference_id}/result.
5
Your server
Wait for matm.success / matm.failed or poll GET /transaction/{reference_id} for the final answer.

1. Add the SDK

You receive two files: payonclick-microatm-sdk-v1.0.0.aar (the SDK) and payonclick-card-reader-v1.0.0.jar (the card-reader driver). Copy both into app/libs. The SDK needs Android 7.0 (API 24) or newer.

app/build.gradle
repositories { flatDir { dirs 'libs' } }

dependencies {
    implementation(name: 'payonclick-microatm-sdk-v1.0.0', ext: 'aar')
    implementation(name: 'payonclick-card-reader-v1.0.0', ext: 'jar')
    // libraries the SDK uses
    implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
    implementation 'com.google.code.gson:gson:2.10.1'
    implementation 'com.github.f0ris.sweetalert:library:1.6.2'
    implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.29'
}
✅
R8 / ProGuard rules are built in

The SDK carries its own consumer rules, so a minified release build needs nothing in your proguard-rules.pro. The SDK’s screens show Payonclick Micro ATM.

Declare BLUETOOTH, BLUETOOTH_ADMIN, BLUETOOTH_SCAN, BLUETOOTH_CONNECT, ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION in the manifest, and request the runtime ones before you open the SDK.

2. Open it

Kotlin
import com.payonclick.matm.PayonclickMatm
import com.payonclick.matm.PayonclickMatmResult

private val microAtm = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { r -> onMicroAtmResult(PayonclickMatm.parseResult(r.resultCode, r.data)) }

// sdk = data.sdk from POST /ext/v1/matm/transactions (via your server)
fun startMicroAtm(sdk: JSONObject, deviceId: String) {
    referenceId = sdk.getString("TXN_ID")          // keep it: needed for the report
    microAtm.launch(PayonclickMatm.createIntent(this, sdk, deviceId))
}
Java
Intent intent = PayonclickMatm.createIntent(this, sdkJson, deviceId);
// optional: a reader other than the one sent to /transactions
PayonclickMatm.withDevice(intent, PayonclickMatm.DEVICE_PAX);
launcher.launch(intent);
ConstantValueMeaning
DEVICE_MOREFUN / DEVICE_PAX / DEVICE_NEWLAND2 / 1 / 3Card reader model (device on /transactions sets it for you).
TYPE_CASH_WITHDRAWAL / _BALANCE_ENQUIRY / _MINI_STATEMENT2 / 4 / 7Already in sdk.TYPE; never change it.
sdk.TXN_IDstringYour reference_id. It ties the bank network’s confirmation to the transaction: createIntent passes it through untouched.

3. Report the result

Kotlin
fun onMicroAtmResult(result: PayonclickMatmResult) {
    when {
        result.isSuccess -> showPayCash(result.amount)       // hand over the cash
        result.isPending -> showPending()                    // do NOT retry for this customer
        else -> showDeclined(result.message)
    }
    // Always report (also CANCELLED / NO_RESPONSE). Your server signs and calls
    // POST /ext/v1/matm/transaction/{reference_id}/result with this body.
    myBackend.reportMicroAtm(referenceId, result.toReportJson())
}
result.outcomeWhat to do at the outlet
SUCCESSPay out the cash (CW) or show the balance / statement. Your wallet is credited when the bank network confirms it (matm.success).
FAILEDNo cash. result.message says why (wrong PIN, insufficient funds…).
PENDINGThe bank has not decided. Tell the customer it is pending; do not start another withdrawal for them.
CANCELLED / NO_RESPONSENo verdict on the phone. Treat as pending — the bank may still complete it.

result.miniStatement holds the mini statement rows (date, txnType, amount, narration); toReportJson() already includes them.

📘
Survive process death

Android can kill your app while the customer enters the PIN. Keep the reference_id in onSaveInstanceState (or on disk) before you open the SDK, and queue the result report until your server confirms it, so a result is never lost.