Complete Email Sortierer implementation with Appwrite and Stripe integration
This commit is contained in:
180
server/ENDPOINT_VERIFICATION.md
Normal file
180
server/ENDPOINT_VERIFICATION.md
Normal file
@@ -0,0 +1,180 @@
|
||||
# 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`
|
||||
Reference in New Issue
Block a user