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-Accountrequest 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. | - |
Summary
Functions
Return Stripe-specific fields (networkId, paymentMethodTypes) for the 402 challenge.
Return the payment method identifier for Stripe.
Validate Stripe method_config at init time. Raises on missing stripe_secret_key or network_id.
Verify a Stripe SPT credential by creating a PaymentIntent with confirm: true.
Functions
@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 containingnetwork_idand optionallypayment_method_types(value)
Returns
Map with networkId and paymentMethodTypes keys, or nil if no network_id configured (map_or_nil)
# 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"
}
}
@spec method_name() :: String.t()
Return the payment method identifier for Stripe.
# descripex:contract
%{}
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)
# descripex:contract
%{
params: %{
config: %{description: "method_config map to validate", kind: :value}
},
returns: %{
type: :atom,
description: "`:ok` on success, raises `ArgumentError` on missing keys"
}
}
@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 (includingstripe_secret_key) (value)
Returns
{:ok, receipt} on success, {:error, error} on failure (tagged_tuple)
Errors
:invalid_payload:verification_failed
# 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"
}
}