1, "ResultDesc" => "Invalid JSON Payload"]); exit; } $stkCallback = $data['Body']['stkCallback']; // 3. Extract the Primary Identifiers and Status $merchantRequestID = $stkCallback['MerchantRequestID'] ?? null; $checkoutRequestID = $stkCallback['CheckoutRequestID'] ?? null; $resultCode = (int)($stkCallback['ResultCode'] ?? -1); $resultDesc = $stkCallback['ResultDesc'] ?? 'Unknown Error'; // 4. Initialize variables for successful transactions $amount = 0; $receiptNumber = null; $phoneNumber = null; $transactionDate = null; // 5. If ResultCode is 0, the payment was SUCCESSFUL, and we can extract the Metadata if ($resultCode === 0 && isset($stkCallback['CallbackMetadata']['Item'])) { foreach ($stkCallback['CallbackMetadata']['Item'] as $item) { $name = $item['Name']; $value = $item['Value'] ?? null; switch ($name) { case 'Amount': $amount = $value; break; case 'MpesaReceiptNumber': $receiptNumber = $value; break; case 'PhoneNumber': $phoneNumber = $value; break; case 'TransactionDate': $transactionDate = $value; break; } } } // 6. Handle the Business Logic in your Database $logMessage = "Checkout ID: $checkoutRequestID | Status: $resultCode ($resultDesc)\n"; if ($resultCode === 0) { // Payment Success! Update your system orders to 'Paid' $logMessage .= "Amount: $amount | Phone: $phoneNumber | Receipt: $receiptNumber\n"; // TODO: Update your database using $checkoutRequestID to mark the order complete } else { // Payment Failed or Cancelled by User! Update your system to 'Failed' $logMessage .= "User did not complete the payment.\n"; // TODO: Mark order as failed using $checkoutRequestID } // 7. Log the output to a file (For debugging purposes) $logEntry = "--- " . date('Y-m-d H:i:s') . " ---\n"; $logEntry .= $logMessage; $logEntry .= "Raw Payload: " . $payload . "\n\n"; file_put_contents(__DIR__ . '/mpesa_webhook_debug.txt', $logEntry, FILE_APPEND); // 8. Always acknowledge receipt to Safaricom with a 2xx Response Code and valid JSON // If you don't do this, Daraja will keep retrying to send you the webhook! http_response_code(200); echo json_encode([ "ResultCode" => 0, "ResultDesc" => "Confirmation Received Successfully" ]);