X402.PaymentSignature (X402 v0.6.0)

Copy Markdown View Source

Decodes and validates x402 v2 PAYMENT-SIGNATURE header values.

The header value is Base64-encoded JSON carrying the v2 PaymentPayload envelope (x402Version: 2). accepted must be a complete X402.PaymentRequirements object and payload must contain the scheme-specific signed data. When requirements are passed to validate/2, every core field is matched and advertised extra values must be preserved.

Payloads that declare x402Version: 1 — or omit the version entirely, which x402 v1 clients do — are rejected with {:error, {:unsupported_x402_version, version}}. This SDK does not speak the v1 wire format (v1 payments arrive in the X-PAYMENT header, which X402.Plug.PaymentGate never reads); rejecting explicitly is safer than the false interop of validating a shape no facilitator settles.

Scheme-specific structural validation (for example the upto ceiling check) dispatches through X402.Scheme.Registry; pass additional X402.Scheme modules with the :schemes option of validate/3 or decode_and_validate/3. Kinds with no registered scheme module pass through with :ok — the facilitator remains the authority.

Summary

Header Encoding

Decodes a Base64 PAYMENT-SIGNATURE value to a map.

Returns the canonical x402 header name.

Payment Verification

Decodes and validates a PAYMENT-SIGNATURE header in one step.

Decodes and validates a PAYMENT-SIGNATURE header against requirements.

Decodes and validates a PAYMENT-SIGNATURE header with custom schemes.

Validates a decoded v2 PAYMENT-SIGNATURE payload.

Validates a decoded PAYMENT-SIGNATURE payload against payment requirements.

Validates a decoded PAYMENT-SIGNATURE payload with custom schemes.

Header Encoding

decode(value)

(since 0.1.0)
@spec decode(String.t()) :: {:ok, map()} | {:error, decode_error()}

Decodes a Base64 PAYMENT-SIGNATURE value to a map.

Examples

iex> payload = %{"x402Version" => 2, "accepted" => %{"scheme" => "exact"}, "payload" => %{}}
iex> value = payload |> Jason.encode!() |> Base.encode64()
iex> X402.PaymentSignature.decode(value)
{:ok, payload}

iex> X402.PaymentSignature.decode("not-base64")
{:error, :invalid_base64}

header_name()

(since 0.1.0)
@spec header_name() :: String.t()

Returns the canonical x402 header name.

Examples

iex> X402.PaymentSignature.header_name()
"PAYMENT-SIGNATURE"

Payment Verification

decode_and_validate(value)

(since 0.1.0)
@spec decode_and_validate(String.t()) ::
  {:ok, map()} | {:error, decode_and_validate_error()}

Decodes and validates a PAYMENT-SIGNATURE header in one step.

Examples

iex> payload = %{"x402Version" => 2, "accepted" => %{"scheme" => "exact", "network" => "eip155:8453", "amount" => "1", "asset" => "asset", "payTo" => "receiver", "maxTimeoutSeconds" => 60, "extra" => %{}}, "payload" => %{}}
iex> value = payload |> Jason.encode!() |> Base.encode64()
iex> X402.PaymentSignature.decode_and_validate(value)
{:ok, payload}

decode_and_validate(value, requirements)

(since 0.1.0)
@spec decode_and_validate(String.t(), map()) ::
  {:ok, map()} | {:error, decode_and_validate_error()}

Decodes and validates a PAYMENT-SIGNATURE header against requirements.

decode_and_validate(value, requirements, opts)

(since 0.6.0)
@spec decode_and_validate(String.t(), map(), keyword()) ::
  {:ok, map()} | {:error, decode_and_validate_error() | term()}

Decodes and validates a PAYMENT-SIGNATURE header with custom schemes.

Behaves like decode_and_validate/2; opts are passed to validate/3.

validate(payload)

(since 0.1.0)
@spec validate(map()) :: {:ok, map()} | {:error, validate_error()}

Validates a decoded v2 PAYMENT-SIGNATURE payload.

Payloads with x402Version: 2 are validated against the v2 PaymentPayload structure. Payloads declaring version 1 — or omitting the version, as v1 clients do — return {:error, {:unsupported_x402_version, version}}; any other version returns {:error, :invalid_x402_version}.

Examples

iex> payload = %{
...>   "x402Version" => 2,
...>   "accepted" => %{
...>     "scheme" => "exact",
...>     "network" => "eip155:8453",
...>     "amount" => "10000",
...>     "asset" => "0xasset",
...>     "payTo" => "0xreceiver",
...>     "maxTimeoutSeconds" => 60,
...>     "extra" => %{}
...>   },
...>   "payload" => %{"signature" => "0xsignature"}
...> }
iex> X402.PaymentSignature.validate(payload)
{:ok, payload}

iex> X402.PaymentSignature.validate(%{"x402Version" => 2})
{:error, :invalid_payload}

validate(payload, requirements)

(since 0.1.0)
@spec validate(map(), map()) :: {:ok, map()} | {:error, validate_error()}

Validates a decoded PAYMENT-SIGNATURE payload against payment requirements.

For v2, this matches the complete accepted object. For the "upto" scheme, it also ensures the signed maximum does not exceed the advertised amount.

validate(payload, requirements, opts)

(since 0.6.0)
@spec validate(map(), map(), keyword()) ::
  {:ok, map()} | {:error, validate_error() | term()}

Validates a decoded PAYMENT-SIGNATURE payload with custom schemes.

Behaves like validate/2, additionally consulting the given X402.Scheme modules (before the built-ins) for scheme-specific payload validation — see X402.Scheme.Registry for the resolution rules.

Options

  • :schemes - Additional X402.Scheme modules consulted (before the built-ins) for scheme-specific payload validation — see X402.Scheme.Registry. The default value is [].

Types

decode_and_validate_error()

@type decode_and_validate_error() :: decode_error() | validate_error()

decode_error()

@type decode_error() :: :invalid_base64 | :invalid_json | :payload_too_large

upto_validation_error()

@type upto_validation_error() :: X402.Scheme.UptoEVM.validation_error()

See X402.Scheme.UptoEVM.validation_error/0.

validate_error()

@type validate_error() ::
  :invalid_payload
  | :invalid_payment_requirements
  | :invalid_x402_version
  | :no_matching_requirements
  | {:unsupported_x402_version, 1 | nil}
  | {:missing_fields, [String.t()]}
  | {:invalid_fields, [String.t()]}
  | {:invalid_upto_payment, upto_validation_error()}