From 2b2f41ebab01acb9284ea50c6c448e5ad8b5ccbf Mon Sep 17 00:00:00 2001 From: fs Date: Sun, 5 Apr 2026 22:55:12 +0200 Subject: [PATCH] fix(helpdesk): extract SOAP fault detail from GetTicketFile error responses Show the actual BC error message instead of just 'HTTP 500' to help diagnose authentication and parameter issues. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Module/Helpdesk/Service/BcSoapGateway.php | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/modules/helpdesk/lib/Module/Helpdesk/Service/BcSoapGateway.php b/modules/helpdesk/lib/Module/Helpdesk/Service/BcSoapGateway.php index a79602d..470f352 100644 --- a/modules/helpdesk/lib/Module/Helpdesk/Service/BcSoapGateway.php +++ b/modules/helpdesk/lib/Module/Helpdesk/Service/BcSoapGateway.php @@ -335,7 +335,10 @@ XML; $httpCode = (int) ($response['http_code'] ?? 0); $rawBody = (string) ($response['body'] ?? ''); if ($httpCode < 200 || $httpCode >= 300) { - return ['ok' => false, 'error' => 'SOAP request failed: HTTP ' . $httpCode]; + // Try to extract SOAP fault from error response body + $faultDetail = $this->extractSoapFault($rawBody); + + return ['ok' => false, 'error' => 'SOAP request failed: HTTP ' . $httpCode . ($faultDetail !== '' ? ' — ' . $faultDetail : '')]; } return $this->parseGetTicketFileResponse($rawBody); @@ -423,6 +426,30 @@ XML; return ['ok' => true, 'data' => $decoded]; } + private function extractSoapFault(string $body): string + { + if ($body === '') { + return ''; + } + + $dom = new \DOMDocument(); + $prev = libxml_use_internal_errors(true); + $loaded = $dom->loadXML($body); + libxml_clear_errors(); + libxml_use_internal_errors($prev); + if (!$loaded) { + return mb_substr(trim($body), 0, 200); + } + + $xpath = new \DOMXPath($dom); + $faultNode = $xpath->query("//*[local-name()='Fault']/*[local-name()='faultstring']")->item(0); + if ($faultNode instanceof \DOMNode) { + return trim((string) $faultNode->textContent); + } + + return mb_substr(trim($body), 0, 200); + } + private function buildSoapEndpoint(): ?string { $baseUrl = trim($this->settingsGateway->getODataBaseUrl());