Learn how to integrate Airtel Money payments into your PHP + MySQL website. This step‑by‑step guide shows API setup, webhook handling, security best practices, database design, and testing so your eCommerce site can accept Airtel Money securely in Uganda and East Africa.
Mobile money is a dominant payment method in Uganda and across Africa. With millions of users actively using Airtel Uganda Airtel Money daily, accepting this payment method on your online store significantly increases customer trust and conversion rates.
This guide explains how to accept Airtel Money online using PHP and MySQL, with sample code, database setup, API integration, webhook handling, and common pitfalls to avoid. By the end, your site will be able to:
✔ Send payment requests to Airtel Money
✔ Handle asynchronous payment confirmations
✔ Update orders based on payment status
✔ Store transaction data securely
✔ Provide users with real‑time payment information
1. Overview — How Airtel Money Online Payments Work
Before we dive into code, here’s the typical flow:
- Customer selects Airtel Money at checkout
- Your site initiates a payment request to Airtel’s API
- Airtel triggers a prompt on the customer’s Airtel Money wallet
- Customer confirms the payment
- Airtel notifies your server via a callback (webhook)
- You update the payment status in your database
This asynchronous callback mechanism ensures security and reliability.
2. Requirements and Setup
a) Requirements
Before integrating Airtel Money, make sure you have:
- PHP 7.4+ (PHP 8.x is recommended)
- MySQL or MariaDB database
- HTTPS enabled (SSL certificate)
- A valid Airtel Money Merchant account
- Airtel Money API credentials (Client ID & Client Secret)
b) Config File (config.php)
Store your sensitive keys securely.
<?php
// Airtel API credentials
define('AIRTEL_CLIENT_ID', getenv('AIRTEL_CLIENT_ID'));
define('AIRTEL_SECRET', getenv('AIRTEL_SECRET'));// Airtel API endpoints
define('AIRTEL_API_SANDBOX', 'https://sandbox.airtel.africa/checkout/v1/paymentrequest');
define('AIRTEL_API_LIVE', 'https://payments.airtel.africa/checkout/v1/paymentrequest');// Choose environment
define('AIRTEL_API_ENDPOINT', AIRTEL_API_SANDBOX);// Your webhook callback
define('AIRTEL_CALLBACK_URL', 'https://yourdomain.com/callbacks/airtel_callback.php');
💡 Store this file outside your public web root and protect it from direct access.
3. Database Design
Create a table to store all payment requests including status updates from callbacks:
CREATE TABLE airtel_payments (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
order_id VARCHAR(150) NOT NULL,
phone_number VARCHAR(20) NOT NULL,
amount DECIMAL(12,2) NOT NULL,
payment_reference VARCHAR(150) DEFAULT NULL,
status ENUM('pending','success','failed','cancelled') DEFAULT 'pending',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
Field Purpose:
order_id: Your internal order tracking codepayment_reference: Airtel Money transaction code (returned via callback)status: Keeps track of payment progressuser_id: Optional — links to your user table
4. Initiating Airtel Money Payments (PHP Request)
When a customer chooses Airtel Money at checkout, your PHP code must:
✔ Validate input
✔ Insert a pending payment
✔ Create a payment request to Airtel API
init_payment.php
<?php
require 'config.php';
require 'db.php'; // MySQL connectionif($_SERVER['REQUEST_METHOD'] === 'POST'){
$userId = intval($_POST['user_id']);
$orderId = mysqli_real_escape_string($conn, $_POST['order_id']);
$phone = mysqli_real_escape_string($conn, $_POST['phone']);
$amount = floatval($_POST['amount']); // Insert pending payment
$stmt = $conn->prepare(
"INSERT INTO airtel_payments(user_id, order_id, phone_number, amount)
VALUES(?,?,?,?)"
);
$stmt->bind_param("issd", $userId, $orderId, $phone, $amount);
$stmt->execute();
$paymentId = $stmt->insert_id;
$stmt->close(); // Build Airtel API payload
$payload = [
"amount" => $amount,
"msisdn" => $phone,
"order_id" => $orderId,
"callback_url" => AIRTEL_CALLBACK_URL,
"client_id" => AIRTEL_CLIENT_ID,
"client_secret"=> AIRTEL_SECRET
]; // Send payment request
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => AIRTEL_API_ENDPOINT,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
]
]); $response = curl_exec($curl);
curl_close($curl); $result = json_decode($response, true); if(isset($result['status']) && strtoupper($result['status']) === 'REQUEST_ACCEPTED'){
echo json_encode([
'success' => true,
'message' => 'Payment request sent. Complete payment from your Airtel Money app.'
]);
} else {
echo json_encode([
'success' => false,
'message' => 'Failed to initiate payment. Try again.',
'response'=> $result
]);
}
}
5. Handling Airtel Money Callbacks (Webhook Listener)
Airtel calls your server when the payment completes or fails. You must securely handle this webhook.
callbacks/airtel_callback.php
<?php
require '../config.php';
require '../db.php';$input = file_get_contents("php://input");
$data = json_decode($input, true);// Log raw webhook for debugging
file_put_contents('../logs/airtel_webhook.log', $input . "\n", FILE_APPEND);$orderId = $data['order_id'] ?? null;
$status = strtoupper($data['status'] ?? '');
$ref = $data['payment_reference'] ?? '';if($orderId){
if($status === 'SUCCESS'){
$newStatus = 'success';
} elseif($status === 'FAILED'){
$newStatus = 'failed';
} else {
$newStatus = 'cancelled';
} $stmt = $conn->prepare(
"UPDATE airtel_payments
SET status=?, payment_reference=?
WHERE order_id=?"
);
$stmt->bind_param("sss", $newStatus, $ref, $orderId);
$stmt->execute();
$stmt->close();
}http_response_code(200);
echo "OK";
Important: Airtel might send multiple webhook calls — your logic should be idempotent (handle duplicates safely).
6. Verifying Payment Status in PHP
You may want to show users their payment status after they submit the payment form:
check_payment.php
<?php
require 'db.php';if(isset($_GET['order_id'])){
$orderId = mysqli_real_escape_string($conn, $_GET['order_id']); $stmt = $conn->prepare(
"SELECT status, payment_reference FROM airtel_payments WHERE order_id=?"
);
$stmt->bind_param("s", $orderId);
$stmt->execute();
$stmt->bind_result($status, $reference);
$stmt->fetch();
$stmt->close(); echo json_encode([
'status' => $status,
'reference' => $reference
]);
}
7. Front‑End Payment Form (PHP + HTML)
Here is an example checkout form using AJAX to submit the Airtel Money request:
<form id="airtelForm">
<input type="hidden" name="user_id" value="1">
<input type="text" name="order_id" placeholder="Order ID" required>
<input type="text" name="phone" placeholder="Airtel Number" required>
<input type="number" name="amount" placeholder="Amount" required>
<button type="submit">Pay with Airtel Money</button>
</form><script>
document.getElementById('airtelForm').addEventListener('submit', function(e){
e.preventDefault();
let formData = new FormData(this); fetch('init_payment.php', {
method:'POST',
body: formData
})
.then(res => res.json())
.then(data => {
alert(data.message);
});
});
</script>
8. Security Best Practices
To keep your payment integration secure:
✔ Use HTTPS
Airtel will only send webhooks to secure HTTPS URLs.
✔ Protect Callback Endpoints
Validate headers or a signature to ensure callbacks come from Airtel (check API docs for signature methods).
✔ Avoid Storing Secrets in Code
Use environment variables in .env or server config.
AIRTEL_CLIENT_ID=your_client_id
AIRTEL_SECRET=your_secret
✔ Log Events for Auditing
Keep logs of API responses and callbacks outside web root.
✔ Validate Inputs
Never trust user input — sanitize all phone numbers and order amounts.
9. Testing Before Go‑Live
Before switching to live environment:
- Use sandbox API URLs
- Test webhook callbacks manually
- Simulate failed payments
- Ensure duplicate callbacks don’t break orders
Conclusion
Accepting Airtel Money payments on your PHP + MySQL website can dramatically boost your eCommerce conversions in Uganda and East Africa.
With this integration, you can:
✔ Initiate Airtel Money payment requests
✔ Receive secure webhook notifications
✔ Update order status in real time
✔ Provide customers with a familiar and trusted payment method
Key Takeaways
- Always use HTTPS for callbacks
- Store API credentials securely
- Log all payment activity
- Handle webhook retries and duplicates
- Test thoroughly in sandbox before going live
💡 Pro Tip: Once live, you can add email or SMS payment confirmations so customers are notified instantly when their payment clears.

















Leave a Reply