# `MPP.Plug`
[🔗](https://github.com/ZenHive/mpp/blob/v0.10.0/lib/mpp/plug.ex#L1)

Plug middleware implementing the MPP 402 payment handshake.

Mount this plug in any Phoenix or Plug router to gate endpoints behind
payment. Each route gets its own pricing via plug opts — no global config.

## Single-Method Usage

    plug MPP.Plug,
      secret_key: "your-hmac-secret",
      realm: "api.example.com",
      method: MyApp.Payments.Stripe,
      amount: "1000",
      currency: "usd"

## Multi-Method Usage

Accept multiple payment methods per endpoint. Each method can have its own
pricing and config. The 402 response includes one `WWW-Authenticate` header
per method; the agent picks whichever it can pay with.

    plug MPP.Plug,
      secret_key: "your-hmac-secret",
      realm: "api.example.com",
      methods: [
        [method: MyApp.Payments.Stripe, amount: "1000", currency: "usd",
         method_config: %{"stripe_secret_key" => "sk_..."}],
        [method: MyApp.Payments.Tempo, amount: "950", currency: "usd"]
      ]

## Flow

1. Request without `Authorization: Payment` → 402 with `WWW-Authenticate` challenge(s)
2. Client pays off-band, retries with `Authorization: Payment <credential>`
3. Valid credential → request passes through with `Payment-Receipt` header + receipt in assigns
4. Invalid credential → 402 with fresh challenge(s) + RFC 9457 error body

## Shared Options

  * `:secret_key` — (required) HMAC-SHA256 key for challenge binding
  * `:realm` — (required) server protection space
  * `:expires_in` — (optional) challenge TTL in seconds (integer, defaults to 300)
  * `:digest` — (optional) expected content digest for body-bound challenges
  * `:opaque` — (optional) base64url-encoded server correlation data
  * `:store` — (optional) shared `MPP.Tempo.Store` replay-protection store

## Single-Method Options

  * `:method` — (required) module implementing `MPP.Method`
  * `:amount` — (required) price in base units (string)
  * `:currency` — (required) currency code (string, normalized to lowercase)
  * `:recipient` — (optional) payment recipient identifier
  * `:description` — (optional) human-readable description
  * `:external_id` — (optional) merchant reference ID included in the challenge request
  * `:method_config` — (optional) server-only config map for `verify/2`

## Multi-Method Options

  * `:methods` — (required) list of keyword lists, each with per-method opts:
    `:method`, `:amount`, `:currency`, and optionally `:recipient`,
    `:description`, `:external_id`, `:method_config`

# `call`

```elixir
@spec call(Plug.Conn.t(), MPP.Plug.Config.t()) :: Plug.Conn.t()
```

Runs the MPP 402 payment handshake for the current request.

Returns `402` with fresh challenges when no valid credential is present;
halts with an RFC 9457 problem body on verification failure; otherwise
passes the connection through with `:mpp_receipt` assigned and a
`Payment-Receipt` response header.

# `init`

```elixir
@spec init(keyword()) :: MPP.Plug.Config.t()
```

Builds validated plug configuration from options at init time.

Normalizes single- or multi-method opts into a `%Config{}` with one
`MethodEntry` per accepted payment method. Raises on missing required
options or duplicate method names.

---

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