Developer notes
| Step | Hook | Class |
|---|---|---|
| Payment list at checkout | prepare_checkout_payment_methods_before_get_payments / _after_get_payments, checkout_select_default_payment_method |
Checkout::preparePaymentParams(), filterPaymentList(), selectDefault() |
| Refusal (block, forged COD) | allow_place_order_post |
Checkout::refusal() |
| Risk record, hold / confirmation status | place_order (before the core sets the status) |
Checkout::placeOrder() |
| Confirmation e-mail | change_order_status_post (once per checkout) |
Verification::sendPending() |
| Order list column and filter | get_orders (back end) |
Orders::listQuery() |
| Cleanup | delete_order |
Orders::deleted() |
All hooks exist with the same arguments in 4.17.2 and 4.21.2. The add-on runs after the core Anti fraud add-on (priority 2200 > 2100): when an earlier handler already set $action = 'save' (Anti fraud hold, zero total), Order Risk Guard only records its score.
Payment hiding adds its own parameter kv_org_hide to the fn_get_payments() parameters so the core static cache of the payment list keeps a separate entry; other add-ons that hide payments (for example Shipping & Payment Restrictions) work at the same time.
Holds only change the status of orders whose payment method has no processor script; online payments are never interrupted. On Multi-Vendor the parent order keeps its “parent” status and the child orders get the hold / confirmation status. One evaluation per checkout is shared by the parent and its children.
Scoring
Section titled “Scoring”Scorer::contextFromCart($cart, $auth) / Scorer::contextFromOrder($order_info) build a context (e-mail, domain, phone keys, IP, IP country, address fingerprints, countries, total, user ID). Scorer::evaluate($ctx) returns:
[ 'score' => 0..100, 'level' => 'L'|'M'|'H', 'signals' => [['code' => 'problem_orders', 'points' => 50, 'n' => 2], ...], 'allow' => bool, 'block' => bool, 'prepay' => bool, 'review' => bool, 'entry_ids' => [...], 'history' => ['orders' => 3, 'settled' => 1, 'problem' => 2],]Scorer::mustBlock(), mustPrepay(), mustReview(), mustVerify() apply the settings. Normalisation is in Normalizer (phones: last 10 digits; addresses: CC|ZIP|street in lower-case letters and digits).
Hooks for developers
Section titled “Hooks for developers”// Add own signals or change the score (keep 'score' 0-100).fn_set_hook('kv_order_risk_guard_evaluate_post', $ctx, $result);
// Send the confirmation code by SMS, WhatsApp or another channel. Add the channel name to $channels.fn_set_hook('kv_order_risk_guard_send_code', $group_id, $order, $code, $link, $channels);
// Change the confirmation e-mail data (group_id, token, code).fn_set_hook('kv_order_risk_guard_notify_pre', $data);Example: an SMS add-on
function fn_my_sms_kv_order_risk_guard_send_code($group_id, $order, $code, $link, &$channels){ $phone = $order['phone'] ?: $order['s_phone']; if ($phone && my_sms_send($phone, "Your order #{$group_id} code: {$code}")) { $channels[] = 'sms'; }}The add-on itself sends e-mail only; it does not include a paid SMS provider.
Data model
Section titled “Data model”| Table | Contents |
|---|---|
?:kv_org_entries |
Block list (list_type B) and allow list (A): type, normalised value, original display, action, points, note, expires_at, hits, last_hit_at. Unique per list, type and value. |
?:kv_org_orders |
One row per scored order (Multi-Vendor: parent and children, same group_id): identifiers, score, level, signals (JSON), action (hold, verify, flag, allow), review decision. |
?:kv_org_verifications |
One row per checkout group: SHA-256 hash of the link token, hash of the code, attempts, sends, status (P pending, V confirmed, C cancelled, X expired), expiry. Plain tokens and codes are never stored. |
?:kv_org_attempts |
The last 500 refused checkouts. |
Order statuses: the codes of “Risk review” and “Awaiting confirmation” are in the hidden settings review_status and verify_status.
Controllers
Section titled “Controllers”| Dispatch | Area | Purpose |
|---|---|---|
kv_order_risk_guard.manage, update, delete, m_delete, import, export |
admin | Lists |
kv_order_risk_guard.order_action (do = approve, cancel, resend, score, block) |
admin | Order panel buttons |
kv_order_risk_guard.cron |
admin console | Expiry (php admin.php --dispatch=kv_order_risk_guard.cron) |
kv_order_risk_guard.confirm |
storefront | Confirmation page (GET), confirm / cancel / resend (POST, CSRF-checked) |
kv_order_risk_guard.cron&cron_key=... |
storefront | Expiry for external cron services |
Full page cache and performance
Section titled “Full page cache and performance”Nothing is printed on cacheable storefront pages: the payment note, the confirmation box and the confirmation page are session pages. No storage_data writes from storefront GET requests (the pseudo-cron run mark is written from admin pages or cron, through a file store while the full page cache is on). Scoring runs a handful of indexed queries once per checkout step and once at order placement.
With the core GDPR add-on, the risk records of a customer are part of the data export; anonymisation wipes e-mail, phone, IP and address from the risk records (scores stay). Block-list entries are kept (fraud prevention); delete them on the list page if needed.
File map
Section titled “File map”app/addons/kv_order_risk_guard/ addon.xml, init.php, func.php controllers/backend/kv_order_risk_guard.php lists, order actions, cron controllers/backend/orders.post.php order panel data, list filter values controllers/frontend/kv_order_risk_guard.php confirmation page, cron URL controllers/frontend/checkout.post.php box on the order-placed page controllers/frontend/orders.post.php box on the customer order page schemas/ gdpr, menu, notifications, permissions, security Tygh/Addons/KvOrderRiskGuard/ Config, Normalizer, Disposable, Lists, Scorer, Checkout, Verification, Orders, Installer, Notifier, ConfirmDataProvider, StorageData, License/*, Upgrade/Synchronizerdesign/backend/templates/addons/kv_order_risk_guard/ views/manage.tpl, components/panel.tpl, hooks/orders, licensedesign/backend/css/addons/kv_order_risk_guard/styles.lessvar/themes_repository/responsive/templates/addons/kv_order_risk_guard/ views/confirm.tpl, components/box.tpl, hooksvar/themes_repository/responsive/css/addons/kv_order_risk_guard/styles.lessvar/langs/en/addons/kv_order_risk_guard.po