Skip to content

Руководство по настройке QryptoPay

QryptoPay — это self-hosted криптоэквайринг для автоматического приёма платежей в криптовалюте на вашем сайте. Модуль позволяет быстро интегрировать оплату: вы сможете автоматически формировать ссылки на оплату, отправлять их клиентам и принимать средства напрямую на свои личные криптокошельки.

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

Что нужно, чтобы начать

QryptoPay является модулем панели управления BeAdmin. Для корректной работы сервиса потребуется:

  • сервер с установленной панелью BeAdmin (см. руководство по установке);
  • доменное имя, направленное на этот сервер (например, qpay.mysite.com).

⚠️ Важно

Доменное имя используется как адрес платёжной страницы, на которую будут перенаправляться клиенты для совершения оплаты. Эта страница работает на том же сервере, где установлен QryptoPay. Если доменное имя отсутствует, его можно добавить позже.

Шаг 1. Установка модуля

Для корректной работы QryptoPay необходимо установить следующие модули:

  • DOCKER — обязателен, так как QryptoPay работает на основе docker-контейнеров;
  • NGINX — может быть установлен позже, однако без него невозможно запустить платёжную страницу.

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

После успешной установки всех зависимостей вернитесь в модуль QryptoPay и запустите установку самого модуля.

Шаг 2. Создание магазина

После успешной установки QryptoPay создайте магазин. Для этого нажмите кнопку Создать и укажите любое удобное название (при необходимости его можно изменить позже).

Если модуль NGINX уже установлен и у вас есть домен для платёжной страницы, в разделе дополнительных параметров можно указать этот домен — в таком случае платёжная страница будет создана автоматически вместе с магазином.

После создания магазина вы сможете перейти к его дальнейшей настройке.

Каждый магазин включает в себя следующие компоненты:

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

ℹ️ Примечание

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

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

Шаг 3. Настройка интеграции

Ключевой элемент интеграции — терминал. У каждого терминала есть следующие параметры:

  • ID — уникальный идентификатор;
  • Пара токенов — публичный и приватный (используются для идентификации платежей);
  • Вебхук — URL-адрес вашего проекта, на который QryptoPay отправляет уведомления о статусах платежей;
  • Ключ для вебхука — используется для авторизации уведомлений на вебхуке.

⚠️ Важно

Приватный токен необходимо хранить в надёжном месте. Если он будет скомпрометирован, злоумышленники могут нарушить логику обработки ваших платежей. Поэтому после генерации QryptoPay не хранит приватный токен на своей стороне.

В случае утери или компрометации вы можете сгенерировать новую пару токенов — не забудьте обновить значения на стороне вашего проекта.

Ключ для вебхука менее критичен, но также рекомендуется не раскрывать его третьим лицам, чтобы исключить подделку уведомлений на вебхук.

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

Сначала сгенерируйте пару токенов для тестового терминала и сохраните у себя приватный токен.

В настройках вашего проекта сохраните параметры терминала в переменных окружения. Например, файл .env может выглядеть так:

TERMINAL_ID: <ID терминала>
PRIVATE_TOKEN: <сгенерированный приватный токен>
WEBHOOK_KEY: <ключ для вебхука из настроек>
PAYMENT_URL: <домен платежной страницы>

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

Ниже приведён пример реализации такого метода на псевдокоде:

function generate_payment_token(private_key_b64, terminal_uuid) -> string
  # декодируем приватный ключ из base64/base64url в seed (сырые байты)
  seed := decode_base64_any(private_key_b64)

  # генерируем уникальный nonce (обычно uuid4)
  nonce := uuid_v4()

  # собираем payload (обязательные поля + данные платежа)
  payload := {
    timestamp: current_unix_time_seconds(),
    nonce: nonce,
    terminal_uuid: terminal_uuid,     // ID терминала в QryptoPay

    amount_fiat: transaction.amount,  // сумма к оплате в USD, в формате 00.00, decimal, больше 0
    payment_mid: transaction.uuid,    // ID транзакции внутри вашего проекта, string
    back_to_store_link: link,         // ссылка на ваш сайт, чтобы клиент мог вернуться после оплаты (можно добавить параметры если нужно), string

    customer: {
      id: customer.uuid,              // ID клиента из вашей системы (обязательно), string
      email: customer.email or ""     // email клиента из вашей системы (опционально), string
    },

    metadata: {                       // любые другие параметры, которые вы хотите передать
      key: value                      // в формате metadata.key=value
    }
  }

  # сериализуем payload в детерминированное (каноничное) представление байт
  payload_bytes := canonical_encode(payload)

  # кодируем payload в безопасный для передачи формат
  payload_part := base64url_no_padding(payload_bytes)

  # рассчитываем криптографическую часть токена на основе приватного ключа и payload_part
  proof_bytes := sign(seed, bytes(payload_part, ASCII))

  # кодируем криптографическую часть токена
  proof_part := base64url_no_padding(proof_bytes)

  # итоговый формат ключа: "<payload_b64u>.<proof_b64u>"
  return payload_part + "." + proof_part
end

⚠️ Важно

Для генерации токена оплаты, помимо данных транзакции, необходимо передать три обязательных параметра: текущую временную метку, nonce (рекомендуется uuid4) и ID терминала.

Временная метка используется для расчёта срока жизни ссылки (чуть больше 1 часа). Nonce нужен для безопасности и предотвращает создание нескольких платёжных намерений по одной ссылке (защита от спама). Без ID терминала QryptoPay не сможет обработать платёж.

Используя полученный токен, выполните POST-запрос в QryptoPay, чтобы получить платёжную ссылку. Например:

POST /public/api/payments/intents/create/
Host: qpay.yoursite.com
Content-Type: application/json

{
  "key": "токен оплаты"
}

⚠️ Важно

На момент выполнения запроса платёжная страница должна быть уже создана на сервере, где установлен QryptoPay.

В случае успешного выполнения запроса вы получите ответ с платёжной ссылкой. Эту ссылку необходимо передать клиенту для перехода к оплате.

{
  "service_id": "be535ba0-7f84-4cd3-9454-b26c4a938479",
  "url": "https://qpay.yoursite.com/?payment=be535ba0-7f84-4cd3-9454-b26c4a979225",
  "expires_at": "2026-01-30T08:21:56.526112Z"
}

В случае ошибки сервер может вернуть один из следующих кодов:

  • 400 — некорректный запрос (ошибка формата или отсутствуют обязательные параметры).
  • 403 — неверная подпись запроса или токен оплаты истёк.
  • 409 — повторное использование одноразового токена. Переданный nonce уже использовался для данного терминала.
  • 444 — временный запрет на создание платёжного намерения (например, из-за ограничений лицензии или превышения лимитов).
  • 445 — создание платёжных намерений запрещено — лицензия исчерпана или доступ ограничен на постоянной основе.
  • 500 — внутренняя ошибка сервера.

⚠️ Важно

Если клиент перешёл по платёжной ссылке, выбрал валюту и начал процесс оплаты (нажал кнопку Продолжить), изменить выбранную валюту он уже не сможет. В этом случае клиенту необходимо вернуться на ваш сайт и сформировать новую ссылку на оплату. Такое поведение реализовано в целях безопасности.

⚠️ Важно

Если вы передаёте email клиента в payload на сторону QryptoPay, и в дальнейшем email клиента изменится, при следующем платеже QryptoPay найдёт клиента по ID и, в случае несовпадения email, перезапишет его. Обновлённый email будет применён также и к ранее созданным платежам.

Общий алгоритм генерации платёжной ссылки выглядит следующим образом:

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

После этого клиент совершает платёж на платёжной странице и при необходимости возвращается в магазин. Уведомление об успешном или неуспешном платеже поступит на ваш проект с задержкой, так как транзакции в блокчейне должны дождаться подтверждений сети. Обычно это занимает от 1–2 минут (Tron, USDT TRC-20) до 10–30 минут (Bitcoin).

Теперь вы можете сформировать платёжную ссылку, перейти по ней, выбрать валюту и нажать кнопку оплаты. Если всё настроено корректно, платёж отобразится в вашем магазине QryptoPay в тестовом терминале.

Шаг 4. Настройка вебхука

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

Уведомление отправляется HTTP-запросом со следующими параметрами:

POST /your/webhook/url
Content-Type: application/json

X-Term-UUID: 2671f44b-a025-44d3-b2f1-a0ea07b8acb7
X-Timestamp: 1738150000
X-Body-SHA256: 9c4d2b0a2f5b7d6c8a...   # 64 hex символа
X-Signature: 7f1c3d5e9a...             # 64 hex символа

{
  ... JSON-тело уведомления ...
}

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

function validate_webhook_response() -> bool
  # собираем сообщение для HMAC: "<terminal_uuid>:<ts>:<body_sha256_hex>"
  message_str := string(term_uuid_header) + ":" + string(ts) + ":" + computed_body_hash
  message_bytes := utf8_bytes(message_str)

  # вычисляем ожидаемую подпись: HMAC-SHA256(secret, message), hex
  expected_sig := hmac_sha256_hex(key = utf8_bytes(secret), msg = message_bytes)

  # сравниваем подпись в постоянное время
  if not constant_time_equals(expected_sig, sig_header) then
    return false
  end

  return true
end

⚠️ Важно

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

  • отсутствует любой из обязательных заголовков;
  • X-Term-UUID не совпадает с ID терминала, который использовался при генерации токена оплаты для этой транзакции;
  • X-Timestamp не является числом (int) или с момента указанной временной метки прошло более 300 секунд (рекомендуемое значение).

Если проверка прошла успешно, вы можете десериализовать тело запроса. В результате вы получите объект примерно следующего вида:

{
  "payment_result": payment_result,   // результат платежа: success, mismatch, unexpected
  "amount_coins": str(coins),         // сумма в криптовалюте, формат 00.00
  "amount_fiat": str(amount_usd),     // сумма в USD, формат 00.00
  "fiat_code": "USD",                 // фиатная валюта
  "coins_asset": "USDC",              // криптовалюта: BTC, ETH, USDT, USDC и т.д.
  "coins_chain": "ETH",               // сеть: BTC, ETH, TRX и т.д.
  "service_id": "qryptopay_pi_uuid",  // внутренний идентификатор платежа в QryptoPay
  "payment_mid": "string",            // ID транзакции в вашем проекте, null если статус unexpected
  "customer": {
    "id": "your_id",                  // ID клиента в вашей системе
    "email": "string"                 // email клиента, null если не был передан
  }
  "metadata": {                       // null если не передана изначально или статус unexpected
    "key1": value1,
  },
  "transaction_ids": [                // связанные транзакции в блокччейне (одна или несколько)
    "686...fbe",
    "8be...6ab"
  ]
}

⚠️ Важно

Если валидация прошла успешно, верните в ответ 200 OK. Иначе QryptoPay будет повторно отправлять уведомления о платеже до тех пор, пока не получит ответ 200.

Полученные данные можно использовать для постобработки платежа. Часть параметров возвращается в исходном виде — например, все значения metadata, переданные через платёжную ссылку.

⚠️ Важно

Если в QryptoPay уже сохранён email клиента, но в очередном платеже email не передан, в уведомлении на вебхук будет указан email из базы QryptoPay.

💡 Совет

Рекомендуем дополнительно валидировать данные из вебхука, сопоставляя их с исходными параметрами транзакции (например, сумму, ID платежа и ID клиента).

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

  • success — оплата прошла успешно. В этом случае рекомендуется сверить значение amount_fiat, полученное в уведомлении, с вашей внутренней суммой перед финализацией платежа;
  • mismatch — клиент недоплатил или переплатил указанную сумму;
  • unexpected — клиент перевёл средства на кошелёк без предварительного формирования платёжной ссылки.

Логику обработки каждого сценария вы можете определить самостоятельно. Например, в случае mismatch можно сравнить сумму из уведомления с ожидаемой суммой и, если оплата была неполной, уведомить клиента о необходимости доплаты. В случае unexpected возможен вариант автоматического пополнения баланса клиента с последующим уведомлением о платеже.

После реализации обработчика заполните поле вебхука в настройках тестового терминала и повторите процесс оплаты — сформируйте новую ссылку и перейдите по ней. Для тестового терминала платёж обрабатывается сразу, а уведомление моментально отправляется на вебхук.

Если уведомление успешно получено на стороне вашего проекта, тестовую интеграцию можно считать завершённой.

Шаг 5. Настройка кошельков

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

Подробная инструкция по добавлению и настройке кошельков доступна по ссылке.

Шаг 6. Настройка основного терминала

После добавления кошельков вы можете перевести сайт на работу с основным терминалом. Для этого выполните следующие действия:

  • сгенерируйте новую пару токенов для основного терминала;
  • отредактируйте настройки терминала и укажите адрес вебхука;
  • замените в файле .env вашего проекта значения ID, PRIVATE_TOKEN и WEBHOOK_KEY на данные из основного терминала.

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

Если все настройки выполнены корректно, платёж будет успешно зачислен в вашем проекте.

BeAdmin © 2025. Все права защищены.