You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5.2 KiB
5.2 KiB
Phase 7: Payment (PayPal Integration)
Status: ⏳ Todo Progress: 0/12 tasks (0%) Started: - Completed: - Assigned to: -
Overview
Integrate PayPal payment gateway: create order, capture payment, handle webhooks, and manage payment success/failure flows.
Goal: Users can pay for their orders securely via PayPal.
Dependencies
- ✅ Phase 5: Cart (payment requires cart data)
- ✅ Phase 6: Checkout (billing info needed for order)
- ⚠️ Required: PayPal credentials (CLIENT_ID, CLIENT_SECRET)
Tasks
Setup
-
Install PayPal SDK
pnpm add @paypal/checkout-server-sdk -
Configure PayPal credentials in .env
PAYPAL_CLIENT_ID=xxx PAYPAL_CLIENT_SECRET=xxx PAYPAL_MODE=sandbox # or 'live' for production -
Add PayPal config to nuxt.config.ts
runtimeConfig: { paypal: { clientId: process.env.PAYPAL_CLIENT_ID, clientSecret: process.env.PAYPAL_CLIENT_SECRET, mode: process.env.PAYPAL_MODE || 'sandbox', }, public: { paypalClientId: process.env.PAYPAL_CLIENT_ID, // For client-side SDK }, }
API Endpoints
-
Create /api/payment/paypal/create.post.ts endpoint
- Body: { cartId, billingAddress }
- Create PayPal order via SDK
- Amount: cart total in EUR
- Description: "Makerspace-Jahreskarte"
- Return: { orderId, approvalUrl }
- See: PayPal Orders API v2
-
Create /api/payment/paypal/capture.post.ts endpoint
- Body: { orderId, paypalOrderId }
- Capture PayPal payment
- If successful:
- Create order in local DB (orders, order_items)
- Queue order for X-API submission (BullMQ)
- Clear user's cart
- Return: { success: true, orderNumber }
- If failed:
- Return: { success: false, error }
-
Create /api/payment/paypal/webhook.post.ts endpoint
- Verify webhook signature (PayPal SDK)
- Handle events:
- CHECKOUT.ORDER.APPROVED
- PAYMENT.CAPTURE.COMPLETED
- PAYMENT.CAPTURE.DENIED
- Update order status in DB based on event
- Log all webhook events
- Return: 200 OK (acknowledge receipt)
Client-Side Integration
- Integrate PayPal button on checkout
- File:
components/Checkout/PayPalButton.vue - Load PayPal JavaScript SDK
- Render PayPal button
- On click: Call /api/payment/paypal/create
- On approve: Call /api/payment/paypal/capture
- On error: Show error message
- See: PayPal Checkout Integration guide
- File:
Payment Flows
-
Implement payment success flow
- After successful capture:
- Redirect to /bestätigung/[orderNumber] (order confirmation page)
- Show success message + order details
- Show estimated delivery/activation time
- Send confirmation email (optional for MVP)
- After successful capture:
-
Implement payment error handling
- On capture failure:
- Show user-friendly error message
- Keep cart intact (don't clear)
- Log error for debugging
- Offer retry or alternative payment method (future)
- On capture failure:
Testing
-
Test PayPal sandbox
- Create sandbox account on PayPal Developer Portal
- Use sandbox credentials in .env
- Test complete flow: create → approve → capture
- Test with PayPal test cards
- Verify order is created in local DB
-
Add payment status tracking
- Order status field: 'pending', 'paid', 'failed', 'completed'
- Update status after PayPal capture
- Display status in user's order history
-
Document PayPal integration
- Document PayPal API flow
- Document webhook events and handling
- Document error scenarios and recovery
- Document sandbox vs production setup
-
Test webhook handling
- Use PayPal webhook simulator in sandbox
- Send test events to webhook endpoint
- Verify events are processed correctly
- Verify order status updates
Acceptance Criteria
- PayPal SDK is installed and configured
- /api/payment/paypal/create endpoint works
- /api/payment/paypal/capture endpoint works
- /api/payment/paypal/webhook endpoint works
- PayPal button renders on checkout page
- Can create PayPal order successfully
- Can capture payment successfully
- Order is created in DB after successful payment
- Cart is cleared after successful payment
- User is redirected to confirmation page
- Payment errors are handled gracefully
- Webhook signature verification works
- Webhook events update order status
- Payment flow is documented
Notes
- Sandbox Testing: Use PayPal sandbox for development
- Webhook URL: Must be publicly accessible (use ngrok for local testing)
- Currency: EUR for all transactions
- Amount Precision: PayPal requires 2 decimal places (e.g., "19.99")
- Order Number: Generate unique order number (e.g., "EXP-2025-0001")
Blockers
- ⚠️ PayPal Credentials: Need sandbox credentials to test integration
- ⚠️ Webhook Testing: Need public URL for webhook endpoint (ngrok)