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

Transport-neutral payment credential verification.

Implements the full MPP verification pipeline — Tier-1 HMAC challenge binding
(server-realm provenance + expiry), Tier-2 pinned-field safety net, and
method-specific verification — without any HTTP or transport dependency.

`MPP.Plug` delegates to this module for HTTP transport. `MPP.Mcp` and
the client SDK (Phase 12) can use it directly for JSON-RPC and other
transports.

## Usage

    opts = [
      secret_key: "hmac-secret",
      realm: "api.example.com",
      method: MyApp.Payments.Stripe,
      charge: charge,
      method_config: %{"stripe_secret_key" => "sk_..."}
    ]

    case MPP.Verifier.verify(credential, opts) do
      {:ok, receipt} -> # payment verified
      {:error, %MPP.Errors{} = error} -> # verification failed
    end

## Options

  * `:secret_key` — (required) HMAC-SHA256 key for challenge verification
  * `:realm` — (required) expected server protection space
  * `:method` — (required) module implementing `MPP.Method`
  * `:charge` — (required) `MPP.Intents.Charge.t()` for this endpoint
  * `:method_config` — (optional) server-only config map, default `%{}`
  * `:digest` — (optional) expected endpoint digest value
  * `:opaque` — (optional) expected endpoint opaque value

## Verification tiers

**Tier 1** — HMAC provenance using the server's configured realm (not the echoed
realm) plus expiry. Failures return `:invalid_challenge` or `:payment_expired`.

**Tier 2** — Field-by-field pinning of the credential's echoed challenge against
this endpoint's configuration (realm, method, intent, request, digest, opaque).
Failures return `:credential_mismatch` so callers can distinguish replay attacks
from corrupt credentials.

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `verify` | 2 | Verify a payment credential against endpoint configuration. Transport-neutral. | `credential: value`, `opts: value` |

# `verify`

```elixir
@spec verify(
  MPP.Credential.t(),
  keyword()
) :: {:ok, MPP.Receipt.t()} | {:error, MPP.Errors.t()}
```

Verify a payment credential against endpoint configuration. Transport-neutral.

## Parameters

  * `credential` - Parsed MPP credential with echoed challenge and payment payload (value)
  * `opts` - Keyword list: :secret_key (HMAC key), :realm, :method (module), :charge (Charge.t()), :method_config (optional map) (value)

## Returns

`{:ok, receipt}` on success, `{:error, %Errors{}}` on failure (`tagged_tuple`)

## Errors

  * `:invalid_challenge`
  * `:credential_mismatch`
  * `:intent_mismatch`
  * `:method_mismatch`
  * `:payment_expired`
  * `:realm_mismatch`
  * `:request_mismatch`
  * `:verification_failed`

```elixir
# descripex:contract
%{
  params: %{
    opts: %{
      description: "Keyword list: :secret_key (HMAC key), :realm, :method (module), :charge (Charge.t()), :method_config (optional map)",
      kind: :value
    },
    credential: %{
      description: "Parsed MPP credential with echoed challenge and payment payload",
      kind: :value
    }
  },
  errors: [:invalid_challenge, :credential_mismatch, :intent_mismatch,
   :method_mismatch, :payment_expired, :realm_mismatch, :request_mismatch,
   :verification_failed],
  returns: %{
    type: :tagged_tuple,
    description: "`{:ok, receipt}` on success, `{:error, %Errors{}}` on failure"
  }
}
```

---

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