Requesting a payment
Invoke the LibLiteActivity, pass a code, and handle the payment result — with sample code and a full result-code reference.
This page documents the core Lib Lite flow: invoking the payment activity from your code and handling the result. For Drop-in button alternatives, see Pay-by-Card button. For installation, see Installation.
The payment flow
1. Your backend creates a code via /code (fixed amount)
↓
2. Your activity gets the code + your Lib Lite API key
↓
3. Your activity launches LibLiteActivity via Intent
↓
4. SDK presents the payment UI; customer picks a card and pays
↓
5. SDK returns via ActivityResultLauncher with one of 5 result codes
↓
6. Your activity sends the txReference to your backend
↓
7. Your backend confirms via webhook or /transactionState before
shipping goods / releasing service
Never trust the SDK's success result alone. Always re-verify on your backend with a webhook or/transactionStatelookup. See Webhooks.
Invoking the payment
The complete launch:
Intent intent = new Intent(context, LibLiteActivity.class);
intent.putExtra(LibLiteActivity.IN_CODE, "1234567890");
intent.putExtra(LibLiteActivity.IN_API_KEY, "YOUR_API_KEY");
intent.putExtra(LibLiteActivity.IN_HASH, "YOUR_SMS_HASH");
intent.putExtra(LibLiteActivity.IN_SYSTEM, "LIVE"); // or "TEST"
// Optional:
intent.putExtra(LibLiteActivity.IN_SUGGESTED_MSISDN, "27832006283");
libLiteActivityLauncher.launch(intent);Extras passed in
| Extra | Type | Required | Description |
|---|---|---|---|
IN_CODE | String | yes | Transaction code from /code. Must be a fixed-amount code. |
IN_API_KEY | String | yes | Your Lib Lite API token from the Portal (Lib Lite Tokens menu). |
IN_SYSTEM | String | yes | LIVE (prod) or TEST (sandbox). The SDK routes accordingly. |
IN_HASH | String | recommended | 11-char SMS hash from Google's SMS Retriever guide. Enables auto-OTP-fill during card registration. |
IN_SUGGESTED_MSISDN | String | optional | International-format MSISDN to pre-fill on the registration screen. Saves the customer typing it. |
Registering the ActivityResultLauncher
Register a launcher in onCreate:
private final ActivityResultLauncher<Intent> libLiteActivityLauncher =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
int resultCode = result.getResultCode();
Intent data = result.getData();
if (data == null) return;
handleLibLiteResult(resultCode, data);
}
);Handling the result
The launcher's result code is one of five LibLiteActivity constants:
private void handleLibLiteResult(int resultCode, Intent data) {
if (resultCode == LibLiteActivity.LIBLITE_PAYMENT_SUCCESS) {
String txReference = data.getStringExtra(LibLiteActivity.OUT_TX_REFERENCE);
String traceId = data.getStringExtra(LibLiteActivity.OUT_TX_TRACE_ID);
// Send txReference to your backend to verify
verifyOnBackend(txReference);
} else if (resultCode == LibLiteActivity.LIBLITE_PAYMENT_FAILED) {
String txReference = data.getStringExtra(LibLiteActivity.OUT_TX_REFERENCE);
// Failure — log txReference for support; show the customer a retry option
handleFailure(txReference);
} else if (resultCode == LibLiteActivity.LIBLITE_USER_CANCELLED) {
int location = data.getIntExtra(LibLiteActivity.OUT_LOCATION, -1);
// Customer aborted. location tells you where in the flow.
handleCancel(location);
} else if (resultCode == LibLiteActivity.LIBLITE_ERROR) {
int errorCode = data.getIntExtra(LibLiteActivity.OUT_ERROR_CODE, -1);
int location = data.getIntExtra(LibLiteActivity.OUT_LOCATION, -1);
// See errors page for what each errorCode means
handleError(errorCode, location);
} else if (resultCode == LibLiteActivity.LIBLITE_INVALID_CODE) {
// The code you passed is invalid (expired, used, malformed, etc.)
handleInvalidCode();
}
}Result codes
| Result code | Meaning | Extras |
|---|---|---|
LIBLITE_PAYMENT_SUCCESS | Customer completed payment (verify server-side) | OUT_TX_REFERENCE, OUT_TX_TRACE_ID |
LIBLITE_PAYMENT_FAILED | Payment was attempted but failed (e.g. bank declined) | OUT_TX_REFERENCE |
LIBLITE_USER_CANCELLED | Customer backed out before completing | OUT_LOCATION — drop-off step indicator |
LIBLITE_ERROR | Something errored before the payment attempt | OUT_ERROR_CODE, OUT_LOCATION |
LIBLITE_INVALID_CODE | IN_CODE was malformed, expired, or already used | (none) |
For the full error code list, see Errors.
What you do server-side
When you receive LIBLITE_PAYMENT_SUCCESS:
- POST the
txReferenceto your backend (don't fulfil the order on the device alone) - Your backend confirms the state:
- Wait for the webhook (recommended) — see Webhooks
- Or poll
/transactionState/{transactionId}— see Querying transactions
- Once confirmed
SUCCESS, fulfil the order / release the service
When you receive LIBLITE_PAYMENT_FAILED:
- Log
txReferencefor support correlation - Show the customer a friendly message ("Payment didn't go through — please try again")
- Don't auto-retry — let the customer initiate
Test card numbers
For sandbox (IN_SYSTEM = "TEST"), see Sandbox and test cards for the test card matrix. The two essentials:
| Card | Use |
|---|---|
50010001000105 | Success |
50010001000101 | Insufficient funds (END_INSUFFICIENT_FUNDS_OR_OVER_CREDIT_LIMIT) |
What's next
- Use a drop-in button instead → Pay-by-Card button
- Hand off to a bank app → Pay-by-App button
- Standalone card management → Manage Card
- Pre-register a card for faster first checkout → Pre-registration
- Full error reference → Errors
- Verify on your backend → Webhooks / Querying transactions
Updated 2 days ago
