Спецификация на Perkly API
Тази документация описва криптографския протокол и наличните адреси (API endpoints) за интеграция с мултитенантната SaaS система Perkly. Всички заявки към API сървъра се насочват към базов адрес: `http://localhost:3000/api/v1` (или вашия домейн) и изискват валиден криптографски подпис в хедърите.
📖 Ръководство за употреба на платформата
Как да стартирате и управлявате програмата за лоялност Perkly стъпка по стъпка.
1 Създаване на Група и Магазин (Tenant)
Влезте в административния панел на адрес /admin с вашите данни. Първо създайте Група (ако имате партньорски сайтове, които ще споделят точки), и след това добавете Магазин (Tenant) вътре в нея. Платформата автоматично ще ви генерира публичен API Key и таен API Secret Key.
2 Инсталиране на плъгина в WooCommerce
Качете архива на плъгина perkly.zip във вашия WordPress сайт през меню Разширения (Plugins) и го активирайте. Отидете в главното меню на WordPress -> Perkly SaaS Settings и въведете адреса на вашия API сървър и двата ключа. Задайте курс на печелене (Earn Rate) и курс на харчене (Spend Rate).
3 Настройка на продукти
При редактиране на продукт в WooCommerce ще видите новия панел Perkly SaaS Options. Оттук можете:
- Да направите продукта "Само с точки" (Points Only) и да зададете неговата цена в точки.
- Да го маркирате като VIP Абонамент (Subscription) и да зададете брой дни (например 30 дни). При покупка клиентът автоматично получава ролята
Club Member.
4 Управление на транзакции и Ledger
Когато клиентите правят поръчки, Perkly автоматично резервира точки от техния акаунт в реално време. При завършване (или плащане) на поръчката, транзакцията се маркира като потвърдена (Confirmed) и се записва постоянно в Ledger-а. Всичко става автоматично и без риск от дублиране на баланси.
5 Одобряване на фактури (Invoice Claims)
Клиентите могат да качват фактури за покупки, извършени извън сайта, през своя WordPress профил ("Лоялна програма"). Вие ще виждате тези заявки директно в менюто WooCommerce -> Invoice Claims. Имате опция да ги прегледате, одобрите (при което точките се начисляват автоматично) или отхвърлите с посочване на причина.
6 Периодична ротация на тайни (Rotate Secret)
За максимална сигурност, можете периодично да натискате бутона Rotate Secret в SaaS контролния панел. Това генерира нов секретен ключ, но позволява на стария да работи в рамките на 24 часа. Това дава време да обновите настройките в WooCommerce сайтовете си без прекъсване на покупките.
🔐 Криптографска защита (HMAC-SHA256)
Всички заявки към API-то се подписват на базата на таен споделен ключ (`API Secret`).
Всяка заявка задължително изисква изпращането на следните HTTP хедъри:
- `x-api-key`: Вашият публичен API ключ, издаден от SaaS портала.
- `x-timestamp`: Текущото UNIX време в секунди (за предпазване от Replay атаки – заявки с разлика над 5 минути се отхвърлят).
- `x-signature`: HMAC-SHA256 подписът, генериран по формулата по-долу.
Формула за генериране на подпис:
Signature = HMAC_SHA256( API_Secret, Method + Path + Timestamp + JSON_Body )
Забележка: При заявки без тяло (напр. GET заявки), `JSON_Body` е празен низ `""`.
Кодови примери за подписване:
$timestamp = time();
$body = json_encode($data, JSON_UNESCAPED_SLASHES);
$string_to_sign = "POST" . "/api/v1/transactions/reserve" . $timestamp . $body;
$signature = hash_hmac('sha256', $string_to_sign, $api_secret);
const timestamp = Math.floor(Date.now() / 1000).toString();
const stringToSign = 'POST' + '/api/v1/transactions/reserve' + timestamp + JSON.stringify(body);
const signature = crypto.createHmac('sha256', apiSecret).update(stringToSign).digest('hex');
🔌 Верификация на връзката
Проверка на комуникацията на магазина с API сървъра и получаване на GitHub токен.
Използва се от WooCommerce клиента за проверка на валидността на `API Key` и `API Secret`. Връща данни за тенанта и частния GitHub токен за автоматични обновления на плъгина.
Успешен отговор (200 OK):
{
"success": true,
"tenant": {
"id": "e30c4e12-32a8-444a-9b1c-99d88a77b66c",
"name": "Моят WooCommerce Магазин",
"group_id": "b10b4f8c-23a9-450f-90e9-aa88bb77cc66",
"site_url": "https://website.com"
},
"update_token": "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
👥 Клиенти и Баланси
Връща наличния баланс на клиента в групата на магазина, както и информация за текущия му VIP абонамент. Ако имейлът не съществува в системата, връща баланс 0 и статус `inactive` без грешка.
Параметри на пътя (Path Params):
- `email`: Имейл адрес на клиента (напр. `customer@email.com`).
Успешен отговор (200 OK):
{
"balance": 850,
"subscription_status": "active",
"subscription_expires_at": "2026-07-12",
"subscription_created_at": "2026-06-12"
}
Връща хронологичен списък с транзакциите с точки на даден клиент. Поддържа странициране чрез query параметри.
Параметри на пътя (Path Params):
- `email`: Имейл адрес на клиента.
Параметри на заявката (Query Params):
- `page` (опционален): Номер на страницата (напр. `1`).
- `limit` (опционален): Максимален брой резултати на страница (напр. `10`).
Успешен отговор (200 OK):
{
"transactions": [
{
"id": "7a8b9c10-d1e2-3f4a-5b6c-7d8e9f0a1b2c",
"amount": 120,
"type": "Earn",
"status": "Completed",
"idempotency_key": "order_10023",
"created_at": "2026-06-12T15:30:00.000Z"
},
{
"id": "8c3b7a5e-14ef-4b2a-89a1-7788aa99bbcc",
"amount": -150,
"type": "Redeem",
"status": "Completed",
"idempotency_key": "order_10022",
"created_at": "2026-06-11T12:00:00.000Z"
}
],
"total": 2,
"page": 1,
"limit": 10,
"pages": 1
}
💸 Сделки и Управление на Точки (Transactions)
Резервира точки от баланса на клиента. Използва се при завършване на поръчка. `amount` е отрицателно число. Изисква активен абонамент.
Параметри на заявката (JSON):
{
"email": "customer@email.com",
"amount": -150,
"idempotency_key": "order_12345"
}
Успешен отговор (200 OK):
{
"transaction_id": "8c3b7a5e-14ef-4b2a-89a1-7788aa99bbcc",
"status": "Pending"
}
Потвърждава резервирана транзакция (точките се отнемат трайно от баланса).
Параметри на заявката (JSON):
{
"transaction_id": "8c3b7a5e-14ef-4b2a-89a1-7788aa99bbcc"
}
Успешен отговор (200 OK):
{
"transaction_id": "8c3b7a5e-14ef-4b2a-89a1-7788aa99bbcc",
"status": "Completed"
}
Начислява точки на баланса на клиента за завършена покупка или действие. `amount` трябва да е положително число. Автоматично създава клиента, ако не съществува.
Параметри на заявката (JSON):
{
"email": "customer@email.com",
"amount": 250,
"idempotency_key": "order_earn_12345"
}
Успешен отговор (200 OK):
{
"transaction_id": "fc4b2a8c-14b5-4122-aa11-8899aabbcc77",
"status": "Completed"
}
Освобождава резервираните точки обратно в баланса на клиента (например при отказ на поръчка преди изпращане).
Параметри на заявката (JSON):
{
"transaction_id": "8c3b7a5e-14ef-4b2a-89a1-7788aa99bbcc"
}
Успешен отговор (200 OK):
{
"transaction_id": "8c3b7a5e-14ef-4b2a-89a1-7788aa99bbcc",
"status": "Cancelled"
}
Възстановява изразходвани точки от приключила Redeem транзакция обратно на клиента (напр. при връщане на продукт). Сумата за възстановяване е положително число и не може да надвишава оригиналната сума на плащането.
Параметри на заявката (JSON):
{
"reference_transaction_id": "8c3b7a5e-14ef-4b2a-89a1-7788aa99bbcc",
"amount": 150,
"idempotency_key": "refund_order_12345"
}
Успешен отговор (200 OK):
{
"transaction_id": "9d8e7f6a-5b4c-3d2e-1f0a-a1b2c3d4e5f6",
"status": "Completed"
}
Ръчно добавяне или отнемане на точки от баланса на клиента. Положително число добавя точки, а отрицателно число ги отнема.
Параметри на заявката (JSON):
{
"email": "customer@email.com",
"amount": -50,
"idempotency_key": "manual_adj_67890"
}
Успешен отговор (200 OK):
{
"transaction_id": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"status": "Completed"
}
👑 Управление на Абонаменти (Subscriptions)
Активира или удължава VIP статуса на клиента след покупка на VIP продукт в WooCommerce. Ако клиентът вече има активен абонамент, дните се прибавят адитивно към оставащото време.
Параметри на заявката (JSON):
{
"email": "customer@email.com",
"status": "active",
"expires_in_days": 30,
"source": "woocommerce_order_12345"
}
Успешен отговор (200 OK):
{
"message": "Subscription updated successfully.",
"event": "activated",
"status": "active",
"days_added": 30,
"expires_at": "2026-07-12T15:00:00.000Z"
}
Ръчно задаване на статус и крайна дата на изтичане на VIP абонамент през административната част на WooCommerce.
Параметри на заявката (JSON):
{
"email": "customer@email.com",
"status": "active",
"start_date": "2026-06-12",
"expires_at": "2026-07-12",
"note": "Ръчно активиран статус"
}
Успешен отговор (200 OK):
{
"message": "Subscription manually updated successfully.",
"status": "active",
"start_date": "2026-06-12",
"expires_at": "2026-07-12"
}
Външен Webhook от WooCommerce при събития за промяна на абонамент (изтичане, спиране, подновяване).
Параметри на заявката (JSON):
{
"email": "customer@email.com",
"status": "expired",
"source": "woocommerce_subscription_webhook"
}
Успешен отговор (200 OK):
{
"success": true,
"message": "Subscription webhook processed successfully.",
"customer": "customer@email.com",
"event": "cancelled",
"status": "expired"
}
📝 Заявки за фактури (Invoice Claims)
Използва се за качване на снимка или PDF на фактура за покупки, извършени извън сайта. Изисква `multipart/form-data` кодиране на заявката. Достъпно само за VIP клиенти с активен абонамент.
Параметри на формата (Form Fields - multipart/form-data):
- `customer_email` (text): Имейл на VIP клиента.
- `amount` (text/number): Обща сума на покупката от фактурата (напр. `250.50`).
- `currency` (text, опционален): Валута на покупката (напр. `BGN`).
- `description` (text, опционален): Описание на покупката.
- `invoice` (file): Файлът на фактурата (JPEG, PNG или PDF до 5MB).
Успешен отговор (201 Created):
{
"success": true,
"message": "Invoice claim submitted successfully for review.",
"claim_id": "fc4b2a8c-14b5-4122-aa11-8899aabbcc77"
}
Извлича история на подадените фактури от даден клиент към текущия магазин.
Параметри на пътя (Path Params):
- `email`: Имейл адрес на клиента.
Успешен отговор (200 OK):
{
"success": true,
"invoices": [
{
"id": "claim-uuid",
"amount": 250.50,
"currency": "BGN",
"points_awarded": 250,
"description": "Покупка от физически магазин",
"image_url": "/uploads/invoices/unique-filename.jpg",
"status": "approved",
"rejection_reason": null,
"created_at": "2026-06-12T15:00:00.000Z"
}
]
}
Извлича всички искове по фактури на текущата група магазини. Използва се в интеграцията на WordPress администратора за показване на чакащи за одобрение документи.
Параметри на заявката (Query Params):
- `status` (опционален): Филтър по статус на иска (`pending`, `approved`, `rejected`).
Успешен отговор (200 OK):
{
"success": true,
"invoices": [
{
"id": "claim-uuid",
"amount": 250.50,
"currency": "BGN",
"points_awarded": null,
"description": "Покупка",
"image_url": "/uploads/invoices/unique-filename.jpg",
"status": "pending",
"rejection_reason": null,
"customer_email": "customer@email.com",
"tenant_name": "Магазин Име",
"site_url": "https://client-site.com",
"created_at": "2026-06-12T15:00:00.000Z"
}
]
}
Одобрява заявката за фактура и начислява посочените точки в баланса на клиента.
Параметри на пътя (Path Params):
- `id`: UUID на иска по фактура.
Параметри на заявката (JSON):
{
"points_awarded": 150,
"reviewer_email": "admin@tenant.com"
}
Успешен отговор (200 OK):
{
"success": true,
"message": "Invoice claim approved and points awarded successfully."
}
Отхвърля иск по фактура. Ако искът е бил одобрен по-рано, системата се опитва да отнеме начислените точки, без да допуска отрицателен баланс.
Параметри на пътя (Path Params):
- `id`: UUID на иска по фактура.
Параметри на заявката (JSON):
{
"rejection_reason": "Документът е нечетлив.",
"reviewer_email": "admin@tenant.com"
}
Успешен отговор (200 OK):
{
"success": true,
"message": "Invoice claim rejected successfully."
}