SFTP для файлів заказів
SFTP-обмін файлами заказів з ApexSFA: підключення за ключем ed25519, теки incoming, processed, failed, статуси й типові проблеми.
Коротко
ApexSFA надає власний SFTP-сервер. Виробник (або його обліковий софт) підключається до нашого сервера під своєю обліковкою й кладе файли заказів у теку incoming/. Раз на хвилину система забирає файли, розбирає їх тими самими шаблонами, що й API файлів заказів, створює заявки під виробником обліковки й переносить файл у processed/ або failed/.
| Параметр | Значення |
|---|---|
| Протокол | лише SFTP (FTP, FTPS, scp і ssh-команди вимкнені) |
| Адреса сервера й порт | видаються при підключенні разом з обліковкою |
| Автентифікація | ключ OpenSSH (ed25519 генерується системою або ваш публічний ключ); пароль — лише за окремим запитом |
| Хто заводить обліковки | дистрибʼютор на порталі ApexSFA |
| Одна обліковка = | один виробник одного дистрибʼютора; своя ізольована тека |
| Частота обробки | щохвилини |
| Макс. розмір файлу | 50 МБ |
| Квота на обліковку | 2 ГБ |
Хто що робить
- Дистрибʼютор створює на порталі обліковку для виробника — система генерує пару ключів ed25519 і показує приватний ключ один раз.
- Дистрибʼютор передає виробнику: адресу сервера, порт, логін, приватний ключ (або підставляє ваш публічний ключ) і відбиток ключа сервера (
SHA256:…). - Виробник кладе файли в
incoming/. - Система забирає файл, створює заявки; файл переїжджає в
processed/абоfailed/. - Дистрибʼютор бачить результат на порталі, а виробник — куди переїхав файл і причину помилки в
.error.txt.
Структура тек
/ ← лише перегляд списку
├── incoming/ ← сюди КЛАСТИ файли
├── processed/ ← розібрані файли (перегляд і скачування)
└── failed/ ← файли з помилкою + пояснення .error.txt (перегляд і скачування)| Тека | Дозволено |
|---|---|
/ | перегляд списку |
/incoming | перегляд, завантаження, перезапис, скачування, видалення, перейменування |
/processed | перегляд, скачування |
/failed | перегляд, скачування |
Приклад вмісту після кількох прогонів:
incoming/
processed/
20261027_081502_zakaz_000123.xml
20261027_091010_zakaz_000124.xml
failed/
20261027_101501_orders_broken.csv
20261027_101501_orders_broken.csv.error.txtЩо відбувається з файлом
| Крок | Поведінка |
|---|---|
| Відбір | беруться лише файли безпосередньо в incoming/ (підтеки ігноруються); файли, імʼя яких починається з ., пропускаються |
| «Тиша» | файл береться, лише якщо його не змінювали щонайменше 20 с — поки SFTP-клієнт дописує файл, його не чіпають |
| Порядок | за алфавітом імені файлу |
| Перенесення | файл переміщується у processed/ або failed/ з новим імʼям {YYYYMMDD_HHMMSS}_{оригінальне імʼя}; час — у UTC |
| Помилка | поруч кладеться {YYYYMMDD_HHMMSS}_{імʼя}.error.txt (UTF-8) з текстом помилки |
Порада. Заливайте файл під тимчасовим імʼям з крапкою на початку (
.zakaz_000123.xml.part) і після завершення перейменовуйте — тоді напівзалитий файл гарантовано не потрапить в обробку.
Які файли обробляються
Формат визначається автоматично за вмістом; розширення файлу значення не має. Підтримуються ті самі формати, що й в API: XML «Заказы», CSV за номером документа, CSV поставки, JSON «Замовлення» / «Накладные» — опис полів у розділі 4.7.
Заявки створюються під виробником обліковки (навіть якщо у файлі вказана інша юрособа). Далі їх обробляє менеджер дистрибʼютора. Файл-відповідь на SFTP не кладеться — її видно дистрибʼютору на порталі; якщо вам потрібна відповідь автоматично, використовуйте API.
Ідемпотентність
- Якщо такий самий вміст файлу вже імпортувався (через SFTP, API чи вручну) і не був помилковим — нових заявок не буде; файл отримує статус
duplicateі переноситься вprocessed/. - Якщо попередній такий самий файл потрапив у
failed— файл розбирається заново (можна покласти той самий файл повторно після виправлення довідників). - На рівні документів: документ, який уже завантажували раніше в іншому файлі, нову заявку не створює.
Статуси файлу
| Статус | Значення | Куди перенесено |
|---|---|---|
processed | розібрано, створено заявки | processed/ |
duplicate | такий вміст уже імпортовано | processed/ |
failed | формат не розпізнано або помилка імпорту | failed/ + .error.txt |
Рядки, де товар чи точку не вдалося зіставити, не роблять файл failed: заявка створюється, а проблемні рядки менеджер добирає на порталі.
Безпека й підключення
- Вхід за замовчуванням тільки за ключем.
- Згенерований ключ — ed25519 у форматі OpenSSH, без парольної фрази. Приватний ключ показується один раз і в ApexSFA не зберігається.
- Можна підставити власний публічний ключ: рядки OpenSSH
ssh-ed25519,ssh-rsaабоecdsa-sha2-nistp256. На обліковці — один ключ: новий замінює попередній. - Після кількох невдалих спроб входу IP-адреса тимчасово блокується.
- Вимкнена обліковка не може увійти, і її
incoming/не обробляється.
Приклад підключення (OpenSSH; адресу, порт і логін видає дистрибʼютор):
chmod 600 apexsfa_vendor.key
sftp -i apexsfa_vendor.key -P <порт> <логін>@<адреса сервера>
sftp> cd incoming
sftp> put zakaz_000123.xml .zakaz_000123.xml.part
sftp> rename .zakaz_000123.xml.part zakaz_000123.xml
sftp> ls ../processedimport paramiko # pip install paramiko
key = paramiko.Ed25519Key.from_private_key_file("apexsfa_vendor.key")
transport = paramiko.Transport(("<адреса сервера>", int("<порт>")))
transport.connect(username="<логін>", pkey=key)
sftp = paramiko.SFTPClient.from_transport(transport)
sftp.put("zakaz_000123.xml", "incoming/.zakaz_000123.xml.part")
sftp.rename("incoming/.zakaz_000123.xml.part", "incoming/zakaz_000123.xml")
print(sftp.listdir("processed"))
sftp.close(); transport.close()// npm i ssh2-sftp-client
import SftpClient from "ssh2-sftp-client";
import { readFile } from "node:fs/promises";
const sftp = new SftpClient();
await sftp.connect({
host: "<адреса сервера>", port: Number("<порт>"), username: "<логін>",
privateKey: await readFile("apexsfa_vendor.key"),
});
await sftp.put("zakaz_000123.xml", "incoming/.zakaz_000123.xml.part");
await sftp.rename("incoming/.zakaz_000123.xml.part", "incoming/zakaz_000123.xml");
console.log(await sftp.list("processed"));
await sftp.end();При першому підключенні клієнт покаже відбиток ключа сервера виду SHA256:… — він має збігатися з тим, що вам передав дистрибʼютор.
Часові пояси й кодування
- Префікс імені
YYYYMMDD_HHMMSS_— UTC. - Кодування файлів — як у відповідному форматі (див. 4.7);
.error.txt— UTF-8.
Типові проблеми
| Симптом | Причина / що робити |
|---|---|
Permission denied (publickey) | не той ключ, ключ перевипущено або обліковку вимкнено — зверніться до дистрибʼютора |
| зʼєднання не встановлюється після кількох невдалих спроб | IP тимчасово заблоковано — зачекайте 30 хв |
файл лежить в incoming/ і не зникає | його ще дописують (менше 20 с тиші), імʼя починається з ., обліковка вимкнена, або це підтека |
файл у processed/, але заявок немає | статус duplicate — такий самий вміст уже імпортовано |
файл у failed/ | читайте сусідній .error.txt; найчастіше — формат не підходить |
| не вдається залити файл | файл понад 50 МБ або вичерпано квоту 2 ГБ |