From e31a2d64e50938a726c15dc61c8fda3d19fed51e Mon Sep 17 00:00:00 2001 From: Muluhabt Date: Wed, 22 Jul 2026 17:29:40 +0300 Subject: [PATCH] Fixing isssues usins AI --- .../modules/payments/payment-client.service.ts | 8 +++++++- .../src/modules/intents/intents.service.ts | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/apps/edr-passenger-api/src/modules/payments/payment-client.service.ts b/apps/edr-passenger-api/src/modules/payments/payment-client.service.ts index 84ca92c02..1ca92e304 100644 --- a/apps/edr-passenger-api/src/modules/payments/payment-client.service.ts +++ b/apps/edr-passenger-api/src/modules/payments/payment-client.service.ts @@ -1,6 +1,7 @@ import { BadGatewayException, BadRequestException, + ConflictException, Injectable, Logger, } from "@nestjs/common"; @@ -154,11 +155,16 @@ export class PaymentClientService { } catch (err) { if (err instanceof AxiosError && err.response) { // 4xx/5xx from the payment service: propagate 404 to callers that handle it; - // everything else is a gateway-level failure from the client's perspective. + // 409 = a legitimate conflict (e.g. another provider's payment is already in + // flight for this booking) — surface its message as-is rather than masking it as + // a gateway failure; everything else is a genuine gateway-level failure. if (err.response.status === 404) throw err; const detail = (err.response.data as { message?: string | string[] })?.message ?? err.message; + if (err.response.status === 409) { + throw new ConflictException(detail); + } this.logger.error( `payment service ${method} ${path} → ${err.response.status}: ${detail}`, ); diff --git a/apps/edr-payment-api/src/modules/intents/intents.service.ts b/apps/edr-payment-api/src/modules/intents/intents.service.ts index 704a46c2f..ce0760f2f 100644 --- a/apps/edr-payment-api/src/modules/intents/intents.service.ts +++ b/apps/edr-payment-api/src/modules/intents/intents.service.ts @@ -1,5 +1,6 @@ import { BadRequestException, + ConflictException, Inject, Injectable, Logger, @@ -106,9 +107,19 @@ export class IntentsService { // so a fresh session opens below. const settled = await this.verifyThenSupersede(existing); if (settled) return this.toSnapshot(settled); + } else if (existing.provider !== request.provider) { + // PROCESSING/SUCCEEDED on a DIFFERENT provider than requested: money may already be + // in flight there. Must not silently hand back that other provider's clientAction + // (e.g. its redirect URL) as if it belonged to the newly requested provider — the + // caller has no way to tell the two apart (see InitiateResponseDto), so it would + // blindly redirect the payer to the wrong gateway's checkout page. + throw new ConflictException( + `A ${existing.provider} payment is already ${existing.status.toLowerCase()} for this ` + + `booking. Complete or wait for it to resolve before switching payment methods.`, + ); } else { - // PROCESSING (money in flight) or SUCCEEDED (already paid): never reopen — - // return the existing intent so the caller adopts its outcome. + // Same provider, already PROCESSING/SUCCEEDED: never reopen — return the existing + // intent so the caller adopts its outcome. return this.toSnapshot(existing); } }