How to Integrate MPesa in HTML

MPesa is Kenya’s leading mobile money service. Integrating it into HTML websites boosts payments. This guide explains the process step-by-step. You’ll learn Daraja API basics for beginners.

Why Integrate MPesa?

MPesa handles C2B payments easily. Customers pay via phone prompts. Websites gain trust with local options. E-commerce sites see higher conversions. It’s secure and fast for Kenyan users.

Key benefits include:

  • Instant STK Push notifications.

  • No extra apps needed.

  • Supports small businesses.

  • Tracks transactions live.

Prerequisites

Start with basics. You need a Safaricom developer account. Use Daraja API sandbox for tests. HTML alone can’t call APIs. Pair it with PHP, Node.js, or Python backend.

Gather these:

  • Consumer Key and Secret.

  • Paybill or Till Number.

  • HTTPS server (required).

  • Text editor like VS Code.

  • Local server like XAMPP.

Step 1: Register on Daraja Portal

Visit developer.safaricom.co.ke. Sign up free. Log in to Daraja dashboard. Create a new app. Select C2B or LIPA NA MPESA.

Fill details:

Field Description
App Name Your website name 
Company Business name 
Products C2B, STK Push, etc. 
Callback URL Your confirmation endpoint 

Save keys. Note them securely. Test in sandbox first.

Step 2: Get OAuth Access Token

Tokens authenticate requests. They expire hourly. Use PHP or JS to fetch.

Sample PHP code:

php
<?php
$consumerKey = 'your_key';
$consumerSecret = 'your_secret';
$credentials = base64_encode($consumerKey . ':' . $consumerSecret);

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials");
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Authorization: Basic ' . $credentials));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($curl);
curl_close($curl);

$token = json_decode($response)->access_token;
echo $token;
?>

Copy this to get_token.php. Run it. Save token for STK Push.

Step 3: Create HTML Payment Form

Build a simple form. Collect phone and amount. Submit to backend.

xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pay with MPesa</title>
<style>
body { font-family: Arial; max-width: 500px; margin: 50px auto; }
input { width: 100%; padding: 10px; margin: 10px 0; }
button { background: #00A651; color: white; padding: 15px; border: none; width: 100%; }
</style>
</head>
<body>
<h1>Buy Now - KSh 500</h1>
<form action="stk_push.php" method="POST">
<label>Phone Number:</label>
<input type="tel" name="phone" placeholder="2547XXXXXXXX" required pattern="254[17][0-9]{8}">
<label>Amount:</label>
<input type="number" name="amount" value="500" min="1" required>
<button type="submit">Pay with MPesa</button>
</form>
</body>
</html>

This form is mobile-friendly. Validates Kenyan numbers.

Step 4: Implement STK Push Backend

Create stk_push.php. Use token from Step 2. Send to MPesa API.

php
<?php
include 'get_token.php'; // Include token logic

$phone = $_POST['phone'];
$amount = $_POST['amount'];
$account = 'your_paybill'; // e.g., 600000
$transaction = 'TXN' . time();
$passkey = 'your_lipa_na_mpesa_passkey';
$shortcode = '174379'; // Sandbox shortcode

$timestamp = date('YmdHis');
$password = base64_encode($shortcode . $passkey . $timestamp);

$data = [
'BusinessShortCode' => $shortcode,
'Password' => $password,
'Timestamp' => $timestamp,
'TransactionType' => 'CustomerPayBillOnline',
'Amount' => $amount,
'PartyA' => $phone,
'PartyB' => $account,
'PhoneNumber' => $phone,
'CallBackURL' => 'https://yourdomain.com/callback.php',
'AccountReference' => 'YourWebsite',
'TransactionDesc' => 'Payment for order'
];

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest');
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $token
]);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($curl);
curl_close($curl);

echo json_encode(json_decode($result, true));
?>

MPesa sends STK prompt to phone. Check CheckoutRequestID.

Step 5: Handle Callbacks

Callbacks confirm payments. Create callback.php. Log results.

php
<?php
$callback = file_get_contents('php://input');
file_put_contents('callbacks.txt', $callback . "\n", FILE_APPEND);

$data = json_decode($callback, true);
$resultCode = $data['Body']['stkCallback']['ResultCode'];

if ($resultCode == 0) {
$mpesaReceipt = $data['Body']['stkCallback']['CallbackMetadata'][0]['Value'];
// Update order status in DB
echo "Payment successful: " . $mpesaReceipt;
} else {
echo "Payment failed";
}
?>

Store in database for orders. Use MySQL for production.

Step 6: Check Transaction Status

Verify payments anytime. Create check_status.php.

php
<?php
$checkoutId = $_POST['checkout_id']; // From STK response
$data = [
'BusinessShortCode' => $shortcode,
'Password' => $password,
'Timestamp' => $timestamp,
'CheckoutRequestID' => $checkoutId
];

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://sandbox.safaricom.co.ke/mpesa/stkpushquery/v1/query');
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $token
]);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($curl);
echo $result;
?>

Poll every 30 seconds if needed.

Security Best Practices

Protect your integration:

  • Never expose keys in HTML/JS.

  • Use HTTPS everywhere.

  • Validate inputs server-side.

  • Rate-limit API calls.

  • Log all transactions.

  • Rotate passkeys regularly.

Common errors:

Error Code Meaning Fix
1 Success 
2001 Invalid phone Check format 
1032 Timeout Retry later 

Testing in Sandbox

Use test credentials:

  • Shortcode: 174379

  • Passkey: bbf279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919

  • Phone: 254708374149

Simulate payments. Go live after approval.

Going Live

Submit to Safaricom. Get production keys. Update URLs. Apply for Paybill via m-pesaforbusiness.co.ke. Expect 1-2 weeks approval.

Production endpoints swap “sandbox” for live.

Frontend Enhancements

Add JS for better UX:

javascript
document.querySelector('form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const response = await fetch('stk_push.php', { method: 'POST', body: formData });
const result = await response.json();
if (result.ResponseCode === '0') {
alert('Check your phone for MPesa PIN prompt!');
}
});

Shows progress without reloads.

Common Challenges

  • No STK Prompt: Check token, passkey.

  • Callback Issues: Ensure public HTTPS URL.

  • CORS Errors: Backend handles APIs.

  • Live Approval: Test thoroughly first.

Alternatives to Daraja

Consider IntaSend or Africa’s Talking for easier integration. Less setup, but fees apply.

Conclusion

MPesa integration transforms HTML sites. Follow these steps for success. Start sandbox today. Scale to live confidently.

Share your love
Achi Systems
Achi Systems

Website Design and Development Services, Responsive Web Design in Nairobi, Website Re-Design, Website Development and Hosting, Website Management, Social Media Marketing and Digital Marketing Services, Search Engine Optimization services. Have your Brand / Campaign moving with the help of a highly experienced Digital Services Professionals!

Articles: 4712