Skip to content

Configuración

Registras PaymentsModule.forRoot() en tu AppModule y le pasas las pasarelas que quieras activar. La librería no lee .env: la configuración de cada pasarela la construyes tú (normalmente desde tus propias variables de entorno — ver Variables de entorno).

Registro del módulo

ts
import { Module } from '@nestjs/common'
import { EventEmitterModule } from '@nestjs/event-emitter'
import { TypeOrmModule } from '@nestjs/typeorm'
import { PaymentsModule, StripeGateway, RedsysGateway, PayPalGateway } from '@kaizen/payments-gateway'

@Module({
  imports: [
    EventEmitterModule.forRoot(),

    TypeOrmModule.forRoot({
      type: 'postgres',
      host: process.env.DB_HOST,
      port: Number(process.env.DB_PORT),
      username: process.env.DB_USER,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_NAME,
      autoLoadEntities: true, 
      synchronize: false,     
    }),

    PaymentsModule.forRoot({
      public_base_url: process.env.PUBLIC_BASE_URL!, 
      gateways: [
        StripeGateway.register({
          secret_key: process.env.STRIPE_SECRET_KEY!,
          webhook_secret: process.env.STRIPE_WEBHOOK_SECRET!,
        }),
        RedsysGateway.register({
          merchant_code: process.env.REDSYS_MERCHANT_CODE!,
          terminal: process.env.REDSYS_TERMINAL!,
          secret_key: process.env.REDSYS_SECRET_KEY!,
          environment: process.env.REDSYS_ENVIRONMENT as 'test' | 'production',
          merchant_url: process.env.REDSYS_MERCHANT_URL!,
          merchant_name: process.env.REDSYS_MERCHANT_NAME,
        }),
        PayPalGateway.register({
          client_id: process.env.PAYPAL_CLIENT_ID!,
          client_secret: process.env.PAYPAL_CLIENT_SECRET!,
          webhook_id: process.env.PAYPAL_WEBHOOK_ID!,
          environment: process.env.PAYPAL_ENVIRONMENT as 'sandbox' | 'production',
          public_base_url: process.env.PUBLIC_BASE_URL!,
        }),
      ],
    }),
  ],
})
export class AppModule {}

Los campos concretos de cada register() (claves, moneda, terminal, endpoints…) se documentan en la página de cada pasarela: Stripe, Redsys y PayPal.

public_base_url

Es la URL pública de tu API (p. ej. https://tu-dominio.com). La librería la usa para las pasarelas que necesitan una vuelta por el navegador: sirve la página de redirección de Redsys y construye la return_url de PayPal. En local suele ser http://localhost:3000.

Dos requisitos obligatorios

Ambos son estándar de NestJS, pero son imprescindibles para que la librería funcione:

1. autoLoadEntities: true

La librería registra sus entidades (Payment, Refund, WebhookEvent) con un forFeature interno. Con este flag el DataSource las reconoce sin que tengas que listarlas.

2. rawBody: true en el bootstrap

El controller de webhooks verifica la firma sobre el body crudo. Actívalo en main.ts:

ts
// main.ts
const app = await NestFactory.create(AppModule, { rawBody: true }) 

WARNING

Sin rawBody: true, la verificación de firma de Stripe falla siempre con 400.

Qué le pasa a tu base de datos

No tienes que crear tablas ni correr migraciones tú. La primera vez que arranca tu app, la librería, sobre tu misma conexión:

  1. Crea el schema payments si no existe.
  2. Crea su tabla de control payments.migrations (separada de la tuya).
  3. Corre sus migraciones pendientes dentro de una transacción.

Es idempotente (arrancar N veces es seguro) y toca exclusivamente el schema payments: nunca usa synchronize global ni altera tus tablas.

Escuchar los eventos

ts
import { Injectable } from '@nestjs/common'
import { OnEvent } from '@nestjs/event-emitter'
import { PaymentEventPayload } from '@kaizen/payments-gateway'

@Injectable()
export class MiPagosListener {
  @OnEvent('payment.captured')
  onCaptured(payload: PaymentEventPayload) {
    // marca el pedido como pagado, envía email, etc.
  }

  @OnEvent('payment.failed')
  onFailed(payload: PaymentEventPayload) {
    // …
  }
}

Sigue con las Variables de entorno.