MPP.Methods.Stripe (mpp v0.11.0)

Copy Markdown View Source

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

FunctionArityDescriptionParam Kinds
challenge_method_details1Return Stripe-specific fields (networkId, paymentMethodTypes) for the 402 challenge.charge: value
verify2Verify a Stripe SPT credential by creating a PaymentIntent with confirm: true.payload: value, charge: value
validate_config!1Validate Stripe method_config at init time. Raises on missing stripe_secret_key or network_id.config: value
method_name0Return 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

challenge_method_details(charge)

@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)

# 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()

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

Return the payment method identifier for Stripe.

# descripex:contract
%{}

validate_config!(config)

@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)

# 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(payload, charge)

@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
# 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"
  }
}