{"id":42424122,"url":"https://github.com/second-state/x402-payment-link","last_synced_at":"2026-01-28T03:06:33.703Z","repository":{"id":330940282,"uuid":"1080217655","full_name":"second-state/x402-payment-link","owner":"second-state","description":null,"archived":false,"fork":false,"pushed_at":"2026-01-26T07:15:00.000Z","size":458,"stargazers_count":227,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-01-26T21:40:41.091Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/second-state.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-21T03:30:13.000Z","updated_at":"2026-01-26T17:19:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/second-state/x402-payment-link","commit_stats":null,"previous_names":["second-state/x402-payment-link"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/second-state/x402-payment-link","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/second-state%2Fx402-payment-link","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/second-state%2Fx402-payment-link/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/second-state%2Fx402-payment-link/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/second-state%2Fx402-payment-link/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/second-state","download_url":"https://codeload.github.com/second-state/x402-payment-link/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/second-state%2Fx402-payment-link/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28835986,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T02:10:51.810Z","status":"ssl_error","status_checked_at":"2026-01-28T02:10:50.806Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-28T03:06:33.032Z","updated_at":"2026-01-28T03:06:33.693Z","avatar_url":"https://github.com/second-state.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# x402 Payment Page Demo\n\nA Flask-based payment page demo implementing the [x402 protocol](https://www.x402.org/) for USDC cryptocurrency payments on the Base chain. Uses the Coinbase facilitator for payment verification and settlement.\n\n## Quick Start\n\n### Prerequisites\n\n- Python 3.13+\n- [uv](https://docs.astral.sh/uv/) package manager\n- A Base wallet address for receiving USDC payments\n\n### Installation\n\n```bash\n# Clone the repository\ngit clone \u003crepository-url\u003e\ncd x402-payment-link\n\n# Install dependencies\nuv sync\n\n# Copy environment template and configure\ncp .env.example .env\n# Edit .env with your wallet address\n```\n\n### Run Locally\n\n```bash\npython3 main.py\n```\n\nThe server starts at `http://localhost:5000` (or your configured `APP_PORT`).\n\n### Run with Docker\n\n```bash\ndocker compose up --build\n```\n\n### Test the Payment Flow\n\n1. Open `http://localhost:5000/demo` in your browser\n2. Fill out the order form and submit\n3. The payment page returns a 402 status with payment requirements\n4. Use an x402-compatible wallet to complete the payment\n\n## Configuration\n\nCreate a `.env` file in the project root. See `.env.example` for a template.\n\n### Required Variables\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `ADDRESS` | Wallet address for receiving USDC payments | `0xYourBaseWalletAddress` |\n| `NETWORK` | Blockchain network | `base-sepolia` (testnet) or `base` (mainnet) |\n\n### Optional Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `APP_PORT` | `5000` | Server port |\n| `ENVIRONMENT` | `staging` | Affects product pricing (`staging` or `production`) |\n| `MAX_DEADLINE_SECONDS` | `60` | Payment timeout in seconds |\n| `FACILITATOR_URL` | `https://x402f1.secondstate.io` | x402 facilitator service URL |\n| `APP_NAME` | `x402-mvp` | Application name shown in paywall |\n| `APP_LOGO` | `/static/secondstate.png` | Logo URL for paywall |\n\n### Email Notifications (Optional)\n\nTo send order confirmation emails via SendGrid:\n\n| Variable | Description |\n|----------|-------------|\n| `SENDGRID_API_KEY` | Your SendGrid API key |\n| `FROM_EMAIL` | Sender email address |\n| `ORDER_CONFIRMATION_RECIPIENT` | CC recipient for order confirmations |\n\n## How It Works\n\nThe x402 protocol enables HTTP-native cryptocurrency payments using the `402 Payment Required` status code.\n\n### Payment Flow\n\n```\n┌──────────┐     ┌──────────────┐     ┌─────────────┐     ┌─────────────┐\n│  Browse  │────▶│ Submit Order │────▶│ Payment 402 │────▶│ Settlement  │\n│ Product  │     │    Form      │     │ Requirements│     │ Confirmation│\n└──────────┘     └──────────────┘     └─────────────┘     └─────────────┘\n```\n\n1. **Browse Product** (`GET /\u003cproduct\u003e`) - User views product page with pricing\n2. **Submit Order** (`POST /\u003cproduct\u003e/order`) - Order details saved, redirects to payment\n3. **Payment Required** (`GET /\u003cproduct\u003e/order/\u003corder_id\u003e`) - Returns 402 with payment requirements if no `X-PAYMENT` header\n4. **Settlement** - Client sends payment via `X-PAYMENT` header; facilitator verifies and settles on blockchain\n5. **Confirmation** - Success page displayed with transaction link; email sent if configured\n\n## Project Structure\n\n```\n├── main.py              # Flask application entry point\n├── config.py            # Environment configuration\n├── products.yaml        # Product catalog\n├── services/\n│   ├── product_service.py     # Product catalog management\n│   ├── order_service.py       # Order persistence (JSONL)\n│   ├── payment_service.py     # x402 payment verification/settlement\n│   └── notification_service.py # SendGrid email notifications\n├── templates/\n│   └── \u003cproduct_id\u003e/\n│       ├── product.html               # Product landing page\n│       ├── order_confirmation.html    # Success page\n│       └── order_confirmation_email.html  # Email template\n├── static/              # Static assets (images, etc.)\n├── data/                # Runtime data (orders, logs)\n├── Dockerfile\n└── docker-compose.yaml\n```\n\n## Adding New Products\n\n1. Add an entry to `products.yaml`:\n\n```yaml\nmy_product:\n  name: My Product\n  description: \"Product description here\"\n  image: https://example.com/image.png\n  staging:\n    price: 0.10\n    shipping: 0.00\n  production:\n    price: 29.99\n    shipping: 4.99\n```\n\n2. Create templates in `templates/my_product/`:\n   - `product.html` - Product landing page with order form\n   - `order_confirmation.html` - Post-payment success page\n   - `order_confirmation_email.html` - Email template (optional)\n\n## Docker Deployment\n\nThe `docker-compose.yaml` configuration:\n\n```yaml\nservices:\n  x402-mvp:\n    build: .\n    restart: unless-stopped\n    ports:\n      - \"${SERVER_PORT}:${APP_PORT}\"\n    volumes:\n      - ./.env:/app/.env\n      - ./data:/app/data\n```\n\n**Volume Mounts:**\n- `.env` - Configuration file\n- `data/` - Persistent storage for orders (`\u003cproduct\u003e.txt`) and logs (`app.log`)\n\n**Port Configuration:**\n- Set `SERVER_PORT` in your environment for the external port\n- Set `APP_PORT` in `.env` for the internal Flask port\n\n## Development\n\n### Services\n\n| Service | Purpose |\n|---------|---------|\n| `product_service` | Reads product catalog from `products.yaml` |\n| `order_service` | Generates order IDs, stores orders as JSONL in `data/` |\n| `payment_service` | Creates payment requirements, verifies/settles via facilitator |\n| `notification_service` | Sends confirmation emails via SendGrid |\n\n### Testing on Testnet\n\n1. Set `NETWORK=base-sepolia` in `.env`\n2. Set `ENVIRONMENT=staging` for lower test prices ($0.10)\n3. Use a testnet wallet with Sepolia USDC\n4. No Coinbase API keys required for testnet\n\n### Order Storage\n\nOrders are stored as JSON lines in `data/\u003cproduct\u003e.txt`:\n\n```json\n{\"time\":\"2024-01-01T12:00:00\",\"email\":\"user@example.com\",\"order_id\":\"ABC123\",\"quantity\":1,\"total\":\"0.10\",\"payment\":false}\n```\n\nAfter payment settlement, a new entry is appended with `\"payment\":true`.\n\n## License\n\nSee [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecond-state%2Fx402-payment-link","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsecond-state%2Fx402-payment-link","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecond-state%2Fx402-payment-link/lists"}