Перевод на банковскую карту¶
При переводе на банковскую карту денежные средства клиента списываются с его счёта в платформе и зачисляются на счёт карты стороннего банка.
Клиент может перевести деньги:
- из авторизованной зоны, в частности в интерфейсе партнёра;
 - из неавторизованной зоны, в частности в интерфейсе стороннего банка.
 
Перевод из авторизованной зоны¶
Описание авторизованной зоны см. в статье «Термины и бизнес-сущности».
Перевод из такой зоны является операцией домена PAYMENTS. Партнёр может реализовать его несколькими способами:
- c помощью API;
 - с помощью формы.
 
Обратите внимание
Не имеет значения, выпущена для клиента банковская карта в платформе или нет — деньги будут списаны с его счёта.
Перевод c помощью API¶
Для перевода средств на банковскую карту c помощью API партнёру необходимо:
- отвечать стандартам безопасности PCI DSS и иметь соответствующий сертификат;
 - использовать собственную форму для перевода средств;
 - знать идентификатор счёта (
accountId) клиента-отправителя — возвращается при выполнении сценария «Создание клиента и счёта». 
Пример успешного сценария перевода средств на банковскую карту c помощью API описан и изображён ниже.
- Клиент нажимает «Перевести» в интерфейсе партнёра.
 - Партнёр отображает клиенту форму для ввода платёжных данных.
 - 
Клиент вводит сумму перевода и номер банковской карты (PAN).
Опциональные шаги
П.4 является опциональным и выполняется лишь в том случае, если бизнес-сценарием предусмотрена комиссия с клиента за совершение перевода.
 - 
Партнёр выполняет сценарий «Получение комиссии».
 - Партнёр отправляет BaaS запрос на перевод средств.
 - 
BaaS возвращает партнёру статус проведения платежа «В процессе проведения» (
status:PROCESSING) и информацию о необходимости подтвердить перевод (needClientApprove).Опциональные шаги
П.7 - п.9 являются опциональными и выполняются лишь в том случае, если
needClientApproveимеет значениеtrue. - 
Партнёр информирует клиента о том, что перевод на указанную карту является потенциально подозрительной операцией: получатель денежных средств, возможно, относится к числу финансовых мошенников.
 - Клиент подтверждает выполнение перевода.
 - Партнёр отправляет BaaS запрос на подтверждение.
 - BaaS переводит средства со счёта клиента на банковскую карту.
 - Партнёр принимает решение об успешности проведения платежа — выполняет действия, указанные в статье «Общие принципы и правила» → «Решение об успешности платежа» → «Асинхронный вариант проведения платежа».
 
%%{init: {
    "sequence" : {
        "wrap":true,
        "messageFontSize":15,
        "noteFontSize":13,
        "actorMargin":
        75 }}}%%
sequenceDiagram
    participant С as Клиент
    participant P as Партнёр
    participant B as BaaS
    С->>P: Перевод на карту в интерфейсе
    Note right of С: «Перевести»
    P->>С: Форма для перевода
    С->>P: Ввод данных
    Note right of С: Сумма перевода, номер карты
    opt Сценарий «Получение комиссии» (опционально)
    P->>+B: 
    B->>-P: 
    Note left of B: clientCommission
    P->>+С: 
    С->>P: 
    Note left of P: clientCommission
    end
    P->>+B: Запрос на перевод
    Note over P, B: productId, transactionId, fromAccountId, pan, transactionAmount, clientCommission
    B->>-P: Ответ на запрос перевода
    Note over P, B: status:PROCESSING, needClientApprove
    opt Получение подтверждения (опционально)
    P->>С: Коммуникация с клиентом
    Note left of P: Подозрительная операция
    С->>P: Подтверждение перевода
    P->>+B: Запрос на подтверждение
    Note over P, B: productId, transactionId, currency, clientApproveStatus:APPROVED
    B->>-P: Ответ на запрос подтверждения
    Note over P, B: clientApproveStatus:APPROVED
    end
    rect rgb(255, 238, 223)
    P->>+B: Сценарий «Решение об успешности платежа»
    B-->>-P: 
    Note left of B: status:SUCCESS
    end
    P->>С: Коммуникация с клиентом
Запросы описаны в документации Payments API. Указанные на диаграмме сценарии см. в статьях:
- «Комиссия» — для получения комиссии;
 - «Общие принципы и правила» → «Решение об успешности платежа» → «Асинхронный вариант проведения платежа» — для принятия решения об успешности платежа.
 
Жизненный цикл операции перевода описан в этой статье.
Обратите внимание
Действия, указанные в статье «Общие принципы и правила» → «Решение об успешности платежа» → «Асинхронный вариант проведения платежа», являются обязательными для выполнения.
Важная информация
При реализации сценария необходимо учитывать существующие правила и ограничения.
Перевод c помощью формы¶
Форма позволяет клиенту совершить перевод по номеру карты. Является альтернативой использованию Payments API. Преимущество использования формы в том, что партнёру не требуется:
- отвечать стандартам безопасности PCI DSS и иметь соответствующий сертификат;
 - разрабатывать собственную форму для перевода средств;
 - поддерживать информационное взаимодействие, описанное в разделе «Перевод c помощью API».
 
Использование формы¶
Партнёру необходимо добавить JavaScript-код на экран или страницу интерфейса, предназначенную для перевода средств на банковскую карту.
Пример JavaScript-кода
  <script src="https://openapi-widget.qiwi.com/script.js" type="text/javascript"></script>
  <script>
    const widget = window.qwl.createPayTransferWidget({
      formUrl: 'https://openapi-widget.qiwi.com',
      token: '4ee7***ce61',
      allowCopy: 'clipboard-read; clipboard-write self',
      signature: '6cff***f555',
      style: {
        isModal: false,
        btn: ':hover {
          background: green;
        }',
        input: 'border-radius: 10px;
            :hover {
              color: red;
            }',
        layout: 'background: tomato;',
        rootId: 'form-container',
        titleColor: '#3c3c5b',
        errorColor: ''
      },
      callback: data => alert(JSON.stringify(data))
    })
    widget.mount()
  </script>
Важная информация
Партнёру необходимо передать BaaS список доменов, на которых будет расположен экран или страница с JavaScript-кодом. В ином случае совершить перевод с помощью формы не удастся.
Описание параметров и переменных
| Наименование | Описание | 
|---|---|
| formUrl | Значение параметра formUrl из ответа на запрос получения токена формы | 
| token | Значение параметра formToken из ответа на запрос получения токена формы | 
| signature | Значение, вычисляемое по алгоритму HmacSHA256 на основе “секрета” и formToken (алгоритм вычисления см. в статье «Общие принципы и правила» → «Вычисление цифровой подписи») | 
| style | Переменная, отвечающая за кастомизацию формы. Подробнее в разделе «Кастомизация» | 
| callback | Callback-функция. Подробнее в разделе «Callback» | 
Получение, вычисление и подстановка значений для formUrl, token, signature в код выполняются при каждой попытке клиента совершить перевод по номеру карты.
Успешный сценарий перевода на банковскую карту c помощью формы изображён на диаграмме ниже.
%%{init: {
    "sequence" : {
        "wrap":true,
        "messageFontSize":13,
        "noteFontSize":12,
        "width":140,
        "actorMargin":90}}}%%
sequenceDiagram
    participant С as Клиент
    participant PF as Партнёр (Frontend)
    participant PB as Партнёр (Backend)
    participant B as BaaS
    С->>PF: Переход на страницу интерфейса
    Note over С, PF: Страница для перевода по номеру карты
    PF->>+PB: Запрос на получение токена формы
    Note right of PF: clientData
    PB->>+B: Запрос на получение токена формы
    Note right of PB: productId, fromAccountId, transactionId
    B-->>-PB: Ответ на запрос получения токена формы
    Note left of B: formToken, formUrl
    PB->>PB: Вычисление signature
    PB-->>-PF: Ответ на запрос получения токена формы
    Note left of PB: formToken, formUrl, signature
    PF->>PF: Встраивание значений в JS-код
    rect rgb(230, 230, 230)
    Note over PF, B: JS-код формы перевода на банковскую карту
    С->>PF: Ввод платёжных данных
    Note over С, PF: Номер карты получателя и сумма перевода
    PF->>+B: Выполнение JS-кода (вызов API)
    B-->>-PF: clientCommission
    PF->>С: Отображение данных на форме в интерфейсе
    Note left of PF: Комиссия
    С->>PF: Подтверждение перевода
    Note over С, PF: «Перевести»
    PF->>+B: Выполнение JS-кода (вызов API)
    B-->>-PF: Результат обработки запроса (объект JSON)
    Note right of PB: status:PROCESSING
    PF->>PF: Вызов callback-функции
    end
    PF->>С: Коммуникация с клиентом
    Note left of PF: Перевод выполняется
    rect rgb(255, 238, 223)
    PF->>+B: Сценарий «Решение об успешности платежа»
    B->>-PF: 
    Note left of PB: status:SUCCESS
    end
    PF->>С: Коммуникация с клиентом
    Note left of PF: Перевод успешен
Запросы описаны в документации Payments API. Сценарий принятия решения об успешности платежа см. в статье «Общие принципы и правила» → «Решение об успешности платежа» → «Асинхронный вариант проведения платежа».
Обратите внимание
- Партнёр не получает, не обрабатывает и не хранит данные карты получателя, а также не вычисляет комиссию за совершение перевода. Это делает форма. Данный этап выделен на схеме серым цветом.
 - Партнёру необходимо самостоятельно реализовать отображение результата проведения платежа. Подробнее в разделе «Callback».
 - Действия, указанные в статье «Общие принципы и правила» → «Решение об успешности платежа» → «Асинхронный вариант проведения платежа».
 
Важная информация
При реализации сценария необходимо учитывать существующие правила и ограничения.
Кастомизация формы¶
Кастомизация позволяет настроить внешний вид формы. CSS-свойства для кастомизации указываются в переменной style.
Пример style
      style: {
        isModal: false,
        btn: ': hover {
          background: gray;
        }',
        input: 'border-radius: 10px;
            :hover {
              color: orange;
            }',
        layout: 'background: orange;',
        rootId: 'form-container',
        titleColor: gray,
        errorColor: 'orange'
      }
Описание параметров
| Наименование | Описание | 
|---|---|
| isModal | Признак, говорящий о том, является ли форма модальным окном (true/false) | 
| btn | CSS-стиль кнопки для перевода. Можно задать стиль кнопки при наведении на неё мышкой с помощью :hover {YOUR_STYLE} | 
| input | CSS-стиль полей с платёжными данными. Можно задать стиль полей при наведении на них мышкой с помощью :hover {YOUR_STYLE} | 
| layout | CSS-стиль подложки (фона). Можно задать стиль фона при наведении на него мышкой с помощью :hover {YOUR_STYLE} | 
| rootId | Идентификатор контейнера, в который будет встраиваться форма | 
| titleColor | Цвет заголовка и кнопки закрытия формы. Указывается, если выбрано модальное отображение (isModal: true). Может иметь вид red, #3c3c3c и др. согласно стандарту CSS | 
| errorColor | Цвет текста ошибки в случае некорректного заполнения полей ввода данных. Может иметь вид red, #3c3c3c и др. согласно стандарту CSS | 
Пример формы

Callback¶
Callback — это функция, которая вызывается после того, как клиент нажал на кнопку «Перевести» и платформа вернула результат обработки запроса на перевод (см. раздел «Использование формы»).
Пример
data => alert(JSON.stringify(data))
Здесь результат выводится с помощью метода alert(). Партнёр может использовать собственное решение.
Callback-функции передаётся единственный аргумент (data) в виде объекта JSON с полем:
result— в случае успешной обработки платёжного запроса;error— в случае ошибки при обработке платёжного запроса.
Формат data аналогичен формату ответа Payments API на запрос перевода средств.
Объект JSON в случае успешной обработки запроса
{
  "result": {
    "productId": "fake-product",
    "transactionId": "96d6***ca6ec",
    "fromAccountId": "34f2***058fa",
    "transactionAmount": {
      "currency": "RUB",
      "value": "12333.00"
    },
    "clientCommission": {
      "currency": "RUB",
      "value": "246.66"
    },
    "creationDateTime": "2022-06-20T17:31:57.688546+03:00",
    "accountingDateTime": "2022-06-20T17:31:57.688553+03:00",
    "status": "PROCESSING",
    "statusDetails": {},
    "needClientApprove": false
  }
}
Описание см. в документации Payments API: Перевод на банковскую карту → Ответ.
Обратите внимание
Наличие result не говорит об успешности самого перевода, статус перевода находится в result.status.
Объект JSON в случае ошибки
{
  "error": {
    "dateTime": "2022-06-28T10:56:08.584631+03:00",
    "description": "Undefined error. Please try to make operation later.",
    "errorCode": "openapi.payment.api.withdrawal.to.card.token.expired",
    "serviceName": "openapi-payment-api",
    "traceId": "6d1c4afcf941a949",
    "userMessage": "Undefined error. Please try to make operation later."
  }
}
Формат error аналогичен формату ошибок Payments API. Справочник кодов ошибок представлен в таблице ниже.
| Код | Описание | 
|---|---|
openapi.frontend.api.client.blocked | 
Клиент заблокирован | 
openapi.frontend.api.precheck.failed | 
Запрос не прошел банковские проверки, такие как превышение лимита. Финансовая операция не создана | 
openapi.frontend.api.invalid.txn.amount | 
Неверная сумма платежа | 
openapi.frontend.api.txn.parameter.changed | 
Платеж с таким идентификатором транзакции уже создан и его параметры отличаются от переданных в запросе | 
openapi.frontend.api.unauthorized | 
Ошибка авторизации: подпись неверна, токен устарел и др. | 
Обратите внимание
Партнёру необходимо самостоятельно реализовать отображение результата проведения платежа. При обработке data мы рекомендуем проверить:
- наличие 
error, чтобы показать клиенту сообщение об ошибке; - значение 
result.status, чтобы основываясь на нём выстроить правильную коммуникацию с клиентом. 
Демонстрационная страница¶
BaaS может открыть партнёру доступ к демо-странице, для этого следует обратиться к курирующему менеджеру.
После открытия страницы перейдите на вкладку Pay transfer widget. Примерный вид страницы — на изображении ниже.

Демо-страница позволяет:
- посмотреть результат кастомизации формы;
 - протестировать работу формы с конкретными данными;
 - получить JavaScript-код, сформированный после применения всех настроек и данных.
 
Чтобы увидеть результат кастомизации, необходимо:
- настроить стили согласно примеру на изображении выше;
 - применить стили, нажав на соответствующую кнопку.
 
Чтобы протестировать работу формы, необходимо:
- ввести значения 
formUrl,token,signature,style(как получить значения см. в разделе «Использование формы»); - применить настройки, нажав на соответствующую кнопку;
 - ввести номер карты получателя и сумму перевода.
 - нажать «Перевести» на форме.
 
Для отображения результата на демо-странице callback-функция определена так, чтобы ответ появился в модальном окне. Партнёр на своей странице может использовать собственное решение.

Обратите внимание
Для formUrl, token, signature на демо-странице допускается использовать лишь значения, полученные из тестовой среды. Для их получения партнёру следует отправлять запросы на тестовый URL.
Тестирование¶
Общие правила тестирования описаны в статье BaaS → «Тестирование». Здесь мы расскажем об особенностях тестирования сценариев перевода средств на банковскую карту из авторизованной зоны.
Тестовые данные
В запросе на перевод или на форме используйте следующий номер карты: 4874154455550061.
Особенности
В тестовой среде отсутствует этап подтверждения перевода — needClientApprove всегда имеет значение false.
Перевод из неавторизованной зоны¶
Описание неавторизованной зоны см. в статье «Термины и бизнес-сущности».
Перевод из такой зоны является операцией домена CARDS и выполняется по сценарию, описанному ниже.
- 
- заходит на сайт или в мобильное приложение интернет-банка;
 - выбирает перевод по номеру карты;
 - указывает данные карты QIWI в качестве отправителя;
 - указывает номер карты другого банка в качестве получателя;
 - вводит сумму и нажимает «Перевести».
 
 - 
Интернет-банк с помощью платёжной системы, которая обслуживает карту, проводит платёж.
 
Партнёр узнаёт о факте совершения перевода, получив уведомление, подробности см. в статье «Уведомление» → «Уведомление об операциях домена CARDS».