Notifly in PrestaShop
PrestaShop is extended through modules that subscribe to core hooks. Let’s
build a compact notiflyalerts module that attaches to three key hooks:
actionValidatedOrder (new order), actionCustomerAccountAdd (registration) and
actionUpdateQuantity (product out of stock). Everything is server-side, with no
JS on the frontend.
We reuse the shared notifly_send() helper — the same one as for the other
CMSes. In the module it is convenient to move it into a private
method, keeping the URL and token in configuration via Configuration::get().
Module skeleton
Section titled “Module skeleton”modules/notiflyalerts/└── notiflyalerts.phpnotiflyalerts.php:
<?phpif (!defined('_PS_VERSION_')) { exit;}
class NotiflyAlerts extends Module{ public function __construct() { $this->name = 'notiflyalerts'; $this->tab = 'administration'; $this->version = '1.0.0'; $this->author = 'Notifly'; parent::__construct(); $this->displayName = 'Notifly Alerts'; $this->description = 'Push notifications about orders, customers and stock.'; }
public function install(): bool { return parent::install() && $this->registerHook('actionValidatedOrder') && $this->registerHook('actionCustomerAccountAdd') && $this->registerHook('actionUpdateQuantity') && Configuration::updateValue('NOTIFLY_URL', 'https://your-notifly.example.com') && Configuration::updateValue('NOTIFLY_TOKEN', 'AGdjfk_L.dKe8q'); }
public function uninstall(): bool { Configuration::deleteByName('NOTIFLY_URL'); Configuration::deleteByName('NOTIFLY_TOKEN'); return parent::uninstall(); }
/** Universal helper (same logic as in /cases/cms/). */ private function send(string $title, string $message, int $priority = 5): void { $url = Configuration::get('NOTIFLY_URL'); $token = Configuration::get('NOTIFLY_TOKEN'); if (!$url || !$token) { return; }
$body = json_encode([ 'title' => mb_substr($title, 0, 200), 'message' => mb_substr($message, 0, 1500), 'priority' => $priority, ], JSON_UNESCAPED_UNICODE);
$ch = curl_init("$url/message?token=$token"); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => $body, CURLOPT_TIMEOUT => 5, ]); curl_exec($ch); curl_close($ch); }Hook: new order
Section titled “Hook: new order”actionValidatedOrder fires when the order is confirmed and payment accepted —
exactly the moment worth picking up the phone for:
public function hookActionValidatedOrder(array $params): void { /** @var Order $order */ $order = $params['order']; $customer = $params['customer'];
$lines = []; foreach ($order->getProducts() as $p) { $lines[] = "• {$p['product_name']} × {$p['product_quantity']}"; }
$this->send( "🛒 Заказ #{$order->reference} — " . Tools::displayPrice($order->total_paid), "Покупатель: {$customer->firstname} {$customer->lastname}\n" . "Оплата: {$order->payment}\n\n" . "Состав:\n" . implode("\n", $lines) . "\n\n" . "Админка: заказ #{$order->id}", 9 // orders — a loud priority ); }Hook: new customer
Section titled “Hook: new customer” public function hookActionCustomerAccountAdd(array $params): void { /** @var Customer $customer */ $customer = $params['newCustomer']; $this->send( "👤 Новый клиент: {$customer->firstname} {$customer->lastname}", "Email: {$customer->email}\n" . "ID: {$customer->id}", 4 ); }Hook: product out of stock
Section titled “Hook: product out of stock”actionUpdateQuantity is called on any stock change. We send a push only when
the product crosses the threshold, so as not to spam on every sale:
public function hookActionUpdateQuantity(array $params): void { $quantity = (int) $params['quantity']; if ($quantity > 3) { return; }
$product = new Product((int) $params['id_product'], false, (int) $this->context->language->id);
$this->send( "📦 Товар на исходе: {$product->name}", "Остаток: $quantity шт.\n" . "ID товара: {$params['id_product']}", $quantity <= 0 ? 8 : 6 ); }}(the closing } ends the module class)
Where to enable the module
Section titled “Where to enable the module”- Zip the
notiflyalertsfolder and upload it via Modules → Module Manager → Upload a module. - After installation, set
NOTIFLY_URL/NOTIFLY_TOKEN— either directly inConfigurationor by adding a settings page viagetContent().
The hooks are registered in the install() method, so there is no need to attach
them separately.
Throttling
Section titled “Throttling”To keep a bulk stock update (for example, from an ERP) from flooding the channel,
cache the sending via Cache:
$cacheKey = 'notifly_' . md5($title);if (Cache::getInstance()->get($cacheKey)) { return;}Cache::getInstance()->set($cacheKey, 1, 60);Benefits
Section titled “Benefits”- An order is visible instantly.
actionValidatedOrderis already a paid order. - You don’t lose a product at zero stock. A zero-stock push = you restock in time.
- Your own module instead of paid “alert” add-ons from PrestaShop Addons.
What to improve next
Section titled “What to improve next”- A module settings page with channel and threshold selection.
- Separate Notifly channels for orders, customers and stock.
- A deep link to the order via extras.