Перейти к основному содержимому
Getly

Меню команд

Перейти на страницу или искать в каталоге

Как доставлять заказы через вебхук sale.completed

Зарегистрируйте HTTPS-эндпоинт, проверьте заголовок X-Getly-Signature-V2, прочитайте buyerEmail и items из sale.completed и доставьте заказ ровно один раз.

6 мин. чтения
1 116 слов
Как доставлять заказы через вебхук sale.completed

Некоторые товары не могут быть файлом в загрузке: аккаунт в вашем сервисе, место на курсовой платформе, которую вы ведёте, лицензия, которую проверяет ваша собственная программа. Для таких случаев Getly сообщает вашему серверу о завершённой продаже в ту же секунду, а доставку делает ваш сервер. Это сообщение и есть вебхук sale.completed.

С 26 сентября 2026 года он важнее, чем раньше. Платный листинг, всё содержимое которого это обещание прислать товар позже на почту, теперь уходит на проверку вместо публикации, если только доставка не автоматизирована так, что Getly может это проверить: ключи Getly, ваш собственный пул ключей или работающий вебхук sale.completed. Эта инструкция разбирает третий путь от начала до конца. По замеру 26 сентября 2026 года ключи Getly используются в 0,11% активных листингов, собственный пул ключей в 0,10%; если всё, что вы отдаёте, это ключ, эти два пути проще сервера. Вебхук нужен, когда доставку может сделать только ваша система.

Шаг 1: зарегистрируйте эндпоинт

  1. В дашборде откройте Разработчик, затем Вебхуки, и нажмите Добавить эндпоинт.
  2. URL эндпоинта: публичный адрес https на вашем сервере. Обычный http, localhost и адреса частных сетей отклоняются.
  3. Магазин: магазин, продажи которого должен получать этот эндпоинт.
  4. События: отметьте именно Продажа завершена. Есть ещё Все события, но проверка, которая пускает в продажу листинги с доставкой на почту, ищет подписку на sale.completed по имени, поэтому отметьте событие явно.
  5. Нажмите Зарегистрировать эндпоинт.

Появится блок Сохраните секрет подписи сейчас. Секрет показывается только один раз. Скопируйте его в окружение сервера (в примерах ниже он называется GETLY_WEBHOOK_SECRET). Если потом редактировать эндпоинт, секрет сохранится; если удалить его и создать новый, секрет будет новым, и сервер будет отклонять доставки, пока вы его не обновите.

Шаг 2: что приходит

Каждая доставка это POST с JSON-телом и тремя заголовками: X-Getly-Event (имя события), X-Getly-Signature-V2 и старый X-Getly-Signature. Тело sale.completed выглядит так:

{
  "deliveryId": "uuid",
  "event": "sale.completed",
  "data": {
    "orderId": "uuid",
    "buyerId": "uuid",
    "buyerEmail": "[email protected]",
    "items": [
      {
        "orderItemId": "uuid",
        "productId": "uuid",
        "price": 2999,
        "sellerAmount": 2399,
        "isGift": false,
        "licenseKey": null
      }
    ],
    "total": 2999
  },
  "timestamp": "2026-10-11T09:00:00.000Z"
}

Что стоит знать до первой строки кода:

  • Суммы в центах: 2999 это $29.99.
  • Одна доставка охватывает ваши позиции в одном заказе. Если в корзине товары нескольких магазинов, каждый магазин получает только свои строки, а total это их сумма.
  • В items может быть больше одного товара. Проходите по всему массиву, а не читайте только первый элемент.
  • buyerEmail это адрес, с которым покупатель платил, тот же, что вы и так видите в разделе покупателей. Когда isGift равно true, это всё равно адрес дарителя; адрес получателя не передаётся, поэтому подарочную позицию отправляйте покупателю.
  • licenseKey содержит ключ, выданный для позиции, если листинг использует ключи Getly или ваш пул ключей, и null в остальных случаях или пока ключ ждёт, когда вы пополните пул.
  • Продажи через ссылку на оплату несут ещё checkoutLinkId, reference и metadata, чтобы платёж можно было сопоставить с тем, что создало ссылку.

Шаг 3: проверьте подпись

Отправить POST на ваш адрес может кто угодно. Подпись это способ убедиться, что этот запрос отправил Getly. Заголовок выглядит как t=1760173200,v1=5f2c...: t это Unix-время в секундах, а v1 это HMAC-SHA256 в hex от строки из t, точки и сырого тела запроса, с вашим секретом подписи в качестве ключа.

Две детали ломают большинство первых попыток. Первая: подписывается сырое тело ровно в том виде, в каком оно пришло. Если распарсить JSON и сериализовать снова, могут измениться пробелы или порядок ключей, и подпись перестанет совпадать. Вторая: отклоняйте старые метки времени. Рекомендуемое окно пять минут, оно не даёт кому-то позже повторить перехваченную доставку.

Вот полный обработчик для Node.js с Express:

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

const app = express();
const SECRET = process.env.GETLY_WEBHOOK_SECRET;
const TOLERANCE_SECONDS = 300;

function verifyGetly(rawBody, header) {
  if (!header) return false;
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const t = Number(parts.t);
  if (!Number.isFinite(t) || !parts.v1) return false;
  if (Math.abs(Date.now() / 1000 - t) > TOLERANCE_SECONDS) return false;
  const expected = crypto.createHmac('sha256', SECRET).update(`${t}.${rawBody}`).digest('hex');
  const a = Buffer.from(expected, 'hex');
  const b = Buffer.from(parts.v1, 'hex');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

// express.raw keeps the body as bytes, exactly as Getly signed it.
app.post('/getly/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
  const raw = req.body.toString('utf8');
  if (!verifyGetly(raw, req.get('X-Getly-Signature-V2'))) {
    return res.status(401).send('invalid signature');
  }

  const { event, data } = JSON.parse(raw);
  if (event !== 'sale.completed') return res.sendStatus(200); // includes the dashboard "test" event

  for (const item of data.items) {
    if (await alreadyDelivered(item.orderItemId)) continue;   // your database
    await deliver({                                           // your system
      email: data.buyerEmail,
      productId: item.productId,
      licenseKey: item.licenseKey,
    });
    await markDelivered(item.orderItemId);
  }

  res.sendStatus(200);
});

app.listen(3000);

alreadyDelivered, deliver и markDelivered пишете вы: таблица с ключом по orderItemId и то, что на вашей стороне создаёт аккаунт или отправляет письмо.

Шаг 4: отвечайте быстро и доставляйте ровно один раз

Getly ждёт ответа 2xx 10 секунд. Всё остальное считается неудачей: 4xx или 5xx, таймаут и редирект тоже, потому что доставки не следуют редиректам. Указывайте конечный адрес, а не тот, что перенаправляет на другой.

Неудачная доставка повторяется с растущими паузами: примерно через 1 минуту, потом через 5 минут, 30 минут и 2 часа. После пятой попытки она помечается как неудачная. Из-за повторов обработчик выше и опирается на orderItemId. Если сервер доставил, но ответил слишком медленно, тот же заказ придёт снова, и без проверки покупатель получит два аккаунта или два письма. orderItemId не меняется между попытками, а timestamp и подпись меняются. Если сама доставка занимает дольше нескольких секунд, запишите заказ, ответьте 200 и сделайте медленную работу в фоновой задаче.

Шаг 5: проверьте до того, как на это полагаться

На карточке эндпоинта нажмите Тест. Getly отправит подписанное событие с именем test и коротким сообщением в data, а уведомление покажет, вернул ли сервер 2xx; если нет, в уведомлении будет начало ответа сервера или ошибка соединения, и это самый быстрый способ понять причину. Логи показывают последние доставки: событие, код ответа сервера и число попыток.

Тестовые покупки из песочницы продавца вебхуки не отправляют: они изолированы от всего, что касается внешних систем. Подпись и ответ проверяйте кнопкой Тест, а код доставки настоящим недорогим листингом.

Следите за здоровьем эндпоинта. Исключение для листингов с доставкой на почту теряется при доказанно плохой истории: три и больше доставок за 30 дней, из которых меньше 90% получили ответ 2xx. Неудачные тестовые доставки на тот же эндпоинт тоже считаются, так что сначала почините эндпоинт, а потом нажимайте «Тест».

Что сделать сегодня

Зарегистрируйте эндпоинт с отмеченным событием Продажа завершена, сохраните секрет, разверните обработчик выше со своей функцией deliver и нажимайте Тест, пока уведомление не скажет, что доставка прошла. Потом откройте описание листинга и прямо напишите, что покупатель получит и когда, например «аккаунт создаётся на почту, с которой вы платите, в течение минуты после оплаты». Работу делает вебхук, а описание это то, что покупатель читает до оплаты.

Готовы начать продавать?

Независимый маркетплейс для цифровых авторов. Получайте 80–90% с каждой продажи. Принимаем карты и стейблкоины.