Частина 3 — Вебхук при зміні статусу

На кожну зміну статусу замовлення — один POST на нашу адресу.

Що
POST з JSON при кожній зміні статусу, включно зі створенням
Де
catalog/model/checkout/order.php → addHistory()
Готово, коли
Ви надсилаєте — ми бачимо події у себе. Вам нічого тестувати

Адреса

http
POST https://prod-observix-integrations.orangeplant-bcc99803.eastus.azurecontainerapps.io/api/crm/hooks/hk_CmWlIqLfxRlJURPOK9x8ge85DyYwzqE8y9C-senpf-U
Content-Type: application/json

Об'єкт

json
{
  // ── Обов'язкові ──────────────────────────────────────────────────────────
  "entity_id":   "38018",                  // order_id
  "status":      "Підтверджено",           // назва статусу як в OpenCart, дослівно
  "occurred_at": "2026-09-22T14:19:00Z",   // date_added з oc_order_history, UTC

  // ── Рекомендовані — сума в звітах і впізнавання клієнта з іншого пристрою ──
  "value":       5800.00,                  // total замовлення
  "currency":    "UAH",
  "email":       "olena@example.com",
  "phone":       "+380671234567",
  "external_id": "CUST-100500",            // customer_id; "" для гостя

  "properties": {
    "obx_visitor_id": "01a0c86c-5956-7801-a63d-e6d75e5520bb",   // з частини 2 — обов'язково

    // + будь-які поля замовлення, які маєте: товари, доставка, оплата, коментар…
    "items": [ { "id": "112", "name": "Плитоноска U-WIN", "quantity": 1, "price": 4900.00 } ],
    "shipping_method": "novaposhta_warehouse",

    // + будь-які поля клієнта, які маєте
    "first_name": "Олена",
    "city": "Київ",

    // + мітки, якщо utm.js уже пише їх у замовлення: gclid, gbraid, wbraid, fbclid, utm_*
    "gclid": "Cj0KCQ…"
  }
}

Кроки

  1. 01

    З addHistory(), після запису в oc_order_history

    Таймаут 3 с, помилки — в лог. Аналітика не має ламати замовлення.

    орієнтовна реалізація · на розгляд
    // catalog/model/checkout/order.php
    public function addHistory($order_id, $order_status_id, $comment = '', $notify = false, $override = false) {
        // ... усе як зараз: INSERT в oc_order_history, зміна статусу, листи ...
    
        // Why тут: через addHistory проходить і створення, і кожна зміна статусу з адмінки чи оплати
        $this->sendToObservix($order_id, $order_status_id);
    }
    
    private function sendToObservix($order_id, $order_status_id) {
        try {
            $order = $this->getOrder($order_id);
            $status = $this->db->query("SELECT name FROM `" . DB_PREFIX . "order_status`
                WHERE order_status_id = " . (int)$order_status_id . " AND language_id = " . (int)$this->config->get('config_language_id'))->row;
    
            $payload = [
                'entity_id'   => (string)$order_id,
                'status'      => $status['name'] ?? (string)$order_status_id,
                'occurred_at' => gmdate('Y-m-d\TH:i:s\Z'),
                'value'       => (float)$order['total'],
                'currency'    => $order['currency_code'],
                'email'       => $order['email'],
                'phone'       => $order['telephone'],
                'external_id' => $order['customer_id'] ? (string)$order['customer_id'] : '',
                'properties'  => [
                    'obx_visitor_id' => $order['obx_visitor_id'] ?? '',
                    'first_name'     => $order['firstname'],
                    'items'          => $this->getProducts($order_id),   // + що ще маєте
                ],
            ];
    
            $ch = curl_init('https://prod-observix-integrations.orangeplant-bcc99803.eastus.azurecontainerapps.io/api/crm/hooks/hk_CmWlIqLfxRlJURPOK9x8ge85DyYwzqE8y9C-senpf-U');
            curl_setopt_array($ch, [
                CURLOPT_POST           => true,
                CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
                CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_UNICODE),
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT        => 3,     // Why: аналітика не має тримати замовлення
            ]);
            curl_exec($ch);
            curl_close($ch);
        } catch (\Throwable $e) {
            $this->log->write('observix: ' . $e->getMessage());   // проковтнути, не ламати замовлення
        }
    }
  2. 02

    Без ретраїв і дедуплікації

    Це на нашому боці. Один виклик.

Перевірка

  • Створити тестове замовлення і змінити йому статус в адмінці двічі
  • У лог нічого не впало; замовлення оформилось як звичайно
  • Скажіть нам номер замовлення — ми підтвердимо, що бачимо три події зі своєї сторони