diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Connectors/Connector.cs b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Connectors/Connector.cs index d1fbd41..38dd622 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Connectors/Connector.cs +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Connectors/Connector.cs @@ -9,6 +9,7 @@ using System.Collections.Concurrent; using System.Net; using System.Net.Http; +using System.ServiceModel; using System.Xml; using static Dynamicweb.Ecommerce.DynamicwebLiveIntegration.Notifications.Communication; @@ -308,6 +309,12 @@ private static void HandleException(ConnectorBase connector, Settings settings, { httpStatusCode = HttpStatusCode.OK; bool skipError = false; + //Do not mark the connection as failed when the ERP itself returned a fault (business error), report it as 500 like the Endpoint path does + if (IsErpBusinessFault(ex)) + { + httpStatusCode = HttpStatusCode.InternalServerError; + skipError = true; + } //Do not ping Endpoints with Internal Server Error 500 (that means that the request was received but generating response failed) if (ex?.InnerException is not null) { @@ -355,6 +362,54 @@ private static void HandleException(ConnectorBase connector, Settings settings, } } + /// + /// Determines whether the exception is a fault returned by the ERP itself (e.g. a NAV/BC business error), + /// as opposed to a failure of the connector service or of its connection to the ERP. + /// + private static bool IsErpBusinessFault(Exception ex) + { + for (var current = ex; current is not null; current = current.InnerException) + { + //Connector service internal error with exception details (DebugInfo=True in the connector service config) + if (current is FaultException detailFault) + { + return IsErpInternalServerError(detailFault.Detail); + } + //Fault passed through from the ERP, or connector service internal error without exception details + if (current is FaultException fault) + { + return !IsInternalServiceFault(fault.Code); + } + } + return false; + } + + private static bool IsInternalServiceFault(FaultCode code) + { + for (var current = code; current is not null; current = current.SubCode) + { + if (string.Equals(current.Name, "InternalServiceFault", StringComparison.Ordinal)) + { + return true; + } + } + return false; + } + + private static bool IsErpInternalServerError(ExceptionDetail detail) + { + //The connector service received an HTTP 500 response from the ERP (e.g. a SOAP fault from the BC OAuth endpoint) + for (var current = detail; current is not null; current = current.InnerException) + { + if (string.Equals(current.Type, typeof(WebException).FullName, StringComparison.Ordinal) && + !string.IsNullOrEmpty(current.Message) && current.Message.Contains("(500)")) + { + return true; + } + } + return false; + } + /// /// Retrieves a PDF document as a Base64-encoded string based on the specified request and submission type. /// diff --git a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj index 840a3f8..bab04e3 100644 --- a/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj +++ b/src/Dynamicweb.Ecommerce.DynamicwebLiveIntegration/Dynamicweb.Ecommerce.DynamicwebLiveIntegration.csproj @@ -1,6 +1,6 @@  - 10.21.9 + 10.21.10 1.0.0.0 Live Integration Live Integration @@ -28,6 +28,7 @@ +