14. API умови

Якщо стандартних 50+ умов FCR недостатньо для вашого сценарію - ви можете створити власні умови у вигляді PHP-методів. Це називається API condition і дозволяє розширити модуль безмежно.

Коли потрібні API умови

  • Інтеграція з зовнішнім сервісом (CRM, ERP, складська система)
  • Складна бізнес-логіка яку важко описати стандартними умовами
  • Перевірка користувача через API (наприклад, чорний список)
  • Розрахунки які залежать від кількох баз даних
  • Кешовані обчислення які мають виконуватись окремо

Файл з методами

FCR шукає файл за шляхом:

upload/catalog/model/extension/module/flexi_checkout_rules_api.php

У цьому файлі ви описуєте PHP-клас ModelExtensionModuleFlexiCheckoutRulesApi зі своїми методами. Кожен метод стає окремою умовою яку можна вибрати в інтерфейсі.

Контракт методу

Кожен метод отримує один параметр - масив $ctx (контекст) і має повертати true або false:

public function methodName($ctx) {
    // ваша логіка
    return true; // або false
}

Структура $ctx:

КлючТипОпис
$ctx['cart']arrayДані кошика: products, total, weight, quantity, has_shipping
$ctx['address']arrayАдреса доставки: country_id, zone_id, city, postcode тощо
$ctx['customer_id']intID клієнта (0 якщо незалогінений)
$ctx['shipping']string|nullКод обраного методу доставки
$ctx['payment']string|nullКод обраного методу оплати

Окрім цього, через $this->registry у методах доступні всі стандартні OpenCart-сервіси: $this->db, $this->config, $this->customer, $this->session тощо.

Приклад файлу

Базовий скелет файлу з декількома готовими умовами:

<?php
class ModelExtensionModuleFlexiCheckoutRulesApi extends Model {

    /**
     * Перевірка чи зараз вихідний день
     */
    public function isWeekend($ctx) {
        $day = (int)date('N');
        return $day >= 6;
    }

    /**
     * Перевірка чи сума кошика - кругле число (1000, 2000, 5000)
     */
    public function hasRoundNumber($ctx) {
        $total = (float)($ctx['cart']['total'] ?? 0);
        return $total > 0 && fmod($total, 100) == 0;
    }

    /**
     * Перевірка чи клієнт - "висококласний" (купував багато)
     */
    public function isHighValueCustomer($ctx) {
        if (empty($ctx['customer_id'])) return false;
        $cid = (int)$ctx['customer_id'];
        $q = $this->db->query(
            "SELECT SUM(total) as spent FROM " . DB_PREFIX . "order
             WHERE customer_id = '" . $cid . "' AND order_status_id > 0"
        );
        $spent = $q->num_rows ? (float)$q->row['spent'] : 0;
        return $spent > 10000;
    }

    /**
     * Перевірка чи місто доставки - Київ (з варіантами написання)
     */
    public function isKyiv($ctx) {
        $city = mb_strtolower($ctx['address']['city'] ?? '');
        return in_array($city, ['київ', 'kyiv', 'kiev']);
    }

}

Використання у FCR

Після створення файлу методи стають доступними у FCR:

  1. Відкрийте редактор будь-якого методу/підсумку
  2. Додайте умову
  3. У списку типів виберіть "Інше → API метод"
  4. У полі "Назва методу" введіть точну назву функції з вашого файлу (наприклад isWeekend)
  5. Натисніть Save
Точне написання

Назва методу чутлива до регістру. isWeekend і isweekend - це різні методи. Якщо помилитеся - FCR не знайде метод і поверне true (умова "пройдена" за замовчуванням).

Обмеження і правила безпеки

Що НЕ можна робити в API методах
  • Не модифікуйте кошик - метод має тільки читати дані, не змінювати їх
  • Не робіть довгих HTTP-запитів - метод викликається при кожному обчисленні підсумків (часто). Зовнішні API мають бути кешовані
  • Не використовуйте eval() або system() з даними з кошика - це дірка в безпеці
  • Не пишіть у $this->session - сесія не повинна змінюватись від перевірок умов
  • Завжди обробляйте помилки - якщо ваш метод викине exception, FCR його перехопить і поверне true

Дебаг API умов

Якщо ваша API умова не працює - увімкніть дебаг розробника. У логи буде записано:

  • Чи знайдено файл flexi_checkout_rules_api.php
  • Чи існує клас і метод
  • Що повернув метод
  • Якщо метод викинув exception - текст помилки

У самому методі ви можете додати власне логування:

public function myCondition($ctx) {
    $log = new Log('fcr_api.log');
    $log->write('myCondition called with cart: ' . json_encode($ctx['cart']));
    // ... ваша логіка
}

Лог буде записаний у storage/logs/fcr_api.log.