181 lines
4.9 KiB
Markdown
181 lines
4.9 KiB
Markdown
# 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":"<submission-id-from-step-4>"}'
|
|
```
|
|
|
|
6. **Test Stripe Webhook:**
|
|
- Use Stripe CLI: `stripe listen --forward-to localhost:3000/stripe/webhook`
|
|
- Trigger test event: `stripe trigger checkout.session.completed`
|