Contracts and Kurv integration
Single source of truth
@payofy/contracts defines all API endpoints and asynchronous webhook payloads with Zod schemas.
The build pipeline exports these schemas to OpenAPI 3.1 definitions. Consuming packages, including @payofy/node and @payofy/js, consume types generated from these contracts. When a contract changes, client types update automatically during the build step.
Kurv isolation
Direct communication with Kurv exists solely within @payofy/kurv. Other modules interact with the PaymentRail interface.
export interface PaymentRail {
tokenizePaymentMethod(params: TokenizePaymentMethodParams): Promise<{ vaultToken: string }>;
charge(params: ChargeParams): Promise<RailChargeResult>;
refund(params: RefundParams): Promise<{ refundId: string; status: "succeeded" | "failed" }>;
void(params: VoidParams): Promise<{ voidId: string; status: "succeeded" | "failed" }>;
createMerchantApplication(params: MerchantApplicationParams): Promise<RailMerchantResult>;
getMerchantStatus(kurvMid: string): Promise<RailMerchantResult>;
verifyWebhookSignature(rawBody: string, signature: string, secret: string): boolean;
}
This boundary prevents payment processor details from leaking into domain entities or transaction accounting.