Примање webhooks

Добивајте потпишано HTTP барање на вашиот сервер секогаш кога ќе се промени член, членарина, влез или продажба во FitManager.

2 мин. читање Ажурирано 04.10.2026 Потребно: Пристап до API

Webhooks ги испраќаат настаните до вашиот софтвер во моментот кога се случуваат, па тој не мора постојано да го прашува API за промени. Кога ќе се случи нешто во вашата теретана, FitManager испраќа POST барање со JSON содржина до секоја крајна точка што е претплатена на тој настан.

Пред да започнете

  • Потребна ви е дозволата settings.manage и пакет со API пристап.
  • Потребна ви е јавна HTTPS адреса на вашиот сервер што прима POST барања и одговара за најмногу 15 секунди.
  • Webhooks се на истата страница како API клучевите: Поставки > Интеграции > API интеграција, картичка Webhook крајни точки.

Додадете крајна точка

  1. Во Webhook крајни точки, кликнете Додади крајна точка.
  2. Внесете URL на крајната точка, на пример https://example.com/webhooks/fitmanager.
  3. По желба додадете Опис за да знаете за што служи крајната точка.
  4. Изберете Околина: Продукциско за вашата вистинска теретана. Ова не може да се смени подоцна.
  5. Означете ги Настаните што ги сакате. Означете * за да ги примате сите настани, вклучително и оние што ќе се додадат во иднина.
  6. Кликнете Зачувај крајна точка.

Крајната точка се појавува во списокот со URL-то, околината и настаните. Секоја крајна точка добива свој таен клуч за потпис, кој ви треба за проверка на барањата (погледнете подолу).

Настани

Настан Се испраќа кога data.object
member.created Ќе се додаде член member
member.updated Ќе се зачува каква било промена на член member
membership.assigned На член ќе му се додели членарина member_membership
membership.expired Членарината на член ќе премине во истечена member_membership
checkin.recorded Ќе се запише скенирање или влез на пристапна точка, одобрен или одбиен access_log
purchase.recorded Ќе се евидентира продажба purchase
* Кој било од горните

Како изгледа една испорака

Секоја испорака е POST со овие заглавија:

Заглавие Вредност
Content-Type application/json
X-FitManager-Event Името на настанот, на пример member.created
X-FitManager-Signature t={timestamp},v1={signature}

Содржината е настанот во обвивка. data го содржи записот онака како што е зачуван, без лозинки:

{
  "id": "evt_01JA3K7Q8ZJ4X6V2N9P5R1T0WB",
  "event": "member.created",
  "created": 1791105164,
  "gym_id": 12,
  "environment": "live",
  "data": {
    "id": 4821,
    "facility_id": 31,
    "first_name": "Elena",
    "last_name": "Stojanovska",
    "email": "elena@example.mk",
    "member_code": "K7PX2QHM",
    "phone": "+389 70 123 456",
    "date_of_birth": null,
    "gender": null,
    "city": "Skopje",
    "country": "MK",
    "rfid_tag": null,
    "status": "active",
    "created_at": "2026-10-04T09:12:44.000000Z",
    "updated_at": "2026-10-04T09:12:44.000000Z",
    "object": "member"
  }
}

Полињата во data го следат записот, па со текот на времето може да се појават нови. Игнорирајте ги полињата што не ги користите наместо да го одбиете барањето.

Проверете го потписот

Проверете го секое барање пред да му верувате:

  1. Прочитајте го заглавието X-FitManager-Signature и поделете го на t (Unix време) и v1 (потписот).
  2. Земете ја суровата содржина на барањето точно како што пристигнала, пред каква било JSON обработка.
  3. Пресметајте HMAC-SHA256 од {t}.{body} со тајниот клуч на крајната точка, како hex низа со мали букви.
  4. Споредете го со v1 со споредба во константно време.
  5. Одбијте го барањето ако t се разликува повеќе од 5 минути од часовникот на вашиот сервер, за да спречите повторно испраќање од трета страна.

За да го видите тајниот клуч, кликнете Таен клуч за потпис на крајната точка, па Копирај. Почнува со whsec_.

PHP

$secret = getenv('FITMANAGER_WEBHOOK_SECRET');
$body = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_FITMANAGER_SIGNATURE'] ?? '';

$parts = [];
foreach (explode(',', $header) as $segment) {
    [$key, $value] = array_pad(explode('=', trim($segment), 2), 2, null);
    $parts[$key] = $value;
}

$timestamp = (int) ($parts['t'] ?? 0);
$expected = hash_hmac('sha256', $timestamp.'.'.$body, $secret);

if (abs(time() - $timestamp) > 300 || ! hash_equals($expected, $parts['v1'] ?? '')) {
    http_response_code(400);
    exit;
}

$event = json_decode($body, true);
http_response_code(200);

Node.js (Express)

const crypto = require('crypto');
const express = require('express');
const app = express();

app.post('/webhooks/fitmanager', express.raw({ type: 'application/json' }), (req, res) => {
  const secret = process.env.FITMANAGER_WEBHOOK_SECRET;
  const header = req.get('X-FitManager-Signature') || '';
  const parts = Object.fromEntries(header.split(',').map(p => p.trim().split('=')));

  const timestamp = parseInt(parts.t, 10);
  const expected = crypto.createHmac('sha256', secret)
    .update(`${timestamp}.${req.body.toString('utf8')}`)
    .digest('hex');

  const valid = parts.v1 && parts.v1.length === expected.length
    && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))
    && Math.abs(Date.now() / 1000 - timestamp) <= 300;

  if (!valid) return res.sendStatus(400);

  const event = JSON.parse(req.body.toString('utf8'));
  res.sendStatus(200);
});

Одговорете брзо

Одговорете со кој било 2xx статус за најмногу 15 секунди. Секој друг одговор, истекување на времето или грешка во врската се смета за неуспех. Ако обработката трае подолго, зачувајте го настанот, одговорете 200 и обработете го потоа.

Неуспеси и повторна испорака

  • FitManager го испраќа секој настан еднаш. Не ја повторува неуспешната испорака сам, па по поправката на серверот користете Повторно испорачај (подолу).
  • По 10 последователни неуспеси, крајната точка автоматски се оневозможува. Добива ознака Оневозможена и причина „Auto-disabled after 10 consecutive delivery failures.“ Секоја успешна испорака го ресетира бројачот.
  • За повторно да ја вклучите, кликнете Овозможи на крајната точка. Ова го ресетира и бројачот на неуспеси. Настаните што се случиле додека била оневозможена не се испраќаат, па повторно испорачајте ги оние што ви требаат.
  • Повторната испорака ја испраќа истата содржина со истиот id, со ново време и нов потпис. Користете го id за да ги игнорирате настаните што веќе сте ги обработиле.

Дневник на испораки

Картичката Неодамнешни испораки го прикажува секое испратено барање, од најново, со Настан, Крајна точка, Статус на одговорот (или Без одговор), бројот на Обид и кога е Испорачано.

  • Филтрирајте со Сите резултати, Успешни или Неуспешни.
  • Кликнете Прегледај за целата содржина, со копче Копирај.
  • Кликнете Повторно испорачај за повторно испраќање. Се додава во дневникот како нов ред со следниот број на обид. Работи само додека крајната точка е овозможена.

Повторна испорака може да побарате и од код со POST /api/v1/webhook-deliveries/{id}/redeliver, што одговара со 202.

Управување со крајна точка

Копче Што прави
Таен клуч за потпис / Сокриј го тајниот клуч Го прикажува или сокрива тајниот клуч, со Копирај и Смени
Смени Веднаш го заменува тајниот клуч. Барањата потпишани со стариот клуч повеќе не поминуваат проверка, па веднаш ажурирајте го серверот
Оневозможи / Овозможи Ги паузира или продолжува испораките
Уреди Ги менува URL-то, описот и настаните. Околината останува иста
Избриши Ја отстранува крајната точка. Испораките престануваат веднаш

Решавање проблеми

Мојата крајна точка не добива ништо

Проверете дали крајната точка не е Оневозможена, дали настанот е означен и дали дејството навистина се случило во теретаната чија контролна табла ја користите. Погледнете ги Неодамнешни испораки со филтерот Неуспешни.

Потписите никогаш не се совпаѓаат

Проверувајте ја суровата содржина. Рамките што го парсираат и повторно кодираат JSON ги менуваат празните места и знаците, што го расипува потписот. Во Express користете express.raw(), во Laravel $request->getContent(). Проверете и дали по менувањето на тајниот клуч сте го ажурирале на двете страни.

Тест крајните точки не добиваат ништо

Крајна точка со Околина поставена на Тест е наменета за настани од тест околината, но тест крајните точки моментално не добиваат испораки. Додека развивате, насочете Продукциска крајна точка кон вашиот развоен сервер.

Билтен

Совети во вашето сандаче

Една е-пошта месечно: што испорачавме, што побараа сопствениците на теретани и една практична идеја за водење на салата. Без спам, отпишување со еден клик.

Отпишете се кога сакате. Никогаш не ја споделуваме вашата адреса.

Користиме колачиња за да ве задржиме најавени, да ги запаметиме вашите преференци и да разбереме како се користи страницата. Политика за приватност