Skip to content

feat: add Stripe payment method support#145

Merged
grandizzy merged 15 commits intomainfrom
georgen/stripe-method-scaffold
Mar 25, 2026
Merged

feat: add Stripe payment method support#145
grandizzy merged 15 commits intomainfrom
georgen/stripe-method-scaffold

Conversation

@decofe
Copy link
Member

@decofe decofe commented Mar 23, 2026

Summary

Adds Stripe charge method support to mpp-rs via Shared Payment Tokens (SPTs), matching the mppx TS SDK wire format.

Changes

  • src/protocol/methods/stripe/StripeMethodDetails (networkId/paymentMethodTypes/metadata under methodDetails), StripeCredentialPayload, CreateTokenResult, server ChargeMethod with analytics metadata propagation
  • src/client/stripe/StripeProvider with create_token callback receiving full challenge context, returning CreateTokenResult { spt, external_id }
  • src/server/stripe() builder, Mpp::create_stripe(), stripe_charge() / stripe_charge_with_options()
  • tests/integration_stripe.rs — e2e tests with mock Stripe API (challenge schema, callback params, metadata, error paths)
  • tests/integration_stripe_live.rs — live tests against Stripe test-mode API (real SPT creation + PaymentIntent verification), skipped when STRIPE_SECRET_KEY not set
  • CI — live Stripe tests run when STRIPE_SECRET_KEY secret is available

Testing

# Unit + mock integration tests
cargo test --features stripe,server,client stripe
cargo test --features integration-stripe --test integration_stripe

# Live Stripe tests (requires sk_test_* key with SPT access)
STRIPE_SECRET_KEY=sk_test_... cargo test --features integration-stripe-live --test integration_stripe_live

Co-Authored-By: grandizzy 38490174+grandizzy@users.noreply.github.com

Prompted by: georgen

Adds the initial implementation for Stripe charge method (TOOLS-322):

- src/protocol/methods/stripe/ — types (StripeChargeRequest,
  StripeCredentialPayload) and server-side ChargeMethod that verifies
  payments by creating a Stripe PaymentIntent with an SPT
- src/client/stripe/ — StripeProvider implementing PaymentProvider
  with a user-provided createToken callback
- src/server/ — StripeBuilder, StripeConfig, stripe() builder fn,
  Mpp::create_stripe(), Mpp::stripe_charge()
- tests/integration_stripe.rs — e2e tests against a mock Stripe API
  (full 402 flow, challenge format, requires_action rejection)
- Cargo.toml — stripe and integration-stripe feature flags

Co-Authored-By: grandizzy <38490174+grandizzy@users.noreply.github.com>
@github-actions
Copy link
Contributor

github-actions bot commented Mar 23, 2026

Tempo Lint Results

Summary

Found 687 issue(s) across 42 file(s)

Severity Count
Errors 0
Warnings 687
Hints 0

Issues by Rule Type

no-unwrap-in-lib (673 occurrences)
  • /home/runner/work/mpp-rs/mpp-rs/src/body_digest.rs:1 - Avoid .unwrap() in library code. Use proper error handling with ? or .expect() with context.
  • /home/runner/work/mpp-rs/mpp-rs/src/client/fetch.rs:1 - Avoid .unwrap() in library code. Use proper error handling with ? or .expect() with context.
  • /home/runner/work/mpp-rs/mpp-rs/src/client/fetch.rs:1 - Avoid .unwrap() in library code. Use proper error handling with ? or .expect() with context.
  • /home/runner/work/mpp-rs/mpp-rs/src/client/fetch.rs:1 - Avoid .unwrap() in library code. Use proper error handling with ? or .expect() with context.
  • /home/runner/work/mpp-rs/mpp-rs/src/client/fetch.rs:1 - Avoid .unwrap() in library code. Use proper error handling with ? or .expect() with context.
  • /home/runner/work/mpp-rs/mpp-rs/src/client/fetch.rs:1 - Avoid .unwrap() in library code. Use proper error handling with ? or .expect() with context.
  • /home/runner/work/mpp-rs/mpp-rs/src/client/fetch.rs:1 - Avoid .unwrap() in library code. Use proper error handling with ? or .expect() with context.
  • /home/runner/work/mpp-rs/mpp-rs/src/client/fetch.rs:1 - Avoid .unwrap() in library code. Use proper error handling with ? or .expect() with context.
  • /home/runner/work/mpp-rs/mpp-rs/src/client/stripe/provider.rs:1 - Avoid .unwrap() in library code. Use proper error handling with ? or .expect() with context.
  • /home/runner/work/mpp-rs/mpp-rs/src/client/tempo/session/channel_ops.rs:1 - Avoid .unwrap() in library code. Use proper error handling with ? or .expect() with context.

... and 663 more

no-leading-whitespace-strings (10 occurrences)
  • /home/runner/work/mpp-rs/mpp-rs/src/error.rs:1 - String literals should not start with leading whitespace. Found: ' for '
  • /home/runner/work/mpp-rs/mpp-rs/src/error.rs:1 - String literals should not start with leading whitespace. Found: ' ({})'
  • /home/runner/work/mpp-rs/mpp-rs/src/error.rs:1 - String literals should not start with leading whitespace. Found: ' is invalid.'
  • /home/runner/work/mpp-rs/mpp-rs/src/error.rs:1 - String literals should not start with leading whitespace. Found: ' is invalid: already used.'
  • /home/runner/work/mpp-rs/mpp-rs/src/error.rs:1 - String literals should not start with leading whitespace. Found: ' (Premium access).'
  • /home/runner/work/mpp-rs/mpp-rs/src/proxy/service.rs:1 - String literals should not start with leading whitespace. Found: ' — '
  • /home/runner/work/mpp-rs/mpp-rs/src/protocol/core/types.rs:1 - String literals should not start with leading whitespace. Found: ' and backslashes '
  • /home/runner/work/mpp-rs/mpp-rs/src/protocol/core/headers.rs:1 - String literals should not start with leading whitespace. Found: ' now'
  • /home/runner/work/mpp-rs/mpp-rs/src/protocol/core/headers.rs:1 - String literals should not start with leading whitespace. Found: ' now'
  • /home/runner/work/mpp-rs/mpp-rs/src/protocol/core/headers.rs:1 - String literals should not start with leading whitespace. Found: ' now'
unsafe-needs-safety-comment (4 occurrences)
  • /home/runner/work/mpp-rs/mpp-rs/src/server/mpp.rs:1 - Unsafe block requires a SAFETY comment explaining why this is safe.
  • /home/runner/work/mpp-rs/mpp-rs/src/server/mpp.rs:1 - Unsafe block requires a SAFETY comment explaining why this is safe.
  • /home/runner/work/mpp-rs/mpp-rs/src/server/mpp.rs:1 - Unsafe block requires a SAFETY comment explaining why this is safe.
  • /home/runner/work/mpp-rs/mpp-rs/src/server/mpp.rs:1 - Unsafe block requires a SAFETY comment explaining why this is safe.

Issues by File

View grouped by file

/home/runner/work/mpp-rs/mpp-rs/src/protocol/core/challenge.rs (85 issues)

  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • ... and 80 more

/home/runner/work/mpp-rs/mpp-rs/src/client/tempo/session/mod.rs (58 issues)

  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • ... and 53 more

/home/runner/work/mpp-rs/mpp-rs/src/client/tempo/signing/mod.rs (54 issues)

  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • ... and 49 more

/home/runner/work/mpp-rs/mpp-rs/src/server/mpp.rs (53 issues)

  • Line 1: [warning] unsafe-needs-safety-comment
  • Line 1: [warning] unsafe-needs-safety-comment
  • Line 1: [warning] unsafe-needs-safety-comment
  • Line 1: [warning] unsafe-needs-safety-comment
  • Line 1: [warning] no-unwrap-in-lib
  • ... and 48 more

/home/runner/work/mpp-rs/mpp-rs/src/protocol/methods/tempo/session_method.rs (39 issues)

  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • ... and 34 more

/home/runner/work/mpp-rs/mpp-rs/src/client/tempo/session/channel_ops.rs (38 issues)

  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • ... and 33 more

/home/runner/work/mpp-rs/mpp-rs/src/protocol/methods/tempo/method.rs (35 issues)

  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • ... and 30 more

/home/runner/work/mpp-rs/mpp-rs/src/protocol/core/headers.rs (34 issues)

  • Line 1: [warning] no-leading-whitespace-strings
  • Line 1: [warning] no-leading-whitespace-strings
  • Line 1: [warning] no-leading-whitespace-strings
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • ... and 29 more

/home/runner/work/mpp-rs/mpp-rs/src/server/middleware.rs (27 issues)

  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • ... and 22 more

/home/runner/work/mpp-rs/mpp-rs/src/mcp.rs (25 issues)

  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • Line 1: [warning] no-unwrap-in-lib
  • ... and 20 more

Showing 10 of 42 files


Posted by https://github.com/tempoxyz/lints

- Add spec-required methodDetails (networkId, paymentMethodTypes) to challenges
- Add StripeChargeOptions (description, external_id, expires, metadata)
- Add ChargeChallenger impl so MppCharge extractor works with Stripe
- Parse Stripe error response bodies for better error messages
- Add Stripe unit and integration tests

Amp-Thread-ID: https://ampcode.com/threads/T-019d1969-811c-7725-aaa6-1e0116d5652c
Co-authored-by: Amp <amp@ampcode.com>
@grandizzy grandizzy changed the title feat: scaffold Stripe payment method support feat: add Stripe payment method support Mar 23, 2026
grandizzy and others added 9 commits March 23, 2026 09:08
- Replace StripeChargeRequest with StripeMethodDetails (correct wire
  shape: networkId/paymentMethodTypes/metadata nested under methodDetails)
- stripe_charge() now emits methodDetails with networkId and
  paymentMethodTypes from config (fixes challenge schema bug)
- Add stripe_charge_with_options() + StripeChargeOptions
- Server verify() propagates metadata: analytics keys (mpp_version,
  mpp_is_mpp, mpp_intent, mpp_challenge_id, mpp_server_id,
  mpp_client_id) + user metadata from methodDetails
- Callback returns CreateTokenResult { spt, external_id } instead of
  plain String (per-payment externalId support)
- Provider extracts metadata from methodDetails.metadata and passes
  challenge JSON to callback
- Remove CreateTokenFn trait alias; use plain generic F: Fn(...)
- Provider reads networkId from methodDetails (not top-level)

Co-Authored-By: grandizzy <38490174+grandizzy@users.noreply.github.com>
Co-Authored-By: grandizzy <38490174+grandizzy@users.noreply.github.com>
- tests/integration_stripe_live.rs: tests against real Stripe test-mode
  API using test_helpers/shared_payment/granted_tokens endpoint.
  Skipped when STRIPE_SECRET_KEY is not set.
- CI runs live tests only when STRIPE_SECRET_KEY secret exists
- Tests: happy path (real SPT + PaymentIntent), invalid SPT rejection,
  expired challenge rejection

Co-Authored-By: grandizzy <38490174+grandizzy@users.noreply.github.com>
…e warning

- create_test_spt now retries without seller_details when Stripe
  returns 'Received unknown parameter' (matches mppx fallback)
- Suppress dead_code warning on ResultExt trait

Co-Authored-By: grandizzy <38490174+grandizzy@users.noreply.github.com>
Remove integration-stripe-live feature flag. Live tests now live in
integration_stripe.rs and skip at runtime when STRIPE_SECRET_KEY is
not set (matching mppx pattern). CI passes STRIPE_SECRET_KEY as env
var to the test step.

Revert #[allow(dead_code)] on ResultExt — pre-existing, not ours.

Co-Authored-By: grandizzy <38490174+grandizzy@users.noreply.github.com>
@grandizzy grandizzy marked this pull request as ready for review March 24, 2026 06:25
@grandizzy
Copy link
Contributor

a nicer split would be in tempo / stripe crates but don't think it worth at this stage

Copy link
Collaborator

@brendanjryan brendanjryan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code-wise this LGTM!

In a follow up PR could we add a small example which shows how to use this with client/server?

here is what we are doing on the python side: tempoxyz/pympp#97

- uses: taiki-e/install-action@cargo-hack
- run: cargo test --features tempo,server,client,axum,middleware,tower,utils
- name: Tests
run: cargo test --features tempo,stripe,server,client,axum,middleware,tower,utils,integration-stripe
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

fn build_analytics(credential: &PaymentCredential) -> HashMap<String, String> {
let challenge = &credential.challenge;
let mut meta = HashMap::new();
meta.insert("mpp_version".into(), "1".into());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

decofe and others added 2 commits March 25, 2026 07:32
* docs: add Stripe example (server + client)

Pay-per-fortune example demonstrating the full SPT flow:
- Axum server with /api/create-spt proxy and /api/fortune gated endpoint
- Headless CLI client using pm_card_visa test card
- Mirrors the pympp examples/stripe/ structure

Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019d20a8-7850-76dc-a346-432e5d2f4f5f

* chore: add changelog

---------

Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-Authored-By: grandizzy <38490174+grandizzy@users.noreply.github.com>
@grandizzy grandizzy merged commit 5f46ac2 into main Mar 25, 2026
4 checks passed
@grandizzy grandizzy deleted the georgen/stripe-method-scaffold branch March 25, 2026 06:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants