# `MPP.Client.PaymentProvider`
[🔗](https://github.com/ZenHive/mpp/blob/v0.10.0/lib/mpp/client/payment_provider.ex#L1)

Behaviour for client-side payment providers.

A payment provider connects the MPP client to a real payment system
(Stripe, Tempo, EVM, etc.). Each provider module implements two callbacks
that the client transport uses when handling 402 challenges:

  1. `supports?/3` — check if this provider handles the given method+intent
  2. `pay/2` — execute payment for a challenge, return a credential

This is the client-side counterpart to `MPP.Method` (server-side verification).
Where a method's `verify/2` checks payment proof, `PaymentProvider.pay/2`
*creates* payment proof.

## Usage

    defmodule MyApp.Payments.StripeProvider do
      use MPP.Client.PaymentProvider

      @impl MPP.Client.PaymentProvider
      def supports?(_method, _intent, _config), do: true

      @impl MPP.Client.PaymentProvider
      def pay(challenge, config) do
        # 1. Parse challenge.request for payment details
        # 2. Execute payment (call Stripe API, sign tx, etc.)
        # 3. Return credential with proof payload
        payload = %{"spt" => create_stripe_token(challenge, config)}
        {:ok, %MPP.Credential{challenge: challenge, payload: payload}}
      end
    end

## Design

**Config is explicit.** Providers receive a `config` map on every call —
no `Application.get_env`, no ENV fallback. The caller passes credentials,
RPC URLs, and other settings at the call site. This enables multi-tenant
usage and parallel testing with different configs.

For multi-provider dispatch, see `MPP.Client.MultiProvider`.

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `pay` | 3 | Execute payment using a provider module for the given challenge. | `module: value`, `challenge: value`, `config: value` |
| `supports?` | 4 | Check if a provider module supports the given method and intent. | `module: value`, `method: value`, `intent: value`, `config: value` |

# `pay`

```elixir
@callback pay(challenge :: MPP.Challenge.t(), config :: map()) ::
  {:ok, MPP.Credential.t()} | {:error, term()}
```

Execute payment for the given challenge and return a credential.

This callback should:
1. Decode the challenge request to extract payment details
2. Execute the payment (sign transaction, call API, etc.)
3. Build and return a `MPP.Credential` with the echoed challenge and proof payload

## Arguments

  * `challenge` — the `MPP.Challenge` struct from the 402 response
  * `config` — provider-specific configuration (API keys, RPC URLs, etc.)

## Returns

  * `{:ok, MPP.Credential.t()}` — payment executed, credential ready to send
  * `{:error, term()}` — payment failed

# `supports?`

```elixir
@callback supports?(method :: String.t(), intent :: String.t(), config :: map()) ::
  boolean()
```

Check if this provider supports the given payment method and intent.

Called before `pay/2` to determine which provider should handle a challenge.
Return `true` if this provider can execute payment for the combination.

## Arguments

  * `method` — payment method name from the challenge (e.g., `"stripe"`, `"tempo"`)
  * `intent` — intent type from the challenge (e.g., `"charge"`, `"session"`)
  * `config` — provider-specific configuration (credentials, endpoints, etc.)

# `pay`

```elixir
@spec pay(module(), MPP.Challenge.t(), map()) ::
  {:ok, MPP.Credential.t()} | {:error, term()}
```

Execute payment using a provider module for the given challenge.

Convenience function that delegates to `module.pay/2`.

# `supports?`

```elixir
@spec supports?(module(), String.t(), String.t(), map()) :: boolean()
```

Check if a provider module supports the given method and intent.

Convenience function that delegates to `module.supports?/3`.

---

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