224 lines
4.5 KiB
Markdown
224 lines
4.5 KiB
Markdown
# 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:**
|
|
```json
|
|
{
|
|
"amount": 99.99,
|
|
"payment_method_id": "pm_...",
|
|
"description": "Premium course purchase"
|
|
}
|
|
```
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"payment_intent_id": "pi_...",
|
|
"client_secret": "pi_..._secret_...",
|
|
"status": "requires_confirmation"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET `/api/v1/payments`
|
|
Lista pagos del usuario
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"reason": "requested_by_customer",
|
|
"amount": 99.99
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Endpoints Subscriptions
|
|
|
|
### POST `/api/v1/subscriptions`
|
|
Crea suscripción
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"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
|
|
|
|
```typescript
|
|
// 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
|
|
|
|
```typescript
|
|
// 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
|
|
|
|
```typescript
|
|
// 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;
|
|
```
|