Извините, мы обновляем протокол

Еще в 2011 году нас спрашивали, зачем вводить номер телефона для выставления счета на стороне партнера? Мы давно хотели облегчить интеграцию для наших партнеров, но раньше сделать это было достаточно сложно. Что же изменилось в QIWI в 2016? Сейчас расскажем, а также поэкспериментируем с хабровским R&D голосованием.

1d234626ddb74cc4b6bb760424637bdd.PNG

Согласования, боль и слезы больших компаний
Если упростить, в работе над любым проектом в компании участвует три группы:
  • Заказчики. Отвечают за бизнес-идею проекта, финансовую оценку, продажи;
  • Проектные менеджеры. Отвечают за техническую реализацию, определяют, какие группы она затронет, контролируют общие сроки и запуск проекта;
  • Разработчики. Реализуют и запускают проект.

У каждого подразделения были свои подгруппы с очередями и приоритетами. Задача на серьезную доработку сайта затрагивала легион коллег:
  • Платежный процессинг:
    • Java-разработчики, отвечающие за платежи, API для крупных партнеров и стандартные внешние API,
    • Oracle-разработчики, отвечающие за проектирование БД и хранимые процедуры;
  • Веб-разработка:
    • Java back-end + API разработчики для веба,
    • JavaScript разработчики, особенно для SPA,
    • Верстальщики;
  • Q&A, дающее добро на итоговый выпуск продукта.

eb1bd5fd77db402d8299b7cdc4a7d5ce.JPG

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

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

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

1. Сейчас наш серверный REST-протокол обязывает указывать номер телефона для выставления счета. Рассматривался вариант доработки для выставления счета на произвольный идентификатор или email.

Плюсы:

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

Минусы:
  • Усложненная интеграция для новых партнеров, т.к. требуется выставлять счет перед переадресацией на страницу оплаты,
  • Очень сложно делать массовые сервисы с оповещением о выставленных счетах,
  • Требует значительной переделки архитектуры счетов в платежном процессинге.

2. У компании был http-протокол с вводом номера на стороне QIWI. Но в нем никак не проверялось, что счет выставляется именно партнером. Этот протокол идеально подходил для сбора пожертвований, но для крупных партнеров его нельзя было применять в таком виде. Выход заключался в добавлении подписи или хеша и их последующей проверке при переадресации на страницу оплаты счета.

Плюсы:

  • Простая реализация для новых партнеров,
  • Небольшие затраты на разработку со стороны команды.

Минусы:
  • Могут появиться «одаренные» партнеры, которые будут хранить секретный ключ и вычислять подпись на клиенте.

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

Упрощайте.

— Pavel Durov (@durov) January 18, 2011

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

Оставался вопрос, как определять секретный ключ. Для basic-авторизации в REST-протоколе используется пара из API ID и API Password, которая позволяет гибко настраивать проверки для партнера. Для одного сайта можно завести несколько авторизационных пар и использовать их на разных серверах и версиях сайта.

Алгоритм и пример


В итоге, пришли к такому алгоритму:
  • Формируем массив из параметров:
    • api_id — id для определения секретного ключа,
    • currency — валюта,
    • from — id провайдера,
    • summ — сумма,
    • to (при наличии) — номер телефона,
    • txn_id — уникальный ID транзакции на стороне провайдера;
  • Добавляем в массив секретный ключ, связанный с api_id;
  • Объединяем все значения параметров в строку, используя разделитель | между параметрами;
  • Вычисляем хеш sha512;
  • Добавляем в запрос строковый параметр signature в шестнадцатиричном виде в нижнем регистре.

Пример реализации на PHP.
//ID проекта, API_ID, API пароль получаются в настройках по url: https://ishop.qiwi.com/options/rest.action
//ID проекта
$SHOP_ID = "260***";
$API_ID = "4683****";
//API пароль
$API_PWD = "1T1ea7****";
$CCY = "RUB";
$AMOUNT = 1.12;
	
//Телефон в формате 71231234567. Необязательный параметр
$PHONE = "";
//ID транзакции
$TXN_ID = "habr".rand(1,90000);

$phoneParam = "";
if ($PHONE != ""){
   $phoneParam='&to='.$PHONE;
   //Формируем массив параметров с номером телефона, если мы его знаем
   $params = array($API_ID,$CCY,$SHOP_ID,$AMOUNT,$PHONE,$TXN_ID);
}else{
   //Формируем массив параметров без номера телефона
   $params = array($API_ID,$CCY,$SHOP_ID,$AMOUNT,$TXN_ID);
}
//Добавляем в параметры секретный ключ
array_push($params,md5($API_PWD));
//Формируем строку из параметров с разделителем "|"
$paramsStr = implode("|", $params);
//Вычисляем хеш
$signature = hash('sha512',$paramsStr);

//Собираем итоговый url для клиента
$url = 'https://bill.qiwi.com/order/external/create.action?from='.$SHOP_ID.'&txn_id='.$TXN_ID.'&summ='.$AMOUNT.'&api_id='.$API_ID.'¤cy='.$CCY.'&signature='.$signature.$phoneParam;

Коллективный R&D
Предлагаю, в качестве эксперимента, вместе решить, как развивать протокол. Мы не решили несколько технических вопросов и предлагаем вам подумать вместе с нами, как развивать протокол. Для этого в конце статьи добавлено голосование.

Основной проблемой остаётся параметр lifetime, отвечающий за время жизни счета. В существующем протоколе он передавался в минутах, а счет выставлялся сразу после переадресации. В новом — счет может выставляться существенно позже, особенно если ссылка была отправлена по электронной почте. Поэтому, скорее всего, требуется добавить новый параметр с абсолютной датой. К примеру, в формате ISO 8601 (2016–09–12T00:00:00), который используется в REST. Но нужны ли там секунды? И просить ли кодировать »:» в »%3A», либо заменить его на »-», т.к. многие до сих пор передают success_url без url кодирования и стучатся в поддержку с вопросами. Скорее всего, новый параметр стоит также включать в вычисляемую подпись.

Обновленный протокол с трудом, но позволяет делать массовые рассылки. Основная проблема в уникальном id транзакции, который необходимо будет генерировать при создании ссылки. Для массовых рассылок с покупкой конкретного предмета это может быть затруднительно. Решением могла бы стать совокупность id покупки и аккаунта пользователя в магазине, но тогда пользователь сможет купить что-то только один раз. Проблему можно было бы решить сделав новые параметры и убрав ограничение по уникальности. Правда, есть сомнения, что это требуется рынку. Проголосуем?

На десерт
Новый протокол уже готов для подключения партнеров, но пока активируется только через службу поддержки. Если вы хотите принять участие в тестировании, пишите на cms@qiwi.ru или обращайтесь в поддержку.

Оценить текущее состояние страницы оплаты вы можете здесь. С днем программиста!

P.S. Приглашаю Java разработчика с хорошим опытом реализации REST API присоединиться к нашей команде по запуску нового ishop.qiwi.com и качественно перевернуть мир для тысяч наших партнеров уже в этом году.

Комментарии (0)

© Habrahabr.ru