fix: ( payments ) bounce D-Money checkout via /go and follow user domain

This commit is contained in:
Abubeker Yasin
2026-07-28 11:39:48 +03:00
parent 686350135d
commit 0d46f3715e
9 changed files with 101 additions and 41 deletions

View File

@@ -415,8 +415,18 @@ export class PaymentsController {
paySupplementaryCharge(
@Param('token') token: string,
@Body() dto: PaySupplementaryChargeDto,
@Headers('origin') origin?: string,
@Headers('referer') referer?: string,
@Headers('x-frontend-base-url') frontendBaseUrl?: string,
) {
return this.supplementaryService.pay(token, dto.method, dto.platform);
// Same domain-follows-the-user rule as /initiate — the self-pay page can be
// opened on either portal domain.
return this.supplementaryService.pay(
token,
dto.method,
dto.platform,
resolveAllowedOrigin(origin, referer, frontendBaseUrl),
);
}
@Post('supplementary/:id/mark-paid')

View File

@@ -48,12 +48,14 @@ const NON_TERMINAL_STATUSES: PaymentIntentStatus[] = [
];
// Methods whose return/failure URLs are browser-facing pages on the passenger
// portal, so they should follow whichever domain the user came in on. DMONEY is
// deliberately excluded — its return URL is a server-to-server webhook host, not
// a page the browser lands on.
// portal, so they should follow whichever domain the user came in on. For DMONEY
// this is the preOrder `redirect_url` (the page the browser lands on after
// checkout) — NOT `notify_url`, which is the server-to-server webhook and is
// configured provider-side, never rebased.
const DOMAIN_AWARE_METHODS = new Set<PaymentMethodType>([
PaymentMethodType.TELEBIRR,
PaymentMethodType.WAAFI,
PaymentMethodType.DMONEY,
]);
@Injectable()

View File

@@ -116,11 +116,21 @@ export class SupplementaryChargesService {
return updated;
}
async pay(token: string, method: string, platform?: 'web' | 'mobile') {
async pay(
token: string,
method: string,
platform?: 'web' | 'mobile',
requestOrigin?: string | null,
) {
const charge = await this.getByToken(token); // validates status/expiry
const paymentMethod = method as ProviderMethod;
const portalUrl = process.env.PORTAL_URL ?? 'http://localhost:5174';
// Self-pay links are opened on whichever portal domain the recipient used
// (bookingedr.et vs passenger.edrsc.com), so the return pages must live on
// that same domain. `requestOrigin` is already allowlist-validated by the
// controller; PORTAL_URL is the fallback for non-browser callers.
const portalUrl =
requestOrigin ?? process.env.PORTAL_URL ?? 'http://localhost:5174';
const returnUrl = `${portalUrl}/pay-balance/${token}/success`;
const failureUrl = `${portalUrl}/pay-balance/${token}/failed`;