openclaw - 💡(How to fix) Fix [RFC] Bundled payment plugin: agent-driven Stripe Link virtual cards + HTTP 402 machine-payment [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#75772Fetched 2026-05-02 05:30:24
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
2
Timeline (top)
closed ×1commented ×1mentioned ×1subscribed ×1

Proposing a new bundled payment plugin for OpenClaw that lets agents pay for things across two complementary rails:

  1. virtual_card — agent issues a one-time-use Stripe Link virtual card and fills it into a browser checkout form via sentinel substitution. Raw PAN/CVV never reach the LLM transcript.
  2. machine_payment — agent executes payment against an HTTP 402 endpoint via Stripe Link's Machine Payments Protocol (MPP). The shared payment token stays function-scoped inside the adapter.

The plugin is approval-gated at every money-moving action and at every browser-fill substitution (severity critical). Buyer approval is enforced server-side by Stripe (biometric on the Link mobile app); the OpenClaw plugin approval gate is additive policy.

Root Cause

Proposing a new bundled payment plugin for OpenClaw that lets agents pay for things across two complementary rails:

  1. virtual_card — agent issues a one-time-use Stripe Link virtual card and fills it into a browser checkout form via sentinel substitution. Raw PAN/CVV never reach the LLM transcript.
  2. machine_payment — agent executes payment against an HTTP 402 endpoint via Stripe Link's Machine Payments Protocol (MPP). The shared payment token stays function-scoped inside the adapter.

The plugin is approval-gated at every money-moving action and at every browser-fill substitution (severity critical). Buyer approval is enforced server-side by Stripe (biometric on the Link mobile app); the OpenClaw plugin approval gate is additive policy.

RAW_BUFFERClick to expand / collapse

Summary

Proposing a new bundled payment plugin for OpenClaw that lets agents pay for things across two complementary rails:

  1. virtual_card — agent issues a one-time-use Stripe Link virtual card and fills it into a browser checkout form via sentinel substitution. Raw PAN/CVV never reach the LLM transcript.
  2. machine_payment — agent executes payment against an HTTP 402 endpoint via Stripe Link's Machine Payments Protocol (MPP). The shared payment token stays function-scoped inside the adapter.

The plugin is approval-gated at every money-moving action and at every browser-fill substitution (severity critical). Buyer approval is enforced server-side by Stripe (biometric on the Link mobile app); the OpenClaw plugin approval gate is additive policy.

Why a bundled plugin?

Agents need a controlled way to pay, and no single primitive covers all merchants:

  • Consumer e-commerce is browser checkout — needs per-purchase virtual cards filled into a form without the agent seeing card values
  • Some endpoints return 402 Payment Required and want a machine-payment proof — needs MPP/x402 wire-shape support
  • Stripe Link is the existing user-facing way to manage funding sources and biometrically approve agent purchases

Without a bundled plugin, every OpenClaw deployment that wants agent purchasing has to build this from scratch — and the security model (sentinel substitution, transcript redaction, function-scoped MPP tokens) is non-trivial to get right.

Architecture (V1)

ComponentPurpose
payment tool (5 actions)setup_status, list_funding_sources, issue_virtual_card, execute_machine_payment, get_payment_status
openclaw payment CLIsetup, funding, virtual-card, execute, status--yes gate on live actions
before_tool_call fill-hook on browserDetects FillSentinel values, requires approval (critical), substitutes real card values inside the runtime, drops references in try/finally
before_message_write redaction-hookDefense-in-depth — scans persisted assistant toolCall.arguments for PAN-shape (Luhn) / CVV-context / Authorization: Payment headers
Two-tier data modelCardSecrets (closed: pan/cvv/expiry variants) + BuyerProfile (holderName, billing, extras: Record<string, string> for forward-compat)

Provider matrix (V1)

Providervirtual_cardmachine_paymentSettlement assetsStatus
Stripe Link CLIusd_card, usdcImplemented
Mockusd_card, usdcImplemented (testing)

Future units (post-V1, separate PRs):

  • F1 — x402 protocol support
  • F2 — Ramp adapter (reconciliation rail)
  • F3 — Mercury adapter (bank_payment rail)

Security invariants (verified end-to-end)

  • retrieveCardSecretsForHook has exactly ONE production call site (verified by grep on every PR commit)
  • --include card flag appears in EXACTLY ONE place in the Stripe Link adapter
  • try { ... } finally { secretsByHandle?.clear(); } discipline guarantees secret clear on every exit path
  • Defense-in-depth: before_message_write hook blocks PAN/CVV/Authorization-Payment in any persisted toolCall — should never fire if the fill-hook is correct
  • Audit JSONL has a runtime allow-list: handle metadata can only contain spendRequestId, providerId, last4, targetMerchantName, issuedAt, validUntil (no PAN, CVV, or holder name persisted)
  • MPP shared payment token is function-scoped in executeMachinePayment; never crosses the function boundary

Stripe collaboration

We coordinated with the Stripe Link CLI team to validate actual JSON output shapes against link-cli 0.4.0 — surfaced multiple flag/path mismatches between the public docs and the live CLI surface (e.g., --test is only valid on spend-request create, not retrieve; spend-request id prefix is lsrq_; --request-approval is fire-and-poll, not blocking). All of these are now correctly handled in the adapter.

Stripe also indicated email/phone/shipping_address will be exposed by link-cli soon. The plugin's BuyerProfile.extras passthrough is designed so these new fields work without plugin code changes — the adapter dumps any non-secret string-typed top-level field from card.* and card.billing_address.* into extras, and the agent can immediately use field: "email" etc.

Testing

End-to-end validated against:

  • Live link-cli 0.4.0 — all 6 adapter methods exercised against the real CLI
  • Stripe Link Mobile app biometric approval — multiple round-trips
  • Full agent-driven happy path through prod OpenClaw 2026.4.29: Telegram message → agent → both approval prompts on phone → form filled correctly on a real Stripe Payment Link checkout
  • Consumption-timing assumption confirmed: Stripe consumes virtual cards on successful charge, NOT first submit/fill — retry-after-failed-checkout works within valid_until
  • Replay/transcript integrity: zero PAN/CVV/holder-name in persisted agent trajectories
  • 462 unit tests + 758/758 contract tests + plugin-inspector PASS + all 4 boundary lints clean

Discussion / open questions

  1. PR shape: planning to open as one PR with squash-merge. The branch has logically distinct commits; squash gives upstream a single clean entry. Acceptable?
  2. Workspace dependency conventions: declared typebox: 1.1.34 and zod: ^4.3.6 in extensions/payment/package.json matching workspace versions. Should they be workspace:* instead?
  3. Plugin-inspector synthetic probes for the 2 hooks: deferred to a follow-up. They'd validate handler-return shape but don't exercise SDK adjusted-params propagation (which is covered by the existing tests). Acceptable for V1?
  4. F1/F2/F3 future units: prefer separate PRs or umbrella tracking issue?

References

extent analysis

TL;DR

The proposed payment plugin for OpenClaw requires review and testing to ensure its security and functionality, particularly with regards to the Stripe Link integration and the handling of sensitive payment information.

Guidance

  • Review the plugin's architecture and implementation to ensure it meets the security invariants and requirements outlined in the proposal, such as the use of sentinel substitution and the redaction of sensitive payment information.
  • Test the plugin thoroughly, including end-to-end testing with the Stripe Link CLI and Mobile app, to ensure it works as expected and does not introduce any security vulnerabilities.
  • Consider the proposed PR shape and workspace dependency conventions to ensure they align with the project's standards and best practices.
  • Evaluate the need for plugin-inspector synthetic probes for the hooks and determine whether they can be deferred to a follow-up or should be included in the initial implementation.

Example

No code snippet is provided as the issue does not contain specific code that needs to be modified or implemented.

Notes

The proposal outlines a complex payment plugin with multiple components and integrations, and its review and testing require careful consideration of security and functionality requirements. The use of Stripe Link and the handling of sensitive payment information add to the complexity and require special attention.

Recommendation

Apply a thorough review and testing process to ensure the plugin meets the required security and functionality standards before merging it into the main codebase. This includes reviewing the architecture and implementation, testing the plugin end-to-end, and evaluating the PR shape and workspace dependency conventions.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING