Requesting a payment

Call MPScanToPay.checkout and handle the delegate callbacks — with sample Swift and the full callback reference.

This page documents the core Scan to PayKit checkout flow: calling checkout(...) from a view controller and handling the delegate callbacks. For drop-in 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 view controller gets the code + your Lib Lite API key
   ↓
3. Your view controller calls MPScanToPay().checkout(...)
   ↓
4. SDK presents the payment UI; customer picks a card and pays
   ↓
5. SDK calls your delegate with one of 5 result methods
   ↓
6. Your view controller sends txReference to your backend
   ↓
7. Your backend confirms via webhook or /transactionState before
   shipping goods / releasing service
⚠️

Never trust the SDK's success callback alone. Always re-verify on your backend with a webhook or /transactionState lookup. See Webhooks.


Calling checkout

import ScanToPayKit

@IBAction func checkoutAction(_ sender: Any) {
    let code      = "6799782555"
    let apiKey    = "YOUR_API_KEY"
    let system    = MPSystem.test          // or .live

    let scanToPay = MPScanToPay()
    scanToPay.checkout(withCode: code,
                       apiKey:   apiKey,
                       system:   system,
                       controller: self,
                       delegate:   self)
}

Optionally pre-fill the customer's MSISDN:

scanToPay.checkout(withCode: code,
                   apiKey:   apiKey,
                   system:   system,
                   controller: self,
                   delegate:   self,
                   preMSISDN: "27832006283")

Parameters

NameTypeRequiredDescription
codeStringyesTransaction code from /code. Must be a fixed-amount code.
apiKeyStringyesYour Lib Lite API token from the Portal
systemMPSystemyes.live (prod) or .test (sandbox)
controllerUIViewControlleryesThe presenting view controller
delegateMPScanToPayDelegateyesWhere the SDK will call back
preMSISDNStringoptionalInternational-format MSISDN to pre-fill on registration

Adopting the delegate

import UIKit
import ScanToPayKit

class CheckoutViewController: UIViewController, MPScanToPayDelegate {

    func scanToPayInvalidCode() {
        // IN_CODE was malformed, expired, or already used
        showAlert(title: "Invalid Code",
                  message: "Please retry — the payment code wasn't accepted.")
    }

    func scanToPayError(_ error: MPError) {
        // Something errored before / outside the payment attempt
        handleSdkError(error)
    }

    func scanToPayPaymentSucceeded(withTransactionReference transactionReference: String!) {
        // Customer completed payment. Verify on backend!
        verifyOnBackend(transactionReference)
    }

    func scanToPayPaymentFailed(withTransactionReference transactionReference: String!) {
        // Payment was attempted but failed (bank declined, etc.)
        logFailure(transactionReference)
    }

    func scanToPayUserDidCancel() {
        // Customer backed out
    }

    func scanToPayUserRegistered() {
        // Card registered successfully (typically follows preRegister)
    }

    func scanToPayUserCompletedWallet() {
        // Manage-card flow completed
    }
}

Delegate callbacks

CallbackWhen you'll see itArgument
scanToPayPaymentSucceeded(withTransactionReference:)Customer completed payment. Verify server-side.String — the transaction reference
scanToPayPaymentFailed(withTransactionReference:)Payment was attempted but failedString — the failed transaction reference
scanToPayUserDidCancel()Customer aborted before completing(none)
scanToPayInvalidCode()The code you passed is invalid(none)
scanToPayError(_:)Something errored before / during the payment attemptMPError — see Errors
scanToPayUserRegistered()(after preRegister(...)) Customer registered a card(none)
scanToPayUserCompletedWallet()(after walletManagement(...)) Customer finished managing cards(none)

What you do server-side

When you receive scanToPayPaymentSucceeded(withTransactionReference:):

  1. POST the transactionReference to your backend
  2. Backend confirms the state:
  3. Once confirmed SUCCESS, fulfil the order / release the service

When you receive scanToPayPaymentFailed(...):

  1. Log the reference for support correlation
  2. Show a friendly retry message
  3. Don't auto-retry — let the customer choose

Test card numbers

For sandbox (system: .test), see Sandbox and test cards. The two essentials:

CardUse
50010001000105Success
50010001000101Insufficient funds

What's next