# Integrations — magento-orderwebhook

> **Last verified:** 2026-02-26 (Europe/London)
> **Owner:** Engineering
> **Related:** [API.md](API.md) | [BOUNDARIES.md](BOUNDARIES.md)

---

## Integration Catalogue

| Name | Direction | Mechanism | Purpose | Criticality | Evidence |
|------|-----------|-----------|---------|-------------|----------|
| NGauge Platform | Outbound | HTTP POST, JSON, Bearer token | Sync order data to NGauge ERP | HIGH — primary function of module | `src/Model/WebhookSender.php` |
| Magento Sales — `sales_order_place_after` | Inbound | Magento event observer | Trigger `order_placed` webhook on checkout completion | HIGH | `src/etc/events.xml`, `src/Observer/OrderPlaceAfter.php` |
| Magento Sales — `sales_order_save_after` | Inbound | Magento event observer | Trigger `order_updated` webhook on status change to `processing` | HIGH | `src/etc/events.xml`, `src/Observer/OrderSaveAfter.php` |
| Magento Order Repository | Outbound | `OrderRepositoryInterface::save()` | Persist NGauge fields + order comment in `sales_order` | HIGH | `src/Model/WebhookSender.php` |
| Magento Encrypted Config | Internal | `EncryptorInterface` (via ObjectManager) | Decrypt API key at send time | HIGH | `src/Model/WebhookSender.php` |
| Magento Admin ACL | Internal | `PortalPeople_OrderWebhook::config` | Control access to ResendWebhook controller | MEDIUM | `src/etc/acl.xml`, `src/Controller/Adminhtml/Order/ResendWebhook.php` |
| magento-deliverydates module | Inbound (optional) | Order object methods `getShippingDate()`, `getShippingMessage()` | Add delivery date and message to webhook payload | LOW (null if absent) | `src/Model/OrderDataBuilder.php` |
| Magento Registry (deprecated) | Internal | `Magento\Framework\Registry::registry('current_order')` | Retrieve current order in admin block | LOW | `src/Block/Adminhtml/Order/NgaugeFields.php` |

---

## Integration Detail

### 1. NGauge Platform (Outbound Webhook)

| Attribute | Detail |
|-----------|--------|
| Protocol | HTTPS |
| Method | POST |
| Content-Type | `application/json` |
| Authentication | `Authorization: Bearer {api_key}` |
| URL | Configurable: `order_webhook/general/api_url` |
| Default base URL | `https://ahshub.portalpeople.app` |
| Retry | Up to `retry_attempts` (default: 3) with exponential backoff |
| Timeout | `order_webhook/general/timeout` (default: 30 seconds) |
| Failure behaviour | Log error, retry, then exit — order processing is not blocked |
| Response handling | `ngauge_order_no`, `ngauge_order_id`, `ngauge_order_link` written to `sales_order` |

```mermaid
%% Title: magento-orderwebhook — NGauge Integration Flow (L3)
%% Layer: L3
%% Owner: Engineering
%% Last verified: 2026-02-26 (Europe/London)
%% Scope: Webhook send and NGauge response handling
%% Excludes: Observer trigger logic, admin resend

sequenceDiagram
  autonumber
  participant Sender as WebhookSender
  participant Config as Magento Config
  participant NGauge as NGauge REST API
  participant DB as sales_order

  Sender->>Config: Decrypt API key (EncryptorInterface via ObjectManager)
  Config-->>Sender: Plaintext API key
  Sender->>NGauge: POST JSON (Bearer token, attempt 1)
  alt Success
    NGauge-->>Sender: 200 + ngauge_order_no / id / link
    Sender->>DB: persistOrder (ngauge fields + comment)
  else Failure
    NGauge-->>Sender: 4xx / 5xx / timeout
    Sender->>Sender: sleep(pow(2, attempt)); retry
    Sender->>NGauge: POST JSON (attempt 2..N)
  end
```

---

### 2. Magento Sales Events (Inbound)

| Event | Observer | Condition | Action |
|-------|----------|-----------|--------|
| `sales_order_place_after` | `OrderPlaceAfter` | `remote_ip` is not empty (frontend order) | Send `order_placed` webhook |
| `sales_order_save_after` | `OrderSaveAfter` | Status changes TO `processing` | Send `order_updated` webhook |

**Important:** The re-entrancy guard (`WebhookSender::$sending`) prevents `sales_order_save_after` from recursively triggering when `WebhookSender::persistOrder()` calls `orderRepository->save()`.

---

### 3. magento-deliverydates (Optional Dependency)

`OrderDataBuilder` calls `$order->getShippingDate()` and `$order->getShippingMessage()`. These methods are provided by the `magento-deliverydates` Magento module. If that module is absent, these fields return null and the payload includes them as null.

`UNKNOWN — Requires Clarification`: No hard module dependency is declared in `module.xml`. It is unclear whether code guards against missing methods on the order object.

---

## Confirmed Facts

- NGauge is the sole external HTTP integration; no other outbound HTTP calls exist.
- The integration is fire-and-forget from the order processing perspective — failures are logged but do not block order completion.
- API key rotation requires updating the Magento admin configuration; no code change needed.
- The module does not poll NGauge — all communication is push-only.

---

## Unknowns

1. `UNKNOWN — Requires Clarification`: Full NGauge API response schema (field names, types, error responses).
2. `UNKNOWN — Requires Clarification`: Is `magento-deliverydates` guaranteed to be present in all environments?
3. `UNKNOWN — Requires Clarification`: Does NGauge support idempotent retries (same order, multiple sends)?
4. `UNKNOWN — Requires Clarification`: Is there a WAF or rate limiter on the NGauge endpoint?

---

## Evidence

- `/modules/magento-orderwebhook/src/etc/events.xml`
- `/modules/magento-orderwebhook/src/Observer/OrderPlaceAfter.php`
- `/modules/magento-orderwebhook/src/Observer/OrderSaveAfter.php`
- `/modules/magento-orderwebhook/src/Model/WebhookSender.php`
- `/modules/magento-orderwebhook/src/Model/OrderDataBuilder.php`
- `/modules/magento-orderwebhook/src/Block/Adminhtml/Order/NgaugeFields.php`
- `/modules/magento-orderwebhook/src/etc/config.xml`
- `/modules/magento-orderwebhook/src/etc/acl.xml`
