/v2/orders/{order_id}/refund

Запрос на возврат средств за заказ.

Доступно только для платежей в статусе CAPTURED и PARTIALLY_REFUNDED. В случае успешного выполнения запроса изменится статус платежа:

  • на REFUNDED, если был произведен полный возврат;
  • на PARTIALLY_REFUNDED, если после совершения возврата в заказе остались ещё товары.

Метод является асинхронным.

Узнать результат возврата можно через механизм событий или вызов метода состояния операции. Событие OPERATION_STATUS_UPDATED будет отправлено как в случае успеха, так и при возникновении ошибки в процессе совершения возврата.

Для выполнения полного возврата достаточно передать refundAmount, равный сумме заказа.

Для выполнения частичного возврата дополнительно нужно передать итоговую корзину предоставляемых товаров и услуг. Сформировать итоговую корзину можно одним из способов:

  • передать целевое состояние корзины после выполнения возврата с помощью поля targetCart. Если это поле не указано, то считается, что корзина возвращается полностью.

    Поле targetShipping применимо только к Yandex Pay Checkout. В остальных случаях следует оставить это поле пустым. Если это поле не указано, то считается, что стоимость доставки возвращается полностью.

  • передать данные о товарах, подлежащих возврату, с помошью поля refundCart: в поле укажите, сколько единиц товара нужно вернуть или на какую сумму следует уменьшить стоимость товара. Если поле не указано, возврат осуществляется на всю корзину.

    Примечание

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

Примеры вызовов

Рассмотрим на примере заказа с orderId = Order-123 и следующей корзиной:

{
    "items": [
        {
            "productId": "id-1",
            "price": "50",
            "title": "Шариковая ручка",
            "quantity": {
                "count": "10"
            },
        },
        {
            "productId": "id-2",
            "price": "200",
            "title": "Блокнот",
            "quantity": {
                "count": "2"
            },
        }
    ]
}

Пример полного возврата

http POST https://sandbox.pay.yandex.ru/api/merchant/v2/orders/Order-123/refund \
        "Authorization: Api-Key ${API_KEY}" 'refundAmount:="900.00"'

Примеры частичного возврата

Возврат единиц товара

Допустим, необходимо вернуть две шариковые ручки. Это делается следующим запросом:

http POST https://sandbox.pay.yandex.ru/api/merchant/v2/orders/Order-123/refund \
  "Authorization: Api-Key ${API_KEY}" \
  'targetCart[items][0]:={"productId": "id-1", "quantityCount": "8"}' \
  'targetCart[items][1]:={"productId": "id-2", "quantityCount": "2"}' \
  'refundAmount:="100.00"'

В данном примере:

  • Количество шариковых ручек уменьшилось на 2, с 10 до 8 единиц.
  • Поле price в запросе пропущено, но его вполне допустимо указать.
  • quantityCount у позиции с блокнотом не изменилось, его можно было не указывать.

Возврат части денег

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

http POST https://sandbox.pay.yandex.ru/api/merchant/v2/orders/Order-123/refund \
  "Authorization: Api-Key ${API_KEY}" \
  'targetCart[items]:=[{"productId": "id-1"}, {"productId": "id-2", "price": "170"}]' \
  'refundAmount:="60.00"'

В данном примере:

  • Цена блокнота уменьшилась на 30 рублей, с 200 до 170 рублей;
  • Таким образом, производится возврат 60 рублей, поскольку блокнотов было два.
  • quantityCount не указаны, но вполне допустимо указать их прежние значения.

Возврат c указанием количества возвращаемого товара

Допустим, необходимо вернуть две шариковые ручки. Это делается следующим запросом:

http POST https://sandbox.pay.yandex.ru/api/merchant/v2/orders/Order-123/refund \
  "Authorization: Api-Key ${API_KEY}" \
  'refundCart[items][0]:={"productId": "id-1", "quantityCount": "2"}' \
  'refundAmount:="100.00"'

В данном примере:

  • Количество шариковых ручек уменьшилось на 2, с 10 до 8 единиц.
  • Поле price в запросе пропущено, но его вполне допустимо было указать.

Возврат с указанием, какую часть от стоимости товара необходимо вернуть

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

http POST https://sandbox.pay.yandex.ru/api/merchant/v2/orders/Order-123/refund \
  "Authorization: Api-Key ${API_KEY}" \
  'refundCart[items]:=[{"productId": "id-1"}, {"productId": "id-2", "price": "30"}]' \
  'refundAmount:="60.00"'

В данном примере:

  • Цена блокнота уменьшилась на 30, с 200 рублей до 170 рублей.
  • Таким образом, производится возврат 60 рублей, поскольку блокнотов было два.
  • quantityCount не указаны, но вполне допустимо указать их прежние значения.

Request

POST

https://pay.yandex.ru/api/merchant/v2/orders/{order_id}/refund

Production

POST

https://sandbox.pay.yandex.ru/api/merchant/v2/orders/{order_id}/refund

Sandbox

Path parameters

Name

Description

order_id*

Type: string

ID заказа на стороне продавца, который был передан в ответе на /orders.

Max length: 2048

Body

application/json
{
    "branchId": "string",
    "externalOperationId": "string",
    "managerId": "string",
    "motive": "string",
    "refundAmount": "123.45",
    "refundCart": {
        "items": [
            {
                "price": "123.45",
                "productId": "string",
                "quantityCount": "123.45"
            }
        ]
    },
    "targetCart": {
        "items": [
            {
                "price": "123.45",
                "productId": "string",
                "quantityCount": "123.45"
            }
        ]
    },
    "targetShipping": {
        "amount": "123.45"
    }
}

Name

Description

refundAmount*

Type: string<double>

Сумма к возврату

Example: 123.45

branchId

Type: string

Идентификатор точки продаж

Max length: 2048

externalOperationId

Type: string

Идентификатор операции возврата в системе продавца. Должен быть уникальным.

Передайте этот параметр, чтобы получить возможность отслеживать состояние операции возврата через метод operations/{external_operation_id}.

Если операция не завершена (обрабатывается или остановлена), то повторный вызов метода возврата с такими же аргументами и таким же значением externalOperationId будет идемпотентным: в ответе вернется та же операция. Иначе вернется ошибка.

Если процесс возврата был успешно запущен, то повторный вызов метода возврата с тем же externalOperationId вернет ошибку с "reasonCode": "DUPLICATE_EXTERNAL_OPERATION_ID".

Max length: 2048

managerId

Type: string

Идентификатор менеджера

Max length: 2048

motive

Type: string

Причина возврата

Max length: 2048

refundCart

Type: TargetCart

Описывает позиции корзины, которые нужно вернуть. Не может быть указано одновременно с полем targetCart. Вместе с этим параметром желательно передавать идентификатор операции externalOperationId, так как он является токеном идемпотентности.

targetCart

Type: TargetCart

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

targetShipping

Type: TargetShipping

Применимо только к Yandex Pay Checkout. В остальных случаях следует оставить это поле пустым.

Описывает итоговое состояние доставки после выполнения возврата. Если это поле не указано или равно null, то считается, что стоимость доставки возвращается полностью.

TargetCart

Name

Description

items

Type: TargetCartItem[]

TargetShipping

Name

Description

amount

Type: string<double>

Стоимость доставки после выполнения операции

Example: 123.45

TargetCartItem

Name

Description

productId*

Type: string

Идентификатор позиции в корзине на момент создания заказа. Если передать идентификатор, которого не было в первоначальной корзине - произойдёт ошибка.

Max length: 2048

price

Type: string<double>

Цена одной единицы товара/услуги после выполнения операции. Необходимо указать, если цена одной единицы уменьшается в результате операции. Это может быть полезным, если необходимо вернуть часть денег за товар или подтверждении заказа. Если не указывать это поле в запросе, то считается, что цена осталась прежней.

Example: 123.45

quantityCount

Type: string<double>

Количество единиц товара/услуги, которое останется у пользователя после выполнения операции. Если не указывать это поле в запросе, то считается, что количество не изменилось.

Example: 123.45

Responses

200 OK

Body

application/json
{
    "code": 200,
    "data": {
        "operation": {
            "amount": "123.45",
            "created": "2022-12-29T18:02:01Z",
            "externalOperationId": "string",
            "operationId": "c3073b9d-edd0-49f2-a28d-b7ded8ff9a8b",
            "operationType": "AUTHORIZE",
            "orderId": "string",
            "params": {},
            "pointsAmount": "123.45",
            "reason": "string",
            "status": "PENDING",
            "updated": "2022-12-29T18:02:01Z"
        }
    },
    "status": "success"
}

Name

Description

code

Type: number

Default: 200

data

Type: OperationResponseData

status

Type: string

Default: success

Enum: success

OperationResponseData

Name

Description

operation

Type: Operation

Operation

Name

Description

amount*

Type: string<double>

Сумма операции в фиатной валюте

Example: 123.45

operationId*

Type: string<uuid>

Max length: 2048

operationType*

Type: string

Enum: AUTHORIZE, BIND_CARD, REFUND, CAPTURE, VOID, RECURRING, PREPAYMENT, SUBMIT

orderId*

Type: string

Max length: 2048

created

Type: string<date-time>

Дата и время создания операции (ISO 8601)

externalOperationId

Type: string

Идентификатор операции на стороне продавца

Max length: 2048

params

Type: object

pointsAmount

Type: string<double>

Сумма операции в баллах Плюса

Example: 123.45

reason

Type: string

Причина ошибки

Max length: 2048

status

Type: string

Default: PENDING

Enum: PENDING, SUCCESS, FAIL

updated

Type: string<date-time>

Дата и время обновления операции (ISO 8601)

Предыдущая