Интеграция

Интеграции ломаются на колбэках

Не потому что это сложно, а потому что пропускают три вещи. Вот они, в том порядке, в каком дают о себе знать.

  1. 01
    Проверьте подпись

    Каждый колбэк несет подпись, посчитанную по сырому телу запроса вашим секретным ключом. Посчитайте ее сами и сравните за постоянное время. Не совпало — ответьте 400 и ничего не меняйте: на публичный адрес может постучаться кто угодно.

    // Считаем по сырому телу, до любого разбора JSON.
    const expected = crypto
      .createHmac('sha256', process.env.MP_SECRET)
      .update(rawBody)
      .digest('hex');
    
    if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))) {
      return res.status(400).end();
    }
  2. 02
    Будьте идемпотентны

    Одно и то же уведомление может прийти дважды, и рано или поздно придет. Опирайтесь на идентификатор платежа, а не на факт входящего запроса. Двойная обработка не должна дважды отгрузить заказ или дважды вернуть деньги.

    const already = await orders.findPayment(body.id);
    if (already?.status === body.status) return res.status(200).end();
  3. 03
    Отвечайте быстро, работайте потом

    Ответьте 200, как только сохранили факт. Медленную работу делайте после. Если ответить поздно или с ошибкой, мы повторим доставку с растущими интервалами, и медленный обработчик превратит один платеж в очередь дублей.

Подтвердите перед отгрузкой

Колбэк говорит, что что-то изменилось. Перед выдачей товара прочитайте платеж через API и действуйте по этому ответу. Это один запрос, который убирает целый класс мошенничества.

Точное имя заголовка, алгоритм и расписание повторов описаны в спецификации, которая выдается вместе с ключами, чтобы эта страница никогда не разошлась с тем, что реально отправляет шлюз.