online payment

This commit is contained in:
2026-01-18 17:13:06 +03:30
parent 27631907cf
commit a10b6129b9
18 changed files with 345 additions and 299 deletions
@@ -20,6 +20,8 @@ export class ZarinpalGateway implements IPaymentGateway {
private readonly zarinpalRequestUrl: string;
private readonly zarinpalVerifyUrl: string;
private readonly zarinpalPaymentBaseUrl: string;
private readonly zarinpalMerchantId: string;
private readonly websiteUrl: string = 'https://negareh.ir'
private readonly axiosConfig = {
timeout: 10_000,
headers: {
@@ -32,6 +34,7 @@ export class ZarinpalGateway implements IPaymentGateway {
this.zarinpalPaymentBaseUrl = zarinpalBaseUrl;
this.zarinpalRequestUrl = `${zarinpalBaseUrl}/pg/v4/payment/request.json`;
this.zarinpalVerifyUrl = `${zarinpalBaseUrl}/pg/v4/payment/verify.json`;
this.zarinpalMerchantId = this.configService.getOrThrow<string>('ZARINPAL_BASE_MERCHANT')
}
private getAxiosErrorData(error: unknown): { status?: number; data?: unknown } | null {
@@ -39,12 +42,12 @@ export class ZarinpalGateway implements IPaymentGateway {
return { status: error.response.status, data: error.response.data };
}
async requestPayment({ amount, merchantId, orderId, domain }: IRequestPaymentParams): Promise<IRequestPaymentData> {
async requestPayment({ amount, orderId }: IRequestPaymentParams): Promise<IRequestPaymentData> {
// Transform camelCase to snake_case for Zarinpal API v4
const callbackUrl = `${domain}/verify/${orderId}`;
const callbackUrl = `${this.websiteUrl}/verify/${orderId}`;
const zarinpalRequest: IZarinpalRequestPayment = {
amount,
merchant_id: merchantId,
merchant_id: this.zarinpalMerchantId,
description: `Payment for order #${orderId}`,
callback_url: callbackUrl,
currency: 'IRT',
@@ -84,7 +87,9 @@ export class ZarinpalGateway implements IPaymentGateway {
throw new BadRequestException(message ?? PaymentMessage.ZARINPAL_PAYMENT_REQUEST_ERROR);
}
return { transactionId: authority };
const paymentUrl = `${this.zarinpalPaymentBaseUrl}/pg/StartPay/${authority}`
return { token: authority, paymentUrl };
} catch (error) {
if (error instanceof BadRequestException) throw error;
@@ -109,13 +114,13 @@ export class ZarinpalGateway implements IPaymentGateway {
}
}
async verifyPayment({ merchantId, amount, transactionId }: IPaymentVerifyParams): Promise<IPaymentVerifyData> {
async verifyPayment({ amount, token }: IPaymentVerifyParams): Promise<IPaymentVerifyData> {
try {
// Transform camelCase to snake_case for Zarinpal API v4
const zarinpalVerifyRequest: IZarinpalVerifyRequest = {
merchant_id: merchantId,
merchant_id: this.zarinpalMerchantId,
amount,
authority: transactionId,
authority: token,
};
const res = await axios.post<IZarinpalVerifyResponse>(
@@ -152,7 +157,5 @@ export class ZarinpalGateway implements IPaymentGateway {
}
}
getPaymentUrl(authority: string): string {
return `${this.zarinpalPaymentBaseUrl}/pg/StartPay/${authority}`;
}
}