Overview
src/app/api/courses/[id]/enroll/route.ts contains a TODO to replace the mock payment flow with a real payment processor and database write. Users can enroll in paid courses without actually being charged, and enrollment records are not persisted — meaning access is lost on restart.
Specifications
Features:
- Paid course enrollment requires a successful payment via Stripe
- Enrollment records are persisted to the database
- Failed payments return HTTP 402 with a clear error
Tasks:
- Integrate Stripe Checkout: create a checkout session and return the session URL to the client
- Handle the Stripe webhook
checkout.session.completed to write the enrollment record
- Create an
enrollments table: (user_id, course_id, enrolled_at, payment_id, status)
- Gate lesson access on the enrollment record
Impacted Files:
src/app/api/courses/[id]/enroll/route.ts
src/app/api/webhooks/stripe/route.ts (new)
src/lib/db/ (new migration)
Acceptance Criteria
- Enrolling in a paid course redirects to Stripe Checkout
- Successful payment creates an enrollment record in the database
- Enrollment survives a server restart and gates lesson access correctly
Overview
src/app/api/courses/[id]/enroll/route.tscontains a TODO to replace the mock payment flow with a real payment processor and database write. Users can enroll in paid courses without actually being charged, and enrollment records are not persisted — meaning access is lost on restart.Specifications
Features:
Tasks:
checkout.session.completedto write the enrollment recordenrollmentstable:(user_id, course_id, enrolled_at, payment_id, status)Impacted Files:
src/app/api/courses/[id]/enroll/route.tssrc/app/api/webhooks/stripe/route.ts(new)src/lib/db/(new migration)Acceptance Criteria