E-commerce

Криптоплатежи для магазинов цифровых товаров

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

У магазина лицензионных ключей, игровых аккаунтов, файлов или доступов необычное свойство: товар выдаётся в момент поступления денег, без участия человека. Именно поэтому крипта ему подходит, и именно поэтому детали платёжной схемы важны. В материале разберём, что меняется, как привязать выдачу к статусу платежа и какие ошибки стоят магазинам остатков.

Почему цифровые товары и крипта подходят друг другу

Три свойства цифровых товаров совпадают с тем, как работают криптоплатежи:

  • Выдача мгновенная, значит и оплата должна быть такой же. Покупатель, который ждёт ключ, не хочет ждать банковского зачисления. Криптоплатёж становится окончательным после подтверждения сетью, и ваша система может выдавать товар сразу.
  • Аудитория уже здесь. Покупатели ключей, игровых предметов, VPN, хостинга и похожих товаров нередко держат стейблкоины и предпочитают платить ими, в том числе клиенты из стран, где карты вашего рынка не работают.
  • Нет карточных чарджбэков. Криптоперевод отправитель отменить не может. Для магазина, которого уже обжигали оспоренные карточные платежи за дешёвые мгновенные товары, это ощутимая разница. Но и возврат становится вашим решением и вашим переводом, поэтому правило возврата нужно написать до запуска.

Цены остаются простыми: вы задаёте цену в долларах США, а покупатель платит эквивалент в том активе и сети, которые выберет на странице оплаты.

Путь от корзины до выданного товара

Путь одного заказа выглядит так:

  1. Покупатель добавляет товар и указывает email (или входит в аккаунт).
  2. На шаге оплаты выбирает «Оплатить криптой». Ваш сервер создаёт платёж под заказ и получает ссылку на страницу оплаты.
  3. Вы перенаправляете покупателя на эту страницу. Он выбирает актив и сеть и платит точную сумму из своего кошелька.
  4. Когда платёж завершён, шлюз вызывает ваш webhook.
  5. Ваш сервер помечает заказ оплаченным, берёт ключ или открывает доступ и отправляет его по email и на странице заказа.

Магазин не генерирует адреса, не следит за блокчейном и не сверяет суммы. Он делает две вещи: создаёт платёж и реагирует на финальный статус. Пошаговая версия с кодом есть в материале как принимать криптоплатежи на сайте.

Создавайте платёж со своим номером заказа

Платёж создаётся с вашего бэкенда одним POST на https://api.qvard.com/api/v1/payment. В запросе ваш ключ в заголовке Authorization: Bearer и JSON с номером заказа в поле id, ценой price в долларах США и, при желании, paymentSystemId, если страница должна открываться с выбранным активом и сетью. В ответ приходит 201 и redirectUrl.

Берите номер заказа, который существует в вашей системе раньше платежа, по одному на покупку. Если запрос завис и вы повторили его с тем же id для того же способа оплаты, вы получите уже созданный платёж, а не второй, поэтому повторы безопасны.

Создавайте платёж после нажатия «Оплатить», а не при сборке корзины. Иначе брошенные корзины превратятся в гору неоплаченных платежей.

Выдавайте только при полной оплате и только один раз

Это правило защищает ваши остатки. У платежа четыре статуса: wait (создан), partial (клиент отправил меньше нужного), completed (вся сумма поступила) и rejected. Qvard вызывает ваш webhook, когда платёж завершён, и передаёт отправленный вами id и status.

Из этого два требования к обработчику:

  • Действуйте только по completed. Никогда не выдавайте ключ из-за того, что покупатель вернулся на сайт, и никогда при частичной сумме. Доказательство оплаты даёт webhook, а не браузер.
  • Будьте идемпотентны. Webhook повторяется, пока ваша точка не ответит ровно HTTP 200 (пять попыток примерно за шесть минут), и повтор может прийти уже после успешной первой доставки. Выдачу ключа и отметку «доставлено» делайте в одной транзакции базы и пропускайте уже выданные заказы. Иначе один платёж обойдётся вам в два ключа.

Проверяйте заголовок X-Qvard-Signature в каждом webhook: сверяйте HMAC-SHA256 подпись вашим секретным ключом за постоянное время и отклоняйте несовпадения. Подробнее в материале как защитить webhook криптоплатежей.

Node.jsdeliver.js
// Called from the Qvard webhook handler after the X-Qvard-Signature check.
async function onQvardEvent({ id, status }) {
  const order = await db.orders.findById(id);
  if (!order) return;                          // unknown order: ignore

  if (status !== 'completed') return;          // deliver only on a full payment
  if (order.deliveredAt) return;               // the webhook can arrive twice

  // One transaction: take a key and mark the order, so a retry cannot take a second key.
  await db.transaction(async (tx) => {
    const key = await tx.licenseKeys.takeFree(order.productId);
    await tx.orders.update(order.id, { state: 'paid', deliveredAt: new Date(), keyId: key.id });
    await mailer.send(order.email, 'Your purchase', 'Key: ' + key.value);
  });
}

Показывайте покупателю, что происходит

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

  • у каждого заказа должна быть страница с текущим статусом: ждём оплату, оплачен и выдан, либо проблема;
  • пока статус «ожидание», страница должна обновляться сама, чтобы ключ появился без перезагрузки;
  • отправляйте ключ ещё и на email: вкладки закрывают, а письмо потом ищут;
  • если заказ ещё не помечен оплаченным, скажите об этом прямо и попросите не платить повторно.

Большинство обращений в магазинах цифровых товаров звучат как «заплатил и ничего не получил». Страница статуса и письмо снимают их лучше всего.

Недоплата и просроченные заказы

Крипто-клиенты иногда отправляют чуть меньше нужного, потому что комиссию вывода с биржи вычли из суммы, или платят позже, чем планировали. Решите заранее, что с этим делать.

  • Частичная оплата. Статус partial. Не выдавайте товар. Обычно либо оставляют заказ открытым и просят доплатить, либо возвращают деньги и отменяют заказ. Выберите один вариант и сообщите клиенту на странице заказа.
  • Курс и время. Курс на странице оплаты фиксируется на один час, поэтому сумма не меняется, пока клиент платит. Держите остаток под заказ не меньше этого времени и освобождайте его, если заказ так и не оплачен.
  • Ограниченный остаток. Если остался один ключ, резервируйте его при создании платежа и снимайте резерв по истечении, иначе двое покупателей оплатят один и тот же ключ.

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

Что сказать покупателям

Понятная страница оплаты конвертирует лучше умной. Рядом с кнопкой напишите:

  • какие активы и сети вы принимаете (см. поддерживаемые монеты) и что платить нужно в той сети, которую клиент выбрал на странице оплаты;
  • что выдача автоматическая после завершения платежа и где появится ключ;
  • правило возврата одним предложением, так как криптоплатёж клиент отменить не может.

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

Что в Qvard готово сегодня, а что нет

Трезво оцените, с чем вы интегрируетесь. Qvard работает через API: магазин создаёт платёж и принимает webhook. Готового плагина для платформ магазинов пока нет, платёжные ссылки и отдельный sandbox в разработке, а после оплаты клиент возвращается на сайт самостоятельно. Для магазина с разработчиком или часом работы фрилансера это небольшой кусок кода. Смотрите документацию для разработчиков и обзор интеграций, а демо-счёт покажет, что увидит ваш клиент.

По деньгам: средства лежат на вашем балансе в Qvard, вы выводите их на свой кошелёк, вывод стоит только сетевую комиссию, абонентской платы нет. Вывода на банковский счёт в фиате нет.

FAQ

Можно ли выдавать товар автоматически после криптоплатежа?

Да. Qvard вызывает ваш webhook, когда платёж завершён, и ваш сервер берёт ключ или открывает доступ и отправляет клиенту. Выдавайте только по статусу completed и делайте обработчик безопасным для повторного запуска.

Что будет, если клиент отправил меньше полной суммы?

Платёж получит статус partial, а webhook о завершении не придёт. Товар не выдавайте. Попросите клиента доплатить или верните ему деньги, как велит ваше правило.

Бывают ли чарджбэки при криптоплатежах?

Нет. Криптоперевод отправитель отменить не может. Это защищает от оспоренных карточных платежей, но возвраты вы отправляете сами, поэтому заранее определите правило возврата.

Можно ли задавать цены в долларах?

Да, цена задаётся в долларах США. Клиент платит эквивалент в активе и сети, которые выберет на странице оплаты, по курсу, зафиксированному на один час.

Есть ли плагин для моей платформы магазина?

Пока нет. Сейчас интеграция идёт через API: один запрос на создание платежа и один webhook для получения результата.

Похожие статьи

Похожие статьи