{"record":{"id":"888c7df1a34f25fb","repo":"nopSolutions/nopCommerce","slug":"cannot-do-refund-for-order","errorCode":null,"errorMessage":"Cannot do refund for order.","messagePattern":"Cannot do refund for order\\.","errorType":"exception","errorClass":"NopException","httpStatus":null,"severity":"error","filePath":"src/Libraries/Nop.Services/Orders/OrderProcessingService.cs","lineNumber":2648,"sourceCode":"            return true;\r\n\r\n        return false;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Refunds an order (from admin panel)\r\n    /// </summary>\r\n    /// <param name=\"order\">Order</param>\r\n    /// <returns>\r\n    /// A task that represents the asynchronous operation\r\n    /// The task result contains a list of errors; empty list if no errors\r\n    /// </returns>\r\n    public virtual async Task<IList<string>> RefundAsync(Order order)\r\n    {\r\n        ArgumentNullException.ThrowIfNull(order);\r\n\r\n        if (!await CanRefundAsync(order))\r\n            throw new NopException(\"Cannot do refund for order.\");\r\n\r\n        var request = new RefundPaymentRequest();\r\n        RefundPaymentResult result = null;\r\n        try\r\n        {\r\n            request.Order = order;\r\n            request.AmountToRefund = order.OrderTotal;\r\n            request.IsPartialRefund = false;\r\n            result = await _paymentService.RefundAsync(request);\r\n            if (result.Success)\r\n            {\r\n                //total amount refunded\r\n                var totalAmountRefunded = order.RefundedAmount + request.AmountToRefund;\r\n\r\n                //update order info\r\n                order.RefundedAmount = totalAmountRefunded;\r\n                order.PaymentStatus = result.NewPaymentStatus;\r\n                await _orderService.UpdateOrderAsync(order);\r","sourceCodeStart":2630,"sourceCodeEnd":2666,"githubUrl":"https://github.com/nopSolutions/nopCommerce/blob/64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2/src/Libraries/Nop.Services/Orders/OrderProcessingService.cs#L2630-L2666","documentation":"Thrown by OrderProcessingService.RefundAsync when CanRefundAsync(order) returns false. A full online refund is allowed only when OrderTotal > 0, RefundedAmount == 0 (no prior partial refunds), PaymentStatus == Paid, and the payment method supports refund (SupportRefundAsync). It blocks refunding zero-total orders, orders already partially refunded, or orders whose gateway cannot refund.","triggerScenarios":"Calling RefundAsync when: OrderTotal == 0; RefundedAmount > 0 (use partial refund instead); PaymentStatus != Paid; or the payment method does not support refund. Typical from admin 'Refund' on an ineligible order.","commonSituations":"Trying a full refund after a partial refund was already issued (must use PartiallyRefundAsync); payment gateway plugin not supporting refund; order not actually Paid (still Pending/Authorized); free order with zero total.","solutions":["Guard with: if (!await _orderProcessingService.CanRefundAsync(order)) return; and inspect why it is ineligible.","If RefundedAmount > 0, use PartiallyRefundAsync(order, remainingAmount) instead of RefundAsync.","Verify _paymentService.SupportRefundAsync(order.PaymentMethodSystemName); install a payment plugin that supports refund, or use the offline refund flow.","Confirm PaymentStatus == Paid before offering the refund action."],"exampleFix":"// before\nvar errors = await _orderProcessingService.RefundAsync(order);\n\n// after\nif (!await _orderProcessingService.CanRefundAsync(order))\n{\n    if (order.RefundedAmount > decimal.Zero)\n        return await _orderProcessingService.PartiallyRefundAsync(order, order.OrderTotal - order.RefundedAmount);\n    return new[] { \"Refund is not available for this order.\" };\n}\nvar errors = await _orderProcessingService.RefundAsync(order);","handlingStrategy":"validation","validationCode":"if (!await _orderProcessingService.CanRefundAsync(order))\n{\n    if (order.RefundedAmount > decimal.Zero)\n        return await _orderProcessingService.PartiallyRefundAsync(order, order.OrderTotal - order.RefundedAmount);\n    return Array.Empty<string>();\n}\n\nreturn await _orderProcessingService.RefundAsync(order);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["If RefundedAmount > 0, use PartiallyRefundAsync, not RefundAsync.","Confirm PaymentStatus == Paid and the gateway supports refund.","Skip refund for zero-total orders."],"tags":["refund","payment","order-processing","payment-method"],"backgroundTag":null,"analyzedSha":"64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2","analyzedAt":"2026-08-13T21:19:38.062Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}