mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
CAC Bank is an OTP debit with no redirect and no webhook: initiate SMSes a code to the payer's mobile, and the charge only settles when that code is confirmed. The payment service already spoke it (passenger uses it); the freight side had the enum values but none of the flow. API: - PaymentClientService.confirmOtp forwards the code to POST /payments/intents/:id/confirm, mapping 400/404 to BadRequest so a mistyped code stays retryable instead of surfacing as a gateway failure. - PaymentService.confirmOtp is keyed by the LOCAL intent id (the invoice's paymentId) rather than the domain reference, so the right invoice settles when several share a booking. On success billing settles the invoice. - payInvoice rejects CAC_BANK without payerAccount before calling the gateway, and no longer runs the demo auto-settle for a COLLECT_OTP intent (it is not paid until the payer confirms). - POST /billing/my-invoices/:id/confirm — ownership-checked, and since warehouse fee invoices are central invoices it covers those too. Portal: - useInvoicePayment owns the whole flow (initiate, redirect-or-OTP, confirm) and replaces the five near-identical pay mutations at the call sites. - PaymentMethodModal gains the CAC Bank option, the payer mobile field, and the OTP step. Click-outside is disabled there so a stray click cannot drop the payer out of a live OTP window. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
39 lines
1.1 KiB
TypeScript
39 lines
1.1 KiB
TypeScript
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
|
|
import { IsIn, IsNotEmpty, IsOptional, IsString } from "class-validator";
|
|
|
|
/** OTP submitted for a COLLECT_OTP provider (CAC Bank). */
|
|
export class ConfirmOtpDto {
|
|
@ApiProperty({ description: "One-time password SMSed by the bank." })
|
|
@IsString()
|
|
@IsNotEmpty()
|
|
otp!: string;
|
|
}
|
|
|
|
/** Gateway options for paying an invoice from the customer portal. */
|
|
export class PayInvoiceDto {
|
|
@ApiPropertyOptional({ description: "Payment method (defaults to TELEBIRR)." })
|
|
@IsOptional()
|
|
@IsString()
|
|
method?: string;
|
|
|
|
@ApiPropertyOptional({ enum: ["web", "mobile"], default: "web" })
|
|
@IsOptional()
|
|
@IsIn(["web", "mobile"])
|
|
platform?: "web" | "mobile";
|
|
|
|
@ApiPropertyOptional({ description: "Payer account / phone, for wallet methods." })
|
|
@IsOptional()
|
|
@IsString()
|
|
payerAccount?: string;
|
|
|
|
@ApiPropertyOptional({ description: "Browser redirect URL on success." })
|
|
@IsOptional()
|
|
@IsString()
|
|
returnUrl?: string;
|
|
|
|
@ApiPropertyOptional({ description: "Browser redirect URL on failure." })
|
|
@IsOptional()
|
|
@IsString()
|
|
failureUrl?: string;
|
|
}
|