Ошибки в OpenCart API или сказ о том, почему нужно тестировать

Совершенно стандартная ситуация. Есть у Вас магазин на opencart, скорее всего, даже сборка ocStore. Ну и понадобилось Вам, заказчику, начальнику маме или папе продать товар с вашего магазина через landing page.
Вспоминаем, что у OpenCart есть даже API, значит не проблема!

Верстаем или заказываем лендинг, создаём API-пользователя и получаем его API-ключ в админке опенкарта, задаём белый IP, пробуем подключиться.

Тут-то и начинаются самые весёлые приключения. Оказывается, что не работает этот ваш OpenCart API.
Не OpenCart, а сам PHP начинает сыпаться разными ошибками в коде. Причём в коде не нашем, а в коде самого OpenCart.
Конкретно мне, при авторизации, встретилось три момента. Первый:
Notice: Undefined index: api_token in /catalog/controller/startup/session.php on line 8
Чуть удивляемся, но ладно, это ж всего лишь notice. Открываем этот файл и смотрим, что же там в этой строчке.

$api_query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "api` `a` LEFT JOIN `" . DB_PREFIX . "api_session` `as` ON (a.api_id = as.api_id) LEFT JOIN " . DB_PREFIX . "api_ip `ai` ON (a.api_id = ai.api_id) WHERE a.status = '1' AND `as`.`session_id` = '" . $this->db->escape($this->request->get['api_token']) . "' AND ai.ip = '" . $this->db->escape($this->request->server['REMOTE_ADDR']) . "'");

Ага, OpenCart отправляет без проверки на существование туда api_token. Если посмотреть по файлу ещё ниже, то можно увидеть, что потом проверяет, вернулось ли что-то или нет.
Недолго думая, меняем эту строчку на что-то такое:

			if (!isset($this->request->get['api_token'])) {
				$this->request->get['api_token'] = '';
			}
			$api_query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "api` `a` LEFT JOIN `" . DB_PREFIX . "api_session` `as` ON (a.api_id = as.api_id) LEFT JOIN " . DB_PREFIX . "api_ip `ai` ON (a.api_id = ai.api_id) WHERE a.status = '1' AND `as`.`session_id` = '" . $this->db->escape($this->request->get['api_token']) . "' AND ai.ip = '" . $this->db->escape($this->request->server['REMOTE_ADDR']) . "'");

Notice пропадает, но нам по прежнему ничего не возвращается. Идём смотреть по цепочке, почему ответ пустой.
Плавно приходим ко второй проблеме, которая находится в модели catalog/model/account/api.php
Что же тут не так?
Нам нужна четвёртая строчка, здесь находится такой вот SQL-запрос:

$query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "api` WHERE `username` = '" . $this->db->escape($username) . "' `key` = '" . $this->db->escape($key) . "' AND status = '1'");

И в нём можно обнаружить, что запрос выполняется с ошибкой. Ошибка в том, что в конструкции WHERE между username и key просто забыли AND. Если бы кто-то хоть раз запускал этот код, то легко бы обнаружил этот нюанс.
Меняем на

$query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "api` WHERE `username` = '" . $this->db->escape($username) . "' AND `key` = '" . $this->db->escape($key) . "' AND status = '1'");

и идём дальше.

Снова запускаем и получаем в лицо новую порцию Notice и Warning.

Notice: Undefined variable: registry in /catalog/controller/api/login.php on line 30
Warning: Missing argument 1 for Session\DB::__construct(), called in /system/library/session.php on line 31 and defined in /system/library/session/db.php on line 14
Notice: Undefined variable: registry in /system/library/session/db.php on line 15

Последуем совету первого notice и пройдём сюда: /catalog/controller/api/login.php на 30-ую строчку.

Что же здесь такое?

$session = new Session($this->config->get('session_engine'), $registry);

Передаётся несуществующая переменная. Несуществующая в этой области видимости. Точно так же, если запустить это хоть один раз, найдётся очень легко. Меняем на

$session = new Session($this->config->get('session_engine'), $this->registry);

И НАКОНЕЦ-ТО, этот злой API даст нам success и заветный API-token.

На этом, конечно, проблемы этого API не заканчиваются. Скорее всего, Вам придётся его дописывать самостоятельно ввиду весьма ограниченного количества методов.

P.S. Актуально для версии 3.0.2 которую поисковики и официальные сайты на 06.04.2019 предлагают скачать последней. Если вы из будущего, возможно уже что-то да изменилось и информация более не актуальна. Статья не имеет цели кого-либо оскорбить.