Skip to content

ЮKassa

OPORA поддерживает полный lifecycle ЮKassa-платежа: создание, захват после авторизации (two-stage), отмена, refund’ы. Separate policy: payment.{read,write} + refund.{read,write} — refund’ы можно гейтить отдельно от обычных оплат (fraud-prevention).

За ~10 минут вы:

  1. Получите shop_id + secret_key в кабинете ЮKassa
  2. Сохраните их в OPORA
  3. Настроите webhook для событий жизненного цикла платежа
  4. Запустите workflow «incoming order → create payment → email’ом ссылку покупателю → webhook succeeded → записать в 1С»
  1. Откройте кабинет ЮKassa: https://yookassa.ru/my
  2. «Настройки»«Магазин»
  3. Раздел «Идентификатор магазина» → скопируйте shop_id (цифровой, например 123456)
  4. «Секретный ключ»«Выпустить ключ» → скопируйте (он показывается один раз, больше не появится; если потеряете — выпустите новый)

SettingsSecrets:

  • yookassa-shop-id: ваш shop_id
  • yookassa-secret-key: ваш secret_key

После создания workflow’а с yookassa.webhook.trigger нодой, OPORA покажет URL вида https://app.opora.example/webhook/<uuid>.

Зарегистрируйте его в ЮKassa:

  1. «Настройки»«HTTP-уведомления» или «Webhooks»
  2. «Добавить URL» → вставьте URL OPORA
  3. События: выберите нужные для вашего workflow’а:
    • payment.waiting_for_capture — двустадийная оплата, ждёт .capture
    • payment.succeeded — платёж прошёл (one-stage или .capture завершён)
    • payment.canceled — отменён вами или истёк
    • refund.succeeded — возврат прошёл
  4. Создайте токен валидации (ЮKassa даёт query-param ?<token> в URL; задайте тот же в настройках trigger-ноды OPORA).

4. Workflow пример: order → payment → succeeded

Section titled “4. Workflow пример: order → payment → succeeded”
webhook.trigger (generic, from вашего frontend'а)
{order_id, amount, customer_email}
yookassa.payment.create
amount = {{trigger.amount}}
description = "Заказ #{{trigger.order_id}}"
metadata = {order_id: "{{trigger.order_id}}"}
return_url = "https://your-shop.ru/payment-return?order={{trigger.order_id}}"
email.send
to = {{trigger.customer_email}}
subject = "Ссылка на оплату заказа #{{trigger.order_id}}"
textBody = "Перейдите: {{payment.create.confirmation.confirmation_url}}"

Параллельно — второй агент на события:

yookassa.webhook.trigger (event: payment.succeeded)
data_table.rows.update
table = "orders"
filter = {order_id: {{trigger.object.metadata.order_id}}}
patch = {payment_status: "paid", payment_id: {{trigger.object.id}}}
onec.odata.create
entity = "Document_Реализация"
data = {Номер: {{trigger.object.metadata.order_id}}, ...}
НодаЧто делаетPolicy
yookassa.webhook.triggerIncoming events (payment / refund lifecycle)
yookassa.payment.createСоздание платежа (one-stage или two-stage)payment.write
yookassa.payment.getСтатус платежа по idpayment.read
yookassa.payment.captureЗахват после авторизации (two-stage)payment.write
yookassa.payment.cancelОтменаpayment.write
yookassa.refund.createВозвратrefund.write
yookassa.refund.getСтатус возвратаrefund.read

Policy-split: refund’ы отдельно

Section titled “Policy-split: refund’ы отдельно”

Policy-разделение позволяет дать одному агенту право создавать платежи (payment.write) но не возвращать (refund.write) — типовая fraud-ловушка, когда скомпрометированный workflow массово refund’ит всё подряд.

В editor’е: открыть ноду yookassa.refund.create → секция «Policies» → выбрать existing refund-policy или создать новую с нужным approval-gate’ом (например, refund > 10000₽ требует approval’а space-owner’а).

Для двустадийной оплаты (товар списывается со счёта клиента после фактической отгрузки, а не в момент клика):

  1. yookassa.payment.create с capture: false → возвращает payment’а в статусе waiting_for_capture
  2. Webhook event payment.waiting_for_capture → ваш workflow решает, захватывать ли
  3. yookassa.payment.capture с amount равным или меньше исходного (частичный захват возможен; remainder возвращается клиенту)

Срок хранения резерва — 7 дней; не захватил — ЮKassa автоматически отменит.

Для платежей через СБП-QR (Система Быстрых Платежей) ЮKassa принимает payment_method_data: {type: "sbp"} при создании платежа. confirmation.confirmation_data вернёт base64-encoded SVG QR’а и deeplink для мобильного банка покупателя.

OPORA не декодирует QR сам — просто прокидывает в output для frontend’а, который его рендерит.

Invalid Credentials при создании платежа

Section titled “Invalid Credentials при создании платежа”
  • shop_id / secret_key спутаны (легко — оба цифро-буквенные). Сверьте с кабинетом ЮKassa.
  • Магазин в test-mode’е, а key боевой (или наоборот). ЮKassa различает prod / test через префикс key’а.
  • IP-whitelist ЮKassa блокирует исходящие запросы с IP’ов, отличных от их списка. Убедитесь что ваш webhook-URL открыт наружу и Caddy/nginx пропускает запросы без auth’а (webhook-path должен быть public).
  • В кабинете ЮKassa: Настройки → HTTP-уведомления → Логи — там видно, что отправлено и с каким статусом.

Refund нельзя сделать больше исходного amount’а. Проверьте refund.create нода получает правильный payment_id + amount не превышает доступный остаток.

Клиент ушёл с платёжной страницы, не завершив 3DS. Через 15 минут статус сменится на canceled автоматически (webhook придёт).

ЮKassa — российский оператор, соответствует 152-ФЗ и ЦБ’шным требованиям. OPORA хранит только metadata (payment id, amount, status, ваши custom metadata) — реквизиты карты клиента никогда не проходят через control plane, всё идёт напрямую между клиентом и ЮKassa.

  • T-Банк / T-Kassa — альтернатива с SBP-QR из коробки и single-source acquirer (карта + СБП + split)
  • Bitrix24 — часто в связке: оплата прошла → обновить сделку в CRM