manicanldes-backend/src/payments/payment.policy.ts

45 lines
1.3 KiB
TypeScript

import { AppError } from '../common/errors/app-error';
import type { CapturedPayment } from './gateway.contract';
export interface ExpectedPayment {
orderId: string;
paymentId: string;
amountMinor: string;
currency: string;
expiresAt: Date;
cancelled: boolean;
alreadyCaptured: boolean;
}
export function captureDecision(
expected: ExpectedPayment,
event: CapturedPayment,
now: Date,
) {
if (
event.orderId !== expected.orderId ||
event.paymentId !== expected.paymentId
)
throw new AppError('PAYMENT_REFERENCE_MISMATCH');
if (event.currency !== expected.currency)
throw new AppError('PAYMENT_CURRENCY_MISMATCH');
if (event.amountMinor !== expected.amountMinor)
throw new AppError('PAYMENT_AMOUNT_MISMATCH');
if (expected.alreadyCaptured) return 'DUPLICATE' as const;
if (expected.cancelled || expected.expiresAt <= now)
return 'REVIEW_AND_REFUND' as const;
return 'COMMIT_RESERVED_STOCK' as const;
}
export function refundAmount(
captured: bigint,
completed: bigint,
pending: bigint,
requested: bigint,
) {
if (
[captured, completed, pending].some((value) => value < 0n) ||
requested <= 0n ||
completed + pending + requested > captured
)
throw new AppError('REFUND_AMOUNT_INVALID');
return requested.toString();
}