---
metadata:
  - name: generator
    content: Diplodoc Platform v5.52.0
alternate:
  - https://pay.yandex.ru/docs/ru/qr-code/api.md
  - href: ru/qr-code/api.md
    type: text/markdown
    title: Markdown version
  - href: ../llms.txt
    type: text/markdown
    title: llms.txt
---
> **Documentation Index:** Fetch the complete configuration index at https://pay.yandex.ru/docs/ru/llms.txt

# Самостоятельная интеграция

**QR‑код от Яндекс Пэй со Сплитом** — сервис для оплаты покупок через СБП и частями в Сплит с помощью статического или динамического QR-кода.

Статический QR-код размещается в офлайн-магазине у кассы в виде специальной таблички, которую выдает Яндекс. Динамический QR-код можно отобразить на экране.

Покупатели могут проводить оплату по QR-коду:

- через СБП в любом банковском приложении;
- частями в Сплит через сервисы Яндекса (только для авторизованных пользователей).

Для интеграции с QR‑код от Яндекс Пэй со Сплитом вы можете использовать готовые решения из [списка поддерживаемых](https://pay.yandex.ru/docs/ru/qr-code/index.md#payment-methods) кассовых ПО или настроить интеграцию самостоятельно через [Cash Register API](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/index.md).

Интеграция доступна для кассового ПО и касс самообслуживания (КСО).

## Подключение сервиса {#connection}

### Шаг 1. Регистрация и подача заявки {#registration}

1. [Зарегистрируйтесь](https://pay.yandex.ru/docs/ru/console/registration.md) в [личном кабинете](https://console.pay.yandex.ru/onboarding?type=OnboardingSplitTypePayBox&utm_medium=le) Яндекс Пэй.

1. [Подайте заявку](https://pay.yandex.ru/docs/ru/console/registration.md#product-qr) на подключение сервиса QR‑код от Яндекс Пэй.

   {% note warning "Важно" %}

   В поле **Кассовое ПО** выберите значение **Другое**.

   {% endnote %}

### Шаг 2. Заполнение реестра обмена информацией {#registry}

1. После подачи заявки предоставьте данные о ваших кассах и магазинах — заполните и отправьте менеджеру интеграции [реестр для обмена информацией о магазинах](https://doc-static.yandex.net/src/docs/pay/Shablon-Reestr-dlya-obmena-informatsiei-o-magazinakh-cash-register.xlsx).

   {% cut "**Какие данные необходимо заполнить**" %}

   - **merchant_id** — [Merchant ID](#merchant-id) из [личного кабинета](https://console.pay.yandex.ru/) Яндекс Пэй — идентификатор бренда или направления, к которому будет привязан магазин;
   - **partner_alias** — ИНН организации;
   - **name** — название магазина;
   - **branch_id** — уникальный код магазина в вашей системе;
   - **offline_pos_legal_address** — фактический адрес магазина (только для офлайн-магазинов);
   - **tmid** — идентификатор кассы или терминала, на которые будет крепиться физически QR-табличка;
   - **contact_phone** — контактный телефон ответственного лица в магазине;
   - **QRID** (заполняет Яндекс) — идентификатор QR-кода, напечатанный на QR-табличке, которая будет наклеена на кассе.

   {% endcut %}

1. На основании данных реестра Яндекс доставит QR-таблички в указанные магазины.
1. Менеджер интеграции отправит вам обновленный реестр.

### Шаг 3. Привязка QR-кода {#link-qr}

После того как вы получите QR-таблички и обновленный реестр, привяжите QR-коды в двух местах:

{% list tabs %}

- В личном кабинете

  <!-- source: ru/_includes/cash-registers.md -->
  1. Перейдите в раздел **Настройки** → **Привязать QR-код**. Проверьте, что в селекторе выбран нужный магазин.
  1. В открывшемся окне укажите ID-номер QR-кода, который указан на табличке, и нажмите кнопку **Привязать**.

  При необходимости вы можете заказать дополнительные QR-коды. Управлять выпущенными QR-кодами можно в настройке **Ваши QR-коды**.
  <!-- endsource: ru/_includes/cash-registers.md -->

  {% note info %}

  Если у вас много QR-кодов, обратитесь к менеджеру интеграции, он привяжет их согласно [реестру для обмена информацией о магазинах](#registry).

  {% endnote %}

- В кассовом ПО

  1. С помощью метода [/v1/accounts](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/QR-tablichki/getAccounts.md) получите список идентификаторов `QRID` и `QRCID` для QR-табличек.

  2. Укажите идентификатор `QRCID` в вашем кассовом ПО для каждой кассы согласно обновленному реестру.

{% endlist %}

### Шаг 4. Получение параметров интеграции {#parameters}

Для интеграции вам обязательно понадобятся два токена:

- [Токен для кассового ПО](#token)
- [Ключ Merchant API](#merchant-api-keys) (API-ключ)

Дополнительно вам понадобятся:

- [Merchant ID](#merchant-id) для идентификации магазина.
- [Callback URL](#callback-settings) для получения нотификаций о статусе платежей — [/webhook](https://pay.yandex.ru/docs/ru/custom/backend/merchant-api/webhook.md). Если получение нотификаций невозможно, используйте поллинг.

#### Получение токена для кассового ПО {#token}

Получите токен у менеджера интеграции.

Используйте для [аутентификации запросов](#auth).

#### Выпуск API-ключа {#merchant-api-keys}

{% note info %}

Если эта настройка у вас не отображается, обратитесь к своему менеджеру интеграции.

{% endnote %}

<!-- source: ru/_includes/integration-params.md -->
Для работы в боевой среде необходимо выпустить собственный API-ключ в личном кабинете Яндекс Пэй:

1. Проверьте, что в селекторе выбран нужный магазин, и перейдите в раздел [Настройки](https://console.pay.yandex.ru/settings) → **Выпустить ключ Merchant API**.
1. В открывшемся окне отобразится API-ключ. Скопируйте и сохраните его.

   {% note tip %}

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

   {% endnote %}

1. Если ранее вы использовали другой API-ключ для тестирования или работы, в коде бэкенда магазина замените текущий API-ключ на новый.

Если вы потеряете или забудете API-ключ, его нужно будет выпустить повторно. Для выпуска ключа в настройках нажмите **Ключ Merchant API** → **Выпустить еще ключ**. Одновременно для магазина можно выпустить не более трех API-ключей.
<!-- endsource: ru/_includes/integration-params.md -->

Используйте для [аутентификации запросов](#auth).

#### Merchant ID {#merchant-id}

Merchant ID — это уникальный идентификатор вашего магазина в системе Яндекс Пэй. Для одного юридического лица создается один магазин с Merchant ID и [API-ключом](#merchant-api-keys).

<!-- source: ru/_includes/integration-params.md -->
Чтобы узнать уникальный Merchant ID магазина, выберите в селекторе нужный магазин и перейдите в раздел **Настройки** → **Merchant ID**.
<!-- endsource: ru/_includes/integration-params.md -->

{% note info %}

Все ваши QR-коды привязываются к одному Merchant ID, а не к торговым точкам.

{% endnote %}

Реализуйте на своей стороне связь **Торговая точка** ⇔ **Касса** ⇔ **QR-код** и при [создании заказа](#create-order) передавайте информацию об отдельных торговых точках в поле `extensions.billingReport.branchId`.

#### Установка Callback URL {#callback-settings}

{% note info %}

Если эта настройка у вас не отображается, обратитесь к своему менеджеру интеграции.

{% endnote %}

<!-- source: ru/_includes/integration-params.md -->
1. Перейдите в раздел [Настройки](https://console.pay.yandex.ru/settings) → **Добавить Callback URL**.
1. В открывшемся окне укажите публично доступный HTTPS URL-адрес бэкенда магазина, для которого вы настраиваете интеграцию, и нажмите кнопку **Сохранить**.
<!-- endsource: ru/_includes/integration-params.md -->

<!-- source: ru/_includes/integration-params.md -->
Указывайте Callback URL без `/v1/webhook` — этот путь добавится автоматически, например:

 #|
|| **Callback URL** | **Куда придет запрос** ||
|| `https://example.merchant.ru` | `https://example.merchant.ru/v1/webhook` ||
|| `https://example.merchant.ru/v1/webhook` | `https://example.merchant.ru/v1/webhook/v1/webhook` ||
|#

URL-адрес для тестового и рабочего окружения может отличаться, например:

 #|
|| **Тип окружения** | **Callback URL** ||
|| Рабочее (Production) | `https://example.merchant.ru` ||
|| Тестовое (Testing) | `https://sandbox.example.merchant.ru` ||
|#
<!-- endsource: ru/_includes/integration-params.md -->

### Шаг 5. Подключение оплаты в Сплит (опционально) {#split}

{% note warning %}

<!-- source: ru/_includes/split-fz-283.md -->
В соответствии с Федеральным законом № 283‑ФЗ «О деятельности по предоставлению сервиса рассрочки» при использовании сервиса Сплит договор о предоставлении сервиса рассрочки с пользователем обязательно должен содержать сведения об объекте рассрочки — товарах, работах, услугах или результатах интеллектуальной деятельности, оплачиваемых в Сплит.
<!-- endsource: ru/_includes/split-fz-283.md -->

Поэтому в [запросе на создание заказа](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/index.md) обязательно передавайте данные всех объектов рассрочки в корзине в параметре `cart.items`.

{% endnote %}

<!-- source: ru/_includes/qr-split.md -->
1. В личном кабинете Яндекс Пэй перейдите в раздел **Настройки** → **Дополнительные сервисы**.
1. Включите опцию **Оплата частями в Сплит**.
1. Ознакомьтесь с тарифом и условиями сервиса Яндекс Пэй для партнеров и нажмите кнопку **Отлично, давайте**. Обратите внимание, что тариф вознаграждения за услуги сервиса изменится.   

После этого покупатели смогут оплачивать покупки вашем магазине в Сплит.

##### **Отключение оплаты в Сплит** {#split-off}

Чтобы отключить оплату в Сплит с помощью QR‑кода от Яндекс Пэй, отключите опцию **Оплата частями в Сплит** в настройках магазина.
<!-- endsource: ru/_includes/qr-split.md -->

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

Изучите [как работает Cash Register API](#how-to), реализуйте и [протестируйте](#testing) все сценарии.

## Как это работает? {#how-to}

{% note tip %}

Вы можете скачать OpenAPI-спецификацию в разделе [Specification](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/index.md#specification).

{% endnote %}

### Схема проведения оплаты {#scheme}

{% note tip %}

Чтобы открыть схему на весь экран, перейдите в режим чтения с помощью кнопки ![](../console/_assets/btn-read-mode.svg) в правом верхнем углу страницы.

{% endnote %}

{% list tabs %}

- Бизнес-процесс

  ![Бизнес-процесс](./_assets/api-scheme-bpmn.png)

- Диаграмма последовательности

  ![Диаграмма последовательности](./_assets/api-scheme-sequence.png){width=600}

{% endlist %}

Изучите [глоссарий](#glossary) и настройте кассовое ПО так, чтобы поддерживались следующие операции:

- [Аутентификация запросов](#auth)
- [Оформление заказа](#create-order) с помощью статического или динамического QR
- [Деактивация (прерывание оплаты)](#deactivate)
- [Возврат](#refund)
- [Получение нотификаций](#webhook)

### Глоссарий {#glossary}

При работе с API важно понимать разницу между заказом, корзиной, позициями и товарами:

```json
{
  "orderId": "order-123",              // ← ЗАКАЗ — запрос на оплату
  "cart": {                            // ← КОРЗИНА — контейнер для позиций
    "items": [                         // ← Массив ПОЗИЦИЙ КОРЗИНЫ
      {                                // ← ПОЗИЦИЯ #1
        "productId": "id-1",           // ← Идентификатор ТОВАРА
        "title": "Шариковая ручка",    // ← Название ТОВАРА
        "quantity": {
          "count": "3"                 // ← Количество ТОВАРА
        },
        "unitPrice": "3.33",           // ← Цена за ЕДИНИЦУ ТОВАРА
        "total": "10"                  // ← Сумма ПОЗИЦИИ
      }
    ],
    "total": {
      "amount": "10"                   // ← Сумма КОРЗИНЫ: 10₽
    }
  }
}
```

- **Заказ** — запрос на оплату с уникальным `orderId`.
- **Корзина** — набор позиций для оплаты — `cart`.
- **Позиция корзины** — элемент массива `items[]` с информацией о товаре.
- **Товар** — продукт, который описывается в позиции (ручка, мясо, услуга).
- **Единица** — одна штука, килограмм, литр товара.
- **Количество** — сколько единиц товара в позиции — `quantity.count`.
- **Цена за единицу** — стоимость одной единицы — `unitPrice`.
- **Сумма позиции** — итоговая стоимость одной позиции в корзине — `items[i].total`. Может не быть равна `quantity.count * unitPrice`.
- **Сумма корзины** — общая стоимость всех позиций в корзине — `cart.total.amount`.

### Аутентификация запросов {#auth}

В каждом запросе передавайте в HTTP-заголовки:

 #|
|| `YandexPayApiKey` | Заголовок: `Authorization: Api-Key <ключ>`.

Выпустите его [личном кабинете](https://console.pay.yandex.ru/settings) по [инструкции](#merchant-api-keys). ||
|| `SoftwareAuthorization` | Заголовок: `Software-Authorization: <ключ>`.

Токен кассового ПО. Получите его в личном кабинете или у менеджера интеграции. ||
|#

Если в запросе отсутствуют или переданы недействительные токены, сервер вернет статус `401 Unauthorized`.

**Пример запроса:**

```bash
curl https://pay.yandex.ru/api/merchant/cash-register/v1/accounts \
  --header 'Authorization: Api-Key <YandexPayApiKey>' \
  --header 'Software-Authorization: <SoftwareAuthorization>' \
```

### Оформление заказа {#create-order}

1. Покупатель формирует корзину.
1. Кассир фиксирует корзину в кассовом ПО.
1. Кассир выбирает способ оплаты **Яндекс Пэй**.
1. Кассовое ПО передает заказ в бэкенд Яндекс Пэй одним из методов:

   - для **статического QR**: [/orders](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/createOrder.md)

   - для **динамического QR**: [/orders/dynamic](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/createDynamicOrder.md)

     с параметрами:

     #|
     || `qrcId` | Обязателен только для **статического QR**.

     Идентификатор зарегистрированного в СБП QR-кода. Его можно получить с помощью метода [/accounts](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/QR-tablichki/getAccounts.md). ||
     || `cart` | Корзина.

     Если в корзине есть позиции с нецелыми ценами (3 ручки за 10 рублей) или весовые товары (500 г. говядины), **для всех позиций в корзине** добавьте цену за единицу товара `unitPrice`. Это избавит от проблем с округлением, например, при [возврате](#refund). ||
     || `currencyCode` | Трехбуквенный код валюты (ISO 4217). ||
     || `orderId` | ID заказа в системе продавца. ||
     || `extensions.billingReport` | Информация о торговой точке и кассире.

     Реализуйте на своей стороне связь **Торговая точка** ⇔ **Касса** ⇔ **QR-код** и передавайте в этом параметре. ||
     |#

1. Бэкенд Яндекс Пэй создает заказ:

   - для **статического QR**: связывает заказ с полученным в запросе QR-кодом;

   - для **динамического QR**: генерирует уникальный QR-код для заказа.

1. В обоих случаях бэкенд Яндекс Пэй возвращает поле `paymentUrl` с уникальной ссылкой на оплату.

   Отобразите эту ссылку в виде QR-кода на экране или распечатайте.

1. Кассир просит покупателя отсканировать:

   - для **статического QR**: QR-табличку;

   - для **динамического QR**: QR-код на экране или в чеке.

1. Покупатель сканирует QR-код, открывает страницу оплаты, выбирает способ оплаты и подтверждает платеж.
1. Кассовое ПО отслеживает статус заказа.

   Основной способ получения информации об изменении заказа — нотификации [/webhook](https://pay.yandex.ru/docs/ru/custom/backend/merchant-api/webhook.md). Если получение нотификаций невозможно, используйте поллинг.

   {% list tabs %}

   - Нотификации

     Если у вас настроены [нотификации](#webhook), то после завершения оплаты Яндекс Пэй отправит событие `ORDER_STATUS_UPDATED` — обновлен статус заказа.

     Проверьте поле `paymentStatus`:

      #|
     || `CAPTURED` | Оплата прошла успешно. Фискализируйте чек. Терминальный успешный статус. ||
     || `FAILED` | Оплата не прошла или при проведении оплаты произошла ошибка. Пересоздайте заказ методом [/orders](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/createOrder.md) или [/orders/dynamic](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/createDynamicOrder.md). Терминальный неуспешный статус. ||
     |#

   - Поллинг

     Через 5–10 секунд после создания заказа начните опрашивать статус заказа методом [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md).

     Проверьте поле `paymentStatus`:

     #|
     || `PENDING` | Оплата в процессе. Запросите статус позже или дождитесь нотификации. ||
     || `CAPTURED` | Оплата прошла успешно. Фискализируйте чек. Терминальный успешный статус. ||
     || `FAILED` | Оплата не прошла или при проведении оплаты произошла ошибка. Пересоздайте заказ методом [/orders](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/createOrder.md) или [/orders/dynamic](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/createDynamicOrder.md). Терминальный неуспешный статус. ||
     |#

   {% endlist %}

   {% note info %}

   Не забудьте фискализировать оплату на кассе в соответствии с [Федеральным законом № 54-ФЗ](https://www.nalog.gov.ru/rn77/about_fts/docs/3909988/).

   {% endnote %}

### Деактивация (прерывание оплаты) {#deactivate}

1. Перед деактивацией кассовое ПО вызывает метод [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md) и проверяет поле `paymentStatus`.

   Деактивация доступна только для заказов в статусе `PENDING`. Если оплата уже прошла, вернется ошибка `ORDER_ALREADY_CAPTURED`. В таком случае [проведите возврат](#refund).

1. Кассовое ПО вызывает метод [/orders/{orderId}/deactivate](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/deactivateOrder.md) и передает `externalOperationId` — уникальный идентификатор операции. По нему можно узнать статус операции и он служит токеном идемпотентности.

1. В результате QR-код будет деактивирован, а заказ перейдет в статус `FAILED`.

   Если у вас настроены [нотификации](#webhook), Яндекс Пэй отправит событие `ORDER_STATUS_UPDATED` — обновлен статус заказа.

### Возврат {#refund}

1. Перед оформлением возврата кассовое ПО вызывает метод [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md) и проверяет поле `paymentStatus`.

   Возврат доступен только для заказов в статусе `CAPTURED` или `PARTIALLY_REFUNDED`.

1. Кассир формирует чек возврата в кассовом ПО.
1. Кассовое ПО вызывает метод [/orders/{orderId}/refund](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/refundOrder.md) с параметрами:

    #|
   || `externalOperationId` | Уникальный идентификатор операции на стороне продавца.

   По нему можно узнать статус операции и он служит токеном идемпотентности. ||
   || `refundAmount` | Сумма к возврату. ||
   || `refundCart` | Корзина возвращаемых позиций. Обязательна для частичного возврата.

   Формат зависит от [вида логики возвратов](#refund-logics). ||
   |#

1. Кассовое ПО отслеживает статус операции возврата.

   Основной способ получения информации об изменении заказа — нотификации [/webhook](https://pay.yandex.ru/docs/ru/custom/backend/merchant-api/webhook.md). Если получение нотификаций невозможно, используйте поллинг.

   {% list tabs %}

   - Нотификации

     Если у вас настроены [нотификации](#webhook), Яндекс Пэй отправит два события:

     - `ORDER_STATUS_UPDATED` — обновлен статус заказа;
     - `OPERATION_STATUS_UPDATED` — обновлен статус операции возврата.

     В нотификации `OPERATION_STATUS_UPDATED` проверьте статус операции `status`:

     #|
     || `SUCCESS` | Операция возврата запущена успешно. Фискализируйте чек возврата. ||
     || `FAIL` | Операция возврата не запущена. Повторно инициируйте возврат методом [/orders/{orderId}/refund](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/refundOrder.md). ||
     |#

     Если возврат прошел успешно, заказ перейдет в статус `PARTIALLY_REFUNDED` или `REFUNDED`.

   - Поллинг

     Начните опрашивать статус заказа методом [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md). Найдите нужную операцию по `externalOperationId` и проверяйте ее статус `status`:

     #|
     || `PENDING` | Операция возврата не завершена. Запросите статус позже или дождитесь нотификации. ||
     || `SUCCESS` | Операция возврата запущена успешно. Фискализируйте чек возврата. ||
     || `FAIL` | Операция возврата не запущена. Повторно инициируйте возврат методом [/orders/{orderId}/refund](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/refundOrder.md). ||
     |#

     Если возврат прошел успешно, заказ перейдет в статус `PARTIALLY_REFUNDED` или `REFUNDED`.

   {% endlist %}

#### Две логики возвратов {#refund-logics}

Cash Register API поддерживает две логики работы с возвратами. Логика определяется при [создании заказа](#create-order) по наличию в позициях корзины `cart` цены за единицу товара `unitPrice`.

{% note warning "Ограничения" %}

Если заказ уже создан, логика не может быть изменена.

Нельзя смешивать логики в одном заказе.

{% endnote %}

Различия проявляются при **частичных возвратах** — когда в `refundCart` указываются конкретные позиции для возврата.

 #|
|| **Виды логики** | **Базовая** | **Расширенная** ||
|| **Когда использовать** | В корзине только позиции с целыми ценами | В корзине есть позиции с нецелыми ценами, весовые товары ||
|| **Как включить** | В `CartItem` не указывать `unitPrice` | В `CartItem` указать `unitPrice` ||
|| **Какие поля**
**указывать в `refundCart`** |

Одно из двух:

- `quantityCount` — количество единиц товара для возврата;
- `price` — на сколько уменьшить цену за единицу товара.

|

- `quantityCount` или `price`;
- `total` — точная сумма возврата за позицию.

  Сумма возврата `refundAmount` должна быть равна сумме всех `total` в `refundCart.items`.

||
|| **Сумма возврата** | Считается автоматически, могут быть проблемы с округлением | Вы указываете точную сумму в `total` ||
|| **Пример создания заказа**

|

10 ручек за 50 рублей,

5 рублей каждая:

```json
{
  "productId": "id-1",
  "title": "Шариковая ручка",
  "total": "50",
  "quantity": {
    "count": "10"
  }
}
```

|

3 ручки за 10 рублей,

3.33 рубля каждая:

```json
{
  "productId": "id-1",
  "title": "Шариковая ручка",
  "total": "10",
  "quantity": {
    "count": "3"
  },
  "unitPrice": "3.33"
}
```

||
|| **Пример возврата**

|

Вернуть 2 ручки:

```json
{
  "refundCart": {
    "items": [
      {
        "productId": "id-1",
        "quantityCount": "2"
      }
    ]
  },
  "refundAmount": "10"
}
```

|

Вернуть 1 ручку:

```json
{
  "refundCart": {
    "items": [
      {
        "productId": "id-1",
        "quantityCount": "1",
        "total": "3.33"
      }
    ]
  },
  "refundAmount": "3.33"
}
```

||
|#

Больше примеров возвратов см. на странице метода [Вернуть деньги за заказ](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/refundOrder.md).

### Получение нотификаций {#webhook}

Основной способ получения информации об изменении заказа — нотификации [/webhook](https://pay.yandex.ru/docs/ru/custom/backend/merchant-api/webhook.md).

Бэкенд Яндекс Пэй отправляет нотификации со следующими событиями:

- `ORDER_STATUS_UPDATED` — обновлен статус заказа;
- `OPERATION_STATUS_UPDATED` — обновлен статус операции.

Чтобы получать нотификации:

1. В личном кабинете Яндекс Пэй установите [Callback URL](#callback-settings).

1. Настройте ваш бэкенд для приема POST-запроса [/webhook](https://pay.yandex.ru/docs/ru/custom/backend/merchant-api/webhook.md) от бэкенда Яндекс Пэй.

Примеры нотификаций см. на странице метода [/webhook](https://pay.yandex.ru/docs/ru/custom/backend/merchant-api/webhook.md).

### Оформление заказа в кассе самообслуживания {#self-checkout}

Процесс аналогичен [оформлению заказа](#create-order) в кассовом ПО со следующим отличием:

1. После создания заказа методы [/orders](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/createOrder.md) и [/orders/dynamic](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/createDynamicOrder.md) возвращают поле `paymentUrl` с уникальной ссылкой на оплату.
2. Отобразите эту ссылку на экране КСО в виде QR-кода.

### Тестирование {#testing}

<!-- source: ru/_includes/testing-qr-api.md -->
Для тестирования Cash Register API доступна sandbox-среда, которая позволяет проверить интеграцию без реальных платежей. В ней все методы API работают так же, как в боевой среде.

**Особенности sandbox:**

- Тестовые ключи отличаются от боевых.
- Базовый URL: `https://sandbox.pay.yandex.ru/api/merchant/cash-register`.
- Включена автоматическая оплата — после создания заказа оплата происходит автоматически, переходить по `paymentUrl` не требуется.

#### Настройка тестовой среды в личном кабинете {#sandbox-settings}

1.  В [личном кабинете](https://console.pay.yandex.ru/settings) откройте раздел **Настройки**.

1.  Включите опцию **Тестовая среда**.

    ![Настройки sandbox](../_assets/test-qr-settings.png){.c-screenshot width=400}

1.  В разделе **Тестирование в Sandbox** скопируйте тестовые ключи и используйте их для [аутентификации запросов](https://pay.yandex.ru/docs/ru/qr-code/api.md#auth):
    - **YandexPayApiKey** — в заголовке `Authorization: Api-Key <ключ>`;
    - **SoftwareAuthorization** — в заголовке `Software-Authorization: <ключ>`.

1.  Настройте [Callback URL](https://pay.yandex.ru/docs/ru/qr-code/api.md#callback-settings) для получения [нотификаций](https://pay.yandex.ru/docs/ru/qr-code/api.md#webhook) о статусе заказа и операций.

1.  Вы также можете посмотреть тестовые платежи в личном кабинете. Подробнее см. в разделе [Просмотр тестовых платежей](https://pay.yandex.ru/docs/ru/testing.md#test-payments).

#### Оформление заказа с помощью статического QR-кода {#test-static-qr}

1.  Получите `qrcId` методом [/accounts](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/QR-tablichki/getAccounts.md).

1.  Создайте заказ методом [/orders](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/createOrder.md) с одной из тестовых сумм для эмуляции результатов оплаты.

    {% cut "Тестовые суммы" %}

    #|
    || **Сумма** | **Результат** ||
    || 10 000 | Успешная оплата через СБП, карту или в Сплит.

    Статус платежа: `paymentStatus: "CAPTURED"`.

    Статус операции: `operationType: "AUTHORIZE"`, `status: "SUCCESS"`. ||

    || 10 001 | Техническая ошибка.

    Статус платежа: `paymentStatus: "FAILED"`, `reason: "WRONG_ENVIRONMENT"`.

    Статус операции: `operationType: "AUTHORIZE"`, `status: "FAIL"`. ||
    || 10 002 | Недостаточно средств.

    Статус платежа: `paymentStatus: "FAILED"`, `reason: "NOT_ENOUGH_FUNDS"`.

    Статус операции: `operationType: "AUTHORIZE"`, `status: "FAIL"`. ||
    || 10 004 | Вечный статус `PENDING`. Используйте для проверки поллинга и деактивации статического QR-кода.

    Статус платежа: `paymentStatus: "PENDING"` — заказ остается в этом статусе до деактивации.

    Статус операции: `operationType: "AUTHORIZE"`, `status: "PENDING"`. ||
    |#

    {% endcut %}

    Для отображения Сплита в способах оплаты передайте `availablePaymentMethods: ["CARD", "SPLIT"]`.

1.  Яндекс Пэй вернет поле `paymentUrl` с уникальной ссылкой на оплату.

    В sandbox оплата произойдет автоматически — переходить по ссылке не требуется.

    В боевой среде перейдите по ссылке и оплатите заказ через СБП, карту или в Сплит.

1.  Проверьте статус заказа одним из способов:

    - Нотификации (рекомендуется) — дождитесь нотификации [/webhook](https://pay.yandex.ru/docs/ru/custom/backend/merchant-api/webhook.md) с событием `ORDER_STATUS_UPDATED`.

    - Поллинг — опрашивайте статус методом [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md). Первый запрос через 5–10 секунд после создания заказа, далее не чаще раза в секунду.

    Ожидаемый результат см. в столбце **Результат** в таблице тестовых сумм.

#### Оформление заказа с помощью динамического QR-кода {#test-dynamic-qr}

1.  Создайте заказ методом [/orders/dynamic](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/createDynamicOrder.md) с одной из тестовых сумм для эмуляции результатов оплаты. Получать `qrcId` не требуется — QR-код генерируется автоматически.

    {% cut "Тестовые суммы" %}

    #|
    || **Сумма** | **Результат** ||
    || 10 000 | Успешная оплата через СБП, карту или в Сплит.

    Статус платежа: `paymentStatus: "CAPTURED"`.

    Статус операции: `operationType: "AUTHORIZE"`, `status: "SUCCESS"`. ||

    || 10 001 | Техническая ошибка.

    Статус платежа: `paymentStatus: "FAILED"`, `reason: "WRONG_ENVIRONMENT"`.

    Статус операции: `operationType: "AUTHORIZE"`, `status: "FAIL"`. ||
    || 10 002 | Недостаточно средств.

    Статус платежа: `paymentStatus: "FAILED"`, `reason: "NOT_ENOUGH_FUNDS"`.

    Статус операции: `operationType: "AUTHORIZE"`, `status: "FAIL"`. ||
    || 10 004 | Вечный статус `PENDING`. Используйте для проверки поллинга и деактивации статического QR-кода.

    Статус платежа: `paymentStatus: "PENDING"` — заказ остается в этом статусе до деактивации.

    Статус операции: `operationType: "AUTHORIZE"`, `status: "PENDING"`. ||
    |#

    {% endcut %}

    Для отображения Сплита в способах оплаты передайте `availablePaymentMethods: ["CARD", "SPLIT"]`.

1.  Яндекс Пэй вернет поле `paymentUrl` с уникальной ссылкой на оплату.

    В sandbox оплата произойдет автоматически — переходить по ссылке не требуется.

    В боевой среде перейдите по ссылке и оплатите заказ через СБП, карту или в Сплит.

1.  Проверьте статус заказа одним из способов:

    - Нотификации (рекомендуется) — дождитесь нотификации [/webhook](https://pay.yandex.ru/docs/ru/custom/backend/merchant-api/webhook.md) с событием `ORDER_STATUS_UPDATED`.

    - Поллинг — опрашивайте статус методом [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md). Первый запрос через 5–10 секунд после создания заказа, далее не чаще раза в секунду.

    Ожидаемый результат см. в столбце **Результат** в таблице тестовых сумм.

#### Поллинг и деактивация (прерывание оплаты) {#test-polling-deactivate}

Деактивация доступна только для статических QR-кодов.

1. Получите `qrcId` методом [/accounts](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/QR-tablichki/getAccounts.md).

1. Создайте заказ методом [/orders](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/createOrder.md) на сумму **10 004 рубля**.

1. Деактивация доступна только для заказов в статусе `paymentStatus: "PENDING"`.

   Проверьте статус заказа методом [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md).

1. Настройте поллинг:
   - Первый запрос — через 5–10 секунд после создания заказа.

   - Последующие запросы — не чаще одного раза в секунду.

1. Убедитесь, что заказ остается в статусе `paymentStatus: "PENDING"` и деактивируйте его методом [/orders/{orderId}/deactivate](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/deactivateOrder.md).

1. Проверьте статусы:
   - операции: `operationType: "AUTHORIZE"`, `status: "FAIL"`;
   - заказа: `paymentStatus: "FAILED"`, `reason: "Payment rolled back by merchant"`.

#### Полный возврат {#test-full-refund}

1. Создайте и оплатите заказ на сумму **10 000 рублей** с помощью [статического](#test-static-qr) или [динамического QR-кода](#test-dynamic-qr).

1. Возврат доступен только для заказов в статусе `paymentStatus: "CAPTURED"` или `paymentStatus: "PARTIALLY_REFUNDED"`.

   Проверьте статус заказа методом [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md).

1. Выполните полный возврат методом [/orders/{orderId}/refund](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/refundOrder.md) с параметрами:
   - `externalOperationId` — уникальный идентификатор операции на стороне продавца. По нему можно узнать статус операции и он служит токеном идемпотентности.
   - `refundAmount` — сумма к возврату. Для полного возврата укажите сумму заказа (**10 000 рублей**).
   - `refundCart` — корзина возвращаемых позиций. Для полного возврата можно не указывать.

1. Проверьте статус операции возврата одним из способов:

   - Нотификации (рекомендуется) — дождитесь нотификации [/webhook](https://pay.yandex.ru/docs/ru/custom/backend/merchant-api/webhook.md) с событием `OPERATION_STATUS_UPDATED`.

   - Поллинг — опрашивайте статус методом [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md). Первый запрос через 5–10 секунд после создания заказа, далее не чаще раза в секунду. Находите нужную операцию по `externalOperationId`, который вы передали в [/orders/{orderId}/refund](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/refundOrder.md).

   Ожидаемый результат: `operationType: "REFUND"`, `status: "SUCCESS"`.

1. Проверьте статус заказа одним из способов:

   - Нотификации (рекомендуется) — дождитесь нотификации [/webhook](https://pay.yandex.ru/docs/ru/custom/backend/merchant-api/webhook.md) с событием `ORDER_STATUS_UPDATED`.

   - Поллинг — опрашивайте статус методом [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md). Первый запрос через 5–10 секунд после создания заказа, далее не чаще раза в секунду.

   Ожидаемый результат: `paymentStatus: "REFUNDED"`.

#### Частичный возврат {#test-partial-refund}

1. Создайте и оплатите заказ с несколькими позициями на сумму **10 000 рублей** с помощью [статического](#test-static-qr) или [динамического QR-кода](#test-dynamic-qr).

   При формировании корзины используйте [одну из логик](https://pay.yandex.ru/docs/ru/qr-code/api.md#refund-logics): **базовую** без цены за единицу товара `CartItem.unitPrice` или **расширенную** — с `CartItem.unitPrice`.

   От корзины при создании заказа зависит будущая логика возврата.

1. Возврат доступен только для заказов в статусе `paymentStatus: "CAPTURED"` или `paymentStatus: "PARTIALLY_REFUNDED"`.

   Проверьте статус заказа методом [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md).

1. Выполните частичный возврат методом [/orders/{orderId}/refund](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/refundOrder.md) с параметрами:
   - `externalOperationId` — уникальный идентификатор операции на стороне продавца. По нему можно узнать статус операции и он служит токеном идемпотентности.
   - `refundAmount` — сумма к возврату.
   - `refundCart` — корзина возвращаемых позиций. Обязательна для частичного возврата.

     Формат `refundCart` зависит от логики возвратов. Подробнее см. в разделах [Две логики возвратов](https://pay.yandex.ru/docs/ru/qr-code/api.md#refund-logics) и [Примеры возвратов](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/refundOrder.md#refund-examples).

1. Проверьте статус операции возврата одним из способов:

   - Нотификации (рекомендуется) — дождитесь нотификации [/webhook](https://pay.yandex.ru/docs/ru/custom/backend/merchant-api/webhook.md) с событием `OPERATION_STATUS_UPDATED`.

   - Поллинг — опрашивайте статус методом [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md). Первый запрос через 5–10 секунд после создания заказа, далее не чаще раза в секунду. Находите нужную операцию по `externalOperationId`, который вы передали в [/orders/{orderId}/refund](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/refundOrder.md).

   Ожидаемый результат: `operationType: "REFUND"`, `status: "SUCCESS"`.

1. Проверьте статус заказа одним из способов:

   - Нотификации (рекомендуется) — дождитесь нотификации [/webhook](https://pay.yandex.ru/docs/ru/custom/backend/merchant-api/webhook.md) с событием `ORDER_STATUS_UPDATED`.

   - Поллинг — опрашивайте статус методом [/orders/{orderId}](https://pay.yandex.ru/docs/ru/custom/backend/cash-register/Zakazy/getOrder.md). Первый запрос через 5–10 секунд после создания заказа, далее не чаще раза в секунду.

   Ожидаемый результат: `paymentStatus: "PARTIALLY_REFUNDED"`.
<!-- endsource: ru/_includes/testing-qr-api.md -->

## Закрывающие документы {#reports}

Ежедневные и ежемесячные отчеты можно получать тремя способами:

- по email — используется по умолчанию, отчеты будут отправляться на указанные адреса почты;
- по SFTP-протоколу — отчеты будут отправляться в папку на SFTP-сервере партнера;
- в S3-хранилище — отчеты будут отправляться в бакет в S3-хранилище партнера.

Подробнее читайте в разделе [Отчетность](https://pay.yandex.ru/docs/ru/reports.md).
