From 8b957e956ef03513a1febd134ab0aaf92540b999 Mon Sep 17 00:00:00 2001 From: Abubeker Yasin Date: Wed, 8 Jul 2026 15:06:54 +0300 Subject: [PATCH] Update waafi.provider.ts --- .../src/providers/waafi/waafi.provider.ts | 49 +++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/packages/payment-providers/src/providers/waafi/waafi.provider.ts b/packages/payment-providers/src/providers/waafi/waafi.provider.ts index 58331ecbd..5914fcd61 100644 --- a/packages/payment-providers/src/providers/waafi/waafi.provider.ts +++ b/packages/payment-providers/src/providers/waafi/waafi.provider.ts @@ -1,4 +1,4 @@ -import { Injectable, Logger } from "@nestjs/common"; +import { Injectable, Logger, OnModuleInit } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { HttpService } from "@nestjs/axios"; import { @@ -26,7 +26,7 @@ const WAAFI_SUCCESS_CODE = "2001"; const WAAFI_HPP_SESSION_MS = 5 * 60_000; @Injectable() -export class WaafiProvider implements PaymentProvider { +export class WaafiProvider implements PaymentProvider, OnModuleInit { readonly method = ProviderMethod.WAAFI; private readonly logger = new Logger(WaafiProvider.name); private readonly httpsAgent: https.Agent; @@ -44,16 +44,59 @@ export class WaafiProvider implements PaymentProvider { this.httpsAgent = new https.Agent({ rejectUnauthorized: !insecure }); } + /** Log the effective Waafi config once at startup (secrets masked) so misconfig is visible. */ + onModuleInit(): void { + this.logger.log( + `Waafi config resolved: ${JSON.stringify(this.effectiveConfig())}`, + ); + } + + /** Snapshot of every resolved Waafi env value; secret fields are masked, not printed raw. */ + private effectiveConfig(): Record { + return { + WAAFI_BASE_URL: this.baseUrl, + WAAFI_MERCHANT_UID: this.merchantUid || "(empty)", + WAAFI_STORE_ID: this.storeId || "(empty)", + WAAFI_HPP_KEY: this.mask(this.hppKey), + WAAFI_WEBHOOK_SECRET: this.mask(this.webhookSecret), + WAAFI_PAYMENT_METHOD: this.paymentMethod, + WAAFI_HPP_SUCCESS_URL: this.successUrl || "(empty)", + WAAFI_HPP_FAILURE_URL: this.failureUrl || "(empty)", + WAAFI_HPP_RESP_FORMAT: this.respDataFormat, + WAAFI_INSECURE_TLS: this.config.get("waafi.insecureTls") ?? false, + }; + } + + /** Mask a secret to `set(len=N,…abcd)` / `(empty)` so presence & length are visible but not the value. */ + private mask(value: string): string { + if (!value) return "(empty)"; + const tail = value.length > 4 ? value.slice(-4) : ""; + return `set(len=${value.length},…${tail})`; + } + async initiate( input: ProviderInitiationInput, ): Promise { const requestBody = this.buildPurchaseRequest(input); + const url = `${this.baseUrl}/asm`; + this.logger.log( + `Waafi HPP_PURCHASE → ${url} | currency=${input.currency} amount=${this.toAmount(input.amountMinor)} (amountMinorIn=${input.amountMinor}) ref=${input.merchantOrderId}`, + ); + this.logger.debug( + `Waafi HPP_PURCHASE request body: ${JSON.stringify(this.sanitize(requestBody))}`, + ); + this.logger.debug( + `Waafi effective config: ${JSON.stringify(this.effectiveConfig())}`, + ); const response = await this.postJson( - `${this.baseUrl}/asm`, + url, requestBody, ); if (response.responseCode !== WAAFI_SUCCESS_CODE) { + this.logger.error( + `Waafi HPP_PURCHASE rejected — sent currency=${input.currency} amount=${this.toAmount(input.amountMinor)} paymentMethod=${this.paymentMethod} | full response: ${JSON.stringify(response)}`, + ); throw new Error( `Waafi HPP_PURCHASE failed: responseCode=${response.responseCode} errorCode=${response.errorCode} msg=${response.responseMsg}`, );