import "server-only"; import type { AdminRefundCommand, PaymentProvider, PaymentProviderError, } from "@salixcommerce/core"; import { hashCommerceRequest } from "../commerce/capability"; import { adminFailure, type AdminContext, type AdminRepository, type AdminResult, } from "./repository"; export function createAdminService(repository: AdminRepository, provider: PaymentProvider | null) { return Object.freeze({ async requestRefund( context: AdminContext, providerPaymentReference: string, command: AdminRefundCommand, ): Promise> { const payment = await repository.loadPayment(providerPaymentReference); if (payment === null) { return { error: adminFailure("NOT_FOUND", "Payment not found.", 404), ok: false }; } if (provider === null || provider.key !== payment.provider) { return { error: adminFailure("PAYMENTS_UNAVAILABLE", "The payment provider is unavailable.", 503), ok: false, }; } if (payment.status !== "succeeded" && payment.status !== "partially_refunded") { return { error: adminFailure("INVALID_REQUEST", "Only a captured payment can be refunded.", 400), ok: false, }; } if (payment.refundedAmountMinor + command.amountMinor > payment.amountMinor) { return { error: adminFailure( "REFUND_EXCEEDS_PAYMENT", "The refund exceeds the captured payment.", 409, ), ok: false, }; } const requestHash = hashCommerceRequest({ command, providerPaymentReference }); const result = await provider.createRefund({ amount: { amountMinor: command.amountMinor, currency: payment.currency }, idempotencyKey: command.idempotencyKey, orderReference: payment.orderReference, providerPaymentReference, reason: command.reason, }); if (!result.ok) return { error: mapProviderError(result.error), ok: false }; return repository.recordRefund(context, command, payment, result.data, requestHash); }, }); } function mapProviderError(error: PaymentProviderError) { if (error.code === "NOT_FOUND") return adminFailure("NOT_FOUND", "Payment not found.", 404); if (error.code === "INVALID_REQUEST") return adminFailure("INVALID_REQUEST", "The refund request is invalid.", 400); if (error.code === "REJECTED") return adminFailure("REFUND_EXCEEDS_PAYMENT", error.message, 409); if (error.code === "CONFIGURATION") return adminFailure("PAYMENTS_UNAVAILABLE", "The payment provider is unavailable.", 503); return adminFailure( "PROVIDER_FAILURE", "The payment provider could not complete the refund.", error.retryable ? 503 : 500, ); }