verpfuschter stand von codex

This commit is contained in:
Codex Agent
2025-10-04 16:38:42 +02:00
parent c87cfb2c10
commit bc6a75961a
23 changed files with 2588 additions and 92 deletions

View File

@@ -28,3 +28,58 @@ Guest Polling (no WebSockets in v1)
Webhooks
- Payment provider events, media pipeline status, and deletion callbacks. All signed with shared secret per provider.
## Purchase Wizard Endpoints (Marketing Flow)
These endpoints support the frontend purchase wizard for package selection, authentication, and payment. They are web routes under `/purchase/` (not `/api/v1`), designed for Inertia.js integration with JSON responses for AJAX/fetch calls. No tenant middleware for auth steps (pre-tenant creation); auth required for payment.
### Flow Overview
1. **Package Selection**: User selects package via marketing page; redirects to wizard with package ID.
2. **Auth (Login/Register)**: Handle user creation/login; creates tenant if registering. Returns user data and next_step ('payment' or 'success' for free packages).
3. **Payment**: Create intent/order, complete via provider callback, finalize purchase (assign package, update tenant).
4. **Success**: Redirect to success page; email welcome if new user.
Error Handling:
- 422 Validation: `{ errors: { field: ['message'] }, message: 'Summary' }` display in forms without reload.
- 401/403: `{ error: 'Auth required' }` show login prompt.
- 500/Other: `{ error: 'Server error' }` generic alert, log trace_id.
- Non-JSON (e.g., 404): Frontend catches "unexpected end of data" and shows "Endpoint not found" or retry.
All responses: JSON only for AJAX; CSRF-protected.
### Endpoints
- **POST /purchase/auth/login**
- Body: `{ login: string (email/username), password: string, remember?: boolean }`
- Response (200): `{ status: 'authenticated', user: { id, email, name, pending_purchase, email_verified }, next_step: 'payment', needs_verification: boolean }`
- Errors: 422 `{ errors: { login: ['Invalid credentials'] } }`
- **POST /purchase/auth/register**
- Body: `{ username, email, password, password_confirmation, first_name, last_name, address, phone, privacy_consent: boolean, package_id?: number }`
- Response (200): `{ status: 'registered', user: { ... }, next_step: 'payment'|'success', needs_verification: boolean, package?: { id, name, price, type } }`
- Errors: 422 `{ errors: { email: ['Taken'], password: ['Too weak'] } }`; creates tenant/user on success.
- **POST /purchase/stripe/intent** (auth required)
- Body: `{ package_id: number }`
- Response (200): `{ client_secret: string, payment_intent_id: string }`
- Errors: 422 `{ errors: { package_id: ['Invalid'] } }`
- **POST /purchase/stripe/complete** (auth required)
- Body: `{ package_id: number, payment_intent_id: string }`
- Response (200): `{ status: 'completed' }`
- Errors: 422 `{ errors: { payment: ['Not succeeded'] } }` finalizes purchase.
- **POST /purchase/paypal/order** (auth required)
- Body: `{ package_id: number }`
- Response (200): `{ order_id: string, status: 'CREATED' }`
- Errors: 422 `{ error: 'Order creation failed' }`
- **POST /purchase/paypal/capture** (auth required)
- Body: `{ order_id: string, package_id: number }`
- Response (200): `{ status: 'captured' }`
- Errors: 422 `{ error: 'Capture incomplete' }` finalizes purchase.
- **POST /purchase/free** (auth required)
- Body: `{ package_id: number }`
- Response (200): `{ status: 'assigned' }`
- Errors: 422 `{ errors: { package_id: ['Not free'] } }` assigns for zero-price packages.