Перейти до змісту

Як підключити магазин

Підключення складається з чотирьох кроків: реєстрація, токен monobank, відправник Нової Пошти та інтеграція з вашим сайтом. Усі налаштування — у вкладках кабінету.

1. Реєстрація

Створіть акаунт на сторінці реєстрації: ім’я або назва компанії, email, пароль і адреса магазину. Ми перевіряємо, що сайт відкривається з інтернету й не закритий від індексації. Назву магазину беремо з сайту, її можна змінити у вкладці «Основне».

Один акаунт — один магазин. У вкладці «Основне» також задаються логотип і акцентний колір чекаута.

2. Токен monobank

  1. Відкрийте web.monobank.ua → Еквайринг → API-токен і скопіюйте токен. Для тестів підійде тестовий токен з api.monobank.ua.
  2. У кабінеті Harno Pay перейдіть у вкладку «Оплата» і вставте токен. Він зберігається зашифрованим.
  3. У тій самій вкладці показано адресу webhook для monobank виду https://pay.harnopay.online/api/webhooks/mono/<id магазину>. Через неї monobank повідомляє нас про статус оплати.

Гроші надходять напряму на ваш рахунок monobank. Harno Pay не є еквайром і не тримає кошти.

3. Доставка

У вкладці «Доставка» задайте ціну доставки Новою Поштою та суму, від якої вона безкоштовна. Доставка за кордон налаштовується зонами: назва, список країн кодами ISO (наприклад, DE, PL) і ціна. Знак * означає всі інші доступні країни. Ціни доставки рахуються на сервері, покупець не може їх змінити.

4. Нова Пошта

У вкладці «Нова Пошта» вкажіть дані відправника:

  • ключ API з кабінету Нової Пошти;
  • місто й номер відділення відправки текстом;
  • телефон, вагу посилки за замовчуванням і опис вантажу;
  • хто платить за доставку і форму оплати.

Контрагента, контактну особу й довідники міста та відділення сервіс знаходить сам. У списку замовлень з доставкою на відділення з’явиться кнопка «Створити ТТН»: вона створює одержувача й накладну, показує номер і вартість. «Друк етикетки» відкриває PDF 100×100, ключ API при цьому не потрапляє в браузер. Статуси незавершених накладних оновлюються автоматично раз на 30 хвилин або кнопкою «Оновити статус».

Обмеження: одна вага на всю посилку, накладні лише «відділення → відділення», без накладеного платежу.

5. Shopify

Умови Shopify не дозволяють публічним застосункам з App Store обходити Shopify Checkout, тому підключення йде через custom app у вашому магазині.

  1. Shopify admin → Settings → Apps → Develop apps → Create app. Admin API scopes: read_products, write_draft_orders, write_orders, read_inventory. Встановіть застосунок і скопіюйте токен shpat_….
  2. У кабінеті Harno Pay, вкладка «Інтеграція»: оберіть Shopify, вкажіть домен my-store.myshopify.com і Admin API токен.
  3. Вставте скрипт у theme.liquid перед </body>:
theme.liquid
<script src="https://pay.harnopay.online/harno-shopify.js"
        data-shop="{{ shop.permanent_domain }}" defer></script>

Скрипт перехоплює кнопки оформлення й відправляє покупця на чекаут Harno Pay. Після оплати замовлення створюється у Shopify, а кошик очищується.

6. Універсальний API

Для будь-якого сайту. Сесію створює сервер магазину за секретним ключем: згенеруйте його у вкладці «Інтеграція» (тип «Універсальний API»). Ключ показується один раз, у базі зберігається лише його хеш. Створювати сесії з браузера не можна: CORS вимкнений, бо інакше ціни не перевірити.

POST /api/v1/sessions
curl -X POST https://pay.harnopay.online/api/v1/sessions \
  -H "Authorization: Bearer gp_..." \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "title": "Худі", "variantTitle": "Графіт / L",
        "sku": "HD-01-L", "price": 189900, "quantity": 1,
        "image": "https://..."
      }
    ],
    "reference": "order-1001",
    "returnUrl": "https://shop.example/thanks",
    "cancelUrl": "https://shop.example/cart"
  }'
Відповідь
201 Created
{ "id": "...", "url": "https://pay.harnopay.online/c/..." }

Перенаправте покупця на url. Валюта береться з налаштувань магазину (поки лише UAH).

Поля запиту
ПолеОпис
items[].titleНазва позиції. Обов’язково.
items[].variantTitle, sku, imageВаріант, артикул і посилання на зображення. Необов’язково.
items[].priceЦіна за одиницю в копійках, ціле число. 1 899,00 ₴ → 189900.
items[].quantityКількість, від 1 до 999.
referenceВаш ідентифікатор замовлення. Повернеться у webhook.
returnUrlКуди повернути покупця після оплати.
cancelUrlПосилання «до кошика» в шапці чекаута.

7. Webhook order.paid

Вкажіть адресу webhook у вкладці «Інтеграція» і створіть секрет підпису. Після оплати на цю адресу приходить POST з даними замовлення. Суми — цілі копійки.

Заголовки
POST /your/webhook
Content-Type: application/json
X-Harno-Timestamp: 1793793600
X-Harno-Signature: v1=5f2c…
X-Harno-Delivery: <id замовлення>
X-Harno-Attempt: 1
Тіло запиту
{
  "event": "order.paid",
  "id": "...",
  "number": 12,
  "reference": "order-1001",
  "currency": "UAH",
  "total": 259700,
  "shippingPrice": 7000,
  "lines": [
    { "title": "Худі", "variantTitle": "Графіт / L",
      "sku": "HD-01-L", "price": 189900, "quantity": 1 }
  ],
  "customer": { "firstName": "...", "lastName": "...",
                "phone": "+380...", "email": "..." },
  "delivery": { "method": "nova_poshta_warehouse",
                "price": 7000, "...": "..." },
  "paidAt": "2026-11-04T12:00:00.000Z"
}
Заголовки
ЗаголовокЗначення
X-Harno-TimestampЧас відправки в секундах (Unix). Відхиляйте запити, старші за кілька хвилин.
X-Harno-Signaturev1=<hex>: HMAC-SHA256 від рядка timestamp.body, ключ — секрет підпису з кабінету.
X-Harno-Deliveryid замовлення. За ним дедуплікуйте повторні доставки.
X-Harno-AttemptНомер спроби, починаючи з 1.

Повтори

Відповідь не 2xx, тайм-аут 10 секунд або мережева помилка — і ми повторюємо доставку з паузами 1 хв, 5 хв, 30 хв, 2 год, 6 год, 12 год і 24 год: усього 8 спроб, після останньої статус «Помилка». Статус, кількість спроб і час наступної видно в кабінеті, там же кнопка «Повторити webhook», яка скидає лічильник.

Доставка «щонайменше один раз»: той самий webhook може прийти повторно. Дедуплікуйте за id замовлення (він же в X-Harno-Delivery).

8. Перевірка підпису

Перевіряйте підпис за сирим тілом запиту, до парсингу JSON, і відхиляйте старі timestamp. Відповідайте 2xx, щойно прийняли замовлення.

Node.js
import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody, headers, secret) {
  const ts = headers["x-harno-timestamp"];
  const sig = (headers["x-harno-signature"] ?? "").replace(/^v1=/, "");
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const expected = createHmac("sha256", secret)
    .update(`${ts}.${rawBody}`)
    .digest("hex");
  return sig.length === expected.length &&
    timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

Залишились питання? Напишіть на [email protected].