Changes include: - Updated architecture documentation - Enhanced module definitions (OQI-001 to OQI-008) - ML integration documentation updates - Trading strategies documentation - Orchestration and inventory updates - Docker configuration updates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
4.5 KiB
4.5 KiB
| id | title | type | status | priority | epic | project | version | created_date | updated_date |
|---|---|---|---|---|---|---|---|---|---|
| ET-PAY-004 | API REST Payments | Technical Specification | Done | Alta | OQI-005 | trading-platform | 1.0.0 | 2025-12-05 | 2026-01-04 |
ET-PAY-004: API REST Payments
Epic: OQI-005 Pagos y Stripe Versión: 1.0 Fecha: 2025-12-05
1. Endpoints Payments
POST /api/v1/payments/intent
Crea Payment Intent para pago one-time
Request:
{
"amount": 99.99,
"payment_method_id": "pm_...",
"description": "Premium course purchase"
}
Response 200:
{
"success": true,
"data": {
"payment_intent_id": "pi_...",
"client_secret": "pi_..._secret_...",
"status": "requires_confirmation"
}
}
GET /api/v1/payments
Lista pagos del usuario
Response 200:
{
"success": true,
"data": {
"payments": [
{
"id": "uuid",
"amount": 99.99,
"status": "succeeded",
"description": "Premium course",
"created_at": "2025-01-20T10:00:00Z"
}
]
}
}
POST /api/v1/payments/:id/refund
Solicita reembolso (admin)
Request:
{
"reason": "requested_by_customer",
"amount": 99.99
}
2. Endpoints Subscriptions
POST /api/v1/subscriptions
Crea suscripción
Request:
{
"price_id": "price_...",
"payment_method_id": "pm_..."
}
GET /api/v1/subscriptions
Lista suscripciones activas
DELETE /api/v1/subscriptions/:id
Cancela suscripción
Query: ?immediate=false
3. Endpoints Payment Methods
POST /api/v1/payment-methods
Guarda método de pago
Request:
{
"payment_method_id": "pm_..."
}
GET /api/v1/payment-methods
Lista métodos guardados
DELETE /api/v1/payment-methods/:id
Elimina método de pago
4. Implementation
// src/modules/payments/payment.controller.ts
export class PaymentController {
async createPaymentIntent(req: Request, res: Response) {
const { amount, payment_method_id, description } = req.body;
const userId = req.user!.id;
const result = await paymentService.createPaymentIntent({
user_id: userId,
amount,
payment_method_id,
description,
});
return successResponse(res, result, 200);
}
async getPayments(req: Request, res: Response) {
const userId = req.user!.id;
const { status, limit = 20, offset = 0 } = req.query;
const payments = await paymentService.getPayments({
user_id: userId,
status,
limit: Number(limit),
offset: Number(offset),
});
return successResponse(res, payments, 200);
}
async requestRefund(req: Request, res: Response) {
const { id } = req.params;
const { reason, amount } = req.body;
const refund = await paymentService.createRefund({
payment_id: id,
reason,
amount,
});
return successResponse(res, refund, 200);
}
}
5. Validations
// Zod schemas
export const createPaymentIntentSchema = z.object({
amount: z.number().positive(),
payment_method_id: z.string().min(1),
description: z.string().optional(),
});
export const createSubscriptionSchema = z.object({
price_id: z.string().startsWith('price_'),
payment_method_id: z.string().min(1),
trial_days: z.number().optional(),
});
export const refundSchema = z.object({
reason: z.enum(['duplicate', 'fraudulent', 'requested_by_customer']),
amount: z.number().positive().optional(),
});
6. Routes
// src/modules/payments/payment.routes.ts
const router = Router();
// Payments
router.post('/intent', authenticate, validate(createPaymentIntentSchema), controller.createPaymentIntent);
router.get('/', authenticate, controller.getPayments);
router.post('/:id/refund', authenticate, requireAdmin, validate(refundSchema), controller.requestRefund);
// Subscriptions
router.post('/subscriptions', authenticate, validate(createSubscriptionSchema), subscriptionController.create);
router.get('/subscriptions', authenticate, subscriptionController.list);
router.delete('/subscriptions/:id', authenticate, subscriptionController.cancel);
// Payment Methods
router.post('/payment-methods', authenticate, paymentMethodController.save);
router.get('/payment-methods', authenticate, paymentMethodController.list);
router.delete('/payment-methods/:id', authenticate, paymentMethodController.delete);
router.patch('/payment-methods/:id/default', authenticate, paymentMethodController.setDefault);
export default router;