# `Unicom360.Webhook.Plug`
[🔗](https://github.com/TechRode-Solution-Limited/unicom360-elixir/blob/v0.1.0/lib/unicom360/webhook/plug.ex#L2)

A plug that receives Unicom360 webhooks: it verifies the signature, parses the event and
calls your handler.

    # In a Phoenix router (or a Plug.Router):
    forward "/webhooks/unicom360/whatsapp", Unicom360.Webhook.Plug,
      secret: {MyApp.Config, :unicom360_webhook_secret, []},
      handler: MyApp.WhatsAppEvents

Options:

  * `:secret` (required) - the 43-character string from the portal, or `{module, function,
    args}` called on each request. Prefer the tuple, so the secret is not compiled into your
    router. A value that is `nil`, empty or only whitespace makes `init/1` raise
    `Unicom360.Error` (`:configuration_error`); a tuple that returns one answers 500 (below).
  * `:handler` (required) - a module implementing `Unicom360.Webhook.Handler`.
  * `:tolerance` - the largest clock skew accepted, in milliseconds. Default `300_000`.

It answers:

  * 200 when the handler returns `:ok`;
  * 401 with the failure's reason as the body, when verification fails;
  * 400 when the body cannot be read, or a verified body is not a JSON object with an event;
  * 413 when the body is over 1 MiB (only when this plug reads the body itself);
  * 500 when the handler returns anything else;
  * 500, without reading the body or calling the handler, and with a log line, when an `{m, f,
    a}` secret returns `nil`, an empty string or only whitespace: anyone can forge a signature
    with an empty key, and it is a fault in your configuration, not a failed verification.

## The raw body

Signatures cover the exact bytes received. Mount this plug ahead of `Plug.Parsers` and it
reads the body itself. Behind `Plug.Parsers`, add `Unicom360.Webhook.BodyReader` as the
parsers' `:body_reader`, and this plug uses `conn.assigns.raw_body`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
