diff --git a/packages/payment-providers/src/providers/dmoney/dmoney.provider.ts b/packages/payment-providers/src/providers/dmoney/dmoney.provider.ts index a4aae8ca3..fa8455db5 100644 --- a/packages/payment-providers/src/providers/dmoney/dmoney.provider.ts +++ b/packages/payment-providers/src/providers/dmoney/dmoney.provider.ts @@ -1,6 +1,6 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import { HttpService } from '@nestjs/axios'; +import { Injectable, Logger } from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; +import { HttpService } from "@nestjs/axios"; import { PaymentProvider, ProviderInitiationInput, @@ -8,10 +8,10 @@ import { ProviderStatus, ProviderPaymentStatus, ProviderMethod, -} from '@edr/types'; -import { AxiosError, AxiosRequestConfig } from 'axios'; -import { firstValueFrom } from 'rxjs'; -import * as crypto from 'node:crypto'; +} from "@edr/types"; +import { AxiosError, AxiosRequestConfig } from "axios"; +import { firstValueFrom } from "rxjs"; +import * as crypto from "node:crypto"; interface DMoneyAuthResponse { token: string; @@ -56,9 +56,11 @@ export class DMoneyProvider implements PaymentProvider { constructor( private readonly config: ConfigService, private readonly http: HttpService, - ) {} + ) { } - async initiate(input: ProviderInitiationInput): Promise { + async initiate( + input: ProviderInitiationInput, + ): Promise { const token = await this.getFabricToken(); const amount = (input.amountMinor / 100).toFixed(2); const timestamp = new Date().toISOString(); @@ -95,8 +97,11 @@ export class DMoneyProvider implements PaymentProvider { return { providerOrderId: response.orderId, clientAction: response.checkoutUrl - ? { type: 'REDIRECT', url: response.checkoutUrl } - : { type: 'REDIRECT', url: `${this.baseUrl}/checkout/${response.orderId}` }, + ? { type: "REDIRECT", url: response.checkoutUrl } + : { + type: "REDIRECT", + url: `${this.baseUrl}/checkout/${response.orderId}`, + }, expiresAt, rawInitiation: { request: this.sanitize(requestBody), @@ -106,7 +111,7 @@ export class DMoneyProvider implements PaymentProvider { } async queryStatus(merchantOrderId: string): Promise { - const token = await this.authenticate(); + const token = await this.getFabricToken(); const timestamp = new Date().toISOString(); const signature = this.signRequest({ merchantId: this.merchantId, @@ -130,14 +135,15 @@ export class DMoneyProvider implements PaymentProvider { return { status: mapped, providerTxnId: response.transactionId, - failureCode: mapped === ProviderPaymentStatus.FAILED ? response.status : undefined, + failureCode: + mapped === ProviderPaymentStatus.FAILED ? response.status : undefined, rawResponse: response as unknown as Record, }; } verifyWebhookSignature(payload: Record): boolean { const { signature, ...data } = payload; - if (!signature || typeof signature !== 'string') return false; + if (!signature || typeof signature !== "string") return false; const expectedSignature = this.signRequest(data); return crypto.timingSafeEqual( @@ -152,17 +158,17 @@ export class DMoneyProvider implements PaymentProvider { private mapStatus(status: string): ProviderPaymentStatus { switch (status?.toUpperCase()) { - case 'SUCCESS': - case 'COMPLETED': + case "SUCCESS": + case "COMPLETED": return ProviderPaymentStatus.SUCCEEDED; - case 'FAILED': - case 'REJECTED': - case 'EXPIRED': - case 'CANCELLED': + case "FAILED": + case "REJECTED": + case "EXPIRED": + case "CANCELLED": return ProviderPaymentStatus.FAILED; - case 'PENDING': + case "PENDING": return ProviderPaymentStatus.REQUIRES_ACTION; - case 'PROCESSING': + case "PROCESSING": return ProviderPaymentStatus.PROCESSING; default: return ProviderPaymentStatus.PROCESSING; @@ -178,7 +184,9 @@ export class DMoneyProvider implements PaymentProvider { ); if (!response.token) { - throw new Error(`DMoney authentication failed: ${JSON.stringify(response)}`); + throw new Error( + `DMoney authentication failed: ${JSON.stringify(response)}`, + ); } return response.token; @@ -186,22 +194,24 @@ export class DMoneyProvider implements PaymentProvider { private signRequest(data: Record): string { const sortedKeys = Object.keys(data).sort(); - const signString = sortedKeys - .map((key) => `${key}=${data[key]}`) - .join('&'); + const signString = sortedKeys.map((key) => `${key}=${data[key]}`).join("&"); return crypto - .createHmac('sha256', this.secretKey) + .createHmac("sha256", this.secretKey) .update(signString) - .digest('hex'); + .digest("hex"); } - private async postJson(url: string, body: unknown, token?: string): Promise { + private async postJson( + url: string, + body: unknown, + token?: string, + ): Promise { const headers: Record = { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }; if (token) { - headers['Authorization'] = `Bearer ${token}`; + headers["Authorization"] = `Bearer ${token}`; } const config: AxiosRequestConfig = { @@ -212,7 +222,9 @@ export class DMoneyProvider implements PaymentProvider { const started = Date.now(); try { const res = await firstValueFrom(this.http.post(url, body, config)); - this.logger.debug(`DMoney POST ${url} status=${res.status} latency=${Date.now() - started}ms`); + this.logger.debug( + `DMoney POST ${url} status=${res.status} latency=${Date.now() - started}ms`, + ); return res.data; } catch (err) { if (err instanceof AxiosError) { @@ -220,7 +232,9 @@ export class DMoneyProvider implements PaymentProvider { `DMoney POST ${url} failed: status=${err.response?.status} body=${JSON.stringify(err.response?.data)}`, ); } else { - this.logger.error(`DMoney POST ${url} threw: ${err instanceof Error ? err.message : err}`); + this.logger.error( + `DMoney POST ${url} threw: ${err instanceof Error ? err.message : err}`, + ); } throw err; } @@ -232,21 +246,21 @@ export class DMoneyProvider implements PaymentProvider { } private get baseUrl(): string { - return this.config.get('dmoney.baseUrl') ?? ''; + return this.config.get("dmoney.baseUrl") ?? ""; } private get merchantId(): string { - return this.config.get('dmoney.merchantId') ?? ''; + return this.config.get("dmoney.merchantId") ?? ""; } private get appSecret(): string { - return this.config.get('dmoney.appSecret') ?? ''; + return this.config.get("dmoney.appSecret") ?? ""; } private get secretKey(): string { - return this.config.get('dmoney.secretKey') ?? ''; + return this.config.get("dmoney.secretKey") ?? ""; } private get notifyUrl(): string { - return this.config.get('dmoney.notifyUrl') ?? ''; + return this.config.get("dmoney.notifyUrl") ?? ""; } private get returnUrl(): string { - return this.config.get('dmoney.returnUrl') ?? ''; + return this.config.get("dmoney.returnUrl") ?? ""; } }