diff --git a/backlog/tasks/task-109 - QR-Code-Payment-Requests-for-rCart.md b/backlog/tasks/task-109 - QR-Code-Payment-Requests-for-rCart.md new file mode 100644 index 0000000..b99d2bf --- /dev/null +++ b/backlog/tasks/task-109 - QR-Code-Payment-Requests-for-rCart.md @@ -0,0 +1,75 @@ +--- +id: TASK-109 +title: QR Code Payment Requests for rCart +status: Done +assignee: [] +created_date: '2026-03-11 23:43' +labels: + - rcart + - payments + - QR + - crypto +dependencies: [] +references: + - modules/rcart/mod.ts + - modules/rcart/schemas.ts + - modules/rcart/components/folk-payment-page.ts + - modules/rcart/components/folk-payment-request.ts + - shared/transak.ts +priority: high +--- + +## Description + + +Add shareable QR code payment system to rCart. When scanned, the QR opens a public payment page where anyone can pay via credit card (Transak), external wallet (MetaMask via EIP-6963), or EncryptID passkey-derived EOA. + +Includes: +- PaymentRequestDoc schema with payment type, inventory limits, enabled methods +- 7 API endpoints (create, list, get, update status, QR SVG, Transak session, page routes) +- folk-payment-page.ts: payer-facing 3-tab payment page (Card/Wallet/EncryptID) +- folk-payment-request.ts: self-service QR generator with passkey auth +- Payment type: single (one-time) or subscription (reusable QR, accepts multiple payments) +- Inventory limits: maxPayments cap with auto-fill status when limit reached +- Payment method toggles: enable/disable card/wallet/encryptid per payment request +- Extracted shared Transak utilities to shared/transak.ts +- publicWrite on cartModule for public payment page access + + +## Acceptance Criteria + +- [ ] #1 POST /api/payments creates payment request with all fields +- [ ] #2 GET /pay/:id renders public payment page with enabled tabs only +- [ ] #3 GET /request renders self-service QR generator with passkey auth +- [ ] #4 GET /api/payments/:id/qr returns SVG QR code +- [ ] #5 Payment type toggle: single vs subscription +- [ ] #6 Inventory limit: maxPayments with auto-fill when reached +- [ ] #7 Payment method toggles: card/wallet/encryptid per request +- [ ] #8 Wallet tab: EIP-6963 discovery + ERC-20/ETH transfer +- [ ] #9 Card tab: Transak iframe integration +- [ ] #10 EncryptID tab: passkey + viem signing + + +## Final Summary + + +Implemented full QR code payment request system for rCart across two sessions: + +**Session 1** — Core implementation: +- Created PaymentRequestDoc schema with Automerge CRDT storage +- Added 7 API routes: create, list, get, status update, QR SVG, Transak session, page routes +- Built folk-payment-page.ts (payer-facing, 3 tabs: Card/Wallet/EncryptID) +- Built folk-payment-request.ts (self-service QR generator with passkey auth) +- Extracted Transak utils to shared/transak.ts, updated rFlows import +- Added amountEditable support for tip/donation use cases + +**Session 2** — Enhancements + 403 fix: +- Fixed 403 "write access required" by adding publicWrite to cartModule +- Added paymentType: 'single' | 'subscription' toggle +- Added maxPayments inventory limit with paymentCount tracking + 'filled' status +- Added enabledMethods toggles (card/wallet/encryptid) per payment request +- Payment page only renders enabled tabs, shows inventory progress bar +- Subscriptions reset to pending after each payment until filled + +Commits: 636fc13, deployed to production. + diff --git a/server/landing.ts b/server/landing.ts index d08b619..a3ebd7c 100644 --- a/server/landing.ts +++ b/server/landing.ts @@ -31,8 +31,26 @@ export function renderMainLanding(modules: ModuleInfo[]): string { - rSpace — Community Platform - + + rSpace — Own Your Community Infrastructure + + + + + + + + + + + + + + + + + + diff --git a/server/shell.ts b/server/shell.ts index 9081994..acfd28e 100644 --- a/server/shell.ts +++ b/server/shell.ts @@ -111,6 +111,14 @@ export function renderShell(opts: ShellOptions): string { ${escapeHtml(title)} + + + + + + + + diff --git a/website/public/og-image.png b/website/public/og-image.png new file mode 100644 index 0000000..9dbc3b4 Binary files /dev/null and b/website/public/og-image.png differ