Developer notes
File map
Section titled “File map”| Path | Purpose |
|---|---|
app/addons/kv_order_notifications_messaging/addon.xml |
Settings (General, Telegram, WhatsApp, SMS, License), tables, privileges, install/uninstall functions |
init.php |
Hook registration, synchronizer and licence blocks |
func.php |
Hook handlers, licence gate fn_kv_order_notifications_messaging_is_licensed(), install (default rules, verify token), uninstall, cron info |
controllers/backend/kv_order_notifications_messaging.php |
Pages log, rules, update_rule, optins, vendor; actions (rules, retry, process, test tools, opt-ins, vendor Telegram connect); console process |
controllers/backend/addons.post.php |
Data for the settings tabs (channel status, webhook URLs) |
controllers/frontend/kv_order_notifications_messaging.php |
worker (background queue run), whatsapp_webhook, twilio_status, unsubscribe |
controllers/frontend/checkout.pre.php, checkout.post.php, profiles.post.php |
Opt-in checkbox data and the checkout choice |
Tygh/Addons/KvOrderNotificationsMessaging/Messaging/* |
The messaging kit (see below) |
.../Notifier.php |
Event → rules → recipients → queued messages |
.../Rules.php |
Rule repository, validation, defaults, variables per event |
.../Variables.php |
Order, shipment, product and review variables; sample values |
.../Consent.php |
Customer opt-ins, phone of an order, signed opt-out tokens |
.../Vendors.php |
Vendor recipients and events, Telegram connect code |
.../Service.php |
Wires the kit: queue table, providers from the storefront’s settings, licence gate, delivery after the response, purge |
.../Config.php |
Typed settings, per storefront in Ultimate (Config::forCompany()) |
.../Log.php |
Delivery log queries |
.../StorageData.php |
Run marks (files while the full page cache is active) |
.../License/Client.php, License/Ed25519.php |
Domain-bound licence client (generated) |
.../Upgrade/Synchronizer.php |
Self-healing in-place upgrades (generated) |
controllers/backend/kv_order_notifications_messaging_license.php |
“Check now” and cron licence check (generated) |
schemas/menu/menu.post.php, menu_vendor.post.php |
Orders → Order messaging (admin), Orders → Message notifications (vendor, also with the Vendor panel configurator) |
schemas/permissions/admin.post.php, vendor_multivendor.post.php |
Privileges; vendors may only use vendor and vendor_telegram |
schemas/security/csrf_validation.post.php |
CSRF check for the storefront opt-out form |
schemas/gdpr/user_data.post.php |
GDPR export and anonymization of opt-ins and messages |
design/backend/templates/addons/kv_order_notifications_messaging/views/kv_order_notifications_messaging/*.tpl |
Admin and vendor pages |
.../settings/{overview,telegram,whatsapp,sms}.tpl |
Setup help and test tools on the settings tabs |
.../license/{card,status_bar,badge,info}.tpl |
Licence UI (generated) |
design/backend/css/addons/kv_order_notifications_messaging/styles.less, js/addons/kv_order_notifications_messaging/backend.js |
Admin styles (scoped .kv-onm*) and tools (no external libraries) |
var/themes_repository/responsive/templates/addons/kv_order_notifications_messaging/hooks/checkout/terms_and_conditions_extra.post.tpl, hooks/profiles/account_update.post.tpl, views/kv_order_notifications_messaging/unsubscribe.tpl |
Storefront opt-in and opt-out |
Tables
Section titled “Tables”| Table | Contents |
|---|---|
cscart_kv_onm_messages |
Queue and delivery log: dedupe_key (unique), event, rule, order, company, recipient type (A/V/C), channel, provider, recipient, payload (JSON, ASCII-escaped), status (Q/P/R/S/F/X), delivery (sent/delivered/read/failed), attempts, next attempt, timestamps, provider message ID, HTTP status, error, claim |
cscart_kv_onm_rules |
Rules: company (Ultimate storefront, 0 = all), event, status, recipient, channel, message, WhatsApp template/language/parameters, active, position |
cscart_kv_onm_optins |
One row per phone (E.164): status Y/N, user, source, IP, timestamps |
cscart_kv_onm_vendors |
Per vendor: Telegram chat and title, WhatsApp and SMS numbers, events |
Characters outside the Basic Multilingual Plane (most emoji) are stored as numeric entities (🛒), because CS-Cart connects with the 3-byte utf8 charset; they are turned back into characters for plain-text channels and the editor, and Telegram’s HTML mode understands them.
All hooks exist with identical arguments in CS-Cart 4.17.2 and 4.21.2. Handlers only insert queue rows.
| Hook | Use |
|---|---|
change_order_status_post |
Order placed (from status N) and status changes; skips parent orders (T) |
create_shipment_post |
Shipment created |
update_product_amount |
Low stock (sign -, new amount ≤ low-stock threshold, not in order management) |
product_reviews_create_post |
New review (core product_reviews add-on) |
place_order |
Applies the checkout opt-in choice to the order’s phone |
update_profile |
Applies the profile opt-in choice |
delete_company |
Removes a deleted vendor’s settings |
init_templater_post |
Upgrade synchronizer (only while pending) |
Licence: License\Client::boot() registers a static before_dispatch handler for admin/console checks and notices.
Delivery
Section titled “Delivery”- A hook calls
Notifier, which finds the active rules, resolves recipients (staff settings, vendor settings, customer phone + consent), renders the text and inserts one row per recipient (dedupe_keystops duplicates: one “placed” per order and recipient, one status message per change within 2 minutes, one low-stock alert per product and day). - With Right away,
Messaging\Dispatcherregisters a shutdown function: on PHP-FPM/LiteSpeed it flushes the response and processes the queue; otherwise it starts a non-blockingGET index.php?dispatch=kv_order_notifications_messaging.worker&token=…(HMAC token of the hour, throttled to one per 2 seconds), which processes the queue. Messaging\Queue::process()claims due rows, sends them, and records the result. Transient failures (network, timeout, HTTP 5xx/429, provider rate limits) are retried after 1, 5, 15, 60 and 180 minutes or the provider’sretry_after, up to 6 attempts; rows not sent within 48 hours expire.- Cron:
php admin.php --dispatch=kv_order_notifications_messaging.process(prints the counts as JSON).
The messaging kit (Messaging\*)
Section titled “The messaging kit (Messaging\*)”The kit knows nothing about orders or this add-on’s settings (configuration arrays in, Result out), so other add-ons can reuse namespaced copies of it.
| Class | Role |
|---|---|
Message |
Channel (telegram, whatsapp, sms), recipient, text, optional WhatsApp template {name, language, params}, options (status_callback, silent) |
Result |
ok, transient, http_status, message_id, error (never contains credentials), retry_after, data |
ProviderInterface |
id(), channel(), isConfigured(), send(Message), test(); never throws |
ProviderFactory::make($id, array $config, $api_base = '') |
telegram (bot_token), whatsapp_cloud (phone_number_id, access_token, api_version), twilio (account_sid, auth_token, from or messaging_service_sid), generic_http (url, method, content_type, body, headers, from, success_marker) |
Providers\TelegramProvider |
sendMessage (HTML parse mode), getMe, recentChats() (getUpdates) |
Providers\WhatsAppCloudProvider |
POST /{phone-number-id}/messages (template or text), phone number lookup |
Providers\TwilioProvider |
Messages.json with basic auth and status callback, account lookup |
Providers\GenericHttpProvider |
Any HTTP SMS API with placeholders |
Http |
cURL client, 5 s connect / 10 s total timeout; a test transport seam |
Phone |
E.164 normalization with a default calling code, masking, lists |
Template |
{variable} rendering (HTML-escaped for Telegram), WhatsApp parameter lists, emoji encoding |
Queue |
Queue + log table: enqueue(), record(), process(), retry(), applyDeliveryReports(), purge(), counters() |
Dispatcher |
Delivery after the response, worker token |
Webhook |
WhatsApp verify handshake and X-Hub-Signature-256, Twilio X-Twilio-Signature, status parsing |
Example (inside the add-on):
use Tygh\Addons\KvOrderNotificationsMessaging\Config;use Tygh\Addons\KvOrderNotificationsMessaging\Messaging\Message;use Tygh\Addons\KvOrderNotificationsMessaging\Service;
$config = Config::current();$result = Service::sendNow($config, new Message('telegram', '700100', '<b>Hello</b>'));// or queue it: Service::enqueue($message, 'telegram', ['event' => 'custom'], $config);Mock servers for development. Define KV_ORDER_NOTIFICATIONS_MESSAGING_API_BASE (for example http://127.0.0.1:8733) in local_conf.php of a development store: Telegram, WhatsApp and Twilio requests then go to <base>/telegram, <base>/whatsapp and <base>/twilio instead of the real APIs, and the settings show a “Development mode” notice. Never define it on a live store.
Webhooks
Section titled “Webhooks”index.php?dispatch=kv_order_notifications_messaging.whatsapp_webhook:GETanswers Meta’shub.challengewhenhub.verify_tokenmatches;POSTrequires a validX-Hub-Signature-256(HMAC-SHA256 of the raw body with the app secret) and updates the delivery status bywamid. Status changes never go backwards (read → delivered is ignored).index.php?dispatch=kv_order_notifications_messaging.twilio_status:POSTwith a validX-Twilio-Signature(HMAC-SHA1 of the callback URL plus the sorted parameters with the auth token). The callback URL is only sent to Twilio from public HTTPS hosts.
Full page cache (4.21)
Section titled “Full page cache (4.21)”The add-on prints nothing on cacheable pages. The opt-in checkbox appears only on the checkout and the profile page (never cached), and the opt-out page, the worker and the webhooks are own dispatches that the full page cache does not store. Storefront GET requests write no ?:storage_data (run marks use StorageData, files while the full page cache is active). Verified with the 4.21 full page cache: no add-on fragments in shared pages, no cache purge from storefront requests.
License check
Section titled “License check”fn_kv_order_notifications_messaging_is_licensed() (cached per request) gates the event hooks (no rows are queued), the queue (Queue gate: nothing is sent), the checkout and profile checkbox, and the admin test sends. Admin pages, rules, the log, opt-ins, the opt-out page, webhooks and uninstall keep working. Off effect: No Telegram, WhatsApp or SMS messages are sent and the opt-in checkbox is hidden at checkout. Orders, checkout and the store e-mails keep working; rules, the delivery log and customer opt-ins are kept.