Payment Service (payment-app)
Relevant source files
The following files were used as context for generating this wiki page:
- apps/payment-app/src/payment-app.module.ts
- apps/payment-app/src/payments/payments.service.ts
- apps/payment-app/prisma/schema.prisma
- apps/payment-app/src/payments/payments.service.spec.ts
- libs/shared/dto/payment.dto.ts
- libs/shared/types/payment.types.ts
- apps/payment-app/test/payments.e2e-spec.ts
- postman-collection.json
The Payment Service (payment-app) is a NestJS-based microservice responsible for handling all payment-related operations within the e-commerce platform. Its primary functions include processing payments for orders, supporting multiple payment methods like Cash on Delivery (COD) and SePay bank transfers, verifying payment status, and managing payment records.
As a microservice, it communicates with other services, primarily the order-app, via a NATS message broker. It uses Prisma ORM to interact with its own dedicated PostgreSQL database, which stores payment and transaction information. The service is designed to be a self-contained unit, encapsulating all logic related to payment processing and external payment gateway integrations.
Architecture and Components
The payment-app follows a standard NestJS module structure. It is designed to receive commands via NATS messages, process them, and interact with both its database and other microservices.
Sources: apps/payment-app/src/payment-app.module.ts, apps/payment-app/src/payments/payments.service.ts
Core Components
| Component | Description |
|---|---|
PaymentsController | Handles incoming NATS messages (events) for payment operations. It delegates the business logic to the PaymentsService. |
PaymentsService | Contains the core business logic for processing, verifying, and managing payments. It interacts with the PrismaService and the ORDER_SERVICE. |
PrismaService | A service that provides database access via the Prisma Client, used for all CRUD operations on the Payment and Transaction models. |
Sources: apps/payment-app/src/payment-app.module.ts:7-19, apps/payment-app/src/payments/payments.controller.spec.ts:8-14, apps/payment-app/src/payments/payments.service.ts:15-21
Service Interaction Diagram
The following diagram illustrates how the payment-app interacts with the API Gateway and the Order Service.
Database Schema
The service uses two primary models in its database: Payment to track the payment status for an order, and Transaction to log incoming webhook data from payment gateways like SePay.
Sources: apps/payment-app/prisma/schema.prisma, apps/payment-app/src/payments/payments.service.spec.ts:29-43, 401-416
Entity Relationship Diagram
This diagram shows the database models and their fields.
Payment Model
This table details the fields in the Payment model.
| Field | Type | Description |
|---|---|---|
id | String | Unique identifier for the payment (CUID). |
orderId | String | The ID of the associated order. It is unique to prevent multiple payments. |
method | PaymentMethod | The payment method used (COD, SEPAY). |
amountInt | Int | The payment amount in the smallest currency unit (e.g., cents). |
status | PaymentStatus | The current status of the payment (UNPAID, PAID). Default is UNPAID. |
payload | Json? | Stores response data from the payment gateway or verification process. |
createdAt | DateTime | Timestamp of when the payment record was created. |
updatedAt | DateTime | Timestamp of the last update to the payment record. |
Sources: apps/payment-app/prisma/schema.prisma, libs/shared/types/payment.types.ts:11-20
Transaction Model
This table logs raw transaction data from webhooks for auditing and to prevent processing duplicate events.
| Field | Type | Description |
|---|---|---|
id | Int | The unique transaction ID from the webhook payload. |
gateway | String | The payment gateway provider (e.g., "MBBank"). |
transactionDate | String | The date and time of the transaction. |
accountNumber | String | The bank account number involved in the transaction. |
transferType | String | The type of transfer (in or out). |
transferAmount | Int | The amount transferred. |
content | String | The transaction description, which may contain an order ID. |
referenceCode | String | A reference code for the transaction. |
Sources: apps/payment-app/prisma/schema.prisma, libs/shared/dto/payment.dto.ts:47-101, apps/payment-app/src/payments/payments.service.spec.ts:401-416
NATS Events and API
The service primarily communicates via NATS. It exposes one public HTTP endpoint for receiving webhooks.
NATS Message Patterns
| Pattern | DTO | Description |
|---|---|---|
PAYMENT.PROCESS | PaymentProcessDto | Initiates a payment for a given order ID, method, and amount. |
PAYMENT.VERIFY | PaymentVerifyDto | Verifies a payment using a payload, typically from a gateway callback. |
PAYMENT.GET_BY_ID | PaymentIdDto | Retrieves a single payment record by its ID. |
PAYMENT.GET_BY_ORDER | PaymentByOrderDto | Retrieves the latest payment record for a given order ID. |
PAYMENT.CONFIRM_COD | ConfirmCodPaymentDto | Manually confirms a COD payment, changing its status to PAID. Accepts either id or orderId. |
Sources: apps/payment-app/test/payments.e2e-spec.ts:100, 151, 230, 256, 281
HTTP Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | /payments/webhook/sepay | Receives webhook notifications from SePay gateway. |
Sources: postman-collection.json, apps/payment-app/src/payments/payments.controller.spec.ts:60-80
Payment Flows
The service supports two primary payment flows: COD and SePay.
Cash on Delivery (COD)
The COD flow is a manual process. A payment is created as UNPAID and is only marked as PAID after an explicit confirmation call, typically made by an administrator or a delivery person.
COD Processing and Confirmation Flow
SePay (Bank Transfer)
The SePay flow involves generating a QR code for the user to scan and make a bank transfer. The system then relies on a webhook from SePay to automatically confirm the payment.
SePay Environment Variables
The SePay integration requires the following environment variables to be set:
| Variable | Description |
|---|---|
SEPAY_ACCOUNT_NUMBER | The bank account number for receiving payments. |
SEPAY_BANK_NAME | The name of the bank (e.g., "MBBank"). |
ACCOUNT_NAME | The name of the account holder. |
Sources: apps/payment-app/src/payments/payments.service.spec.ts:208-270
SePay Initiation Flow
SePay Webhook Handling Flow
When a payment is made, SePay sends a webhook to the /payments/webhook/sepay endpoint.
Data Transfer Objects (DTOs)
These are the primary DTOs used for communication with the Payment Service.
Sources: libs/shared/dto/payment.dto.ts
PaymentProcessDto
Used for the PAYMENT.PROCESS event.
| Field | Type | Validation |
|---|---|---|
orderId | string | IsNotEmpty, IsString |
method | PaymentMethod | IsNotEmpty, IsEnum(PaymentMethod) |
amountInt | number | IsNotEmpty, IsNumber, IsPositive |
Sources: libs/shared/dto/payment.dto.ts:9-24
SePayWebhookDto
Used to validate the incoming webhook from SePay.
| Field | Type | Validation |
|---|---|---|
id | number | IsNotEmpty, IsNumber |
gateway | string | IsNotEmpty, IsString |
transactionDate | string | IsNotEmpty, IsString |
accountNumber | string | IsNotEmpty, IsString |
content | string | IsNotEmpty, IsString |
transferType | 'in' | 'out' | IsNotEmpty, IsIn(['in', 'out']) |
transferAmount | number | IsNotEmpty, IsNumber, IsPositive |
referenceCode | string | IsNotEmpty, IsString |
description | string | IsNotEmpty, IsString |