fix: make payment event reduction monotonic
This commit is contained in:
1 parent
98e0813061
commit
fe44bc2091
11 files changed
+458
-16
No files matched your search
@@ -39,7 +39,35 @@ const gatewayFault = <T>(reason: string): PaymentResult<T> => ({
|
||||
reason,
|
||||
});
|
||||
export function derivePaymentStatus(events: readonly PaymentEvent[]): PaymentStatus {
|
||||
return events.at(-1)?.status ?? "created";
|
||||
const ordered = [...events].sort((left, right) => {
|
||||
if (left.sequence !== undefined && right.sequence !== undefined) {
|
||||
const numeric = Number(left.sequence) - Number(right.sequence);
|
||||
if (Number.isFinite(numeric) && numeric !== 0) return numeric;
|
||||
const lexical = String(left.sequence).localeCompare(String(right.sequence));
|
||||
if (lexical) return lexical;
|
||||
}
|
||||
return (
|
||||
(left.occurredAt ?? left.at) - (right.occurredAt ?? right.at) ||
|
||||
left.id.localeCompare(right.id)
|
||||
);
|
||||
});
|
||||
let status: PaymentStatus = "created";
|
||||
for (const event of ordered) {
|
||||
if (status === "refunded") continue;
|
||||
if (
|
||||
status === "partially_refunded" &&
|
||||
!["partially_refunded", "refunded"].includes(event.status)
|
||||
)
|
||||
continue;
|
||||
if (
|
||||
status === "captured" &&
|
||||
["created", "pending", "authorized", "failed", "cancelled"].includes(event.status)
|
||||
)
|
||||
continue;
|
||||
if (status === "authorized" && ["created", "pending"].includes(event.status)) continue;
|
||||
status = event.status;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
export function defineGateway<T extends PaymentGateway>(gateway: T): T {
|
||||
if (!gateway.id.trim()) throw new Error("WRN-PAYMENT-GATEWAY: id is required");
|
||||
@@ -269,6 +297,8 @@ export function definePayment(options: PaymentOptions) {
|
||||
type: event.type,
|
||||
status: event.status,
|
||||
at: Date.now(),
|
||||
occurredAt: event.occurredAt,
|
||||
sequence: event.sequence,
|
||||
payload: event.payload,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user