Guides / Developer tutorial

Sending WhatsApp Order Confirmations in PHP and Laravel

Order confirmations on WhatsApp get read in minutes, not days. Here's how to send them from vanilla PHP, from Laravel (the right way, with queues), and - if your store runs WooCommerce - with no code at all.

1. Plain PHP with cURL

send-whatsapp.php
<?php
function sendWhatsApp(string $to, string $message): array {
    $ch = curl_init("https://your-platform-domain.com/api/v1/send");
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 20,
        CURLOPT_HTTPHEADER => [
            "Content-Type: application/json",
            "Authorization: Bearer " . getenv("WA_API_KEY"),
        ],
        CURLOPT_POSTFIELDS => json_encode([
            "to" => $to,
            "type" => "text",
            "message" => $message,
        ]),
    ]);
    $response = json_decode(curl_exec($ch), true) ?? [];
    curl_close($ch);
    return $response;
}

// After a successful checkout:
$result = sendWhatsApp(
    "923001234567",
    "Thanks Ahmed! Order #1042 confirmed - Rs 4,500. We'll message you when it ships."
);
if (empty($result["success"])) {
    error_log("WhatsApp send failed: " . ($result["error"] ?? "unknown"));
}

2. Laravel: HTTP client + a clean service

app/Services/WhatsApp.php
<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;

class WhatsApp
{
    public static function send(string $to, string $message): bool
    {
        $response = Http::withToken(config('services.whatsapp.key'))
            ->timeout(20)
            ->post(config('services.whatsapp.url') . '/api/v1/send', [
                'to' => $to,
                'type' => 'text',
                'message' => $message,
            ]);

        return $response->ok() && $response->json('success') === true;
    }
}
config/services.php + .env
// config/services.php
'whatsapp' => [
    'url' => env('WHATSAPP_API_URL'),
    'key' => env('WHATSAPP_API_KEY'),
],

// .env
WHATSAPP_API_URL=https://your-platform-domain.com
WHATSAPP_API_KEY=wapi_xxxxxxxxxxxx

3. Send from a queued job (recommended)

Never block the checkout response on an HTTP call. Dispatch a queued job so confirmations go out asynchronously and retry on failure:

app/Jobs/SendOrderConfirmation.php
<?php

namespace App\Jobs;

use App\Models\Order;
use App\Services\WhatsApp;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;

class SendOrderConfirmation implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable;

    public int $tries = 3;
    public array $backoff = [10, 60, 300];

    public function __construct(public Order $order) {}

    public function handle(): void
    {
        WhatsApp::send(
            $this->order->customer_phone,
            "Hi {$this->order->customer_name}, order #{$this->order->id} " .
            "({$this->order->total_formatted}) is confirmed. " .
            "Track it here: {$this->order->tracking_url}"
        );
    }
}

// In your controller after checkout:
SendOrderConfirmation::dispatch($order);

4. WooCommerce: skip the code entirely

If the store is WooCommerce, don't write any of this - install the free WooCommerce WhatsApp plugin instead. It sends per-status notifications (processing, shipped, completed, cancelled, refunded) with editable templates and an admin new-order alert, all from a settings page.

💡 Even with the plugin installed, the PHP examples above still work side by side for custom flows like OTP at checkout or delivery-day reminders.

5. Production checklist

  • Use a queued job (or at minimum a try/catch) so a WhatsApp outage never breaks checkout.
  • Log the error field from every failed response - 402 means your platform plan or quota lapsed, 503 means the number needs a QR re-scan.
  • Normalize phones to international digits (0300… → 92300…) before sending.
  • Keep messages transactional and expected - confirmations, shipping updates, OTPs - to protect your number's reputation.

Try it with your own number

Free account, QR-code setup, plans from Rs 1,500/month. Everything in this guide works out of the box.