# Пользовательский интерфейс

# Платежная страница

Платежная страница Mandarin имеет адаптивный дизайн, содержит ваш логотип, а также информацию о платеже, переданную вами в API-запросе.

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

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

Платежная страница на русском языке

Payment Page Desktop - Russian

Платежная страница на английском языке

Payment Page Desktop - English

Мобильная верстка платежной страницы

Payment Page Mobile - Russian&English

# Custom Form

# Встроенная форма обработки карточных данных

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

При создании вашей платежной страницы и интеграции в неё формы следует помнить - если вы переносите комиссии на плательщика, в интерфейсе Custom Form необходимо указывать "Комиссия платежного сервиса" или "Комиссия за оплату картой", в зависимости от того, кто берёт комиссию (Mandarin или ваш сервис) , поскольку Custom Form - это White label решение. Например, "Сумма к оплате: 3060.0 руб. (в т.ч. комиссия платёжного сервиса 60.0 руб.)".

Custom Form представляет собой форму с полями, которые на самом деле являются отдельными страницами в iframe. Соответственно, вы можете стилизовать всё, что окружает поля iframe.

Такая форма состоит из двух частей: html-код, представляющий собой схему расположения будущих полей, состоящую из элементов div с классами, обозначающими, в какой из элементов будет помещено соответствующее поле iframe, окруженное элементом form с уникальным идентификатором (произвольным). Также в форму добавляется кнопка, ссылка или другой элемент, служащий триггером сабмита формы.

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

# Основные принципы формы

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

Заполнение полей mandarinpay-field для формы :

Параметр Тип операции Обязателен
card-number Pay, Payout Да
card-holder Pay Опционально
card-expiration Pay Да
card-cvv Pay Да (возможна оплата без cvv, для уточнения обратитесь в техническую поддержку)

Код формы

<form id="form-hosted-pay">
    <div class="mandarinpay-field-card-number"></div>
    <div class="mandarinpay-field-card-holder"></div>
    <div class="mandarinpay-field-card-expiration"></div>
    <div class="mandarinpay-field-card-cvv"></div>
    <button onclick="return mandarinpay.hosted.process(this);">Оплатить</a>
</form>

Классы mandarinpay-field-card-number, mandarinpay-field-card-holder, mandarinpay-field-card-expiration и mandarinpay-field-card-cvv будут заполнены соответствующими полями iframe.

Эта форма обрабатывается скриптом hosted fields, который подключается к HTML: <script src="https://secure.mandarinpay.com/api/hosted/v2.js"></script>

После подключения скрипта hosted fields необходимо передать ему идентификатор html-формы и operationId, полученное в поле jsOperationId синхронного ответа.

Это делается функцией mandarinpay.hosted.setup:

<script>
mandarinpay.hosted.setup("#form-hosted-pay", 
{
  operationId: "9874694yr87y73e7ey39ed80",
});
</script>

В этот момент происходит инициализация формы, в div элементы формы помещаются соответствующие iframe полей, и форму можно заполнять. Данные заполненной формы передаются в скрипт hosted fields командой mandarinpay.hosted.process(this);, как показано в примере html-кода формы, или командой mandarinpay.hosted.process('#form-hosted-pay');. Данные команды в данном случае равнозначны.

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

# Верстка и внешний вид формы

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

Пример более практичного кода формы оплаты

<form id="form-hosted-pay">
  <div style="margin: 10px; padding: 10px; border: 1px solid gray">
    Card Number:
    <div class="mandarinpay-field-card-number hosted-field"><div class="glyphicon glyphicon-check"></div></div>
    Card Holder:
    <div class="mandarinpay-field-card-holder hosted-field"><div class="glyphicon glyphicon-check"></div></div>
    Card Expiration:
    <div class="mandarinpay-field-card-expiration hosted-field"><div class="glyphicon glyphicon-check"></div></div>
    CVV:
    <div class="mandarinpay-field-card-cvv hosted-field"><div class="glyphicon glyphicon-check"></div></div>
    <br/>
    <a href="#" onclick="return mandarinpay.hosted.process(this);" class="btn btn-default">Оплатить</a>
  </div>
</form>

Пример более практичного кода формы выплаты

<form id="form-hosted-pay">
  <div style="margin: 10px; padding: 10px; border: 1px solid gray">
    Card Number:
    <div class="mandarinpay-field-card-number hosted-field"><div class="glyphicon glyphicon-check"></div></div>
    <br/>
    <a href="#" onclick="return mandarinpay.hosted.process(this);" class="btn btn-default">Выплатить</a>
  </div>
</form>

Как видите, добавлены дополнительные классы, инлайн-стили, добавили в поля формы дополнительные элементы <div class="glyphicon glyphicon-check"></div>, позволяющие использовать глификонки Bootstrap (для этого, разумеется, надо подключить соответствующий компонент Bootstrap), заменили кнопку "Оплатить" на ссылку (для её отображения также используется Bootstrap).

Следует помнить, что в процессе взаимодействия пользователя с формой тегам div могут быть присвоены классы mandarinpay-field-state-error, mandarinpay-field-state-focused и mandarinpay-field-state-valid, обозначающими, соответственно, состояние каждого поля и введенных в него значений (скрипт hosted fields также осуществляет валидацию значений по мере ввода).

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

CSS для полей

.hosted-field
{
    background: #f0f0f0;
    height: 40px;
    padding: 5px;
    border: 1px solid gray;
    border-radius: 10px;
}

.hosted-field {
    position: relative;
}

.hosted-field .glyphicon {
    visibility: hidden;
    position: absolute;
    right: 5px;
    top: 5px;
    color: green;
    float: right;
}

.mandarinpay-field-state-error
{
    background: #fff0f0;
    border: 1px solid #900000;
}

.mandarinpay-field-state-focused
{
    background: #ffffff;
    border: 1px solid yellowgreen;
}

.mandarinpay-field-state-valid {
    background: #c0ffc0 !important;
    border: 1px solid green !important;
}

.mandarinpay-field-state-valid  .glyphicon{
    visibility: visible;
}

Но таким образом можно настроить только те элементы, которые существуют на странице; всё, отображаемое непосредственно в iframe, для стилей недоступно. Стилизация содержимого iframe осуществляется посредством добавления соответствующего поля в объект, передаваемый mandarinpay.hosted.setup. Для изменения доступны placeholder и CSS-стили.

Пример стилизации для оплаты

mandarinpay.hosted.setup("#form-hosted-pay",
{ 
  operationId: "9874694yr87y73e7ey39ed80",
  fields:
  {
    "card-number": {
      settings: {
        placeholder: "НОМЕР КАРТЫ",
        styles: {
          "font-size": "20px",
          "font-family": "Helvetica",
          "color": "#0000c0"
        },
        placeholderStyles: {
          "color": "pink" 
        },
      }
    },
    "card-cvv": {
      settings: {
        placeholder: "123",
        styles: {
          "font-size": "20px",
          "font-family": "Helvetica",
          "color": "#555"
        },
      }
    },
  }
});

Пример стилизации для выплаты

mandarinpay.hosted.setup("#form-hosted-pay",
{ 
  operationId: "9874694yr87y73e7ey39ed80",
  fields:
  {
    "card-number": {
      settings: {
        placeholder: "НОМЕР КАРТЫ",
        styles: {
          "font-size": "20px",
          "font-family": "Helvetica",
          "color": "#0000c0"
        },
        placeholderStyles: {
          "color": "pink" 
        },
      }
    }
  }
});
  • color в формате #000000.
  • font-size с единицами px и pt.
  • font-family (можно использовать запятые и кавычки).
  • font-style.

В результате получаем некий подобный базовый вариант внешнего вида:

Custom Form

# События формы и их обработка

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

Имплементация хуков для оплаты

mandarinpay.hosted.setup("#form-hosted-pay",
{ 
  operationId: "9874694yr87y73e7ey39ed80",
  onsuccess: function(data) {
    // Событие, срабатывающее при успешной оплате.
    // Возвращаемые данные содержат информацию для дальнейшей обработки или демонстрации пользователю.
    alert("Success, id: " + data.transaction.id + ' card number: ' + data.cardInfo.maskedCardNumber);
  },
  onerror: function(data) {
    // Событие, срабатывающее при неудаче - например, нет денег на карте, неверный номер карты и так далее.
    alert("Error code: " + data.errorCode +" text: " + data.error);
  },
  oncancel: function(data) {
    // Событие, срабатывающее при отказе пользователя от оплаты - например, закрытие окна 3-D Secure вместо ввода кода.
    console.log(data);
  },
  onvalidationerror: function() {
    // Событие срабатывает при попытке отослать невалидные данные при нажатии на кнопку оплаты.
    alert("Validation error");
  },
  onformstatechange: function(state) {
    // Событие, отрабатывающее каждый раз на изменение состояния формы - например, ввод данных пользователем, потеря фокуса и так далее. Если, например, надо активировать кнопку оплаты только если все данные, введенные пользователем во все поля, валидны - удобно использовать это событие для проверки.
    console.log(state);
  },

  fields:
  {
    "card-number": {
      settings: {
        placeholder: "НОМЕР КАРТЫ",
        styles: {
          "font-size": "20px",
          "font-family": "Helvetica",
          "color": "#0000c0"
        },
        placeholderStyles: {
          "color": "pink" 
        },
      }
    },
    "card-cvv": {
      settings: {
        placeholder: "123",
        styles: {
          "font-size": "20px",
          "font-family": "Helvetica",
          "color": "#555"
        },
      }
    },
  }
});

Имплементация хуков для выплаты

mandarinpay.hosted.setup("#form-hosted-pay",
{ 
  operationId: "9874694yr87y73e7ey39ed80",
  onsuccess: function(data) {
    // Событие, срабатывающее при успешной оплате.
    // Возвращаемые данные содержат информацию для дальнейшей обработки или демонстрации пользователю.
    alert("Success, id: " + data.transaction.id + ' card number: ' + data.cardInfo.maskedCardNumber);
  },
  onerror: function(data) {
    // Событие, срабатывающее при неудаче - например, нет денег на карте, неверный номер карты и так далее.
    alert("Error code: " + data.errorCode +" text: " + data.error);
  },
  oncancel: function(data) {
    // Событие, срабатывающее при отказе пользователя от оплаты - например, закрытие окна 3-D Secure вместо ввода кода.
    console.log(data);
  },
  onvalidationerror: function() {
    // Событие срабатывает при попытке отослать невалидные данные при нажатии на кнопку оплаты.
    alert("Validation error");
  },
  onformstatechange: function(state) {
    // Событие, отрабатывающее каждый раз на изменение состояния формы - например, ввод данных пользователем, потеря фокуса и так далее. Если, например, надо активировать кнопку оплаты только если все данные, введенные пользователем во все поля, валидны - удобно использовать это событие для проверки.
    console.log(state);
  },

  fields:
  {
    "card-number": {
      settings: {
        placeholder: "НОМЕР КАРТЫ",
        styles: {
          "font-size": "20px",
          "font-family": "Helvetica",
          "color": "#0000c0"
        },
        placeholderStyles: {
          "color": "pink" 
        },
      }
    }
  }
});

# Добавление функционала Apple Pay

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

Начнем с инициализации формы. Для ранее рассматривающегося функционала нам это не было важно, но вообще mandarinpay.hosted.setup это promise, возвращающий сессию с дополнительными функциями. Обсуждение промисов выходит за рамки данной инструкции, поэтому в данном примере предполагается, что промисы всегда fulfilled, и показываем только обработку успешно возвращенных данных.

Инициализация скрипта с доступом к дополнительному функционалу

// Важно обратить внимание на то, что область видимости переменной hostedSession должна быть глобальной - возможно обращаться к этой переменной из разных мест и даже скриптов.
var hostedSession;

mandarinpay.hosted.setup("#form-hosted-pay",
{ 
  operationId: "9874694yr87y73e7ey39ed80",
  onsuccess: function(data) {
  },
  onerror: function(data) {
  },
  oncancel: function(data) {
  },
  onformstatechange: function(state) {
  },
  fields:
  {
    "card-number": {
      settings: {
        placeholder: "НОМЕР КАРТЫ",
        styles: {
          "font-size": "20px",
          "font-family": "Helvetica",
          "color": "#0000c0"
        },
        placeholderStyles: {
          "color": "pink" 
        },
      }
    },
    "card-cvv": {
      settings: {
        placeholder: "123",
        styles: {
          "font-size": "20px",
          "font-family": "Helvetica",
          "color": "#555"
        },
      }
    },
  }
}).then(function(result){
    // Получаем результат промиса - сессию - и сохраняем её в нашей глобальной переменной hostedSession - дальше возможно или обращаться к сессии из других мест через переменную hostedSession (например, при нажатии на кнопку Apple Pay), или, например, передавать сессию напрямую в функцию.
    hostedSession = result;
    // Проверка на то, поддерживает ли устройство и мерчант эппл-пей возможно, разумеется, только после получения сессии, поэтому запускается по возвращению промиса.
    setupPromiseReturned(result);
  });

function setupPromiseReturned(result){
  // запускаем промис isApplePaySupportedAsync . Когда промис вернет ответ, передаётся ответ в функцию processApplePayResolve. Ответ, собственно, может быть только true или false.
  result.isApplePaySupportedAsync().then(processApplePayResolve);
}
function processApplePayResolve(result){
  // Скрипт прислал ответ, можно ли в данном случае показывать кнопку Apple Pay. Проверка включает в себя и поддержку браузера, и настройки мерчанта. Ответ может быть true или false
  if (result){
    console.log('Apple Pay поддерживается. Показываем кнопку.');
    $('.apple-pay-button').show();
  }else{
    console.log('Apple Pay не поддерживается. Не показываем кнопку.');
  }
}

Также добавляем кнопку Apple Pay в форму. Добавлять можно в любое место.

Код формы с кнопкой Apple Pay

<form id="form-hosted-pay">
  <div style="margin: 10px; padding: 10px; border: 1px solid gray">
    Card Number:
    <div class="mandarinpay-field-card-number hosted-field"><div class="glyphicon glyphicon-check"></div></div>
    Card Holder:
    <div class="mandarinpay-field-card-holder hosted-field"><div class="glyphicon glyphicon-check"></div></div>
    Card Expiration:
    <div class="mandarinpay-field-card-expiration hosted-field"><div class="glyphicon glyphicon-check"></div></div>
    CVV:
    <div class="mandarinpay-field-card-cvv hosted-field"><div class="glyphicon glyphicon-check"></div></div>
    <br/>
    <a href="#" onclick="return mandarinpay.hosted.process(this);" class="btn btn-default">Оплатить</a>
    <div class="apple-pay-button apple-pay-button-black" style="display: none;" onclick="return hostedSession.popupApplePay('#form-hosted-pay');"></div>             
  </div>
</form>

Обратите внимание на то, что кнопка спрятана по умолчанию - ведь неизвестно, поддерживается Apple Pay или нет до отработки промисов, а потому не можем сразу показывать кнопку. В случае положительного ответа от промиса isApple PaySupportedAsync кнопка показывается пользователю, а в случае отрицательного просто остается спрятанной.

Apple предлагает собственные инструкции по форме, размеру, правилам показа и прочим особенностям работы (opens new window) с кнопкой Apple Pay, пример одной из возможных реализаций верстки приводится ниже.

@supports (-webkit-appearance: -apple-pay-button) {
    .apple-pay-button {
        display: inline-block;
        -webkit-appearance: -apple-pay-button;
    }
    .apple-pay-button-black {
        -apple-pay-button-style: black;
    }
    .apple-pay-button-white {
        -apple-pay-button-style: white;
    }
    .apple-pay-button-white-with-line {
        -apple-pay-button-style: white-outline;
    }
}

Учитывая возможности, предоставляемые скриптом hosted fields, возможности интеграции формы оплаты в ваш интерфейс ограничены только фантазией вашего дизайнера и опытом программиста. Некоторые примеры интеграции формы hosted fields можно увидеть на демо-странице (opens new window).

# Оплата через СБП для Custom Form

Каждый запрос должен быть аутентифицирован с помощью токена (access_token), полученного в соответствии с протоколом OAuth 2.0 для приложений. Токен действует в течение 36 000 секунд (10 часов). Если срок действия истек, токен нужно запросить еще раз.

Обратитесь в Службу поддержки (opens new window), чтобы узнать ваш client_id и client_secret, чтобы получить access_token.

Запрос на получение токена:

Включает в себя обязательные form-data параметры, которые передаются в теле запроса (параметры application.client_id и application.client_secret неизменны для приложения и хранятся на стороне клиента).

Параметр Описание Пример
grant_type Грант авторизации (всегда равен client_credentials). client_credentials
client_id Идентификатор клиента (равен значению application.client_id, предоставленному Mandarin). VvPtlhcyldKtkuoUWY42 pErdrj4er2AwFoBWrn8n
client_secret Секретный ключ-пароль клиента (равен значению application.client_secret, предоставленному Mandarin). uQfOIMsltZYL8x3XMqUGP5 iFM59PyFnKlN0UmD3Ihre2 Ry3AGazUAv5jPdUI4dBJqV 0Of6b9GFvWvzGahYnq2aVV xkxn9n4qWF57FP0C01Kp6l EtajhfYv3UZ2f4pAZ7
scope Запрашиваемые скоупы (области доступа).
Разделитель - пробел.
Запрашивать можно любой список скоупов, при этом в ответе вернется тот список запрошенных скоупов, который может быть предоставлен для данного приложения.
secure:sbp_transaction.read
secure:sbp_transaction.write
curl --location --request POST 'https://accounts.mandarinbank.com/oauth/token/' \
--form 'grant_type=client_credentials' \
--form 'client_id=VvPtlhcyldKtkuoUWY42pErdrj4er2AwFoBWrn8n' \
--form 'client_secret=uQfOIMsltZYL8x3XMqUGP5iFM59PyFnKlN0UmD3Ihre2Ry3AGazUAv5jPdUI4dBJqV0Of6b9GFvWvzGahYnq2aVVxkxn9n4qWF57FP0C01Kp6lEtajhfYv3UZ2f4pAZ7' \
--form 'scope=secure:sbp_transaction.read secure:sbp_transaction.write'

Ответ:

Параметр Описание Пример
access_token Токен (ключ доступа). VnuxZiW14mXBedDeZO7d W7GBmzPxMn
expires_in Срок действия токена (в секундах). Всегда равен 36 000 секунд (10 часов). 36000
token_type Тип токена (всегда равен Bearer). Bearer
scope Разрешенные скоупы (области доступа). secure:sbp_transaction.read
secure:sbp_transaction.write
{
    "access_token": "VnuxZiW14mXBedDeZO7dW7GBmzPxMn",
    "expires_in": 36000,
    "token_type": "Bearer",
    "scope": "secure:sbp_transaction.read secure:sbp_transaction.write"
}

Использование токена:

Указывается в headers каждого запроса, в поле Authorization, после зарезервированного слова Bearer.

Authorization:Bearer VnuxZiW14mXBedDeZO7dW7GBmzPxMn

# Запрос на создание транзакции оплаты

Headers:

  • Authorization: Bearer <your_api_key>
  • Content-Type: application/json
Параметр Обязателен Параметр Обязателен
payment Да customValues[] Нет
payment.action Да customValues[].name Нет
payment.orderId Да customValues[].value Нет
payment.price Да metadata Нет
payment.orderActualTill Нет urls Нет
customerInfo Да urls.return Нет
customerInfo.email Да urls.callback Нет
customerInfo.phone Нет*
allowinteractive Нет
interactive Нет
POST https://secure.mandarinpay.com/api/transactions
{
	"payment": {
		"action": "pay",
		"orderId": "your_unique_order_id",
		"price": "1000.00",
		"orderActualTill": "2020-02-20 12:34:56+00:00"
	},
	"customerInfo": {
		"email": "user@example.com",
		"phone": "+79001234567"
	},
	"customValues": [
		{"name": "first parameter to save and show", "value": "p1"},
		{"name": "second parameter to save and show", "value": "p2"}
	],
	"metadata": {
		"first_parameter_to_callback_and_not_to_show": "p1",
		"second_parameter_to_callback_and_not_to_show": "p2"
	},
	"urls": {
		"callback": "http://...",
		"return": "http://..."
	}
}

Ответ в случае успешного создания транзакции (200 ОК):

{
	"id": "43913ddc000c4d3990fddbd3980c1725",
	"userWebLink": "https://secure.mandarinpay.com/Pay?transaction=0eb51e74-e704-4c36-b5cb-8f0227621518",
}

Параметры ответа:

  • userWebLink - не используется для Custom Form
  • id - созданная транзакция, данный id необходимо использовать в следующем запросе для СБП

Ответ в случае, если транзакция не создана (400 Bad request):

{
	"error": "Invalid request"  
}

# Запрос на формирование qrCodeUrl

Используем id транзакции из предыдущего запроса

POST https://secure.mandarinpay.com/public/sbp/43913ddc000c4d3990fddbd3980c1725

Ответ в случае успешного создания транзакции (200 ОК):

{
  "qrCodeUrl": "https://.../qr.png",
  "paymentUrl": "https://.../pay",
  "status": "pending"
}

Параметры ответа:

  • qrCodeUrl - открывает qr-код для сканирования, его показываем плательщику спомощью Custom Form
  • paymentUrl - страница оплаты, альтернатива QR
  • status - статус оплаты

# Запрос статуса оплаты СБП

ПРАВИЛА ЗАПРОСА СТАТУСА

  • Интервал: 5 секунд (минимум — 2 секунды).
  • Прекратить запрос статуса при получении: success/failed
  • Лимит: 30 минут (если дольше 30 минут статус pending, операцию считать неуспешной).

Описание статусов:

Статус Описание
success Оплата прошла успешно, средства списаны со счета плательщика
failed Оплата была отклнонена (см. детали ошибки в мониторинге транзакций (opens new window))
pending Ожидание оплаты (плательщик еще не произвел действий для оплаты)
GET https://secure.mandarinpay.com/public/sbp/43913ddc000c4d3990fddbd3980c1725

Ответ в случае успеха:

{
    "status": "success"
}

Ответ в случае неуспеха:

{
    "status": "failed"
}

Ответ в случае ожидания оплаты:

{
    "status": "pending"
}

# Интерактивный платеж как пример реализации Custom Form

Интерактивный платеж использует токен карты. В отличие от обычного рекуррентного платежа, в случае интерактивной оплаты пользователь вводит CVV/CVC-код. Для реализации формы ввода CVV/CVC-кода вы должны использовать технологию Custom Form.

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

Интерактивный платеж может быть реализован двумя способами:

  • interactive. Платеж будет осуществлен в интерактивном режиме независимо от статуса токена. Для этого необходимо передать "interactive": true.

  • allowinteractive. Платеж будет произведен с помощью автосписания (рекуррентный платеж). Если токен находится в статусе payout-only, то он будет осуществлен в интерактивном режиме. Для этого необходимо передать "allowinteractive": true.

Платеж происходит в два этапа:

  1. Инициация (в интерактивном режиме через API).

  2. Создание транзакции (с применением Custom Form).

# Инициация

В качестве примера рассмотрим запрос платежа по сохраненной карте в интерактивном режиме, где "interactive": true.

Для запроса платежа по сохраненной карте без ввода CVV/CVC-кода и без прохождения 3-D Secure, где "allowinteractive": true, необходимо использовать те же параметры.

В синхронном ответе содержится id платежа, и jsOperationId для создания транзакции через Custom Form.

Запрос interactive платежа для одностадийной оплаты

POST https://secure.mandarinpay.com/api/transactions
{
	"payment": {
		"action": "pay",
		"orderId": "your_unique_order_id",
		"price": "1000.00"
	},
	"target": {
		"card": "0eb51e74-e704-4c36-b5cb-8f0227621518"
	},
	"interactive": true,
	"customValues": [
		{"name": "first parameter to save and show", "value": "p1"},
		{"name": "second parameter to save and show", "value": "p2"}
	],
	"metadata": {
		"parameter to callback and not to show 0": "0",
		"parameter to callback and not to show 1": "1"
	},
	"urls": {
		"callback": "http://...",
		"return": "http://..."
	}
}

Запрос interactive авторизации для двухстадийной оплаты

POST https://secure.mandarinpay.com/api/transactions
{
	"payment": {
		"action": "preauth",
		"orderId": "your_unique_order_id",
		"price": "1000.00"
	},
	"target": {
		"card": "0eb51e74-e704-4c36-b5cb-8f0227621518"
	},
	"interactive": true,
	"customValues": [
		{"name": "first parameter to save and show", "value": "p1"},
		{"name": "second parameter to save and show", "value": "p2"}
	],
	"metadata": {
		"parameter to callback and not to show 0": "0",
		"parameter to callback and not to show 1": "1"
	},
	"urls": {
		"callback": "http://...",
		"return": "http://..."
	}
}

Ответ в случае успешной инициации (200 ОК)

{
	"id": "43913ddc000c4d3990fddbd3980c1725",
	"jsOperationId": "9874694yr87y73e7ey39ed80"
}

Ответ в случае, если инициация не произошла (400 Bad request)

{
	"error": "Invalid request"  
}

# Создание транзакции

Полученный в синхронном ответе jsOperationId в рамках предыдущего запроса необходимо использовать для создания транзакции через Custom Form. В этом случае необходимо передать только значение CVV. Передача остальных карточных данных не требуется.

Детальное описание находится в соответствующем разделе.

Создание транзакции через Custom Form

HTML-форма соответствует той, которую используется для полной формы оплаты, просто удаляются все поля кроме поля CVV:

<form id="form-hosted-pay">
  <div style="margin: 10px; padding: 10px; border: 1px solid gray">
    CVV:
    <div class="mandarinpay-field-card-cvv hosted-field"><div class="glyphicon glyphicon-check"></div></div>
    <br/>
    <a href="#" onclick="return mandarinpay.hosted.process(this);" class="btn btn-default">Оплатить</a>
  </div>
</form>

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

<script>
mandarinpay.hosted.setup("#form-hosted-pay", {
  operationId: "9874694yr87y73e7ey39ed80",
  onsuccess: function(data) {
    alert("Success, id: " + data.transaction.id);
  },
  onerror: function(data) {
    alert("Error: " + data.error);
  }
});
</script>