If you run a Laravel store, the moment a customer pays is the moment they want a message. Not an email they read tomorrow. A WhatsApp they see now.
Here is the whole thing. Send the confirmation, then verify the delivery webhook so you know it landed. No package to install, just the HTTP client you already have.
What you need
An EnoSend account with a connected WhatsApp number. Plans start at GHS 30/month, no per-message fees, 3-day trial.
An API key from the dashboard. It looks like
wa_live_...and you only see it once.Your instance id from the dashboard, and your webhook signing secret for step 3.
1. Store the credentials in .env, never in code
ENOSEND_API_KEY=wa_live_YOUR_KEY
ENOSEND_INSTANCE_ID=your_instance_id
ENOSEND_WEBHOOK_SECRET=your_webhook_secret2. Send the confirmation
Call this from wherever your payment succeeds, for example a listener on your OrderPaid event.
use Illuminate\Support\Facades\Http;
$instance = config('services.enosend.instance');
$res = Http::withToken(config('services.enosend.key'))
->post("https://api.enosend.com/api/wa/v1/instances/{$instance}/messages/text", [
'number' => $order->customer_phone, // 233244000000
'text' => "Hi {$order->customer_name}, your order #{$order->id} "
. "is confirmed. Total: GHS {$order->total}. "
. "We will message you when it ships.",
]);
$messageId = $res->json('message_id'); // log this against the orderNote the phone number has no plus sign and no spaces, just country code and number, like 233244000000.
3. Verify the delivery webhook
EnoSend signs every webhook with HMAC-SHA256 so you can prove it came from us and was not faked. The signature arrives in the X-AddinyHost-Signature header as sha256=<hex>. Recompute it over the raw body and compare.
use Illuminate\Http\Request;
Route::post('/webhooks/enosend', function (Request $request) {
$raw = $request->getContent();
$header = (string) $request->header('X-AddinyHost-Signature');
$expected = 'sha256=' . hash_hmac('sha256', $raw, config('services.enosend.secret'));
if (! hash_equals($expected, $header)) {
abort(401, 'bad signature');
}
$payload = json_decode($raw, true);
// { "event": "...", "instance_id": "...", "data": { ... } }
if ($payload['event'] === 'MESSAGES_UPDATE') {
// a delivery or read status update, reconcile it against the order
}
return response()->json(['ok' => true]);
});Use hash_equals, not ==. It compares in constant time, so nobody can guess your signature by watching how long the server takes to answer.
Test it before you ship
Open the API tester in the EnoSend dashboard, send yourself a message, and watch the webhook hit your /webhooks/enosend route. When the payload matches what your code expects, you are done.
Bottom line
Two pieces of code, one honest rule: verify the signature. That is a full WhatsApp order-confirmation flow in Laravel. Wire it into your payment listener and your customers hear from you the second they pay.