Some checks failed
Build / Build Backend (push) Has been cancelled
Build / Build Mobile (TypeScript Check) (push) Has been cancelled
Lint / Lint Backend (push) Has been cancelled
Lint / Lint Mobile (push) Has been cancelled
Test / Backend E2E Tests (push) Has been cancelled
Test / Mobile Unit Tests (push) Has been cancelled
Build / Build Docker Image (push) Has been cancelled
- Add exports module with PDF/CSV/Excel generation - Add reports module for inventory analytics - Add POS integrations module - Add database migrations for exports, movements and integrations - Add GitHub Actions CI/CD workflow with Docker support - Add mobile export and reports screens with tests - Update epic documentation with traceability - Add deployment and security guides Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
347 lines
9.5 KiB
Markdown
347 lines
9.5 KiB
Markdown
# MII-011: Pagos con Tarjeta
|
|
|
|
---
|
|
id: MII-011
|
|
type: Epic
|
|
status: Completado
|
|
priority: P0
|
|
phase: 3
|
|
story_points: 8
|
|
created_date: 2026-01-10
|
|
updated_date: 2026-01-13
|
|
simco_version: "4.0.0"
|
|
---
|
|
|
|
## Metadata
|
|
|
|
| Campo | Valor |
|
|
|-------|-------|
|
|
| **ID** | MII-011 |
|
|
| **Nombre** | Pagos con Tarjeta |
|
|
| **Fase** | 3 - Monetizacion |
|
|
| **Prioridad** | P0 |
|
|
| **Story Points** | 8 |
|
|
| **Estado** | Completado |
|
|
|
|
---
|
|
|
|
## 1. Descripcion
|
|
|
|
Implementar pagos con tarjeta de credito/debito usando Stripe, con PCI compliance delegado y experiencia de pago fluida.
|
|
|
|
### Objetivo
|
|
|
|
Permitir a los usuarios comprar creditos instantaneamente con tarjeta de manera segura.
|
|
|
|
---
|
|
|
|
## 2. Requerimientos Relacionados
|
|
|
|
| RF | Descripcion | Prioridad |
|
|
|----|-------------|-----------|
|
|
| FR-100 | Pago inmediato con tarjeta, PCI delegado (Stripe) | P0 |
|
|
| FR-103 | Confirmacion de pago via webhooks | P0 |
|
|
| FR-104 | Reconciliacion (CREATED/PENDING/PAID/EXPIRED/CANCELED) | P0 |
|
|
|
|
---
|
|
|
|
## 3. Criterios de Aceptacion
|
|
|
|
### AC-001: Pago con Tarjeta
|
|
```gherkin
|
|
DADO que seleccione un paquete
|
|
CUANDO ingreso mis datos de tarjeta
|
|
ENTONCES el pago se procesa inmediatamente
|
|
Y recibo confirmacion de exito o error
|
|
Y mis creditos se acreditan al instante
|
|
```
|
|
|
|
### AC-002: Formulario Seguro
|
|
```gherkin
|
|
DADO que estoy en el checkout
|
|
CUANDO ingreso datos de tarjeta
|
|
ENTONCES uso el componente Stripe Elements
|
|
Y los datos nunca tocan mi servidor
|
|
Y veo indicadores de seguridad
|
|
```
|
|
|
|
### AC-003: Tarjeta Guardada
|
|
```gherkin
|
|
DADO que pague con una tarjeta
|
|
CUANDO hago otra compra
|
|
ENTONCES puedo usar la tarjeta guardada
|
|
Y solo ingreso CVV
|
|
O puedo agregar otra tarjeta
|
|
```
|
|
|
|
### AC-004: Error de Pago
|
|
```gherkin
|
|
DADO que mi pago falla
|
|
CUANDO veo el error
|
|
ENTONCES el mensaje es claro (fondos, tarjeta invalida, etc)
|
|
Y puedo intentar de nuevo
|
|
Y no se cobran creditos
|
|
```
|
|
|
|
### AC-005: Webhook de Confirmacion
|
|
```gherkin
|
|
DADO que Stripe confirma el pago
|
|
CUANDO recibo el webhook
|
|
ENTONCES actualizo el estado de la orden
|
|
Y acredito los creditos
|
|
Y envio confirmacion al usuario
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Tareas Tecnicas
|
|
|
|
| ID | Tarea | Estimacion | Estado |
|
|
|----|-------|------------|--------|
|
|
| T-001 | Configurar Stripe SDK backend | 1 SP | Completado |
|
|
| T-002 | Crear endpoints de pago | 2 SP | Completado |
|
|
| T-003 | Implementar webhook handler | 2 SP | Completado |
|
|
| T-004 | Integrar Stripe Elements en mobile | 2 SP | Completado |
|
|
| T-005 | Implementar guardado de tarjetas | 1 SP | Completado |
|
|
|
|
---
|
|
|
|
## 5. Modelo de Datos
|
|
|
|
### Tabla: payment_orders
|
|
```sql
|
|
CREATE TABLE payment_orders (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID REFERENCES users(id),
|
|
package_id UUID REFERENCES packages(id),
|
|
amount_mxn DECIMAL(10,2) NOT NULL,
|
|
credits_amount DECIMAL(12,4) NOT NULL,
|
|
payment_method VARCHAR(20), -- 'CARD', 'OXXO', 'SEVEN_ELEVEN'
|
|
status VARCHAR(20) DEFAULT 'CREATED',
|
|
stripe_payment_intent_id VARCHAR(100),
|
|
stripe_customer_id VARCHAR(100),
|
|
paid_at TIMESTAMP,
|
|
expires_at TIMESTAMP,
|
|
metadata JSONB,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
-- Status: CREATED, PENDING, PAID, FAILED, EXPIRED, CANCELED, REFUNDED
|
|
```
|
|
|
|
### Tabla: payment_methods
|
|
```sql
|
|
CREATE TABLE payment_methods (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID REFERENCES users(id),
|
|
type VARCHAR(20), -- 'CARD'
|
|
stripe_payment_method_id VARCHAR(100),
|
|
last_four VARCHAR(4),
|
|
brand VARCHAR(20),
|
|
exp_month INT,
|
|
exp_year INT,
|
|
is_default BOOLEAN DEFAULT false,
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Flujo de Pago
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ FLUJO DE PAGO CON TARJETA │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
│ │ Seleccionar │→│ Crear │→│ Pagar │→│ Confirmar│ │
|
|
│ │ Paquete │ │ Orden │ │ (Stripe) │ │(Webhook) │ │
|
|
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
|
│ │ │ │ │ │
|
|
│ │ │ │ │ │
|
|
│ ▼ ▼ ▼ ▼ │
|
|
│ Mostrar CREATED PENDING PAID │
|
|
│ precios en DB PaymentIntent Acreditar │
|
|
│ creditos │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Endpoints API
|
|
|
|
| Metodo | Endpoint | Descripcion | Auth |
|
|
|--------|----------|-------------|------|
|
|
| POST | /payments/card/intent | Crear PaymentIntent | JWT |
|
|
| POST | /payments/card/confirm | Confirmar pago | JWT |
|
|
| GET | /payments/methods | Listar tarjetas guardadas | JWT |
|
|
| POST | /payments/methods | Agregar tarjeta | JWT |
|
|
| DELETE | /payments/methods/:id | Eliminar tarjeta | JWT |
|
|
| POST | /payments/webhook/stripe | Webhook Stripe | Stripe Sig |
|
|
|
|
---
|
|
|
|
## 8. Integracion Stripe
|
|
|
|
### Backend - Crear PaymentIntent
|
|
|
|
```typescript
|
|
async createCardPayment(userId: string, packageId: string) {
|
|
const pkg = await this.packagesService.findOne(packageId);
|
|
const user = await this.usersService.findOne(userId);
|
|
|
|
// Crear o obtener Stripe Customer
|
|
let customerId = user.stripeCustomerId;
|
|
if (!customerId) {
|
|
const customer = await this.stripe.customers.create({
|
|
email: user.email,
|
|
phone: user.phone,
|
|
metadata: { userId }
|
|
});
|
|
customerId = customer.id;
|
|
await this.usersService.update(userId, { stripeCustomerId: customerId });
|
|
}
|
|
|
|
// Crear orden
|
|
const order = await this.ordersService.create({
|
|
userId,
|
|
packageId,
|
|
amountMxn: pkg.priceMxn,
|
|
creditsAmount: pkg.currentCredits,
|
|
paymentMethod: 'CARD',
|
|
status: 'CREATED'
|
|
});
|
|
|
|
// Crear PaymentIntent
|
|
const paymentIntent = await this.stripe.paymentIntents.create({
|
|
amount: Math.round(pkg.priceMxn * 100), // centavos
|
|
currency: 'mxn',
|
|
customer: customerId,
|
|
metadata: {
|
|
orderId: order.id,
|
|
userId,
|
|
packageId
|
|
}
|
|
});
|
|
|
|
await this.ordersService.update(order.id, {
|
|
stripePaymentIntentId: paymentIntent.id,
|
|
stripeCustomerId: customerId,
|
|
status: 'PENDING'
|
|
});
|
|
|
|
return {
|
|
orderId: order.id,
|
|
clientSecret: paymentIntent.client_secret
|
|
};
|
|
}
|
|
```
|
|
|
|
### Webhook Handler
|
|
|
|
```typescript
|
|
@Post('webhook/stripe')
|
|
async handleStripeWebhook(@Req() req: RawBodyRequest) {
|
|
const sig = req.headers['stripe-signature'];
|
|
const event = this.stripe.webhooks.constructEvent(
|
|
req.rawBody,
|
|
sig,
|
|
process.env.STRIPE_WEBHOOK_SECRET
|
|
);
|
|
|
|
switch (event.type) {
|
|
case 'payment_intent.succeeded':
|
|
await this.handlePaymentSuccess(event.data.object);
|
|
break;
|
|
case 'payment_intent.payment_failed':
|
|
await this.handlePaymentFailed(event.data.object);
|
|
break;
|
|
}
|
|
|
|
return { received: true };
|
|
}
|
|
|
|
async handlePaymentSuccess(paymentIntent: Stripe.PaymentIntent) {
|
|
const orderId = paymentIntent.metadata.orderId;
|
|
const order = await this.ordersService.findOne(orderId);
|
|
|
|
// Actualizar orden
|
|
await this.ordersService.update(orderId, {
|
|
status: 'PAID',
|
|
paidAt: new Date()
|
|
});
|
|
|
|
// Acreditar creditos
|
|
await this.creditsService.addCredits(
|
|
order.userId,
|
|
order.creditsAmount,
|
|
'PURCHASE',
|
|
orderId
|
|
);
|
|
|
|
// Notificar usuario
|
|
await this.notificationsService.send(order.userId, {
|
|
title: 'Pago exitoso',
|
|
body: `Se acreditaron ${order.creditsAmount} creditos a tu cuenta`
|
|
});
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 9. Pantallas Mobile
|
|
|
|
| Pantalla | Componentes |
|
|
|----------|-------------|
|
|
| **CheckoutScreen** | Resumen, Stripe Elements, confirmar |
|
|
| **SavedCardsScreen** | Lista tarjetas, agregar nueva |
|
|
| **PaymentSuccessScreen** | Confirmacion, creditos, continuar |
|
|
| **PaymentErrorScreen** | Error, reintentar, soporte |
|
|
|
|
---
|
|
|
|
## 10. Dependencias
|
|
|
|
### Entrada (Requiere)
|
|
- MII-009: Wallet y Creditos
|
|
- MII-010: Paquetes de Recarga
|
|
|
|
### Salida (Bloquea)
|
|
- Ninguna directa
|
|
|
|
---
|
|
|
|
## 11. Seguridad
|
|
|
|
| Aspecto | Implementacion |
|
|
|---------|----------------|
|
|
| PCI DSS | Delegado a Stripe |
|
|
| Datos tarjeta | Nunca tocan nuestro servidor |
|
|
| Webhooks | Verificacion de firma Stripe |
|
|
| Idempotencia | Payment Intent ID unico |
|
|
|
|
---
|
|
|
|
## 12. Riesgos
|
|
|
|
| Riesgo | Probabilidad | Impacto | Mitigacion |
|
|
|--------|--------------|---------|------------|
|
|
| Fraude | Media | Alto | Stripe Radar, 3D Secure |
|
|
| Webhook perdido | Baja | Alto | Retry, reconciliacion |
|
|
| Doble cobro | Baja | Alto | Idempotencia, locks |
|
|
|
|
---
|
|
|
|
## 13. Referencias
|
|
|
|
- [REQUERIMIENTOS-FUNCIONALES.md](../00-vision-general/REQUERIMIENTOS-FUNCIONALES.md) - Seccion 5.11
|
|
- [INT-001](../02-integraciones/INT-001-stripe.md) - Integracion Stripe
|
|
- [ADR-0004](../97-adr/ADR-0004-pagos-efectivo-mexico.md) - Estrategia de pagos
|
|
|
|
---
|
|
|
|
**Ultima Actualizacion:** 2026-01-10
|