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 VnpayService implements IPaymentGateway {
private readonly logger = new Logger(VnpayService.name);
readonly provider: PaymentProvider = 'VNPAY';
private get tmnCode(): string {
return requireEnv('VNPAY_TMN_CODE');
}
private readonly tmnCode: string;
private readonly hashSecret: string;
private readonly baseUrl: string;
private readonly apiUrl: string;
private get hashSecret(): string {
return requireEnv('VNPAY_HASH_SECRET');
}
private get baseUrl(): string {
return process.env['VNPAY_BASE_URL'] ?? 'https://sandbox.vnpayment.vn/paymentv2/vpcpay.html';
}
private get apiUrl(): string {
return process.env['VNPAY_API_URL'] ?? 'https://sandbox.vnpayment.vn/merchant_webapi/api/transaction';
constructor(private readonly config: ConfigService) {
this.tmnCode = this.config.getOrThrow<string>('VNPAY_TMN_CODE');
this.hashSecret = this.config.getOrThrow<string>('VNPAY_HASH_SECRET');
this.baseUrl = this.config.get<string>('VNPAY_BASE_URL', 'https://sandbox.vnpayment.vn/paymentv2/vpcpay.html');
this.apiUrl = this.config.get<string>('VNPAY_API_URL', 'https://sandbox.vnpayment.vn/merchant_webapi/api/transaction');
}
async createPaymentUrl(params: CreatePaymentUrlParams): Promise<CreatePaymentUrlResult> {