Full PHP example for initiating payments and handling webhooks.
<?php
// Initiate M-Pesa Payment
function initiatePayment($apiKey, $trackingCode, $msisdn, $amount, $callbackUrl) {
$data = [
'msisdn' => $msisdn,
'amount' => $amount,
'callback' => $callbackUrl
];
$headers = [
'Content-Type: application/json',
'apikey: ' . $apiKey,
'linkid: ' . $trackingCode
];
$ch = curl_init('https://felixdev.io/api/v1/initiate');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$result = json_decode($response, true);
if ($httpCode === 200 && $result['success']) {
return [
'success' => true,
'request_id' => $result['request_id'],
'message' => 'Payment initiated successfully'
];
} else {
return [
'success' => false,
'error' => $result['error'] ?? 'Unknown error',
'message' => $result['message'] ?? 'Payment failed'
];
}
}
// Handle Webhook Callback
function handleWebhook() {
$rawPayload = file_get_contents('php://input');
$headers = getallheaders();
$payload = json_decode($rawPayload, true);
// Verify signature
$signature = $headers['X-Signature'] ?? '';
$apiKey = $headers['X-API-Key'] ?? '';
$linkId = $headers['X-Link-ID'] ?? '';
// Generate expected signature
$secretKey = 'your_app_key' . $linkId;
$expectedSignature = hash_hmac('sha256', $rawPayload, $secretKey);
if (hash_equals($signature, $expectedSignature)) {
// Webhook is authentic
if ($payload['status'] === 'completed') {
// Payment successful
$receiptNumber = $payload['mpesa_receipt_number'];
$amount = $payload['amount'];
$phone = $payload['msisdn'];
// Update your database
updatePaymentStatus($payload['request_id'], 'completed', $receiptNumber);
// Send confirmation
sendPaymentConfirmation($phone, $amount, $receiptNumber);
} else {
// Payment failed/cancelled
updatePaymentStatus($payload['request_id'], $payload['status']);
}
// Always return 200 OK
http_response_code(200);
echo json_encode(['status' => 'received']);
} else {
// Invalid signature
http_response_code(401);
echo json_encode(['error' => 'Invalid signature']);
}
}
// Example usage
$result = initiatePayment(
'pk_your_api_key_here',
'sc_your_tracking_code_here',
'254712345678',
100,
'https://yoursite.com/webhook'
);
if ($result['success']) {
echo "Payment initiated: " . $result['request_id'];
} else {
echo "Error: " . $result['error'];
}
?>