mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 18:48:11 +00:00
feat: (payment) add telebirr mini-app in-app payment flow
This commit is contained in:
@@ -56,7 +56,7 @@ class WaiveSupplementaryChargeDto {
|
||||
|
||||
class PaySupplementaryChargeDto {
|
||||
@ApiProperty({ enum: PaymentMethodTypeEnum, example: 'TELEBIRR' }) @IsEnum(PaymentMethodTypeEnum) method: PaymentMethodTypeEnum;
|
||||
@ApiPropertyOptional({ enum: ['web', 'mobile'], default: 'web' }) @IsOptional() @IsIn(['web', 'mobile']) platform?: 'web' | 'mobile';
|
||||
@ApiPropertyOptional({ enum: ['web', 'mobile', 'inapp'], default: 'web' }) @IsOptional() @IsIn(['web', 'mobile', 'inapp']) platform?: PaymentPlatformDto;
|
||||
}
|
||||
|
||||
@ApiTags("Payment")
|
||||
@@ -307,7 +307,14 @@ export class PaymentsController {
|
||||
})
|
||||
@ApiQuery({ name: "bookingId", required: true })
|
||||
@ApiQuery({ name: "method", enum: PaymentMethodTypeEnum, required: true })
|
||||
@ApiQuery({ name: "platform", enum: ["web", "mobile"], required: false })
|
||||
@ApiQuery({
|
||||
name: "platform",
|
||||
enum: ["web", "mobile"],
|
||||
required: false,
|
||||
description:
|
||||
"Browser-only endpoint — `inapp` is not offered here. A mini-app payer has no browser " +
|
||||
"to redirect and must go through POST /payments/initiate for the bridge payload.",
|
||||
})
|
||||
@ApiProduces("text/html")
|
||||
async checkout(
|
||||
@Query("bookingId") bookingId: string,
|
||||
|
||||
@@ -28,7 +28,8 @@ export enum PaymentMethodTypeEnum {
|
||||
CBE_BILL = "CBE_BILL", // Ethiopia (pay at any CBE channel by bill number)
|
||||
}
|
||||
|
||||
export type PaymentPlatformDto = "web" | "mobile";
|
||||
/** Mirrors `PaymentPlatform` in @edr/types — see there for what each surface means. */
|
||||
export type PaymentPlatformDto = "web" | "mobile" | "inapp";
|
||||
|
||||
export class InitiatePaymentDto {
|
||||
@ApiProperty({ example: "booking-uuid" }) @IsString() bookingId: string;
|
||||
@@ -45,12 +46,14 @@ export class InitiatePaymentDto {
|
||||
@IsString()
|
||||
paymentMethodId?: string;
|
||||
@ApiPropertyOptional({
|
||||
enum: ["web", "mobile"],
|
||||
enum: ["web", "mobile", "inapp"],
|
||||
default: "web",
|
||||
description: "Payment platform (web or mobile)",
|
||||
description:
|
||||
"Payer surface. `inapp` = the portal is running inside a SuperApp mini-app WebView " +
|
||||
"(Telebirr), which cannot follow redirect flows and gets a bridge payload instead.",
|
||||
})
|
||||
@IsOptional()
|
||||
@IsIn(["web", "mobile"])
|
||||
@IsIn(["web", "mobile", "inapp"])
|
||||
platform?: PaymentPlatformDto;
|
||||
@ApiPropertyOptional({
|
||||
description:
|
||||
@@ -117,9 +120,20 @@ export class SupportedPaymentMethodDto {
|
||||
|
||||
export class ClientActionDto {
|
||||
@ApiProperty({
|
||||
enum: ["REDIRECT", "LAUNCH_APP", "COLLECT_OTP", "SHOW_BILL_REFERENCE"],
|
||||
enum: [
|
||||
"REDIRECT",
|
||||
"LAUNCH_APP",
|
||||
"INVOKE_BRIDGE",
|
||||
"COLLECT_OTP",
|
||||
"SHOW_BILL_REFERENCE",
|
||||
],
|
||||
})
|
||||
type: "REDIRECT" | "LAUNCH_APP" | "COLLECT_OTP" | "SHOW_BILL_REFERENCE";
|
||||
type:
|
||||
| "REDIRECT"
|
||||
| "LAUNCH_APP"
|
||||
| "INVOKE_BRIDGE"
|
||||
| "COLLECT_OTP"
|
||||
| "SHOW_BILL_REFERENCE";
|
||||
@ApiPropertyOptional({ description: "Set when type=REDIRECT (web flow)" })
|
||||
url?: string;
|
||||
@ApiPropertyOptional({
|
||||
@@ -134,6 +148,18 @@ export class ClientActionDto {
|
||||
description: "Set when type=LAUNCH_APP (mobile flow)",
|
||||
})
|
||||
shortCode?: string;
|
||||
@ApiPropertyOptional({
|
||||
description:
|
||||
"Set when type=INVOKE_BRIDGE (telebirr mini app) — which SuperApp host bridge to call",
|
||||
enum: ["TELEBIRR"],
|
||||
})
|
||||
bridge?: "TELEBIRR";
|
||||
@ApiPropertyOptional({
|
||||
description:
|
||||
"Set when type=INVOKE_BRIDGE (telebirr mini app). Signed query string handed verbatim " +
|
||||
"to the host bridge (js_fun_start_pay). NOT a URL — never navigate to it.",
|
||||
})
|
||||
rawRequest?: string;
|
||||
@ApiPropertyOptional({ description: "Set when type=COLLECT_OTP (e.g. CAC Bank)" })
|
||||
providerOrderId?: string;
|
||||
@ApiPropertyOptional({ description: "Set when type=COLLECT_OTP" })
|
||||
|
||||
@@ -5,6 +5,7 @@ import { SmsClientService } from '../notifications/sms-client.service';
|
||||
import { EmailClientService } from '../notifications/email-client.service';
|
||||
import { PaymentClientService } from './payment-client.service';
|
||||
import { PaymentReferenceType, PaymentService as PaymentServiceEnum, ProviderMethod } from '@edr/types';
|
||||
import { PaymentPlatformDto } from './payments.dto';
|
||||
|
||||
const CHARGE_TTL_MS = 72 * 60 * 60 * 1000; // 72 hours
|
||||
|
||||
@@ -119,7 +120,7 @@ export class SupplementaryChargesService {
|
||||
async pay(
|
||||
token: string,
|
||||
method: string,
|
||||
platform?: 'web' | 'mobile',
|
||||
platform?: PaymentPlatformDto,
|
||||
requestOrigin?: string | null,
|
||||
) {
|
||||
const charge = await this.getByToken(token); // validates status/expiry
|
||||
|
||||
Reference in New Issue
Block a user