feat: ( payment ) create payment microservice

This commit is contained in:
Abubeker Yasin
2026-06-11 15:25:24 +03:00
parent 3235567b41
commit 2b430f8e76
54 changed files with 2809 additions and 0 deletions

View File

@@ -74,3 +74,98 @@ export interface PaymentProvider {
initiate(input: ProviderInitiationInput): Promise<ProviderInitiationResult>;
queryStatus(merchantOrderId: string): Promise<ProviderStatus>;
}
/* ------------------------------------------------------------------------------------------------
* Payment microservice contracts (docs/payment-service)
*
* Shared shapes exchanged between the payment microservice (apps/edr-payment-api) and the
* domain apps (passenger/freight). Both sides import these so the wire format cannot drift.
* ---------------------------------------------------------------------------------------------- */
/** Which domain app owns the order being paid for. Routing discriminator on every intent. */
export enum PaymentService {
PASSENGER = "PASSENGER",
FREIGHT = "FREIGHT",
}
/** What kind of domain order the intent references (soft reference — never a cross-schema FK). */
export enum PaymentReferenceType {
BOOKING = "BOOKING",
SHIPMENT = "SHIPMENT",
}
/** `merchant_order_id` prefix per owning service — lets a webhook be routed before a DB lookup. */
export const MERCHANT_ORDER_PREFIX: Record<PaymentService, string> = {
[PaymentService.PASSENGER]: "PSG-",
[PaymentService.FREIGHT]: "FRT-",
};
/** Body of `POST /payments/initiate` on the payment service (internal, service-authenticated). */
export interface InitiatePaymentRequest {
service: PaymentService;
referenceType: PaymentReferenceType;
/** Domain order id (booking/shipment id). Soft reference; the app has already validated it. */
referenceId: string;
/** Human-readable order ref (e.g. booking ref) shown on provider pages. Defaults to referenceId. */
orderRef?: string;
/** App-asserted authoritative amount in minor units (computed server-side by the domain app). */
amountMinor: number;
currency: string;
provider: ProviderMethod;
platform?: PaymentPlatform;
payerAccount?: string;
/** Optional caller key to dedupe retried initiations beyond the per-reference upsert. */
idempotencyKey?: string;
}
/** Response of `POST /payments/initiate` and shape of intent lookups. */
export interface PaymentIntentSnapshot {
intentId: string;
service: PaymentService;
referenceType: PaymentReferenceType;
referenceId: string;
merchantOrderId: string;
provider: ProviderMethod;
status: ProviderPaymentStatus;
amountMinor: number;
currency: string;
clientAction?: ClientAction;
providerTxnId?: string;
paidAt?: string;
failureCode?: string;
failureMessage?: string;
expiresAt?: string;
}
export type PaymentEventType = "payment.succeeded" | "payment.failed";
/** Versioned envelope delivered (at-least-once) to the owning app's mark-paid consumer. */
interface PaymentEventBase {
version: 1;
/** Outbox row id — stable across redeliveries; consumers may use it as a dedupe key. */
eventId: string;
eventType: PaymentEventType;
occurredAt: string;
service: PaymentService;
intentId: string;
referenceType: PaymentReferenceType;
referenceId: string;
merchantOrderId: string;
provider: ProviderMethod;
amountMinor: number;
currency: string;
}
export interface PaymentSucceededEvent extends PaymentEventBase {
eventType: "payment.succeeded";
providerTxnId?: string;
paidAt: string;
}
export interface PaymentFailedEvent extends PaymentEventBase {
eventType: "payment.failed";
failureCode?: string;
failureMessage?: string;
}
export type PaymentEvent = PaymentSucceededEvent | PaymentFailedEvent;