Подгответе клиент
Користете HTTPS клиент со JSON поддршка и разумен timeout. Заглавието Content-Type мора да биде application/json.
XNet · HTTPS · JSON
Практичен водич за сигурна интеграција со XNet: еден endpoint, предвидлив JSON договор и корелирани одговори за секое барање.
https://vps.xnet.mk:50443/api/commands
01 · Quickstart
Сите команди се испраќаат како UTF-8 JSON преку HTTPS. За секое барање креирајте нови идентификатори и краток рок на важност.
Користете HTTPS клиент со JSON поддршка и разумен timeout. Заглавието Content-Type мора да биде application/json.
Генерирајте нов messageId, стабилен clientSessionId и conversation id. Започнете со turn 1.
Секое барање содржи username и password; заштитените операции ги проверуваат директно во Users кешот.
Проверете HTTP статус, status и error. replyToMessageId секогаш треба да одговара на испратениот messageId.
Адреса на сервисот: Документацијата е на api.xnet.mk, а API повиците одат на vps.xnet.mk со задолжителната порта 50443. Користете ја целата адреса прикажана погоре; портата 443 моментално не е API endpoint.
02 · Contract
Структурата е верзионирана и обезбедува следливост меѓу апликации, клиенти и разговори. Полето data секогаш е JSON object.
{
"schemaVersion": 1,
"messageId": "<new-uuid>",
"authentication": {
"username": "<username>",
"password": "<password>"
},
"client": {
"appId": "idiot.mk",
"appVersion": "1.0.0",
"clientSessionId": "<session-uuid>"
},
"conversation": {
"id": "<conversation-uuid>",
"turn": 1
},
"operation": "system.ping",
"sentAtUtc": "<current-utc-time>",
"expiresAtUtc": "<short-future-utc-time>",
"data": {}
}
| Поле | Тип | Значење |
|---|---|---|
| schemaVersion | integer | Мора да биде 1. |
| messageId | UUID | Нов, непразен идентификатор за секое барање. |
| authentication.username authentication.password | string | Задолжителни во секое барање; кај заштитените операции се проверуваат преку Users кешот. |
| client | object | Идентитет на апликацијата, верзија и непразен session UUID. |
| conversation | object | Непразен id и turn поголем од 0. |
| operation | string | Името на серверската функционалност. |
| expiresAtUtc | ISO 8601 / null | Ако е зададено, мора да биде во иднина. |
| data | object | Параметри за операцијата; никогаш JSON запишан како string. |
03 · Operations
Еден contract ги покрива автентикацијата, јавниот feed, објавувањето, гласањето, коментарите, пријавите и администраторската модерација.
Проверува дали сервисот прифаќа и обработува валидни команди.
// request.data
{}
// response.data
{ "text": "pong" }Креира корисник директно во Hetz базата без stored procedure, го mirror-запишува во локалниот кеш и враќа основни податоци.
{
"userId": 123,
"username": "developer",
"email": "dev@example.com",
"confirmed": true,
"emailDelivery": "not-required"
}| Категорија | operation | authentication | Намена |
|---|---|---|---|
| Auth | user.confirm-email user.resend-confirmation | credentials present | Задржани за компатибилност; email потврдата привремено не е потребна. |
| Auth | user.login user.me | verified credentials | Проверка на username/password и враќање безбеден профил без токени. |
| Finmath | catalog.country-city finmath.company.register finmath.company.delete-or-archive finmath.bookkeeping.register finmath.bookkeeping.clients | verified credentials | Каталог, регистрација, реални фирма-до-фирма врски и интерни фирми од базата на книговодството, без директна клиентска MySQL конекција. |
| Обврски | obvrski.list obvrski.save obvrski.delete obvrski.reorder obvrski.step.save obvrski.step.delete | verified credentials | Читање, промена и зачуван редослед само на обврските и нивните чекори за најавениот корисник во фиксната база 09_obvrski. Клиентот користи appId: "obvrski" и не избира база. |
| Feed | post.list post.get post.comment.list | credentials present | Јавни одобрени објави и коментари. |
| Content | post.create post.my post.vote post.comment.create post.report | verified credentials | Објавување, сопствена историја и интеракции. |
| Admin | admin.post.pending admin.post.moderate admin.report.list admin.report.resolve | verified credentials + admin | Одобрување објави и обработка на пријави. |
04 · user.register
Секое барање содржи username и password. Нема access/refresh токени или серверски сесии; заштитените операции ги проверуваат credentials преку Users кешот.
Привремено не е потребно. Новите и постојните сметки серверот ги смета за потврдени.
Испрати username и password во authentication; успешниот одговор нема токени.
Ги проверува credentials повторно и враќа безбеден профил и isAdmin.
Дозволени се idiot.mk origins. Ограничувањето е 120 барања во минута по IP.
| Поле | Услов | Валидација |
|---|---|---|
| username | Задолжително | 3–45 знаци, без празни места. |
| password | Задолжително | 8–256 знаци. Се испраќа само преку HTTPS. |
| Задолжително | Валидна адреса, најмногу 60 знаци. | |
| name, surname | Опционално | Најмногу 45 знаци по поле. |
| pid, address, city, country, phone | Опционално | Најмногу 45 знаци по поле. |
| languageId | Опционално | Цел број од 1 до 127; стандардно 1. |
| birthday | Опционално | YYYY-MM-DD; не смее да биде во иднина. |
| primeRegistrant | Опционално | Најмногу 45 знаци. |
| profilePicture | Опционално | String до 700.000 знаци; избегнувајте го кога не е неопходно. |
Безбедност: Лозинката не се враќа во одговорот и се зачувува како PBKDF2-SHA256 hash. Не логирајте password или profilePicture во клиентската апликација.
05 · Finmath 3
Клиентот користи appId finmath-3. По најавата, response.data.finmath го содржи корисничкиот профил и сите достапни фирми; клиентот не се поврзува директно на MySQL.
По проверка на credentials враќа finmath.connections за избор на фирма или книговодство, без токени.
Со проверени username/password ги враќа активните држави и градови на mk, en или sq.
Бара одобрена книговодствена конекција, запишува директно во Hetz базата без stored procedures и го освежува локалниот kesh.
Проверува само zz_NNNNNNN_* табели. Непразна табела ја архивира фирмата; ако сите се празни, во deleted_companies LIKE 00_x.log_root ги зачувува целата фирма и сите user-connections како JSON, па ги брише само тие централни редови.
Креира книговодство со нова база со следниот слободен 04_ реден број и одобрена улога FinmathAccounter.
Ги спојува активните реални фирми од company_relations со валидните интерни фирми од my_settings и активните директни интерни конекции за истата книговодствена база. Позитивен ID и непразен краток назив се задолжителни; дозволен е и назив од еден знак, а zz_ работни табели не се услов.
Сите legacy Data_In повици од shared root одат во Listener. Нема повик или fallback кон 00.get_data; Listener проверува пристап и ја рутира конкретната операција. При MySQL 1146 за побарана фирмена табела, ја обновува од соодветниот 00_x шаблон и ја повторува операцијата еднаш.
{
"bookkeepingConnectionId": 321,
"password": "user-password",
"shortName": "firma_2026",
"wholeName": "Фирма ДООЕЛ Скопје",
"address": "Партизанска",
"number": "10",
"city": "Скопје",
"country": "Македонија",
"taxNumber": "MK1234567",
"pid": "1234567",
"taxObligated": true,
"planType": 1,
"accountantPlan": 1,
"kontenPlanSource": 1,
"sourceType": 1
}
06 · Responses
Успешен одговор има status completed и error null. Одбиено барање има status rejected, data null и структуриран error. Кај MySQL грешка се враќаат бројот, SQL state, конкретната порака и безбедна конекциска дијагностика без лозинката.
Клиентот генерира уникатен идентификатор.
Серверот го враќа истиот id за корелација.
Го покажува следниот turn во разговорот.
| HTTP | Кога | Вообичаен error.code |
|---|---|---|
| 200 | Успешен system.ping. | — |
| 201 | Успешна регистрација. | — |
| 400 | Невалиден envelope или непозната операција. | unsupported-version, invalid-client, unsupported-operation |
| 401 | Недостасуваат или не се точни credentials. | missing-credentials, invalid-credentials |
| 403 | Недоволни администраторски права. | admin-required |
| 408 | Истечено барање. | message-expired |
| 409 | Корисничкото име или email веќе постои. | user-already-exists |
| 422 | Невалидни податоци за регистрација. | validation-error |
| 429 | Надминато ограничување по IP. | rate-limit-exceeded |
| 503 | Регистрациската база е недостапна. | database-unavailable, database-error |
06 · Examples
Примерот автоматски создава свежи UUID вредности и рок од пет минути, за да не копирате истечено барање.
const now = new Date();
const payload = {
schemaVersion: 1,
messageId: crypto.randomUUID(),
authentication: { username: "<username>", password: "<password>" },
client: {
appId: "idiot.mk",
appVersion: "1.0.0",
clientSessionId: crypto.randomUUID()
},
conversation: { id: crypto.randomUUID(), turn: 1 },
operation: "system.ping",
sentAtUtc: now.toISOString(),
expiresAtUtc: new Date(now.getTime() + 5 * 60_000).toISOString(),
data: {}
};
const response = await fetch("https://vps.xnet.mk:50443/api/commands", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
signal: AbortSignal.timeout(15_000)
});
const result = await response.json();
if (!response.ok || result.status !== "completed") {
throw new Error(result.error?.code ?? `HTTP ${response.status}`);
}
07 · Checklist
Овие правила треба да бидат дел од секоја клиентска имплементација, без оглед на програмскиот јазик.
Не реупотребувајте messageId. Задржете clientSessionId само додека работи една клиентска инстанца.
Испраќајте ISO 8601 UTC времиња и краток expiresAtUtc за да се одбиваат застарени команди.
Редактирајте лозинки и големи бинарни/string полиња пред логирање.
Не повторувајте write операција автоматски. error.retryable моментално е false.
08 · Codex bridge
Теренските комуникатори одржуваат TLS WebSocket конекција и се докажуваат со сопствен ECDSA P-256 клуч и server challenge. Приватниот клуч останува DPAPI-заштитен на теренскиот компјутер; нема заеднички клуч, XNet корисник или лозинка.
Listener-от извршува команди само преку loopback каналот. Оддалечен агент пристапува преку посебен gateway контролиран со XNet Update API клуч; ова не е дел од business API и не користи корисничко име или лозинка.