Mercadopago.Webhook.Validator (mercadopago_sdk_elixir v0.2.1)

Copy Markdown View Source

Validates MercadoPago webhook signatures (HMAC-SHA256).

Call validate/5 on every incoming webhook. It returns {:ok, ts} on success and {:error, %InvalidSignatureError{}} on failure — an invalid signature is an expected outcome for any public endpoint, so it is reported as data, not by raising. Use validate!/5 when you prefer a raising variant.

Legacy QR Code notifications are not signed by MercadoPago, so validation will always fail for them. QR payments delivered through the Orders API are signed and should be validated like any other event.

Example

case Mercadopago.Webhook.Validator.validate(
       conn.req_headers |> Map.new() |> Map.get("x-signature"),
       conn.req_headers |> Map.new() |> Map.get("x-request-id"),
       conn.params["data"]["id"],
       webhook_secret,
       tolerance_seconds: 300
     ) do
  {:ok, _ts} -> send_resp(conn, 200, "")
  {:error, %InvalidSignatureError{} = e} -> send_resp(conn, 401, e.message)
end

Raising variant:

:ok = Mercadopago.Webhook.Validator.validate!(x_sig, x_req, data_id, secret)

Summary

Functions

Validates the signature of a MercadoPago webhook notification.

Like validate/5, but returns :ok on success and raises InvalidSignatureError on failure.

Functions

validate(x_signature, x_request_id, data_id, secret, opts \\ [])

@spec validate(
  String.t() | nil,
  String.t() | nil,
  String.t() | nil,
  String.t(),
  keyword()
) ::
  {:ok, String.t()}
  | {:error, Mercadopago.Webhook.Validator.InvalidSignatureError.t()}

Validates the signature of a MercadoPago webhook notification.

Arguments

  • x_signature - raw value of the x-signature request header
  • x_request_id - value of the x-request-id header (may be nil)
  • data_id - value of the data.id query parameter (may be nil). Pass it exactly as received; it is lowercased internally before the HMAC, as the MercadoPago manifest requires.
  • secret - HMAC key configured in Tus Integraciones

Options

  • :tolerance_seconds - max allowed drift between header timestamp and now
  • :supported_versions - list of accepted signature versions (default: ["v1"])
  • :now - zero-arity function returning current time in milliseconds (for testing)

Returns

{:ok, ts} on success (where ts is the verified timestamp string), {:error, %InvalidSignatureError{}} on failure. Raises ArgumentError when secret is missing — that is a caller misconfiguration, not webhook input.

validate!(x_signature, x_request_id, data_id, secret, opts \\ [])

@spec validate!(
  String.t() | nil,
  String.t() | nil,
  String.t() | nil,
  String.t(),
  keyword()
) :: :ok

Like validate/5, but returns :ok on success and raises InvalidSignatureError on failure.