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 /transactionState lookup. 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

ExtraTypeRequiredDescription
IN_CODEStringyesTransaction code from /code. Must be a fixed-amount code.
IN_API_KEYStringyesYour Lib Lite API token from the Portal (Lib Lite Tokens menu).
IN_SYSTEMStringyesLIVE (prod) or TEST (sandbox). The SDK routes accordingly.
IN_HASHStringrecommended11-char SMS hash from Google's SMS Retriever guide. Enables auto-OTP-fill during card registration.
IN_SUGGESTED_MSISDNStringoptionalInternational-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 codeMeaningExtras
LIBLITE_PAYMENT_SUCCESSCustomer completed payment (verify server-side)OUT_TX_REFERENCE, OUT_TX_TRACE_ID
LIBLITE_PAYMENT_FAILEDPayment was attempted but failed (e.g. bank declined)OUT_TX_REFERENCE
LIBLITE_USER_CANCELLEDCustomer backed out before completingOUT_LOCATION — drop-off step indicator
LIBLITE_ERRORSomething errored before the payment attemptOUT_ERROR_CODE, OUT_LOCATION
LIBLITE_INVALID_CODEIN_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:

  1. POST the txReference to your backend (don't fulfil the order on the device alone)
  2. Your backend confirms the state:
  3. Once confirmed SUCCESS, fulfil the order / release the service

When you receive LIBLITE_PAYMENT_FAILED:

  1. Log txReference for support correlation
  2. Show the customer a friendly message ("Payment didn't go through — please try again")
  3. 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:

CardUse
50010001000105Success
50010001000101Insufficient funds (END_INSUFFICIENT_FUNDS_OR_OVER_CREDIT_LIMIT)

What's next