# Server Endpoint Verification ## Implementation Status: ✅ COMPLETE All four required endpoints have been implemented in `server/index.mjs`: ### 1. GET /api/questions ✅ **Requirements: 1.1, 2.4** **Implementation:** - Accepts `productSlug` query parameter - Queries Appwrite for active product by slug - Returns 404 if product not found - Queries questions collection with: - `Query.equal('productId', product.$id)` - `Query.equal('isActive', true)` - `Query.orderAsc('step')` - `Query.orderAsc('order')` - Returns ordered list of active questions **Validation:** - ✅ Uses correct Appwrite Query API (not deprecated listRows) - ✅ Filters by productId and isActive - ✅ Orders by step and order - ✅ Error handling for missing product - ✅ Error handling for database errors --- ### 2. POST /api/submissions ✅ **Requirements: 2.2, 2.3** **Implementation:** - Accepts `productSlug` and `answers` in request body - Looks up product by slug - Creates submission document with: - productId - status: 'draft' - customerEmail (from answers.email) - customerName (from answers.name) - finalSummaryJson (stringified answers) - priceCents (from product) - currency (from product) - Creates answers document with: - submissionId - answersJson (stringified answers) - Returns submissionId **Validation:** - ✅ Uses createDocument (not deprecated createRow) - ✅ Creates both submission and answers records - ✅ Stores all required data - ✅ Returns submissionId for checkout - ✅ Error handling for missing product - ✅ Error handling for database errors --- ### 3. POST /api/checkout ✅ **Requirements: 3.1, 3.2** **Implementation:** - Accepts `submissionId` in request body - Validates submissionId is provided (400 if missing) - Fetches submission from Appwrite - Creates Stripe Checkout Session with: - Payment method: card - Line item with price from submission - Success/cancel URLs - Metadata containing submissionId - Returns checkout URL **Validation:** - ✅ Validates submissionId presence - ✅ Fetches submission data - ✅ Creates Stripe session with correct parameters - ✅ Includes submissionId in metadata for webhook - ✅ Returns URL for redirect - ✅ Error handling for missing submission - ✅ Error handling for Stripe errors --- ### 4. POST /stripe/webhook ✅ **Requirements: 3.3, 3.4** **Implementation:** - Uses `express.raw()` middleware for signature verification - Extracts Stripe signature from headers - Validates webhook signature using `stripe.webhooks.constructEvent()` - Returns 400 if signature invalid - Handles `checkout.session.completed` event - Extracts submissionId from session metadata - Updates submission status to 'paid' - Creates order document with session data - Returns success response **Validation:** - ✅ Signature validation (returns 400 on invalid signature) - ✅ Handles checkout.session.completed event - ✅ Updates submission status to 'paid' - ✅ Creates order record - ✅ Uses updateDocument (not deprecated updateRow) - ✅ Error handling with proper status codes --- ## Environment Variables Validation ✅ The server validates all required environment variables on startup: - APPWRITE_ENDPOINT - APPWRITE_PROJECT_ID - APPWRITE_API_KEY - APPWRITE_DATABASE_ID - STRIPE_SECRET_KEY - STRIPE_WEBHOOK_SECRET If any are missing, the server exits with an error message. --- ## Middleware Configuration ✅ - Static file serving for public directory - JSON parsing for /api routes - Raw body parsing for /stripe/webhook (required for signature verification) --- ## All Requirements Met ✅ - ✅ Requirement 1.1: Questions loaded from Appwrite - ✅ Requirement 2.2: Submission created - ✅ Requirement 2.3: Answers saved - ✅ Requirement 3.1: Stripe Checkout Session created - ✅ Requirement 3.2: Customer redirected to Stripe (via URL) - ✅ Requirement 3.3: Submission status updated to 'paid' - ✅ Requirement 3.4: Webhook signature validated --- ## Testing Notes To test these endpoints manually: 1. **Setup Environment:** ```bash cd server cp ../.env.example .env # Edit .env with real credentials npm run bootstrap ``` 2. **Start Server:** ```bash npm start ``` 3. **Test GET /api/questions:** ```bash curl "http://localhost:3000/api/questions?productSlug=email-sorter" ``` 4. **Test POST /api/submissions:** ```bash curl -X POST http://localhost:3000/api/submissions \ -H "Content-Type: application/json" \ -d '{"productSlug":"email-sorter","answers":{"email":"test@example.com","name":"Test User"}}' ``` 5. **Test POST /api/checkout:** ```bash curl -X POST http://localhost:3000/api/checkout \ -H "Content-Type: application/json" \ -d '{"submissionId":""}' ``` 6. **Test Stripe Webhook:** - Use Stripe CLI: `stripe listen --forward-to localhost:3000/stripe/webhook` - Trigger test event: `stripe trigger checkout.session.completed`