Skip to content

mppx validate: Stripe testmode payment support#641

Merged
brendanjryan merged 1 commit into
wevm:mainfrom
bensandler-stripe:bensandler-validate-stripe-payments
Jul 13, 2026
Merged

mppx validate: Stripe testmode payment support#641
brendanjryan merged 1 commit into
wevm:mainfrom
bensandler-stripe:bensandler-validate-stripe-payments

Conversation

@bensandler-stripe

@bensandler-stripe bensandler-stripe commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Adds Stripe payment validation to mppx validate. When a server's 402 challenge includes a Stripe payment method, validate can now complete the full payment flow end-to-end using a test card.

Stripe testmode payments:

  • Pays with pm_card_visa automatically when test key is available
  • If the server rejects the test payment (e.g. it's running in livemode), skips gracefully with a hint rather than reporting a failure
  • Validates full round-trip: SPT creation → credential submission → receipt verification

Other incidental fixes:

Existing JSON output mode (-j) for agents:

  • Runs fully non-interactive (no prompts, no console output leaking into stdout)
  • Returns structured results with suggestions array of actionable next steps (e.g. "validate testnet too")
  • Designed for CI pipelines and AI agent consumption

Examples

Live app
bensandler@st-bensandler3  ~/stripe/mppx   bensandler-validate-stripe-payments  npx tsx src/bin.ts validate https://v0-starlink-payment-api.vercel.app

mppx validate https://v0-starlink-payment-api.vercel.app


Discovery (/openapi.json)
  ✓ Document found and parseable
  ✓ Valid OpenAPI structure
  ✓ Paid endpoints found (2 endpoint(s))

POST /api/flight-starlink
  Challenge
  ✓ Returns 402 without credentials
  ✓ WWW-Authenticate header present (Payment scheme)
  ✓ Challenge parseable (4 methods: tempo/charge, evm/charge, solana/charge, stripe/charge)
  ✓ Challenge has id
  ✓ Challenge has realm
  ✓ Challenge expires in the future (5m from now)
  ⚠ Realm matches server hostname (realm="v0-starlink-payment-gnznzttgq-ben-sandler-s-projects.vercel.app" vs host="v0-starlink-payment-api.vercel.app")
    → Set the realm to your production hostname (or base domain) in the challenge.
  ✓ [tempo] Valid recipient address
  ✓ [tempo] Valid currency address (mainnet)
  ✓ [tempo] Amount is valid integer string
  ✓ [evm] Valid recipient address
  ✓ [evm] Valid currency address (mainnet)
  ✓ [evm] Amount is valid integer string
  ✓ [evm] Has chainId (8453)
  ✓ [stripe] Amount is valid integer string
  ✓ [stripe] Valid currency code (USD)
  ✓ [stripe] Has networkId (profile_61UfVbHEBmn7)
  ✓ [stripe] Has paymentMethodTypes (card, link, crypto)
  Error Handling
  ✓ Malformed credential returns 402 (not 500)
  ✓ Error response includes fresh challenge

    Attempting payment with wallet 0x79EBcD74c8e1db9fb78D06Ac53534eE8c92e6f40
▸   Pay $0.01 USDC.e on Tempo Mainnet. Continue? (y/N) y
  ✓ Payment [tempo]: submitted
  ✓ Payment: successful (HTTP 200)
  ✓ Payment-Receipt header present
  ✓ Receipt parseable
  ✓ Receipt status is "success"
  ✓ Receipt reference valid (0x358f6e240ecb344871...)
  ✓ Receipt timestamp recent (0s ago)
  ✓ Response body non-empty (application/json, 245B)
  ✓ Content-Type header set (application/json)
  ✓ On-chain transaction (https://explore.tempo.xyz/receipt/0x358f6e240ecb344871bb7a1f4ca317ddcb87b63f3432a7be73bb62d4a040efa3)

    Attempting payment with wallet 0x79EBcD74c8e1db9fb78D06Ac53534eE8c92e6f40
▸   Pay $0.01 USDC on Base. Continue? (y/N) y
  ✓ Payment [evm]: submitted
  ✓ Payment: successful (HTTP 200)
  ✓ Payment-Receipt header present
  ✓ Receipt parseable
  ✓ Receipt status is "success"
  ✓ Receipt reference valid (0xd0523e736c8600c117...)
  ✓ Receipt timestamp recent (0s ago)
  ✓ Response body non-empty (application/json, 245B)
  ✓ Content-Type header set (application/json)
  ✓ On-chain transaction (https://basescan.org/tx/0xd0523e736c8600c1175d06ae2e92ffd801758dc5d1e91ee1e0f1072df5f3bc9e)

    Attempting: $0.50 USD via Stripe (testmode)
  ✓ Payment [stripe]: submitted
  ○ Payment [stripe]: server is in livemode
    → Run your server with a Stripe test key to automatically validate Stripe payments in testmode.

GET /api/flight-starlink/{flightNumber}
  Challenge
  ✓ Returns 402 without credentials
  ✓ WWW-Authenticate header present (Payment scheme)
  ✓ Challenge parseable (4 methods: tempo/charge, evm/charge, solana/charge, stripe/charge)
  ✓ Challenge has id
  ✓ Challenge has realm
  ✓ Challenge expires in the future (5m from now)
  ⚠ Realm matches server hostname (realm="v0-starlink-payment-gnznzttgq-ben-sandler-s-projects.vercel.app" vs host="v0-starlink-payment-api.vercel.app")
    → Set the realm to your production hostname (or base domain) in the challenge.
  ✓ [tempo] Valid recipient address
  ✓ [tempo] Valid currency address (mainnet)
  ✓ [tempo] Amount is valid integer string
  ✓ [evm] Valid recipient address
  ✓ [evm] Valid currency address (mainnet)
  ✓ [evm] Amount is valid integer string
  ✓ [evm] Has chainId (8453)
  ✓ [stripe] Amount is valid integer string
  ✓ [stripe] Valid currency code (USD)
  ✓ [stripe] Has networkId (profile_61UfVbHEBmn7)
  ✓ [stripe] Has paymentMethodTypes (card, link, crypto)
  Error Handling
  ✓ Malformed credential returns 402 (not 500)
  ✓ Error response includes fresh challenge

    Attempting payment with wallet 0x79EBcD74c8e1db9fb78D06Ac53534eE8c92e6f40
▸   Pay $0.01 USDC.e on Tempo Mainnet. Continue? (y/N) y
  ✓ Payment [tempo]: submitted
  ✓ Payment: successful (HTTP 200)
  ✓ Payment-Receipt header present
  ✓ Receipt parseable
  ✓ Receipt status is "success"
  ✓ Receipt reference valid (0xbb94ab6eb3f9188830...)
  ✓ Receipt timestamp recent (0s ago)
  ✓ Response body non-empty (application/json, 186B)
  ✓ Content-Type header set (application/json)
  ✓ On-chain transaction (https://explore.tempo.xyz/receipt/0xbb94ab6eb3f9188830d53b29a76909c1ad9732a959dc4f373f2b0ee02da21d21)

    Attempting payment with wallet 0x79EBcD74c8e1db9fb78D06Ac53534eE8c92e6f40
▸   Pay $0.01 USDC on Base. Continue? (y/N) y
  ✓ Payment [evm]: submitted
  ✓ Payment: successful (HTTP 200)
  ✓ Payment-Receipt header present
  ✓ Receipt parseable
  ✓ Receipt status is "success"
  ✓ Receipt reference valid (0x2a0ccc543e2978ede0...)
  ✓ Receipt timestamp recent (0s ago)
  ✓ Response body non-empty (application/json, 186B)
  ✓ Content-Type header set (application/json)
  ✓ On-chain transaction (https://basescan.org/tx/0x2a0ccc543e2978ede0e858bfac25f3f7ee6999b1ea5500b364f989d9a7088af1)

    Attempting: $0.50 USD via Stripe (testmode)
  ✓ Payment [stripe]: submitted
  ○ Payment [stripe]: server is in livemode
    → Run your server with a Stripe test key to automatically validate Stripe payments in testmode.

Summary: 83 passed, 2 warning(s), 2 skipped

  Tip: also validate your testnet server for free. This CLI automatically provisions and funds a testnet wallet for testing.
 bensandler@st-bensandler3  ~/stripe/mppx   bensandler-validate-stripe-payments  npx tsx src/bin.ts validate https://v0-starlink-payment-api.vercel.app -j
{
  "url": "https://v0-starlink-payment-api.vercel.app",
  "discovery": {
    "found": true,
    "valid": true,
    "endpoints": [
      {
        "method": "POST",
        "path": "/api/flight-starlink"
      },
      {
        "method": "GET",
        "path": "/api/flight-starlink/{flightNumber}",
        "parameters": [
          {
            "name": "flightNumber",
            "in": "path",
            "schema": {
              "type": "string",
              "example": "UA2145"
            }
          }
        ]
      }
    ],
    "checks": [
      {
        "label": "Document found and parseable",
        "severity": "pass"
      },
      {
        "label": "Valid OpenAPI structure",
        "severity": "pass"
      },
      {
        "label": "Paid endpoints found",
        "detail": "2 endpoint(s)",
        "severity": "pass"
      }
    ],
    "doc": {
      "openapi": "3.1.0",
      "info": {
        "title": "Flight Starlink Checker API",
        "version": "2.0.0"
      },
      "x-service-info": {
        "categories": [
          "data",
          "travel"
        ],
        "docs": {
          "homepage": "https://v0-starlink-payment-api.vercel.app"
        }
      },
      "paths": {
        "/api/flight-starlink": {
          "post": {
            "summary": "Check if a flight has Starlink WiFi (POST with body)",
            "x-payment-required": true,
            "requestBody": {
              "required": true,
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "required": [
                      "flightNumber"
                    ],
                    "properties": {
                      "flightNumber": {
                        "type": "string",
                        "example": "UA2145"
                      },
                      "date": {
                        "type": "string",
                        "example": "2026-07-10"
                      }
                    }
                  }
                }
              }
            },
            "responses": {
              "200": {
                "description": "Flight found with Starlink WiFi status"
              },
              "400": {
                "description": "Missing or unsupported flight number"
              },
              "402": {
                "description": "Payment required"
              },
              "404": {
                "description": "Flight not found"
              }
            }
          }
        },
        "/api/flight-starlink/{flightNumber}": {
          "get": {
            "summary": "Check if a flight has Starlink WiFi (x402-compatible GET)",
            "x-payment-required": true,
            "parameters": [
              {
                "name": "flightNumber",
                "in": "path",
                "required": true,
                "schema": {
                  "type": "string",
                  "example": "UA2145"
                }
              }
            ],
            "responses": {
              "200": {
                "description": "Flight found with Starlink WiFi status"
              },
              "400": {
                "description": "Unsupported airline"
              },
              "402": {
                "description": "Payment required"
              },
              "404": {
                "description": "Flight not found"
              }
            }
          }
        }
      }
    }
  },
  "endpoints": [
    {
      "method": "POST",
      "path": "/api/flight-starlink",
      "challenge": [
        {
          "label": "Returns 402 without credentials",
          "severity": "pass"
        },
        {
          "label": "WWW-Authenticate header present",
          "detail": "Payment scheme",
          "severity": "pass"
        },
        {
          "label": "Challenge parseable",
          "detail": "4 methods: tempo/charge, evm/charge, solana/charge, stripe/charge",
          "severity": "pass"
        },
        {
          "label": "Challenge has id",
          "severity": "pass"
        },
        {
          "label": "Challenge has realm",
          "severity": "pass"
        },
        {
          "label": "Challenge expires in the future",
          "detail": "5m from now",
          "severity": "pass"
        },
        {
          "label": "Realm matches server hostname",
          "severity": "warn",
          "detail": "realm=\"v0-starlink-payment-gnznzttgq-ben-sandler-s-projects.vercel.app\" vs host=\"v0-starlink-payment-api.vercel.app\"",
          "hint": "Set the realm to your production hostname (or base domain) in the challenge."
        },
        {
          "label": "[tempo] Valid recipient address",
          "severity": "pass"
        },
        {
          "label": "[tempo] Valid currency address",
          "detail": "mainnet",
          "severity": "pass"
        },
        {
          "label": "[tempo] Amount is valid integer string",
          "severity": "pass"
        },
        {
          "label": "[evm] Valid recipient address",
          "severity": "pass"
        },
        {
          "label": "[evm] Valid currency address",
          "detail": "mainnet",
          "severity": "pass"
        },
        {
          "label": "[evm] Amount is valid integer string",
          "severity": "pass"
        },
        {
          "label": "[evm] Has chainId",
          "detail": "8453",
          "severity": "pass"
        },
        {
          "label": "[stripe] Amount is valid integer string",
          "severity": "pass"
        },
        {
          "label": "[stripe] Valid currency code",
          "detail": "USD",
          "severity": "pass"
        },
        {
          "label": "[stripe] Has networkId",
          "detail": "profile_61UfVbHEBmn7",
          "severity": "pass"
        },
        {
          "label": "[stripe] Has paymentMethodTypes",
          "detail": "card, link, crypto",
          "severity": "pass"
        }
      ],
      "errorHandling": [
        {
          "label": "Malformed credential returns 402",
          "detail": "not 500",
          "severity": "pass"
        },
        {
          "label": "Error response includes fresh challenge",
          "severity": "pass"
        }
      ],
      "payment": [
        {
          "label": "Payment [tempo]",
          "detail": "non-interactive mode, use --yes to approve",
          "severity": "skip"
        },
        {
          "label": "Payment [evm]",
          "detail": "non-interactive mode, use --yes to approve",
          "severity": "skip"
        },
        {
          "label": "Payment [stripe]: submitted",
          "severity": "pass"
        },
        {
          "label": "Payment [stripe]: server is in livemode",
          "severity": "skip",
          "hint": "Run your server with a Stripe test key to automatically validate Stripe payments in testmode."
        }
      ]
    },
    {
      "method": "GET",
      "path": "/api/flight-starlink/{flightNumber}",
      "challenge": [
        {
          "label": "Returns 402 without credentials",
          "severity": "pass"
        },
        {
          "label": "WWW-Authenticate header present",
          "detail": "Payment scheme",
          "severity": "pass"
        },
        {
          "label": "Challenge parseable",
          "detail": "4 methods: tempo/charge, evm/charge, solana/charge, stripe/charge",
          "severity": "pass"
        },
        {
          "label": "Challenge has id",
          "severity": "pass"
        },
        {
          "label": "Challenge has realm",
          "severity": "pass"
        },
        {
          "label": "Challenge expires in the future",
          "detail": "5m from now",
          "severity": "pass"
        },
        {
          "label": "Realm matches server hostname",
          "severity": "warn",
          "detail": "realm=\"v0-starlink-payment-gnznzttgq-ben-sandler-s-projects.vercel.app\" vs host=\"v0-starlink-payment-api.vercel.app\"",
          "hint": "Set the realm to your production hostname (or base domain) in the challenge."
        },
        {
          "label": "[tempo] Valid recipient address",
          "severity": "pass"
        },
        {
          "label": "[tempo] Valid currency address",
          "detail": "mainnet",
          "severity": "pass"
        },
        {
          "label": "[tempo] Amount is valid integer string",
          "severity": "pass"
        },
        {
          "label": "[evm] Valid recipient address",
          "severity": "pass"
        },
        {
          "label": "[evm] Valid currency address",
          "detail": "mainnet",
          "severity": "pass"
        },
        {
          "label": "[evm] Amount is valid integer string",
          "severity": "pass"
        },
        {
          "label": "[evm] Has chainId",
          "detail": "8453",
          "severity": "pass"
        },
        {
          "label": "[stripe] Amount is valid integer string",
          "severity": "pass"
        },
        {
          "label": "[stripe] Valid currency code",
          "detail": "USD",
          "severity": "pass"
        },
        {
          "label": "[stripe] Has networkId",
          "detail": "profile_61UfVbHEBmn7",
          "severity": "pass"
        },
        {
          "label": "[stripe] Has paymentMethodTypes",
          "detail": "card, link, crypto",
          "severity": "pass"
        }
      ],
      "errorHandling": [
        {
          "label": "Malformed credential returns 402",
          "detail": "not 500",
          "severity": "pass"
        },
        {
          "label": "Error response includes fresh challenge",
          "severity": "pass"
        }
      ],
      "payment": [
        {
          "label": "Payment [tempo]",
          "detail": "non-interactive mode, use --yes to approve",
          "severity": "skip"
        },
        {
          "label": "Payment [evm]",
          "detail": "non-interactive mode, use --yes to approve",
          "severity": "skip"
        },
        {
          "label": "Payment [stripe]: submitted",
          "severity": "pass"
        },
        {
          "label": "Payment [stripe]: server is in livemode",
          "severity": "skip",
          "hint": "Run your server with a Stripe test key to automatically validate Stripe payments in testmode."
        }
      ]
    }
  ],
  "summary": {
    "passed": 43,
    "failed": 0,
    "warnings": 2,
    "skipped": 6
  },
  "suggestions": [
    "Validate your testnet server to test without real funds (Tempo wallets are automatically provisioned).",
    "Validate your testmode Stripe server to test card payments end-to-end (auto-pays with test card)."
  ]
}
Test app
bensandler@st-bensandler3  ~/stripe/mppx   bensandler-validate-stripe-payments  npx tsx src/bin.ts validate https://v0-starlink-payment-api-git-test-ben-sandler-s-projects.vercel.app

mppx validate https://v0-starlink-payment-api-git-test-ben-sandler-s-projects.vercel.app


Discovery (/openapi.json)
  ✓ Document found and parseable
  ✓ Valid OpenAPI structure
  ✓ Paid endpoints found (2 endpoint(s))

POST /api/flight-starlink
  Challenge
  ✓ Returns 402 without credentials
  ✓ WWW-Authenticate header present (Payment scheme)
  ✓ Challenge parseable (2 methods: evm/charge, stripe/charge)
  ✓ Challenge has id
  ✓ Challenge has realm
  ✓ Challenge expires in the future (5m from now)
  ⚠ Realm matches server hostname (realm="v0-starlink-payment-5x67zj7z3-ben-sandler-s-projects.vercel.app" vs host="v0-starlink-payment-api-git-test-ben-sandler-s-projects.vercel.app")
    → Set the realm to your production hostname (or base domain) in the challenge.
  ✓ [evm] Valid recipient address
  ✓ [evm] Valid currency address (testnet)
  ✓ [evm] Amount is valid integer string
  ✓ [evm] Has chainId (84532)
  ✓ [stripe] Amount is valid integer string
  ✓ [stripe] Valid currency code (USD)
  ✓ [stripe] Has networkId (profile_61UfVbHEBmn7)
  ✓ [stripe] Has paymentMethodTypes (card, link, crypto)
  Error Handling
  ✓ Malformed credential returns 402 (not 500)
  ✓ Error response includes fresh challenge

    Attempting payment with wallet 0x79EBcD74c8e1db9fb78D06Ac53534eE8c92e6f40
    Auto-approved: $0.01 USDC on Base Sepolia (testnet)
  ✓ Payment [evm]: submitted
  ✓ Payment: successful (HTTP 200)
  ✓ Payment-Receipt header present
  ✓ Receipt parseable
  ✓ Receipt status is "success"
  ✓ Receipt reference valid (0x88315025784948679f...)
  ✓ Receipt timestamp recent (0s ago)
  ✓ Response body non-empty (application/json, 245B)
  ✓ Content-Type header set (application/json)
  ✓ On-chain transaction (https://sepolia.basescan.org/tx/0x88315025784948679f15972919ca28fcab6fa1141549fa3b666d22dbfbe95f27)

    Attempting: $0.50 USD via Stripe (testmode)
  ✓ Payment [stripe]: submitted
  ✓ Payment [stripe]: successful (HTTP 200)

GET /api/flight-starlink/{flightNumber}
  Challenge
  ✓ Returns 402 without credentials
  ✓ WWW-Authenticate header present (Payment scheme)
  ✓ Challenge parseable (2 methods: evm/charge, stripe/charge)
  ✓ Challenge has id
  ✓ Challenge has realm
  ✓ Challenge expires in the future (5m from now)
  ⚠ Realm matches server hostname (realm="v0-starlink-payment-5x67zj7z3-ben-sandler-s-projects.vercel.app" vs host="v0-starlink-payment-api-git-test-ben-sandler-s-projects.vercel.app")
    → Set the realm to your production hostname (or base domain) in the challenge.
  ✓ [evm] Valid recipient address
  ✓ [evm] Valid currency address (testnet)
  ✓ [evm] Amount is valid integer string
  ✓ [evm] Has chainId (84532)
  ✓ [stripe] Amount is valid integer string
  ✓ [stripe] Valid currency code (USD)
  ✓ [stripe] Has networkId (profile_61UfVbHEBmn7)
  ✓ [stripe] Has paymentMethodTypes (card, link, crypto)
  Error Handling
  ✓ Malformed credential returns 402 (not 500)
  ✓ Error response includes fresh challenge

    Attempting payment with wallet 0x79EBcD74c8e1db9fb78D06Ac53534eE8c92e6f40
    Auto-approved: $0.01 USDC on Base Sepolia (testnet)
  ✓ Payment [evm]: submitted
  ✓ Payment: successful (HTTP 200)
  ✓ Payment-Receipt header present
  ✓ Receipt parseable
  ✓ Receipt status is "success"
  ✓ Receipt reference valid (0xf9079c7e47b74cfcb3...)
  ✓ Receipt timestamp recent (0s ago)
  ✓ Response body non-empty (application/json, 186B)
  ✓ Content-Type header set (application/json)
  ✓ On-chain transaction (https://sepolia.basescan.org/tx/0xf9079c7e47b74cfcb3fae50f53f0733424faf3f5b8331383cc100adfaf0d9912)

    Attempting: $0.50 USD via Stripe (testmode)
  ✓ Payment [stripe]: submitted
  ✓ Payment [stripe]: successful (HTTP 200)

Summary: 59 passed, 2 warning(s)

  Tip: also validate your mainnet server to confirm real payments work end-to-end.
 bensandler@st-bensandler3  ~/stripe/mppx   bensandler-validate-stripe-payments  npx tsx src/bin.ts validate https://v0-starlink-payment-api-git-test-ben-sandler-s-projects.vercel.app -j
{
  "url": "https://v0-starlink-payment-api-git-test-ben-sandler-s-projects.vercel.app",
  "discovery": {
    "found": true,
    "valid": true,
    "endpoints": [
      {
        "method": "POST",
        "path": "/api/flight-starlink"
      },
      {
        "method": "GET",
        "path": "/api/flight-starlink/{flightNumber}",
        "parameters": [
          {
            "name": "flightNumber",
            "in": "path",
            "schema": {
              "type": "string",
              "example": "UA2145"
            }
          }
        ]
      }
    ],
    "checks": [
      {
        "label": "Document found and parseable",
        "severity": "pass"
      },
      {
        "label": "Valid OpenAPI structure",
        "severity": "pass"
      },
      {
        "label": "Paid endpoints found",
        "detail": "2 endpoint(s)",
        "severity": "pass"
      }
    ],
    "doc": {
      "openapi": "3.1.0",
      "info": {
        "title": "Flight Starlink Checker API",
        "version": "2.0.0"
      },
      "x-service-info": {
        "categories": [
          "data",
          "travel"
        ],
        "docs": {
          "homepage": "https://v0-starlink-payment-api.vercel.app"
        }
      },
      "paths": {
        "/api/flight-starlink": {
          "post": {
            "summary": "Check if a flight has Starlink WiFi (POST with body)",
            "x-payment-required": true,
            "requestBody": {
              "required": true,
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "required": [
                      "flightNumber"
                    ],
                    "properties": {
                      "flightNumber": {
                        "type": "string",
                        "example": "UA2145"
                      },
                      "date": {
                        "type": "string",
                        "example": "2026-07-10"
                      }
                    }
                  }
                }
              }
            },
            "responses": {
              "200": {
                "description": "Flight found with Starlink WiFi status"
              },
              "400": {
                "description": "Missing or unsupported flight number"
              },
              "402": {
                "description": "Payment required"
              },
              "404": {
                "description": "Flight not found"
              }
            }
          }
        },
        "/api/flight-starlink/{flightNumber}": {
          "get": {
            "summary": "Check if a flight has Starlink WiFi (x402-compatible GET)",
            "x-payment-required": true,
            "parameters": [
              {
                "name": "flightNumber",
                "in": "path",
                "required": true,
                "schema": {
                  "type": "string",
                  "example": "UA2145"
                }
              }
            ],
            "responses": {
              "200": {
                "description": "Flight found with Starlink WiFi status"
              },
              "400": {
                "description": "Unsupported airline"
              },
              "402": {
                "description": "Payment required"
              },
              "404": {
                "description": "Flight not found"
              }
            }
          }
        }
      }
    }
  },
  "endpoints": [
    {
      "method": "POST",
      "path": "/api/flight-starlink",
      "challenge": [
        {
          "label": "Returns 402 without credentials",
          "severity": "pass"
        },
        {
          "label": "WWW-Authenticate header present",
          "detail": "Payment scheme",
          "severity": "pass"
        },
        {
          "label": "Challenge parseable",
          "detail": "2 methods: evm/charge, stripe/charge",
          "severity": "pass"
        },
        {
          "label": "Challenge has id",
          "severity": "pass"
        },
        {
          "label": "Challenge has realm",
          "severity": "pass"
        },
        {
          "label": "Challenge expires in the future",
          "detail": "5m from now",
          "severity": "pass"
        },
        {
          "label": "Realm matches server hostname",
          "severity": "warn",
          "detail": "realm=\"v0-starlink-payment-5x67zj7z3-ben-sandler-s-projects.vercel.app\" vs host=\"v0-starlink-payment-api-git-test-ben-sandler-s-projects.vercel.app\"",
          "hint": "Set the realm to your production hostname (or base domain) in the challenge."
        },
        {
          "label": "[evm] Valid recipient address",
          "severity": "pass"
        },
        {
          "label": "[evm] Valid currency address",
          "detail": "testnet",
          "severity": "pass"
        },
        {
          "label": "[evm] Amount is valid integer string",
          "severity": "pass"
        },
        {
          "label": "[evm] Has chainId",
          "detail": "84532",
          "severity": "pass"
        },
        {
          "label": "[stripe] Amount is valid integer string",
          "severity": "pass"
        },
        {
          "label": "[stripe] Valid currency code",
          "detail": "USD",
          "severity": "pass"
        },
        {
          "label": "[stripe] Has networkId",
          "detail": "profile_61UfVbHEBmn7",
          "severity": "pass"
        },
        {
          "label": "[stripe] Has paymentMethodTypes",
          "detail": "card, link, crypto",
          "severity": "pass"
        }
      ],
      "errorHandling": [
        {
          "label": "Malformed credential returns 402",
          "detail": "not 500",
          "severity": "pass"
        },
        {
          "label": "Error response includes fresh challenge",
          "severity": "pass"
        }
      ],
      "payment": [
        {
          "label": "Payment [evm]: submitted",
          "severity": "pass"
        },
        {
          "label": "Payment: successful",
          "detail": "HTTP 200",
          "severity": "pass"
        },
        {
          "label": "Payment-Receipt header present",
          "severity": "pass"
        },
        {
          "label": "Receipt parseable",
          "severity": "pass"
        },
        {
          "label": "Receipt status is \"success\"",
          "severity": "pass"
        },
        {
          "label": "Receipt reference valid",
          "detail": "0x74bbe13f08e7ded821...",
          "severity": "pass"
        },
        {
          "label": "Receipt timestamp recent",
          "detail": "0s ago",
          "severity": "pass"
        },
        {
          "label": "Response body non-empty",
          "detail": "application/json, 245B",
          "severity": "pass"
        },
        {
          "label": "Content-Type header set",
          "detail": "application/json",
          "severity": "pass"
        },
        {
          "label": "On-chain transaction",
          "detail": "https://sepolia.basescan.org/tx/0x74bbe13f08e7ded821b187295f43885886b133a916443875216729a42fb3bf87",
          "severity": "pass"
        },
        {
          "label": "Payment [stripe]: submitted",
          "severity": "pass"
        },
        {
          "label": "Payment [stripe]: successful",
          "detail": "HTTP 200",
          "severity": "pass"
        }
      ]
    },
    {
      "method": "GET",
      "path": "/api/flight-starlink/{flightNumber}",
      "challenge": [
        {
          "label": "Returns 402 without credentials",
          "severity": "pass"
        },
        {
          "label": "WWW-Authenticate header present",
          "detail": "Payment scheme",
          "severity": "pass"
        },
        {
          "label": "Challenge parseable",
          "detail": "2 methods: evm/charge, stripe/charge",
          "severity": "pass"
        },
        {
          "label": "Challenge has id",
          "severity": "pass"
        },
        {
          "label": "Challenge has realm",
          "severity": "pass"
        },
        {
          "label": "Challenge expires in the future",
          "detail": "5m from now",
          "severity": "pass"
        },
        {
          "label": "Realm matches server hostname",
          "severity": "warn",
          "detail": "realm=\"v0-starlink-payment-5x67zj7z3-ben-sandler-s-projects.vercel.app\" vs host=\"v0-starlink-payment-api-git-test-ben-sandler-s-projects.vercel.app\"",
          "hint": "Set the realm to your production hostname (or base domain) in the challenge."
        },
        {
          "label": "[evm] Valid recipient address",
          "severity": "pass"
        },
        {
          "label": "[evm] Valid currency address",
          "detail": "testnet",
          "severity": "pass"
        },
        {
          "label": "[evm] Amount is valid integer string",
          "severity": "pass"
        },
        {
          "label": "[evm] Has chainId",
          "detail": "84532",
          "severity": "pass"
        },
        {
          "label": "[stripe] Amount is valid integer string",
          "severity": "pass"
        },
        {
          "label": "[stripe] Valid currency code",
          "detail": "USD",
          "severity": "pass"
        },
        {
          "label": "[stripe] Has networkId",
          "detail": "profile_61UfVbHEBmn7",
          "severity": "pass"
        },
        {
          "label": "[stripe] Has paymentMethodTypes",
          "detail": "card, link, crypto",
          "severity": "pass"
        }
      ],
      "errorHandling": [
        {
          "label": "Malformed credential returns 402",
          "detail": "not 500",
          "severity": "pass"
        },
        {
          "label": "Error response includes fresh challenge",
          "severity": "pass"
        }
      ],
      "payment": [
        {
          "label": "Payment [evm]: submitted",
          "severity": "pass"
        },
        {
          "label": "Payment: successful",
          "detail": "HTTP 200",
          "severity": "pass"
        },
        {
          "label": "Payment-Receipt header present",
          "severity": "pass"
        },
        {
          "label": "Receipt parseable",
          "severity": "pass"
        },
        {
          "label": "Receipt status is \"success\"",
          "severity": "pass"
        },
        {
          "label": "Receipt reference valid",
          "detail": "0xfc775e1157ec22e922...",
          "severity": "pass"
        },
        {
          "label": "Receipt timestamp recent",
          "detail": "0s ago",
          "severity": "pass"
        },
        {
          "label": "Response body non-empty",
          "detail": "application/json, 186B",
          "severity": "pass"
        },
        {
          "label": "Content-Type header set",
          "detail": "application/json",
          "severity": "pass"
        },
        {
          "label": "On-chain transaction",
          "detail": "https://sepolia.basescan.org/tx/0xfc775e1157ec22e9220a44cc6c2255787f14009480f14c1d42ba142f693a1b65",
          "severity": "pass"
        },
        {
          "label": "Payment [stripe]: submitted",
          "severity": "pass"
        },
        {
          "label": "Payment [stripe]: successful",
          "detail": "HTTP 200",
          "severity": "pass"
        }
      ]
    }
  ],
  "summary": {
    "passed": 59,
    "failed": 0,
    "warnings": 2,
    "skipped": 0
  },
  "suggestions": [
    "Validate your mainnet server to confirm real payments work end-to-end."
  ]
}

@bensandler-stripe bensandler-stripe force-pushed the bensandler-validate-stripe-payments branch 4 times, most recently from 5053c86 to 7b7e756 Compare July 13, 2026 20:36
@pkg-pr-new

pkg-pr-new Bot commented Jul 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/mppx@641

commit: e6d38e4

@bensandler-stripe bensandler-stripe force-pushed the bensandler-validate-stripe-payments branch 5 times, most recently from 6de4dd3 to c1117aa Compare July 13, 2026 21:05
async function provisionAndPayTestnet(
challenge: Challenge.Challenge,
verbose: boolean,
silent?: boolean,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

easier to review when hiding whitespace:

Image

@bensandler-stripe bensandler-stripe force-pushed the bensandler-validate-stripe-payments branch 11 times, most recently from 0d03ca6 to b4584f8 Compare July 13, 2026 23:07
@bensandler-stripe bensandler-stripe marked this pull request as ready for review July 13, 2026 23:15
@bensandler-stripe bensandler-stripe force-pushed the bensandler-validate-stripe-payments branch from b4584f8 to 1bcd956 Compare July 13, 2026 23:17
@bensandler-stripe bensandler-stripe force-pushed the bensandler-validate-stripe-payments branch from 1bcd956 to 392ad27 Compare July 13, 2026 23:35
  Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

  GIT_VALID_PII_OVERRIDE
@bensandler-stripe bensandler-stripe force-pushed the bensandler-validate-stripe-payments branch from 392ad27 to e6d38e4 Compare July 13, 2026 23:37
@brendanjryan brendanjryan merged commit be7d166 into wevm:main Jul 13, 2026
14 checks passed
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.

2 participants