jsonFactory->create(); $rawBody = (string)$this->request->getContent(); $startedAt = microtime(true); $context = $this->apiLog->getWebhookContext($rawBody); try { $processingResult = $this->processor->execute( $rawBody, (string)$this->request->getHeader('sign') ); $this->writeWebhookLog($context + $processingResult, $rawBody, 200, $startedAt); return $result->setData(['success' => true]); } catch (AuthenticationException $exception) { $this->logger->warning('Rejected a 17TRACK webhook with an invalid signature.'); $this->writeWebhookLog($context + [ 'status' => 'error', 'message' => $exception->getMessage(), ], $rawBody, 401, $startedAt); return $result->setHttpResponseCode(401)->setData([ 'success' => false, 'message' => $exception->getMessage(), ]); } catch (InputException $exception) { $this->writeWebhookLog($context + [ 'status' => 'error', 'message' => $exception->getMessage(), ], $rawBody, 400, $startedAt); return $result->setHttpResponseCode(400)->setData([ 'success' => false, 'message' => $exception->getMessage(), ]); } catch (\Throwable $exception) { $this->logger->critical('Unable to process a 17TRACK webhook.', ['exception' => $exception]); $this->writeWebhookLog($context + [ 'status' => 'error', 'message' => $exception->getMessage(), ], $rawBody, 500, $startedAt); return $result->setHttpResponseCode(500)->setData([ 'success' => false, 'message' => (string)__('Unable to process the webhook.'), ]); } } public function createCsrfValidationException(RequestInterface $request): ?InvalidRequestException { return null; } public function validateForCsrf(RequestInterface $request): ?bool { // 17TRACK cannot know Magento's form key; authenticity is verified with its signed raw request body. return true; } private function writeWebhookLog(array $data, string $rawBody, int $httpStatus, float $startedAt): void { $this->apiLog->write([ 'direction' => 'inbound', 'operation' => 'webhook', 'api_path' => $this->apiLog->getWebhookPath(), 'order_id' => $data['order_id'] ?? null, 'order_number' => $data['order_number'] ?? null, 'tracking_number' => $data['tracking_number'] ?? null, 'event' => $data['event'] ?? null, 'status' => (string)($data['status'] ?? 'error'), 'http_status' => $httpStatus, 'message' => (string)($data['message'] ?? ''), 'request_data' => $rawBody, 'response_data' => ['success' => $httpStatus === 200], 'duration_ms' => max(0, (int)round((microtime(true) - $startedAt) * 1000)), ]); } }