# `MPP.Methods.Stripe`
[🔗](https://github.com/ZenHive/mpp/blob/v0.12.0/lib/mpp/methods/stripe.ex#L1)

Stripe payment method — verifies payment via Stripe PaymentIntent with SPT.

The client creates a Shared Payment Granted Token (SPT) via Stripe, includes
it in the credential payload, and the server creates a PaymentIntent with
`confirm: true` to charge it immediately.

## Configuration

Pass Stripe-specific config via `:method_config` in `MPP.Plug` opts:

    plug MPP.Plug,
      secret_key: "hmac-secret",
      realm: "api.example.com",
      method: MPP.Methods.Stripe,
      amount: "5000",
      currency: "usd",
      method_config: %{
        "stripe_secret_key" => "sk_test_...",
        "network_id" => "profile_1Mqx...",
        "payment_method_types" => ["card"]
      }

## Config Keys

  * `"stripe_secret_key"` — (required) Stripe secret key for PaymentIntent creation
  * `"network_id"` — (required) Stripe Business Network profile ID
  * `"payment_method_types"` — (optional) accepted payment methods, defaults to `["card"]`
  * `"connect"` — (optional) server-side Stripe Connect settlement policy (see below)
  * `"realm"` — (optional, injected by Plug) server realm for analytics metadata

## Stripe Connect settlement

Pass a `"connect"` map in `method_config` to route the resulting PaymentIntent
to a connected account (destination charge, direct charge, or application-fee
split). Connect settlement is a **server-only credential** — it is merged into
the charge at verify time and is **never serialized into the public 402
challenge**, matching the mppx reference (`src/stripe/server/Charge.ts`, where
`connect` is documented as "Not included in MPP challenges").

    method_config: %{
      "stripe_secret_key" => "sk_test_...",
      "network_id" => "profile_1Mqx...",
      "connect" => %{
        # Destination charge: platform is merchant of record, funds routed on.
        "transfer_data" => %{"destination" => "acct_seller", "amount" => 4000},
        "application_fee_amount" => 500,
        "on_behalf_of" => "acct_seller",
        "transfer_group" => "order_42",
        # Direct charge: run the PaymentIntent on the connected account itself.
        "stripe_account" => "acct_seller"
      }
    }

Wire mapping applied to the PaymentIntent (form-encoded), per the mppx reference:

  * `"application_fee_amount"` (integer) → `application_fee_amount`
  * `"on_behalf_of"` (string) → `on_behalf_of`
  * `"transfer_data"` `%{"destination" => ..., "amount" => ...}` →
    `transfer_data[destination]` / `transfer_data[amount]`
  * `"transfer_group"` (string) → `transfer_group`
  * `"stripe_account"` (string) → `Stripe-Account` request header

Settlement is validated against the charge amount before the PaymentIntent is
created: account ids must be non-empty, fee/transfer amounts must be
non-negative integers not exceeding the payment amount.

## Credential Payload

The credential `payload` map must contain:

  * `"spt"` — (required) Stripe Shared Payment Granted Token (e.g., `"spt_1N4..."`)
  * `"externalId"` — (optional) caller-provided correlation ID, echoed in receipt

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `challenge_method_details` | 1 | Return Stripe-specific fields (`networkId`, `paymentMethodTypes`) for the 402 challenge. | `charge: value` |
| `verify` | 2 | Verify a Stripe SPT credential by creating a PaymentIntent with `confirm: true`. | `payload: value`, `charge: value` |
| `validate_config!` | 1 | Validate Stripe method_config at init time. Raises on missing `stripe_secret_key` or `network_id`. | `config: value` |
| `method_name` | 0 | Return the payment method identifier for Stripe. | - |

# `challenge_method_details`

```elixir
@spec challenge_method_details(MPP.Method.intent()) :: map() | nil
@spec challenge_method_details(MPP.Intents.Charge.t()) :: map() | nil
```

Return Stripe-specific fields (`networkId`, `paymentMethodTypes`) for the 402 challenge.

## Parameters

  * `charge` - Charge struct with method_details containing `network_id` and optionally `payment_method_types` (value)

## Returns

Map with `networkId` and `paymentMethodTypes` keys, or `nil` if no `network_id` configured (`map_or_nil`)

```elixir
# descripex:contract
%{
  params: %{
    charge: %{
      description: "Charge struct with method_details containing `network_id` and optionally `payment_method_types`",
      kind: :value
    }
  },
  returns: %{
    type: :map_or_nil,
    description: "Map with `networkId` and `paymentMethodTypes` keys, or `nil` if no `network_id` configured"
  }
}
```

# `method_name`

```elixir
@spec method_name() :: String.t()
```

Return the payment method identifier for Stripe.

```elixir
# descripex:contract
%{}
```

# `validate_config!`

```elixir
@spec validate_config!(map()) :: :ok
@spec validate_config!(map()) :: :ok
```

Validate Stripe method_config at init time. Raises on missing `stripe_secret_key` or `network_id`.

## Parameters

  * `config` - method_config map to validate (value)

## Returns

`:ok` on success, raises `ArgumentError` on missing keys (`atom`)

```elixir
# descripex:contract
%{
  params: %{
    config: %{description: "method_config map to validate", kind: :value}
  },
  returns: %{
    type: :atom,
    description: "`:ok` on success, raises `ArgumentError` on missing keys"
  }
}
```

# `verify`

```elixir
@spec verify(map(), MPP.Intents.Charge.t()) ::
  {:ok, MPP.Receipt.t()} | {:error, MPP.Errors.t()}
```

Verify a Stripe SPT credential by creating a PaymentIntent with `confirm: true`.

## Parameters

  * `payload` - Credential payload map containing `"spt"` (Stripe Shared Payment Granted Token) (value)
  * `charge` - Charge intent struct with amount, currency, and method_details (including `stripe_secret_key`) (value)

## Returns

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

## Errors

  * `:invalid_payload`
  * `:verification_failed`

```elixir
# descripex:contract
%{
  params: %{
    payload: %{
      description: "Credential payload map containing `\"spt\"` (Stripe Shared Payment Granted Token)",
      kind: :value
    },
    charge: %{
      description: "Charge intent struct with amount, currency, and method_details (including `stripe_secret_key`)",
      kind: :value
    }
  },
  errors: [:invalid_payload, :verification_failed],
  returns: %{
    type: :tagged_tuple,
    description: "`{:ok, receipt}` on success, `{:error, error}` on failure"
  }
}
```

---

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