Webhook verification and signature validation for the WhatsApp Business API.
Meta sends webhook events as HTTP POST requests with an HMAC-SHA256
signature in the X-Hub-Signature-256 header. This module provides
functions to verify subscription requests and validate incoming payloads.
Subscription Verification
When you configure a webhook URL, Meta sends a GET request with query parameters to verify your endpoint:
case WhatsApp.Webhook.verify_subscription(params, "my_verify_token") do
{:ok, challenge} -> send_resp(conn, 200, challenge)
{:error, _error} -> send_resp(conn, 403, "Forbidden")
endSignature Validation
if WhatsApp.Webhook.valid?(raw_body, signature_header, app_secret) do
# process the event
end
Summary
Functions
Compute the HMAC-SHA256 signature of a payload.
Validate that a webhook payload was signed by Meta.
Verify a webhook subscription request.
Functions
Compute the HMAC-SHA256 signature of a payload.
Returns the hex-encoded digest string.
Parameters
payload- The raw payload to signsecret- The secret key (your App Secret)
Examples
iex> WhatsApp.Webhook.compute_signature("test", "secret")
"0329a06b62cd16b33eb6792be8c60b158d89a2ee3a876fce9a881ebb488c0914"
Validate that a webhook payload was signed by Meta.
Computes an HMAC-SHA256 digest of raw_body using app_secret as the key,
then performs a constant-time comparison against the signature provided in
the X-Hub-Signature-256 header.
Parameters
raw_body- The raw request body as a binarysignature_header- The value of theX-Hub-Signature-256header (e.g.,"sha256=abc...")app_secret- Your Facebook App Secret
Examples
iex> sig = "sha256=" <> WhatsApp.Webhook.compute_signature("body", "secret")
iex> WhatsApp.Webhook.valid?("body", sig, "secret")
true
@spec verify_subscription(map(), String.t()) :: {:ok, String.t()} | {:error, WhatsApp.Error.t()}
Verify a webhook subscription request.
Meta sends a GET request with query parameters when verifying a webhook URL.
The parameters may use dot notation (hub.mode) or underscore notation
(hub_mode) depending on the framework.
Returns {:ok, challenge} if the parameters are valid, or
{:error, %WhatsApp.Error{}} otherwise.
Parameters
params- Query parameters map from the GET requestverify_token- The verify token you configured in the Meta dashboard
Examples
iex> params = %{"hub.mode" => "subscribe", "hub.verify_token" => "tok", "hub.challenge" => "123"}
iex> {:ok, "123"} = WhatsApp.Webhook.verify_subscription(params, "tok")