feat(payments): implement Payments module with VNPay, MoMo, ZaloPay integration

Implement complete payment processing module following DDD + CQRS patterns:

- Domain layer: PaymentEntity aggregate, Money value object, domain events
- Infrastructure: PrismaPaymentRepository, VnpayService, MomoService, ZalopayService
- PaymentGatewayFactory pattern for provider abstraction
- CQRS Commands: CreatePayment, HandleCallback, RefundPayment
- CQRS Queries: GetPaymentStatus, ListTransactions
- Callback/webhook endpoints with signature verification and idempotency
- 23 unit tests covering domain, VNPay service, and gateway factory

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-08 01:57:23 +07:00
parent 207a2013f3
commit ad7713968a
42 changed files with 1985 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
import { Module } from '@nestjs/common';
import { CqrsModule } from '@nestjs/cqrs';
// Domain
import { PAYMENT_REPOSITORY } from './domain/repositories/payment.repository';
// Infrastructure
import { PrismaPaymentRepository } from './infrastructure/repositories/prisma-payment.repository';
import { PAYMENT_GATEWAY_FACTORY } from './infrastructure/services/payment-gateway.interface';
import { PaymentGatewayFactory } from './infrastructure/services/payment-gateway.factory';
import { VnpayService } from './infrastructure/services/vnpay.service';
import { MomoService } from './infrastructure/services/momo.service';
import { ZalopayService } from './infrastructure/services/zalopay.service';
// Application — Commands
import { CreatePaymentHandler } from './application/commands/create-payment/create-payment.handler';
import { HandleCallbackHandler } from './application/commands/handle-callback/handle-callback.handler';
import { RefundPaymentHandler } from './application/commands/refund-payment/refund-payment.handler';
// Application — Queries
import { GetPaymentStatusHandler } from './application/queries/get-payment-status/get-payment-status.handler';
import { ListTransactionsHandler } from './application/queries/list-transactions/list-transactions.handler';
// Presentation
import { PaymentsController } from './presentation/controllers/payments.controller';
const CommandHandlers = [
CreatePaymentHandler,
HandleCallbackHandler,
RefundPaymentHandler,
];
const QueryHandlers = [GetPaymentStatusHandler, ListTransactionsHandler];
@Module({
imports: [CqrsModule],
controllers: [PaymentsController],
providers: [
// Repositories
{ provide: PAYMENT_REPOSITORY, useClass: PrismaPaymentRepository },
// Gateway Services
VnpayService,
MomoService,
ZalopayService,
{ provide: PAYMENT_GATEWAY_FACTORY, useClass: PaymentGatewayFactory },
// CQRS
...CommandHandlers,
...QueryHandlers,
],
exports: [PAYMENT_REPOSITORY, PAYMENT_GATEWAY_FACTORY],
})
export class PaymentsModule {}