Skip to content

[Feature/Roadmap] Let a buyer pick a payment rail for a resource #16

Description

@SergeevDmitry

Depends on: the bug "Settlement is recorded as failed when the facilitator returns no tx hash" and the tracking issue "Transaction recovery and operator reconciliation".

Context & Rationale

CommerceResource.paymentMethods is already an array, but PaymentMethodName is the single literal 'x402', and pickProvider() takes the first configured provider rather than honouring the buyer's choice. The shared response exposes one payment requirement, and MCP and A2A carry a bare _payment string. None of that breaks today because there is one rail; all of it breaks the moment #6 lands. #6 as written proposes a per-resource merchant switch; this issue replaces that with per-resource offers the buyer chooses between.

Proposed Changes

  • Advertise one offer per enabled rail on a resource, and route the buyer's proof to exactly the provider whose offer it matches.
  • Reject unknown, disabled, unadvertised or mismatched methods before verification.
  • Define how HTTP, MCP and A2A carry the selection plus proof for more than one rail, without changing each provider's native challenge format.
  • Bind the AP2 mandate to the selected amount, currency, rail, network, asset and destination.
  • Surface the selected provider in config validation, discovery, doctor, receipts and errors.

Non-goals / Invariants Preserved

  • Existing single-rail x402 configs and the bare-string carrier keep working, or get a documented, versioned migration. Ambiguous legacy input is rejected, not guessed.
  • An unresolved purchase cannot be re-paid on another rail; no automatic fallback after settlement dispatch.
  • Different amounts or assets are distinct offers. Exchange, split payment and smart routing are out of scope.

Impact & Value

Done when one merchant capability can accept payment over more than one rail, the buyer sees the offers and chooses explicitly, the chosen rail is part of the transaction terms and the receipt, and authorization and replay protection bind to that offer, with no change to the merchant backend or the protocol adapter.

Open question

For MCP and A2A, do we extend _payment into an object with method and proof, or add a sibling field and keep the string for x402 compatibility? The object with a compatibility shim is cleaner, but it touches the frozen contract surface.

Test plan

Two deterministic providers; select each; substitute the proof for the other rail (rejected); replay; an AP2 mandate for rail A presented with rail B (rejected); exactly one settlement and one backend call per purchase.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions