Коротко
| Что | Как устроено |
|---|---|
| Справочник пунктов | Своя таблица {prefix}ozwc_points: около 88 тысяч строк, индексы по координатам, городу и номеру прохода синхронизации |
| Окно выбора пункта | Поиск, «Рядом со мной» и карта работают только с этой таблицей, без запросов к Ozon |
| Запросы к Ozon на оформлении | Расчёт цены и проверка пункта; ответы кэшируются в сессии WooCommerce на 20 минут, таймаут 4 секунды |
| Фоновые задачи | Action Scheduler WooCommerce, группа ozon-delivery-woo |
| Сервер лицензий | На оформлении заказа не вызывается; ответы подписаны Ed25519 |
| Без сервера лицензий | До 14 дней по последнему подписанному статусу годовой лицензии |
| Ключи и журналы | Ключи — в опциях без автозагрузки, в HTML и журналах их нет; телефоны в журналах маскируются |
| Заказы | Только CRUD-методы WooCommerce, совместимость с HPOS и блочным оформлением объявлена |
Таблица пунктов выдачи и индексы
Ozon не отдаёт пункты по городу и не даёт готовой карты, поэтому справочник хранится в базе сайта. Таблица создаётся при активации через dbDelta с кодировкой базы WordPress:
CREATE TABLE {prefix}ozwc_points (
point_id bigint(20) unsigned NOT NULL, -- номер пункта Ozon, 16 цифр
type varchar(16), name varchar(191), point_number varchar(64),
address varchar(500), city varchar(191),
lat decimal(9,6), lon decimal(9,6),
is_bulky tinyint(1), storage_days smallint(5) unsigned, fitting_rooms smallint(5) unsigned,
schedule varchar(255), -- недельный график одной строкой
max_weight_g int(10) unsigned, max_length_mm int(10) unsigned,
max_width_mm int(10) unsigned, max_height_mm int(10) unsigned,
max_price decimal(12,2), min_weight_g int(10) unsigned, min_price decimal(12,2),
sync_run int(10) unsigned, -- номер прохода синхронизации
info_at int(10) unsigned, -- когда обновлялись подробности
PRIMARY KEY (point_id),
KEY geo (lat, lon),
KEY city (city),
KEY sync_run (sync_run)
);
geo (lat, lon)— поиск ближайших пунктов и пунктов в области карты.city— подсказка для города покупателя до выбора пункта: сколько пунктов и примерная цена.sync_run— удаление пунктов, которых больше нет в Ozon, после завершённого прохода.
В строке — только то, что нужно окну выбора: адрес, город, координаты, срок хранения, примерочные, график и пределы веса, размеров и стоимости. Исходный ответ Ozon (около 2 КБ на пункт) не хранится, график Ozon (даты примерно на три недели вперёд) сжимается в недельную строку. В таблицу попадают только активные пункты, куда возит ваш метод доставки. Имя таблицы можно сменить фильтром ozwc_points_table — он нужен только для тестов, чтобы тест не тронул рабочий справочник.
Как обновляется справочник
| Что | Как |
|---|---|
| Когда | Раз в сутки ночью, между 00:20 и 02:20 UTC; минута зависит от адреса сайта, чтобы магазины не приходили к Ozon одновременно |
| Источник | delivery-point/list — только номера пунктов и методы доставки, по 100 на страницу; delivery-point/info — подробности пачками до 100 |
| Объём | Полный проход по list; info — только для новых пунктов и тех, чьи данные старше 7 дней, не больше 15 000 за проход |
| Удаление | Пункты, которых нет в list, удаляются только после завершённого прохода. Пока проход идёт, покупатели видят прежний справочник |
| Шаги | Задачи Action Scheduler до 15 секунд; состояние и курсор сохраняются после каждой страницы, от параллельного запуска защищает блокировка |
| Ошибки | Временные ошибки — до 5 повторов с паузой. Если Ozon отвечает 404 на пачку из-за пропавших пунктов, плагин убирает их из пачки и повторяет запрос |
| Таймауты | list — 4 секунды, info — 6 секунд |
Первая загрузка занимает 5–15 минут: пока открыта вкладка «Пункты выдачи», загрузка идёт быстрее, если закрыть — продолжится в фоне.
Одно оформление заказа: запросы к Ozon и к базе
| Момент | Запросы к базе сайта | Запросы к Ozon |
|---|---|---|
| Покупатель на оформлении, пункт ещё не выбран | Одна сводка по городу: WHERE city = … с фильтром по посылке | Если указан телефон — order/checkout для одного пункта города: примерная цена и срок |
| Окно выбора: «Рядом со мной», поиск, карта | Ближайшие — по индексу geo, от 1 до 5 запросов с расширяющейся областью, не больше 2000 строк в каждом; поиск — по словам в городе, адресе и номере пункта; карта — пункты видимой области, а если их больше 2000, сервер сам собирает их в группы | Нет |
| Покупатель выбрал пункт | Строка пункта по первичному ключу | delivery-point/check-availability и order/checkout |
| Пересчёт оформления, смена адреса | — | Нет: ответ берётся из кэша сессии |
| «Оформить заказ» | — | order/checkout заново, только если расчёту больше 5 минут |
| После оплаты | — | order/create — в фоновой задаче, а не в запросе покупателя |
Как устроен кэш и защита:
- Кэш расчёта — в сессии WooCommerce покупателя, а не в кэше объектов WordPress. Ключ — пункт, вес, размеры и объявленная стоимость посылки, телефон и метод доставки. Запись живёт 20 минут, в сессии хранится не больше 20 записей.
- Таймауты на оформлении — 4 секунды и один повтор. Любая ошибка Ozon превращается в понятное сообщение покупателю или скрытый способ доставки — оформление заказа не падает.
- Токен
xapi.ozon.ru/oauth/tokenхранится в базе и обновляется за 5 минут до истечения; при ответе 401 плагин один раз получает новый токен и повторяет запрос. - Защита Ozon от DDoS отвечает перенаправлением 302 или 307 с cookie: плагин повторяет тот же POST по адресу из
Location, не больше 3 перенаправлений, и хранит cookie по хосту. - Лимит номеров: не больше 5 разных номеров телефона на сессию и 15 на IP-адрес в час — сайт нельзя использовать для массовой проверки чужих номеров в Ozon. Счётчик по IP хранится во временных данных WordPress (transient): если на сайте подключён внешний кэш объектов, например Redis, WordPress хранит их там.
- Сервер лицензий на оформлении заказа не вызывается: плагин читает сохранённый статус из небольшой опции с автозагрузкой.
Фоновые задачи Action Scheduler
Все задачи — в группе ozon-delivery-woo планировщика Action Scheduler, который входит в WooCommerce и работает поверх WP-Cron. Если сайт посещают редко, настройте системный cron.
| Хук | Когда | Что делает |
|---|---|---|
ozwc_points_sync_daily | Раз в сутки, 00:20–02:20 UTC | Начинает проход по справочнику |
ozwc_points_sync_step | Шагами до 15 секунд | Загружает страницы list и info |
ozwc_order_create | После оплаты; при сбое — повторы через 1, 5 и 15 минут, 1 и 3 часа | Создаёт заказ в Ozon с защитой от дублей |
ozwc_order_cancel | Заказ на сайте стал «Отменён» или «Возвращён» | Отменяет отправление в Ozon |
ozwc_order_refresh | После «Собрано» и других действий с отправлением | Обновляет статус одного заказа |
ozwc_orders_sync | Каждые 30 минут | Обновляет статусы отправлений |
ozwc_returns_check | Каждые 12 часов | Обновляет возвраты |
ozwc_license_checkin | Раз в сутки, минута зависит от сайта | Проверяет лицензию |
ozwc_license_order | После создания отправления; при сбое связи — повторы с паузами от минуты до суток | Сообщает серверу лицензий хэш заказа |
ozwc_license_order_cancel | После отмены отправления до отгрузки | Отмечает отмену на сервере лицензий |
Деактивация плагина останавливает фоновые задачи; таблица, настройки и данные заказов остаются.
Что уходит на сервер лицензий
Сервер лицензий — https://api.ev-gerasimov.ru. Он нужен для пробного периода, проверки лицензии и обновлений. Таймаут запроса — 8 секунд, в каждый запрос плагин добавляет одноразовый nonce.
| Запрос | Когда | Что передаётся |
|---|---|---|
/api/v1/checkin | Вскоре после активации, затем раз в сутки | Случайный номер установки, домен и адрес сайта, версии плагина, WordPress, WooCommerce и PHP, ключ лицензии и метка сборки, число отправлений |
/api/v1/activate | При вводе ключа | Ключ, номер установки, домен и адрес сайта |
/api/v1/deactivate | По кнопке «Отвязать сайт» | Ключ, номер установки, домен |
/api/v1/order | После создания отправления | Номер установки, домен, ключ, метка сборки и order_ref = sha256(домен + номер заказа + соль установки) |
/api/v1/order-cancel | После отмены отправления до приёма в пункте отгрузки | То же, с тем же order_ref |
| Обновления | Когда WordPress проверяет обновления | Ссылку на архив плагин запрашивает у сервера прямо перед скачиванием |
Имена, телефоны, адреса, e-mail, суммы и состав заказов покупателей на сервер не передаются; IP-адрес сайта сервер видит при запросе. Тот же перечень — в п. 12.5 оферты и на вкладке «Лицензия» в плагине.
Подпись ответов: Ed25519
- Все JSON-ответы сервера лицензий, включая ошибки, подписаны Ed25519. Поле
sig— подпись канонического JSON без самогоsig: ключи объектов отсортированы на всех уровнях, списки — в исходном порядке, без пробелов,JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE. - Плагин проверяет подпись функцией
sodium_crypto_sign_verify_detached, а если расширения sodium нет — через sodium_compat из WordPress. - Ответ принимается, только если подпись верна и в нём те же номер установки, домен и
nonce, что в запросе: старый ответ подставить нельзя. - Адрес сервера и открытый ключ зашиты в сборку плагина и из сети не загружаются. Открытый ключ (base64, 32 байта) —
DQk2vmKAOr3sJXAlaU6uUbmFOxO78EiuAO5w4CpoAIA=; его же отдаёт сервер по адресуhttps://api.ev-gerasimov.ru/api/v1/pubkey.
Если сервер лицензий недоступен
- Оформление заказов от сервера не зависит: статус лицензии хранится на сайте.
- Годовая лицензия работает по последнему подписанному статусу до 14 дней, бессрочная — без ограничения срока.
- Пробные заказы, пока сервер молчит, считаются на сайте, а отчёты о них досылаются, когда связь вернётся.
- Если проверки не было больше 3 дней, в админке появляется предупреждение о связи.
- Через 14 дней без связи годовая лицензия считается непроверенной: работает остаток пробного периода, если он есть, иначе способ Ozon скрывается на оформлении. Уже созданные отправления доводятся до конца.
Ключи, журналы и персональные данные
- Ключи Ozon. Настройки плагина — в опции без автозагрузки, Client Secret — в отдельной опции без автозагрузки, токен доступа — тоже. Ключей Ozon нет в HTML, JavaScript и журналах: все запросы к Ozon идут с сервера сайта.
- Ключи карт. Публичные ключи Яндекс.Карт и 2ГИС попадают в код страницы оформления, только если выбранная карта может понадобиться. Ограничьте их адресом сайта в кабинетах этих сервисов. Для DaData нужен только публичный ключ.
- Журнал — WooCommerce → Статус → Журналы, источник
ozon-delivery-woo. Перед записью маскируются заголовокBearer …, поляclient_secret,access_token,refresh_token, любые поля, в названии которых естьsecret,token,authorization,passwordилиcookie, и российские телефоны в любом формате — от номера остаются код оператора и последние две цифры. Отладочные сообщения пишутся, только если включено подробное логирование. Сроком хранения журналов управляет WooCommerce. - Данные в Ozon — ФИО и телефон получателя, выбранный пункт, вес, размеры и объявленная стоимость посылки и описание без персональных данных (по шаблону с
{order}и{site}). - Мета заказа — номер и адрес выбранного пункта, номер отправления, статус и история статусов, без списка всех пунктов города.
- Удаление. Деактивация данные не удаляет. Удаление плагина стирает настройки, справочник и данные лицензии на сайте, только если на вкладке «Журнал и данные» отмечено «Удалить настройки и справочник пунктов». Данные заказов не удаляются никогда.
Совместимость: HPOS, блоки, PHP
- HPOS. Плагин работает с заказами только через CRUD-методы WooCommerce и объявляет совместимость с HPOS (
custom_order_tables). Включён ли HPOS, определяется черезOrderUtilвtry/catch. - Блочное оформление. Совместимость с
cart_checkout_blocksобъявлена, данные корзины идут через Store API (extensions.ozwc), без отдельной сборки JavaScript. Подробно — в статье Блочное и классическое оформление. - PHP 7.4–8.3, 64-битный. Номера Ozon 16-значные. На 32-битном PHP плагин не включается и пишет об этом в админке, сайт работает как раньше.
- Код — без обфускации. Дорабатывать его под свой сайт можно, кроме проверки лицензии, подсчёта пробных отправлений, передачи технических данных и метки сборки (п. 4.7 и 4.10 оферты).
Вопросы техлида
Нагрузит ли плагин базу и Ozon на распродаже?
Окно выбора пункта работает только со своей таблицей: поиск ближайших пунктов в справочнике на 88 тысяч строк занимает несколько миллисекунд. Запросы к Ozon на оформлении — расчёт цены и проверка выбранного пункта, повторные пересчёты берут ответ из кэша сессии.
Нужен ли Redis или другой кэш объектов?
Нет. Кэш расчёта хранится в сессии WooCommerce, а счётчик номеров по IP — во временных данных WordPress: с внешним кэшем объектов они хранятся в нём, без него — в базе сайта.
Что будет с оформлением, если Ozon не отвечает?
Через 4 секунды и один повтор покупатель увидит сообщение, а остальные способы доставки работают. Ozon иногда «зависает» на отдельных запросах, поэтому таймауты короткие, а фоновые задачи повторяют запросы сами.
Как проверить, что ответ пришёл от настоящего сервера лицензий?
Сверьте открытый ключ из раздела «Подпись ответов» с ответом https://api.ev-gerasimov.ru/api/v1/pubkey. Плагин принимает только ответы с верной подписью этим ключом.
Читайте дальше
- Требования к сайту и хостингуWordPress, WooCommerce, 64-битный PHP, cron, исходящие запросы и оформление заказа.
- Блочное и классическое оформление заказаКак плагин работает с блоком «Оформление заказа» и с шорткодами WooCommerce.
- Выбор пункта выдачи в WooCommerceСправочник 88 тысяч пунктов, карта и список, поиск адреса, проверка доступности пункта.
- Ozon Delivery API: обзор на русскомДоступ и токен, порядок методов, пункты выдачи, ошибки, перенаправление 307 и таймауты.
- Лицензия, пробный период и обновления50 заказов бесплатно, ключ на сайт и оптовые цены, перенос на другой домен.
- Инструкция: установка и настройка плагина12 шагов от кабинета Ozon до первого заказа на сайте WooCommerce.