From 500707307c24ff55d83719d1fbd929a51f59be90 Mon Sep 17 00:00:00 2001 From: "@ChristelLoftus" <christel@bob.co.za> Date: Tue, 27 Aug 2024 11:28:10 +0200 Subject: [PATCH] Start webhook implementation --- Model/Carrier/UData.php | 7 ++ Observer/OrderCreateWebhook.php | 119 ++++++++++++++++++++++++++++++++ Observer/OrderUpdateWebhook.php | 76 ++++++++++++++++++++ etc/events.xml | 6 ++ etc/frontend/di.xml | 8 +++ 5 files changed, 216 insertions(+) create mode 100644 Observer/OrderCreateWebhook.php create mode 100644 Observer/OrderUpdateWebhook.php diff --git a/Model/Carrier/UData.php b/Model/Carrier/UData.php index d173baa..a7e5d2e 100644 --- a/Model/Carrier/UData.php +++ b/Model/Carrier/UData.php @@ -20,4 +20,11 @@ class UData * @var string */ public const RATES_ENDPOINT = 'https://api.dev.bobgo.co.za/rates-at-checkout/magento'; + + /** + * Order create/update webhook URL + * + * @var string + */ + public const WEBHOOK_URL = 'https://api.dev.bobgo.co.za/webhook/channel'; } diff --git a/Observer/OrderCreateWebhook.php b/Observer/OrderCreateWebhook.php new file mode 100644 index 0000000..f301cc8 --- /dev/null +++ b/Observer/OrderCreateWebhook.php @@ -0,0 +1,119 @@ +<?php + +namespace BobGroup\BobGo\Observer; + +use Magento\Framework\Event\Observer; +use Magento\Framework\Event\ObserverInterface; +use Magento\Framework\HTTP\Client\Curl; +use BobGroup\BobGo\Model\Carrier\UData; +use Psr\Log\LoggerInterface; +use Magento\Store\Model\StoreManagerInterface; + +class OrderCreateWebhook implements ObserverInterface +{ + protected Curl $curl; + protected LoggerInterface $logger; + protected StoreManagerInterface $storeManager; + + public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager) + { + $this->logger = $logger; + $this->curl = $curl; // Initialize the Curl instance + $this->storeManager = $storeManager; + } + + public function execute(Observer $observer) + { + $this->logger->info('OrderCreateWebhook: execute method started'); + + $order = $observer->getEvent()->getOrder(); + if (!$order) { + $this->logger->error('OrderCreateWebhook: No order object found in observer'); + return; + } + + // Log order creation data + $this->logger->info('Order Created:', ['order_id' => $order->getId(), 'order_data' => $order->getData()]); + + // Extract order data and send to the webhook URL + $this->sendWebhook($order, 'order_created'); + + $this->logger->info('OrderCreateWebhook: execute method finished'); + } + + private function sendWebhook($order, $eventType) + { + $this->logger->info('OrderCreateWebhook: sendWebhook method started'); + + // Webhook URL + $url = $this->getWebhookUrl(); + $this->logger->info('OrderCreateWebhook: Webhook URL', ['url' => $url]); + + // Get Store UUID and add to query parameters + $storeUuid = $this->getStoreUuid(); + $this->logger->info('UUID: ', ['uuid' => $storeUuid]); + $url .= '?channel=' . urlencode($storeUuid); + $this->logger->info('Webhook URL', ['url' => $url]); + + // Prepare payload + $data = [ + 'event' => $eventType, + 'order_id' => $order->getId(), + 'order_data' => $order->getData() + ]; + + // Log webhook payload + $this->logger->info('Sending Webhook:', ['url' => $url, 'payload' => $data]); + + // Send the webhook + $this->makeHttpPostRequest($url, $data); + + $this->logger->info('OrderCreateWebhook: sendWebhook method finished'); + } + + + private function makeHttpPostRequest($url, $data) + { + $this->logger->info('URL:', ['url' => $url]); + $this->logger->info('Data:', ['data' => $data]); + + // Perform the API request + $payloadJson = json_encode($data); + if ($payloadJson === false) { + $this->logger->error('Payload Webhook failed: Unable to encode JSON.'); + throw new \RuntimeException('Failed to encode payload to JSON.'); + } + + $this->logger->info('Payload Webhook:', ['response' => $payloadJson]); + + // Set headers and post the data + $this->curl->addHeader('Content-Type', 'application/json'); + $this->curl->post($url, $payloadJson); + $statusCode = $this->curl->getStatus(); + $responseBody = $this->curl->getBody(); + + // Log status code and response body + $this->logger->info('Webhook Response Status:', ['status' => $statusCode]); + $this->logger->info('Webhook Response Body:', ['response' => $responseBody]); + + // Decode the response + $response = json_decode($responseBody, true); + if (json_last_error() !== JSON_ERROR_NONE) { + $this->logger->error('Failed to decode webhook response:', ['error' => json_last_error_msg()]); + } else { + $this->logger->info('Response Webhook:', ['response' => $response]); + } + } + + private function getWebhookUrl(): string + { + return UData::WEBHOOK_URL; + } + + private function getStoreUuid(): string + { + $storeId = $this->storeManager->getStore()->getId(); + return $storeId; + //return $this->storeManager->getStore()->getConfig('general/store_information/store_id'); + } +} diff --git a/Observer/OrderUpdateWebhook.php b/Observer/OrderUpdateWebhook.php new file mode 100644 index 0000000..ad2a4ad --- /dev/null +++ b/Observer/OrderUpdateWebhook.php @@ -0,0 +1,76 @@ +<?php + +namespace BobGroup\BobGo\Observer; + +use Magento\Framework\Event\Observer; +use Magento\Framework\Event\ObserverInterface; +use Magento\Framework\HTTP\Client\Curl; +use Magento\Store\Model\StoreManagerInterface; +use BobGroup\BobGo\Model\Carrier\UData; +use Psr\Log\LoggerInterface; + +class OrderUpdateWebhook implements ObserverInterface +{ + protected Curl $curl; + protected LoggerInterface $logger; + protected StoreManagerInterface $storeManager; + + public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager) + { + $this->logger = $logger; + $this->curl = $curl; + $this->storeManager = $storeManager; + } + + public function execute(Observer $observer) + { + $order = $observer->getEvent()->getOrder(); + if (!$order) { + return; + } + + $this->sendWebhook($order, 'order_updated'); + } + + private function sendWebhook($order, $eventType) + { + $url = $this->getWebhookUrl(); + + // Get Store UUID and add to query parameters + $storeUuid = $this->getStoreUuid(); + $url .= '?channel=' . urlencode($storeUuid); + + $data = [ + 'event' => $eventType, + 'order_id' => $order->getId(), + 'order_data' => $order->getData() + ]; + + $this->makeHttpPostRequest($url, $data); + } + + private function makeHttpPostRequest($url, $data) + { + $payloadJson = json_encode($data); + if ($payloadJson === false) { + throw new \RuntimeException('Failed to encode payload to JSON.'); + } + + $this->curl->addHeader('Content-Type', 'application/json'); + $this->curl->post($url, $payloadJson); + $statusCode = $this->curl->getStatus(); + $responseBody = $this->curl->getBody(); + + $response = json_decode($responseBody, true); + } + + private function getWebhookUrl(): string + { + return UData::WEBHOOK_URL; + } + + private function getStoreUuid(): string + { + return $this->storeManager->getStore()->getConfig('general/store_information/store_id'); + } +} diff --git a/etc/events.xml b/etc/events.xml index bfb5e96..3e71bc3 100644 --- a/etc/events.xml +++ b/etc/events.xml @@ -1,3 +1,9 @@ <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> + <event name="sales_order_place_after"> + <observer name="order_create_webhook" instance="BobGroup\BobGo\Observer\OrderCreateWebhook"/> + </event> + <event name="sales_order_save_after"> + <observer name="order_update_webhook" instance="BobGroup\BobGo\Observer\OrderUpdateWebhook"/> + </event> </config> diff --git a/etc/frontend/di.xml b/etc/frontend/di.xml index bc1aaeb..25a80a9 100644 --- a/etc/frontend/di.xml +++ b/etc/frontend/di.xml @@ -13,4 +13,12 @@ <argument name="logger" xsi:type="object">Psr\Log\LoggerInterface</argument> </arguments> </type> + <type name="BobGroup\BobGo\Observer\OrderCreateWebhook"> + <arguments> + <argument name="logger" xsi:type="object">Psr\Log\LoggerInterface</argument> + <argument name="curl" xsi:type="object">Magento\Framework\HTTP\Client\Curl</argument> + <argument name="storeManager" xsi:type="object">Magento\Store\Model\StoreManagerInterface</argument> + </arguments> + </type> + </config> -- GitLab