{"record":{"id":"90d54cefb2d39f36","repo":"nopSolutions/nopCommerce","slug":"capture-is-in-refund-status-status-due-to-refun","errorCode":null,"errorMessage":"Capture is in {refund.Status} status due to {refund.StatusDetails?.Reason}","messagePattern":"Capture is in (.+?) status due to (.+?)","errorType":"exception","errorClass":"NopException","httpStatus":null,"severity":"warning","filePath":"src/Plugins/Nop.Plugin.Payments.PayPalCommerce/Services/PayPalCommerceServiceManager.cs","lineNumber":2582,"sourceCode":"\n            if (string.IsNullOrEmpty(nopOrder.CaptureTransactionId))\n                throw new NopException(\"Capture ID not set\");\n\n            var request = new CreateRefundRequest\n            {\n                CaptureId = nopOrder.CaptureTransactionId,\n                Amount = amount.HasValue ? PrepareMoney(amount.Value, currencyCode) : null\n            };\n            var refund = await _httpClient.RequestAsync<CreateRefundRequest, CreateRefundResponse>(request, settings);\n\n            if (refund.Status?.ToUpper() == RefundStatusType.CANCELLED.ToString())\n                throw new NopException(\"The refund was cancelled\");\n\n            if (refund.Status?.ToUpper() == RefundStatusType.FAILED.ToString())\n                throw new NopException(\"The refund could not be processed\");\n\n            if (refund.Status?.ToUpper() == RefundStatusType.PENDING.ToString())\n                throw new NopException($\"Capture is in {refund.Status} status due to {refund.StatusDetails?.Reason}\");\n\n            //save id to avoid double refund\n            var refundIds = await _genericAttributeService\n                .GetAttributeAsync<List<string>>(nopOrder, PayPalCommerceDefaults.RefundIdAttributeName)\n                ?? new();\n            if (!refundIds.Contains(refund.Id))\n                refundIds.Add(refund.Id);\n            await _genericAttributeService.SaveAttributeAsync(nopOrder, PayPalCommerceDefaults.RefundIdAttributeName, refundIds);\n\n            return refund;\n        });\n    }\n\n    #endregion\n\n    #region Recurring payments\n\n    /// <summary>","sourceCodeStart":2564,"sourceCodeEnd":2600,"githubUrl":"https://github.com/nopSolutions/nopCommerce/blob/64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2/src/Plugins/Nop.Plugin.Payments.PayPalCommerce/Services/PayPalCommerceServiceManager.cs#L2564-L2600","documentation":"Thrown by RefundAsync when PayPal returns status PENDING (with a reason in StatusDetails). A pending refund means PayPal has accepted it but money movement is delayed (e.g. bank-funded), so it is not yet complete. The message is interpolated with refund.Status and refund.StatusDetails?.Reason and surfaced as the Error string.","triggerScenarios":"PayPal returns PENDING because the refund is funded from a bank or echeck; PayPal is performing review/compliance hold on the refund.","commonSituations":"Refund issued against a capture whose funding source is a bank account (echeck); PayPal risk review; high-value refund under manual processing.","solutions":["Do not treat the order as refunded yet; record the refund as pending and notify staff.","Poll the PayPal refund resource (or listen for the refund-completed webhook) to confirm completion.","Inform the customer that bank-funded refunds can take several business days to settle."],"exampleFix":"// before\nvar (refund, err) = await _serviceManager.RefundAsync(settings, order, amount);\n\n// after\nvar (refund, err) = await _serviceManager.RefundAsync(settings, order, amount);\nif (!string.IsNullOrEmpty(err) && refund?.Status?.ToUpper() == RefundStatusType.PENDING.ToString())\n{\n    MarkOrderRefundPending(order, refund.Id);\n    NotifyAdmin($\"Refund pending: {err}\");\n    return;\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"var (refund, error) = await mgr.RefundAsync(settings, order, amount);\nif (!string.IsNullOrEmpty(error) && refund?.Status?.ToUpper() == \"PENDING\")\n{\n    MarkOrderRefundPending(order, refund.Id);\n    // reconcile later via webhook when status becomes COMPLETED\n    return;\n}","preventionTips":["Handle PayPal refund-completed webhooks to finalize pending refunds.","Treat PENDING as unsettled, not as success.","Tell customers bank-funded refunds take days to settle."],"tags":["payments","paypal-commerce","refund","status","async-settlement"],"backgroundTag":null,"analyzedSha":"64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2","analyzedAt":"2026-08-13T21:19:38.062Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}