Возврат средств после оплаты

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

Платежная платформа поддерживает возвраты через Gate или через Dashboard. В этом разделе представлена информация о возврате через Gate.

Общая информация

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

Чтобы инициировать возврат при работе через Gate, стороны веб-сервиса необходимо отправить запрос к конечной точке /v2/payment/card/refund. При этом следует учитывать особенности и ограничения, перечисленные далее в соответствующих разделах.

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

  • reversal, если возврат инициируется до закрытия операционного дня и на всю сумму оплаты;
  • refund, если возврат инициируется до закрытия операционного дня и на часть суммы оплаты или после закрытия операционного дня вне зависимости от суммы.

Исключением является возврат после оплаты, проведенной с использованием карты платежной системы Visa. Для выполнения такого возврата в зависимости от того, когда он инициируется, и вне зависимости от суммы формируется одна из следующих операций:

  • reversal, если возврат инициируется до закрытия операционного дня;
  • refund, если возврат инициируется после закрытия операционного дня.
Прим.: Под операционным днем понимается временной диапазон, за который выполненные операции учитываются для проведения клиринга. Этот диапазон равен одним суткам с учетом варьирования их продолжительности при переходах на летнее и зимнее время. Начало и окончание операционного дня в разных случаях могут варьироваться с учетом разных факторов, информацию о которых следует уточнять у курирующего менеджера Rocketpay.

Таким образом, возврат инициируется одним запросом и может выполняться для двух типов платежей — разовых и повторяемых оплат — с помощью одной из двух операций: refund или reversal.

Рис.: Схема соответствия между запросом, платежами и операциями


Схема соответствия между запросом, платежами и операциями

После выполнения возврата к веб-сервису передается оповещение, в котором содержится информация о результате выполнения возврата и о статусе платежа после возврата. Статус платежа может принимать следующие значения:

  • success — платеж проведен, возврат для платежа не выполнен;
  • reversed — до закрытия операционного дня для платежа выполнен возврат всей суммы;
  • refunded — после закрытия операционного дня для платежа выполнен возврат всей суммы;
  • partially reversed — до закрытия операционного дня для платежа выполнен возврат части суммы (только для карт платежных систем Visa);
  • partially refunded — для платежа выполнен возврат части суммы (для карт платежных систем Visa — после закрытия операционного дня);
  • scheduled recurring processing — для повторяемой оплаты выполнен возврат всей суммы или части суммы, при этом ожидаются дальнейшие списания средств в рамках этой оплаты.

Особенности

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

При выполнении возврата изменяются данные о сумме платежа. В оповещении о результате возврата указывается актуальная сумма платежа, доступная для дальнейших возвратов. Актуальная сумма платежа рассчитывается как разница между исходной суммой платежа и суммой, возвращенной пользователю. Допустим, исходная сумма равна 13,70 долларов США. Тогда при возврате на сумму 10,00 долларов актуальная сумма платежа принимает значение 3,70 долларов, а при еще одном возврате на сумму 3,70 долларов — 0,00 долларов. Это правило справедливо в том числе для регулярных оплат, при которых актуальную сумму платежа составляют суммы всех списаний в рамках этого платежа за вычетом суммы всех выполненных возвратов.

В то же время для разовых оплат, в рамках которых выполнено несколько платежных операций, сумма платежа, доступная для дальнейших возвратов, может отличаться от суммы платежа, передаваемой в оповещении. Поэтому для оповещений о результатах таких оплат введен дополнительный параметр, в котором указывается сумма, доступная для дальнейших возвратов — remaining_refund. Подробная информация о таких оплатах представлена в разделе Разбиение суммы платежа.

Ограничения

Выполнение возвратов возможно с учетом следующих ограничений:

  • В рамках оплаты, для которой выполняется возврат, должно быть выполнено хотя бы одно списание средств пользователя, при этом самой оплате должен соответствовать один из следующих статусов: success, partially paid, sсheduled recurring processing или partially refunded.

    Если в рамках оплаты не выполнено ни одного успешного списания или статус оплаты не соответствует ни одному из перечисленных, то запрос на возврат отклоняется и к веб-сервису направляется оповещение с кодом ошибки, например 3081.

  • Валюта возврата должна соответствовать валюте оплаты, для которой выполняется возврат.

    Если в запросе передана валюта, не соответствующая валюте оплаты, то запрос на возврат отклоняется и к веб-сервису направляется оповещение с кодом ошибки 3284 (подробнее о таких кодах — в разделе Статусы операций и коды ответов).

  • Должна соблюдаться допустимая частота отправки запросов.

    Если повторный запрос на возврат отправлен ранее, чем через две минуты, то этот запрос отклоняется и к веб-сервису направляется оповещение с кодом ошибки 3285.

  • Остаток средств на счете мерчанта должен быть достаточным для выполнения возврата.

    Информацию об остатке средств можно получить с помощью запроса через Data API (Использование Data API) или в Dashboard (раздел Контроль балансов), а также при обращении к курирующему менеджеру Rocketpay.

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

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

  • Оплата, для которой выполняется возврат, не должна быть оспариваемой.

    Если для оплаты начался процесс опротестования, то запрос на возврат отклоняется и к веб-сервису направляется оповещение с кодом ошибки 3288.

Помимо перечисленных ограничений для частичных возвратов действуют следующие:

  • При проведении частичного возврата его сумма не должна превышать актуальную сумму платежа, иначе запрос на возврат отклоняется и к веб-сервису направляется оповещение с кодом ошибки 3283.
  • Инициировать новый частичный возврат можно только после выполнения предыдущего, иначе запрос на возврат отклоняется и к веб-сервису направляется оповещение с кодом ошибки 3285.

Формат запроса

Формат запроса на возврат соответствует описанному в разделе Общий порядок интеграции, конечной точкой API для этого запроса выступает /v2/payment/card/refund, а в теле запроса должны использоваться следующие объекты и параметры:

  • general — объект, содержащий основные идентификационные сведения запроса:
    • project_id — идентификатор проекта, полученный от Rocketpay при интеграции;
    • payment_id — идентификатор платежа, для которого необходимо выполнить возврат;
    • signature — подпись к данным запроса, составленная после указания целевых параметров (подробнее — в разделе Подписывание и проверка подписи).
  • payment — объект, содержащий сведения о платеже:
    • description — описание причины возврата; относится только к операции возврата и не меняет описание оплаты, если оно было передано ранее.

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

  • amount — сумма возврата, не превышающая актуальную сумму платежа, в дробных единицах валюты;
  • currency — код валюты возврата в формате ISO-4217 alpha-3; указываемая валюта должна быть той же, что и валюта платежа.

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

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

Рис.: Пример набора данных в запросе на возврат средств

{
  "general": {
    "project_id": 239,
    "payment_id": "payment2",
    "signature": "of8k9xeKJ7KLTZYO56lCv+f1M0Sf/7eg=="
  },
  "payment": {
    "description": "refund",
// При частичном возврате:
    "amount": 1000,
    "currency": "USD"
  }
}

Формат оповещений

Формат оповещения о результате возврата соответствует описанному в разделе Оповещения (callbacks) в Gate. Информация об актуальной сумме платежа содержится в объекте payment, а о сумме, возвращенной пользователю, — в объекте operation. Также оповещение может содержать описание причины возврата в объекте operation_description, если это было настроено специалистами технической поддержки по запросу мерчанта.

Прим.: В случае, если для одной оплаты выполняются несколько частичных возвратов, при разборе оповещений следует учитывать, что каждому отдельному частичному возврату (то есть каждой отдельной операции) соответствует свой идентификатор. Его значение передается в параметре operation_id объекта operation.

Далее представлены примеры информации из оповещений о полном и частичном возврате для разовой оплаты на исходную сумму 13,70 USD:

  1. на сумму 10,00 USD, при этом актуальная сумма платежа равна 3,70 USD, а статус платежа соответствует partially refunded;
  2. на сумму 13,70 USD, при этом актуальная сумма платежа равна 0,00 USD, а статус платежа соответствует refunded.

В каждом из этих примеров содержится описание оплаты, так как оно было передано в запросе на оплату, и описание причины возврата.

Рис.: Пример данных из оповещения о частичном возврате средств

{ 
  "project_id":239,
  "payment":{ 
    "id":"payment2",
    "type":"purchase", // Тип платежа — разовая оплата
    "status":"partially refunded", // Статус платежа после частичного возврата
    "date":"2019-11-13T14:52:14+0000",
    "method":"card",
    "sum":{ 
      "amount":370, // Актуальная сумма платежа
      "currency":"USD" // Код валюты платежа
    },
    "description":"Tai massage session" // Описание оплаты
  },
  "account":{ 
    "number":"424242******4243",
    "type":"visa",
    "card_holder":"JUDY DOE",
    "expiry_month":"03",
    "expiry_year":"2023"
  },
  "operation_description":"Deficient service", // Описание причины возврата
  "operation":{ 
    "id":3862,
    "type":"refund", // Тип операции
    "status":"success", // Статус операции
    "date":"2019-11-13T14:52:15+0000",
    "created_date":"2019-11-13T14:52:12+0000",
    "request_id":"0c4457b5fe8dada59-e7b58eceb8aecfa791-00049391",
    "sum_initial":{ 
      "amount":1000, // Сумма возврата
      "currency":"USD" // Код валюты возврата (в соответствии с валютой платежа)
    },
    "sum_converted":{ 
      "amount":1000,
      "currency":"USD"
    },
    "code":"0",
    "message":"Success",
    "provider":{ 
      "id":414,
      "payment_id":"",
      "endpoint_id":414
    }
  },
  "signature":"of8k9xerKSK4XL1QFaDH3p9Mh0CIcjmOwSwKJ7KLTZYO56lCv+f1M0Sf/7eg=="
}

Рис.: Пример данных из оповещения о полном возврате средств

{ 
  "project_id":239,
  "payment":{
    "id":"payment2",
    "type":"purchase", // Тип платежа — разовая оплата
    "status":"refunded", // Статус платежа после полного возврата
    "date":"2019-11-13T13:52:09+0000",
    "method":"card",
    "sum":{ 
      "amount":0, // Актуальная сумма платежа
      "currency":"USD" // Валюта платежа
    },
    "description":"Tai massage session" // Описание оплаты
  },
  "account":{
    "number":"424242******4243",
    "token":"14c24c8a5384b413f11b2956a82ddaeea609ea49",
    "type":"visa",
    "card_holder":"JUDY DOE",
    "expiry_month":"03",
    "expiry_year":"2023"
  },
  "customer":{
    "id":"1478"
  },
  "operation_description":"Service cancellation", // Описание причины возврата
  "operation":{
    "id":3861,
    "type":"refund", // Тип операции
    "status":"success", // Статус операции
    "date":"2019-11-13T13:52:09+0000",
    "created_date":"2019-11-13T13:52:08+0000",
    "request_id":"67a97cd6b14f1aa0543c81e18cd270b66-aadc6e790206d5-00038611",
    "sum_initial":{ 
      "amount":1370, // Сумма возврата
      "currency":"USD" // Код валюты возврата (в соответствии с валютой платежа)
    },
    "sum_converted":{
      "amount":1370,
      "currency":"USD"
    },
    "code":"0",
    "message":"Success",
    "provider":{
      "id":414,
      "payment_id":"",
      "endpoint_id":414
    }
  },
  "signature":"of8k9xerKSK4XL1QFaDH3p9Mh0CIcjmOwSwKJ7KLTZYO56lCv+f1M0Sf/7eg=="
}

В следующем примере содержится информация о том, что для повторяемой оплаты с суммой всех списаний, равной 7,99 EUR, выполнен возврат на сумму 7,99 EUR и до выполнения следующего списания актуальная сумма платежа равна 0,00 EUR. Статус платежа в данном случае не изменился, так как в рамках этого платежа ожидаются дальнейшие списания (подробнее о статусах — в разделе Типы платежей, операции и платежи).

Рис.: Пример данных из оповещения о полном возврате средств

{ 
  "project_id":239,
  "payment":{ 
    "id":"payment3",
    "type":"recurring", // Тип платежа — повторяемая оплата
    "status":"scheduled recurring processing", // Статус платежа после возврата
    "date":"2019-11-13T17:23:26+0000",
    "method":"card",
    "sum":{ 
      "amount":0, // Актуальная сумма платежа
      "currency":"EUR" // Валюта платежа
    },
  },
  "account":{ 
    "number":"424242******4243",
    "token":"14c24c8a5384b413f11b2956a82ddaeea609ea49",
    "type":"visa",
    "card_holder":"JUDY DOE",
    "expiry_month":"03",
    "expiry_year":"2023"
  },
  "customer":{ 
    "id":"1478"
  },
  "recurring":{ 
    "id":1061,
    "currency":"EUR",
    "valid_thru":"2027-05-31T00:00:00+0000"
  },
  "operation_description":"Refund for payment3 order", // Описание причины возврата
  "operation":{ 
    "id":3861,
    "type":"refund", // Тип операции
    "status":"success", // Статус операции при успешном возврате
    "date":"2019-11-13T17:23:26+0000",
    "created_date":"2019-11-13T17:23:25+0000",
    "request_id":"bb36c8b4bce2c4-0198d59676189b0e344d1-00056689",
    "sum_initial":{ 
      "amount":799, // Сумма возврата
      "currency":"EUR" // Код валюты возврата (в соответствии с валютой платежа)
    },
    "sum_converted":{ 
      "amount":799,
      "currency":"EUR"
    },
    "code":"0",
    "message":"Success",
    "provider":{ 
      "id":414,
      "payment_id":"",
      "endpoint_id":6
    }
  },
  "signature":"of8k9xerKSK4XL1QFaDH3p9Mh0CIcjmOwSwKJ7KLTZYO56lCv+f1M0Sf/7eg=="
}

В следующем примере содержится информация о том, что для разовой оплаты отклонен возврат на сумму 60,00 USD в связи с нехваткой средств на счете мерчанта, о чем свидетельствует код ошибки 3028 (подробнее о таких кодах — в разделе Статусы операций и коды ответов). Сумма и статус платежа в данном случае не изменились.

Рис.: Пример данных из оповещения об отказе в возврате средств

{ 
  "project_id":239,
  "payment":{ 
    "id":"payment7",
    "type":"purchase", // Тип платежа — разовая оплата
    "status":"success", // Статус платежа при отказе в возврате
    "date":"2019-12-29T15:29:47+0000",
    "method":"card",
    "sum":{ 
      "amount":6000, // Сумма платежа
      "currency":"USD" // Валюта платежа
    },
  },
  "account":{ 
    "number":"424242******4243",
    "token":"14c24c8a5384b413f11b2956a82ddaeea609ea49",
    "type":"visa",
    "card_holder":"JUDY DOE",
    "expiry_month":"03",
    "expiry_year":"2023"
  },
  "operation_description":"Error", // Описание причины возврата
  "operation":{ 
    "id":3869,
    "type":"reversal", // Тип операции
    "status":"decline", // Статус операции при отказе в возврате
    "date":"2019-12-29T15:32:29+0000",
    "created_date":"2019-12-29T15:32:29+0000",
    "request_id":"713446e4b43-06bfc7eed42c4c854697846a-00059692",
    "sum_initial":{ 
      "amount":6000, // Сумма возврата
      "currency":"USD" // Код валюты возврата (в соответствии с валютой платежа)
    },
    "sum_converted":{ 
      "amount":6000,
      "currency":"USD"
    },
    "code":"3028", // Код ошибки
    "message":"Insufficient funds on merchant balance", // Описание ошибки
    "provider":{ 
      "id":120,
      "payment_id":"",
      "endpoint_id":120
    }
  },
  "signature":"of8k9xerKSK4XL1QFaDH3p9Mh0CIcjmOwSwKJ7KLTZYO56lCv+f1M0Sf/7eg=="
}

Дополнительные материалы

При работе с возвратами также могут быть полезны следующие материалы: