feat(api): add Vietnam validators and migrate payment services to ConfigService

- Create custom class-validator decorators: IsVietnamPhone, IsVietnamDistrict, IsVND
- Replace process.env/requireEnv() with NestJS ConfigService DI in VNPay, MoMo, ZaloPay services
- Update all payment infrastructure tests with ConfigService mocks (42 tests passing)

TEC-1569

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ho Ngoc Hai
2026-04-09 09:23:10 +07:00
parent 628150b7d8
commit ee50b4c07c
13 changed files with 418 additions and 82 deletions

View File

@@ -1,5 +1,6 @@
import * as crypto from 'crypto';
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { type PaymentProvider } from '@prisma/client';
import {
type IPaymentGateway,
@@ -10,33 +11,21 @@ import {
type RefundResult,
} from './payment-gateway.interface';
function requireEnv(key: string): string {
const value = process.env[key];
if (!value) {
throw new Error(`Missing required environment variable: ${key}`);
}
return value;
}
@Injectable()
export class ZalopayService implements IPaymentGateway {
private readonly logger = new Logger(ZalopayService.name);
readonly provider: PaymentProvider = 'ZALOPAY';
private get appId(): string {
return requireEnv('ZALOPAY_APP_ID');
}
private readonly appId: string;
private readonly key1: string;
private readonly key2: string;
private readonly endpoint: string;
private get key1(): string {
return requireEnv('ZALOPAY_KEY1');
}
private get key2(): string {
return requireEnv('ZALOPAY_KEY2');
}
private get endpoint(): string {
return process.env['ZALOPAY_ENDPOINT'] ?? 'https://sb-openapi.zalopay.vn/v2';
constructor(private readonly config: ConfigService) {
this.appId = this.config.getOrThrow<string>('ZALOPAY_APP_ID');
this.key1 = this.config.getOrThrow<string>('ZALOPAY_KEY1');
this.key2 = this.config.getOrThrow<string>('ZALOPAY_KEY2');
this.endpoint = this.config.get<string>('ZALOPAY_ENDPOINT', 'https://sb-openapi.zalopay.vn/v2');
}
async createPaymentUrl(params: CreatePaymentUrlParams): Promise<CreatePaymentUrlResult> {