feat: ( payment ) integrate the passenger to payment microservice

This commit is contained in:
Abubeker Yasin
2026-06-12 11:47:11 +03:00
parent 2b430f8e76
commit ef7b85c8cb
31 changed files with 1555 additions and 1650 deletions

View File

@@ -75,6 +75,25 @@ export class InitiatePaymentRequestDto implements InitiatePaymentRequest {
@MaxLength(32)
payerAccount?: string;
@ApiPropertyOptional({
description:
"Per-transaction browser return URL on success — each calling app passes its own UI " +
"(passenger portal vs freight portal). UX only; never confirms payment. Falls back to " +
"the provider config when omitted.",
})
@IsOptional()
@IsString()
@MaxLength(2048)
returnUrl?: string;
@ApiPropertyOptional({
description: "Failure/cancel counterpart of returnUrl",
})
@IsOptional()
@IsString()
@MaxLength(2048)
failureUrl?: string;
@ApiPropertyOptional({
description: "Caller key to dedupe retried initiations",
})

View File

@@ -9,7 +9,6 @@ import { DataSource, QueryFailedError } from "typeorm";
import { createMerchantOrderId } from "@edr/payment-providers";
import {
InitiatePaymentRequest,
MERCHANT_ORDER_PREFIX,
PaymentIntentSnapshot,
PaymentReferenceType,
PaymentService,
@@ -60,6 +59,7 @@ export class IntentsService {
async initiate(
request: InitiatePaymentRequest,
): Promise<PaymentIntentSnapshot> {
if (request.idempotencyKey) {
const byKey = await this.intentsRepository.findByIdempotencyKey(
request.service,
@@ -85,7 +85,7 @@ export class IntentsService {
);
}
const merchantOrderId = `${MERCHANT_ORDER_PREFIX[request.service]}${createMerchantOrderId()}`;
const merchantOrderId = createMerchantOrderId();
const result = await provider.initiate({
merchantOrderId,
orderRef: request.orderRef ?? request.referenceId,
@@ -93,6 +93,9 @@ export class IntentsService {
currency: request.currency,
platform: request.platform,
payerAccount: request.payerAccount,
returnUrl: request.returnUrl,
redirectUrl: request.returnUrl,
failureUrl: request.failureUrl,
});
try {
@@ -116,8 +119,6 @@ export class IntentsService {
);
return this.toSnapshot(intent);
} catch (err) {
// Concurrent initiate for the same reference lost the partial-unique race — return the
// winner's intent. The provider session we just opened is simply abandoned.
if (
err instanceof QueryFailedError &&
(err.driverError as { code?: string })?.code === PG_UNIQUE_VIOLATION