renzojohnson/whatsapp-webhook
最新稳定版本:v0.26.03.16
Composer 安装命令:
composer require renzojohnson/whatsapp-webhook
包简介
Lightweight WhatsApp Cloud API webhook parser. Typed notifications for messages, statuses, and errors. HMAC signature verification. Zero dependencies.
README 文档
README
Lightweight WhatsApp Cloud API webhook parser. Typed notifications for messages, statuses, and errors. HMAC signature verification. Zero dependencies.
Author: Renzo Johnson
Requirements
- PHP 8.4 or higher (uses
readonlyclasses and enums) ext-json- No other extensions or libraries required (zero dependencies)
Installation
composer require renzojohnson/whatsapp-webhook
Quick Start
use RenzoJohnson\WhatsAppWebhook\WebhookHandler; use RenzoJohnson\WhatsAppWebhook\MessageType; use RenzoJohnson\WhatsAppWebhook\Notification\MessageNotification; $handler = new WebhookHandler('your-app-secret'); // Register listeners $handler->onMessage(MessageType::Text, function (MessageNotification $msg): void { echo "Message from {$msg->from}: {$msg->text()}"; }); // Verify signature and handle $rawBody = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? ''; if (!$handler->verifySignature($rawBody, $signature)) { http_response_code(401); exit; } $handler->handle($rawBody); http_response_code(200);
Webhook Endpoint Setup
use RenzoJohnson\WhatsAppWebhook\WebhookHandler; use RenzoJohnson\WhatsAppWebhook\WebhookException; $handler = new WebhookHandler('your-app-secret'); // Step 1: Handle Meta's verification challenge (GET) if ($_SERVER['REQUEST_METHOD'] === 'GET') { $challenge = $handler->handleVerification($_GET, 'your-verify-token'); if ($challenge !== null) { echo $challenge; exit; } http_response_code(403); exit; } // Step 2: Verify signature (POST) $rawBody = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? ''; if (!$handler->verifySignature($rawBody, $signature)) { http_response_code(401); exit; } // Step 3: Parse and handle try { $notifications = $handler->handle($rawBody); http_response_code(200); } catch (WebhookException $e) { http_response_code(400); }
Message Types
| Type | Enum | Description |
|---|---|---|
text |
MessageType::Text |
Plain text message |
image |
MessageType::Image |
Image with optional caption |
video |
MessageType::Video |
Video with optional caption |
audio |
MessageType::Audio |
Audio message |
document |
MessageType::Document |
Document with filename |
sticker |
MessageType::Sticker |
Sticker |
location |
MessageType::Location |
GPS coordinates with name/address |
contacts |
MessageType::Contacts |
Contact cards |
button |
MessageType::Button |
Quick reply button tap |
interactive |
MessageType::Interactive |
Button reply or list selection |
reaction |
MessageType::Reaction |
Emoji reaction |
order |
MessageType::Order |
Product order |
Listen by Message Type
use RenzoJohnson\WhatsAppWebhook\MessageType; use RenzoJohnson\WhatsAppWebhook\Notification\MessageNotification; $handler->onMessage(MessageType::Text, function (MessageNotification $msg): void { echo $msg->text(); }); $handler->onMessage(MessageType::Image, function (MessageNotification $msg): void { echo "Image: {$msg->mediaId()} ({$msg->mediaMimeType()})"; echo "Caption: {$msg->caption()}"; }); $handler->onMessage(MessageType::Location, function (MessageNotification $msg): void { echo "Location: {$msg->latitude()}, {$msg->longitude()}"; echo "Name: {$msg->locationName()}"; }); $handler->onMessage(MessageType::Interactive, function (MessageNotification $msg): void { if ($msg->interactiveType() === 'button_reply') { echo "Button: {$msg->interactiveButtonTitle()} (ID: {$msg->interactiveButtonId()})"; } if ($msg->interactiveType() === 'list_reply') { echo "List: {$msg->interactiveListTitle()}"; } }); $handler->onMessage(MessageType::Reaction, function (MessageNotification $msg): void { echo "Reacted with {$msg->reactionEmoji()} to {$msg->reactionMessageId()}"; });
Listen to All Messages
$handler->onAnyMessage(function (MessageNotification $msg): void { error_log($msg->getSummary()); });
Status Updates
use RenzoJohnson\WhatsAppWebhook\StatusType; use RenzoJohnson\WhatsAppWebhook\Notification\StatusNotification; $handler->onStatus(StatusType::Delivered, function (StatusNotification $status): void { echo "Delivered to {$status->recipientId}"; }); $handler->onStatus(StatusType::Read, function (StatusNotification $status): void { echo "Read by {$status->recipientId}"; }); $handler->onStatus(StatusType::Failed, function (StatusNotification $status): void { if ($status->hasErrors()) { echo "Error {$status->errorCode()}: {$status->errorTitle()}"; } }); $handler->onAnyStatus(function (StatusNotification $status): void { error_log($status->getSummary()); });
Pricing and Conversation Info
$handler->onAnyStatus(function (StatusNotification $status): void { if ($status->isBillable()) { echo "Category: {$status->pricingCategory()}"; echo "Model: {$status->pricingModel()}"; } if ($status->conversationId()) { echo "Conversation: {$status->conversationId()}"; echo "Origin: {$status->conversationOrigin()}"; } });
Forwarded Messages
$handler->onAnyMessage(function (MessageNotification $msg): void { if ($msg->isForwarded()) { echo "This message was forwarded"; } if ($msg->isFrequentlyForwarded()) { echo "This message has been forwarded many times"; } if ($msg->contextMessageId()) { echo "Reply to: {$msg->contextMessageId()}"; } });
Parse Without Dispatching
$notifications = $handler->parse($rawBody); foreach ($notifications as $notification) { if ($notification instanceof MessageNotification) { echo $notification->getSummary(); } }
Error Handling
use RenzoJohnson\WhatsAppWebhook\WebhookException; try { $handler->parse($rawBody); } catch (WebhookException $e) { // Invalid JSON, wrong object type, empty entry }
Related Packages
- whatsapp-cloud-api — Send WhatsApp messages via Cloud API
Links
License
MIT License. Copyright (c) 2026 Renzo Johnson.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 2
- 点击次数: 5
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-03-17