SurfSense/_bmad-output/implementation-artifacts/5-2-stripe-payment-integration.md
Vonic 04fb9eec0f docs: rewrite story 3.5 and epic 5 stories to match actual codebase
Stories were written for a subscription SaaS model, but SurfSense is a
self-hosted product with BYOK + optional PAYG page packs via Stripe.

Key corrections:
- Story 3.5: Not "remove BYOK + token billing" → actual gap is adding
  HTTP-layer quota pre-check before document upload enqueue
- Story 5.1: Pricing UI already exists (Free/PAYG/Enterprise) → gap is
  wiring "Get Started" button to existing Stripe checkout endpoint
- Story 5.2: mode=payment PAYG already works → needs verification/hardening
  not a subscription checkout rewrite
- Story 5.3: Webhook already handles checkout.session.completed correctly
  → no subscription events needed, gap is idempotency test + purchase history UI
- Story 5.4: PageLimitService + enforcement in tasks/connectors already exists
  → gap is HTTP-layer pre-check, quota UI indicator, and 402 frontend handling

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 14:08:55 +07:00

3.8 KiB
Raw Blame History

Story 5.2: Xác minh & Hardening Stripe PAYG Flow

Status: ready-for-dev

Context / Correction Note

⚠️ Story gốc bị sai hướng. Story gốc mô tả implement mode: "subscription" Stripe Checkout. Thực tế, SurfSense dùng mô hình PAYG (Pay-As-You-Go page packs) với mode: "payment" (one-time purchase). Endpoint POST /api/v1/stripe/create-checkout-session đã tồn tại và hoạt động. Story này chỉ cần hardening, không cần implement mới.

Story

As a Kỹ sư Hệ thống, I want đảm bảo Stripe PAYG checkout flow hoạt động ổn định end-to-end, so that user có thể mua page packs và pages được cộng vào tài khoản đúng cách.

Actual Architecture (as-is)

Đã implement:

  • POST /api/v1/stripe/create-checkout-session — tạo Stripe Checkout Session (mode: "payment")
    • Nhận search_space_id, quantity
    • Tạo PagePurchase record với status PENDING
    • Trả về checkout_url
  • _fulfill_completed_purchase() — khi webhook confirm, tăng user.pages_limit
  • _get_checkout_urls() — tạo success/cancel URL cho Stripe redirect

Config cần thiết (env vars):

  • STRIPE_SECRET_KEY
  • STRIPE_PRICE_ID — price ID cho 1 page pack
  • STRIPE_WEBHOOK_SECRET
  • STRIPE_PAGES_PER_UNIT — pages per pack (default: 1000)

Còn thiếu / chưa xác minh:

  • Frontend chưa gọi endpoint này (chặn bởi Story 5.1)
  • Chưa có test end-to-end với Stripe test mode
  • STRIPE_PRICE_ID cần được tạo trên Stripe Dashboard và config đúng

Acceptance Criteria

  1. Với Stripe test keys, tạo checkout session thành công, redirect đến Stripe test checkout page.
  2. Sau khi hoàn tất thanh toán (dùng test card 4242 4242 4242 4242), webhook trigger và pages_limit của user tăng lên đúng số lượng.
  3. Nếu STRIPE_SECRET_KEY hoặc STRIPE_PRICE_ID không được cấu hình, API trả về lỗi có thể đọc được (không crash 500).

Tasks / Subtasks

  • Task 1: Verify Stripe config
    • Subtask 1.1: Kiểm tra surfsense_backend/app/config.py — đảm bảo STRIPE_SECRET_KEY, STRIPE_PRICE_ID, STRIPE_WEBHOOK_SECRET, STRIPE_PAGES_PER_UNIT được đọc từ env vars.
    • Subtask 1.2: Đảm bảo _ensure_page_buying_enabled() trả về lỗi 503 rõ ràng thay vì crash khi Stripe chưa config.
  • Task 2: Test end-to-end với Stripe CLI
    • Subtask 2.1: Dùng stripe listen --forward-to localhost:8000/api/v1/stripe/webhook để test webhook locally.
    • Subtask 2.2: Verify PagePurchase.status chuyển từ PENDINGCOMPLETED sau webhook.
    • Subtask 2.3: Verify user.pages_limit tăng đúng quantity × STRIPE_PAGES_PER_UNIT.
  • Task 3: Thêm Stripe setup vào .env.example
    • Subtask 3.1: Bổ sung STRIPE_SECRET_KEY, STRIPE_PRICE_ID, STRIPE_WEBHOOK_SECRET, STRIPE_PAGES_PER_UNIT vào surfsense_backend/.env.example với comment hướng dẫn.

Dev Notes

Current Flow (hoạt động)

FE → POST /api/v1/stripe/create-checkout-session
   → Stripe Checkout (hosted page)
   → Stripe → POST /api/v1/stripe/webhook (checkout.session.completed)
   → _fulfill_completed_purchase() → user.pages_limit += pages_granted
   → Stripe redirects FE → success_url

PagePurchase Status Enum

  • PENDING — checkout tạo nhưng chưa thanh toán
  • COMPLETED — thanh toán thành công, pages đã được grant
  • FAILED — thanh toán thất bại

References

  • surfsense_backend/app/routes/stripe_routes.py
  • surfsense_backend/app/db.py (class PagePurchase, lines ~1616+)
  • Stripe Test Cards: https://stripe.com/docs/testing

Dev Agent Record

Agent Model Used

TBD

File List

  • surfsense_backend/app/routes/stripe_routes.py
  • surfsense_backend/app/config.py
  • surfsense_backend/.env.example