mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 00:36:31 +02:00
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>
3.7 KiB
3.7 KiB
Story 5.1: Kết nối Pricing UI với Stripe Checkout
Status: ready-for-dev
Context / Correction Note
⚠️ Story gốc bị sai hướng. Story gốc mô tả tạo mới pricing page với Free/Pro/Team subscription tiers. Thực tế, pricing page đã tồn tại với mô hình PAYG (Pay-As-You-Go page packs), không phải subscription. Stripe checkout endpoint cũng đã tồn tại. Task thực tế là wire up nút "Get Started" của PAYG tier với endpoint hiện có.
Story
As a Người dùng đã đăng nhập, I want bấm "Get Started" trên trang Pricing để mua page packs, so that tôi có thể tiếp tục upload tài liệu sau khi hết quota.
Actual Architecture (as-is)
Đã tồn tại và hoạt động:
surfsense_web/app/(home)/pricing/page.tsx— pricing page routesurfsense_web/components/pricing/pricing-section.tsx— UI với 3 tiers:- FREE: 500 pages included, button href="/login"
- PAY AS YOU GO: $1/1,000 pages, button href="/login" ← cần sửa
- ENTERPRISE: Contact Sales, button href="/contact"
surfsense_backend/app/routes/stripe_routes.py:create_checkout_session— endpointPOST /api/v1/stripe/create-checkout-sessionđã implement, mode=payment, yêu cầusearch_space_idvàquantity
Chưa làm:
- Nút "Get Started" của PAYG tier chỉ link đến
/login, chưa gọi Stripe checkout - Không có flow chọn số lượng page packs (quantity)
Acceptance Criteria
- Khi user đã đăng nhập bấm "Get Started" ở PAYG tier, hiện modal/form cho phép chọn số lượng pack (1, 5, 10, etc.).
- Sau khi confirm, gọi
POST /api/v1/stripe/create-checkout-sessionvớiquantityvàsearch_space_id, nhậncheckout_url. - Redirect user đến
checkout_url(Stripe-hosted checkout page). - Nếu user chưa đăng nhập, redirect đến
/logintrước (behavior hiện tại giữ nguyên cho FREE tier).
Tasks / Subtasks
- Task 1: Cập nhật nút PAYG trong
pricing-section.tsx- Subtask 1.1: Thay
href="/login"bằngonClickhandler. Nếu user chưa authenticated, redirect/login. Nếu đã authenticated, mở modal chọn quantity. - Subtask 1.2: Tạo
PurchasePagesModalcomponent với dropdown/input chọn số pack (1–10), hiển thị tổng tiền (quantity × $1).
- Subtask 1.1: Thay
- Task 2: Gọi Stripe checkout API
- Subtask 2.1: Khi user confirm trong modal, gọi
POST /api/v1/stripe/create-checkout-sessionvới{ quantity, search_space_id }. - Subtask 2.2: Nhận
checkout_urlvà redirect bằngwindow.location.href = checkout_url.
- Subtask 2.1: Khi user confirm trong modal, gọi
- Task 3: Xử lý return URL sau checkout
- Subtask 3.1: Kiểm tra success/cancel URL config hiện tại trong
stripe_routes.py(_get_checkout_urls). - Subtask 3.2: Sau purchase thành công, hiển thị toast "Mua thành công! X pages đã được thêm vào tài khoản."
- Subtask 3.1: Kiểm tra success/cancel URL config hiện tại trong
Dev Notes
Stripe Checkout Request Schema (hiện tại)
class CreateCheckoutSessionRequest(BaseModel):
search_space_id: int
quantity: int # số pack, mỗi pack = STRIPE_PAGES_PER_UNIT pages
API Endpoint
POST /api/v1/stripe/create-checkout-session
Authorization: Bearer <token>
Body: { "search_space_id": 1, "quantity": 2 }
Response: { "checkout_url": "https://checkout.stripe.com/..." }
References
surfsense_web/components/pricing/pricing-section.tsxsurfsense_backend/app/routes/stripe_routes.py(lines ~204–271)surfsense_web/app/dashboard/[search_space_id]/purchase-cancel/page.tsx
Dev Agent Record
Agent Model Used
TBD
File List
surfsense_web/components/pricing/pricing-section.tsxsurfsense_web/components/pricing/PurchasePagesModal.tsx(new)