Вопросы
api_help@qiwi.com
NAV
shell php

Платежи с баланса мобильного оператора

Последнее обновление: 2017-10-05 | Редактировать на GitHub

Mobile Payments API открывает доступ к операциям сплатежами из вашего сервиса. Поддерживаются следующие операции:

Процесс оплаты заказа

  1. Пользователь формирует заказ на сайте провайдера.
  2. Мерчант выполняет запрос Инициировать платеж с параметрами авторизации.
  3. Сразу после инициирования платежа пользователь получает СМС от своего мобильного оператора с информацией о счете и подтверждает оплату ответным СМС. Если пользователь отказался от оплаты, то счет автоматически отклоняется.

    Mobile SMS

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

    В отсутствие уведомлений провайдер может запросить текущий статус платежа.

  5. После подтверждения оплаты счета провайдер исполняет заказ пользователя.

Данное API можно использовать только после регистрации и подключения.

Авторизация

Запросы мерчанта к Pull API авторизуются посредством HTTP basic-авторизации. Для авторизации используются API ID и API password. Заголовок представляет собой параметр Authorization, значение которого представлено как: Basic Base64(API_ID:API_PASSWORD)

user@server:~$ curl "адрес сервера"
  --header "Authorization: Basic MjMyNDQxMjM6NDUzRmRnZDQ0Mw=="

Служебные данные

Параметр Описание Тип Обяз.
API_ID Идентификатор для авторизации провайдера в API Integer +
API_PASSWORD Пароль для авторизации в API String +
ID проекта Числовой идентификатор провайдера (идентификатор проекта или PRV_ID) Integer +

Инициация платежа и оплата

Запрос инициирует новый платеж на указанный номер телефона. Тип запроса - HTTP PUT.

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

user@server:~$ curl "https://api.qiwi.com/api/v2/prv/373712/bills/BILL-1"
  -X PUT --header "Accept: text/json"
  --header "Authorization: Basic ***"
  -d 'user=tel%3A%2B79161111111&amount=10.00&ccy=RUB&comment=test&pay_source=mobile&lifetime=2016-09-25T15:00:00'


HTTP/1.1 200 OK
Content-Type: text/json
{
  "response": {
     "result_code": 0,
     "bill": {
        "bill_id": "BILL-1",
        "amount": "10.00",
        "ccy": "RUB",
        "status": "waiting",
        "error": 0,
        "user": "tel:+79161111111",
        "comment": "test"
     }
  }
}

Запрос → PUT

Параметр Описание Тип Обяз.
user Идентификатор номера QIWI Wallet, на который выставляется счет (в международном формате), с префиксом tel: String(20) +
amount Сумма, на которую выставляется счет. Округляется в меньшую сторону до двух десятичных знаков Number(6.2) +
ccy Идентификатор валюты (Alpha-3 ISO 4217 код). Может использоваться любая валюта, предусмотренная договором с КИВИ String(3) +
comment Комментарий к счету String(255) +
lifetime Дата, до которой счет будет доступен для оплаты. Если счет не будет оплачен до этой даты, ему присваивается финальный статус и последующая оплата станет невозможна.
Внимание! По истечении 28 суток от даты выставления счет автоматически будет переведен в финальный статус.
dateTime +
pay_source mobile - оплата счета будет производиться с баланса мобильного телефона пользователя String +

Ответ ←


HTTP/1.1 200 OK
Content-Type: text/json;charset=utf-8
{
  "response": {
     "result_code": 0,
     "bill": {
        "bill_id": "BILL-1",
        "amount": "10.00",
        "originAmount": "10.00"
        "ccy": "RUB",
        "originCcy": "RUB",
        "status": "waiting",
        "error": 0,
        "user": "tel:+79031234567",
        "comment": "test"
     }
  }
}


HTTP/1.1 500
Content-Type: text/json;charset=utf-8
{
 "response": {
  "result_code": 150,
  "description": "Authorization failed"
  }
}

Формат ответа в исходном запросе:

Параметр Тип Описание
result_code Integer Код результата
description String Описание ошибки. Передается в случае ошибки
bill Object Описание счета
bill.bill_id String Копия параметра bill_id из исходного запроса
bill.amount String Сумма счета. Округляется в меньшую сторону до двух десятичных знаков.
bill.originAmount String Сумма счета в исходной валюте счета (см. параметр originCcy). Округляется в меньшую сторону до двух десятичных знаков.
bill.ccy String Идентификатор валюты (Alpha-3 ISO 4217 код)
bill.originCcy String Идентификатор валюты выставленного счета (Alpha-3 ISO 4217 код)
bill.status String Текущий статус счета
bill.error Integer Константа, всегда 0
bill.user String Копия параметра user из исходного запроса
bill.comment String Копия параметра comment из исходного запроса

<?php
//Пример реализации запроса на PHP
//Идентификатор магазина из вкладки "Данные магазина"
//https://ishop.qiwi.com/options/http.action
$SHOP_ID = "21379721";
//API ID из вкладки "Данные магазина"
//https://ishop.qiwi.com/options/rest.action
$REST_ID = "62573819";
//API пароль из вкладки "Данные магазина"
//https://ishop.qiwi.com/options/rest.action
$PWD = "**********";
//ID счета
$BILL_ID = "99111-ABCD-1-2-1";
$PHONE = "79191234567";

$data = array(
    "user" => "tel:+" . $PHONE,
    "amount" => "1000.00",
    "ccy" => "RUB",
    "comment" => "Все очень хорошо",
    "lifetime" => "2015-01-30T15:35:00",
    "pay_source" => "mobile",
    "prv_name" => "Хороший магазин"
);

$ch = curl_init('https://api.qiwi.com/api/v2/prv/'.$SHOP_ID.'/bills/'.$BILL_ID);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $REST_ID.":".$PWD);
curl_setopt($ch, CURLOPT_HTTPHEADER,array (
    "Accept: application/json"
));
$results = curl_exec ($ch) or die(curl_error($ch));
echo $results;
echo curl_error($ch);
curl_close ($ch);
?>

Проверка статуса платежа

Запрос позволяет проверить текущий статус оплаты клиентом.

Запрос → GET

user@server:~$ curl "https://api.qiwi.com/api/v2/prv/373712/bills/BILL-1"
  --header "Authorization: Basic ***"
  --header "Accept: text/json"

Ответ ←


HTTP/1.1 200 OK
Content-Type: text/json
{
  "response": {
     "result_code": 0,
     "bill": {
        "bill_id": "BILL-1",
        "amount": "10.00",
        "originAmount": "10.00"
        "ccy": "RUB",
        "originCcy": "RUB",
        "status": "paid",
        "error": 0,
        "user": "tel:+79031234567",
        "comment": "test"
     }
  }
}


HTTP/1.1 500
Content-Type: text/json
{
 "response": {
  "result_code": 150,
  "description": "Authorization failed"
  }
}

Формат ответа в исходном запросе:

Параметр Тип Описание
result_code Integer Код результата
description String Описание ошибки. Передается в случае ошибки
bill Object Описание счета
bill.bill_id String Уникальный идентификатор счета в системе провайдера
bill.amount String Сумма счета, округленная до 2 или 3 знаков после запятой. Способ округления зависит от валюты.
bill.originAmount String Сумма счета в исходной валюте счета (см. параметр originCcy), округленная до 2 или 3 знаков после запятой. Способ округления зависит от валюты.
bill.ccy String Идентификатор валюты (Alpha-3 ISO 4217 код)
bill.originCcy String Идентификатор валюты выставленного счета (Alpha-3 ISO 4217 код)
bill.status String Текущий статус счета
bill.error Integer Константа, 0
bill.user String Идентификатор кошелька пользователя, которому выставлен счет (номер телефона в международном формате с префиксом tel:)
bill.comment String Комментарий к счету

Статусы операций

Статусы платежей

Статус Описание Финальный
waiting Платеж инициирован, ожидает оплаты -
paid оплачен +
rejected отклонен +
unpaid Ошибка при проведении оплаты. Не оплачен +
expired Время жизни платежа истекло. Не оплачен +

Список ошибок

Код Описание Fatal
0 Успех  
5 Неверные данные в параметрах запроса +
13 Сервер занят, повторите запрос позже -
78 Недопустимая операция +
150 Ошибка авторизации +
152 Не подключен или отключен протокол -
155 Данный идентификатор провайдера (API ID) заблокирован +
210 Платеж не найден +
215 Платеж с таким bill_id уже существует +
241 Сумма слишком мала +
300 Техническая ошибка -
303 Неверный номер телефона +
316 Попытка авторизации заблокированным провайдером -
319 Нет прав на данную операцию -
339 Ваш IP-адрес или массив адресов заблокирован +
341 Обязательный параметр указан неверно или отсутствует в запросе +
700 Превышен месячный лимит на операции +
774 Счет клиента в системе QIWI временно заблокирован -
1001 Запрещенная валюта для провайдера +
1003 Не удалось получить курс конвертации для данной пары валют -
1019 Не удалось определить сотового оператора для мобильной коммерции +
1419 Нельзя изменить данные счета – он уже оплачивается или оплачен +

Уведомления об оплате счетов

Последнее обновление: 2017-11-14 | Редактировать на GitHub

Уведомление представляет собой POST-запрос. Тело запроса содержит сериализованные данные счета в теле запроса (кодировка UTF-8), и параметр command=bill.

Запрос → POST

Пример

user@server:~$ curl "https://service.ru/qiwi-notify.php"
  -v -w "%{http_code}"
  -X POST --header "Accept: text/xml"
  --header "Content-Type: application/x-www-form-urlencoded; charset=utf-8"
  --Authorization: "Basic MjA0Mjp0ZXN0Cg=="
  -d "bill_id=BILL-1%26status=paid%26pay_date=2016%3A11%3A16T11%3A00%3A15%26amount=1.00%26user=tel%3A%2B79031811737%26prv_name=TEST%26ccy=RUB%26comment=test%26command=bill"
Параметр Описание Тип Обяз.
status Текущий статус счета String +
amount Сумма, на которую выставлялся счет, округленная до двух десятичных знаков Number(6.2) +
user Номер QIWI Кошелька, на который был выставлен счет String +
pay_date Дата оплаты счета (заполняется, если счет оплачен) DateTime (YYYY-MM-DDThh:mm:ss) +
prv_name Наименование проекта, указанное на сайте ishop.qiwi.com в разделе:”Настройки”->”Данные проекта”->”Короткое наименование” String +
ccy Идентификатор валюты (Alpha-3 ISO 4217 код) String(3) +
comment Комментарий к счету String(255) +
command bill - всегда по умолчанию String +

Ответ ←

HTTP/1.1 200 OK
Content-Type: text/xml

<?xml version="1.0"?>
<result>
<result_code>0</result_code>
</result>

Ответ на запрос должен быть в формате XML.

Авторизация уведомлений

Для авторизации можно использовать basic-авторизацию или авторизацию подписи. При запросах уведомлений на сервер провайдера также можно использовать SSL (в том числе самоподписанный сертификат). В HTTPS-запросах необходимо проверять серверный сертификат QIWI Wallet.

Basic-авторизация

POST /qiwi-notify.php HTTP/1.1
Accept: text/xml
Content-type: application/x-www-form-urlencoded
Authorization: Basic ***
Host: service.ru

command=bill&bill_id=BILL-1&status=paid&error=0&amount=1.00&user=tel%3A%2B79031811737&prv_name=Retail_Store&ccy=RUB&comment=test

Логин равен ID магазина. Для получения пароля нажмите кнопку “Сменить пароль оповещения” в Личном кабинете мерчантав разделе “Настройки”->”REST-Протокол”.

Авторизация по подписи

<?php

function hexToStr($hex){
    $string='';
    for ($i=0; $i < strlen($hex)-1; $i+=2){
        $string .= chr(hexdec($hex[$i].$hex[$i+1]));
    }
    return $string;
}

//функция генерации подписи по ключу и строке параметров
function checkSign($key, $req){
    $sign_hash = hash_hmac("sha1", $req, $key);
    $sign_tr = hexToStr($sign_hash);
    $sign = base64_encode($sign_tr);
    return $sign;
}

//Функция возвращает упорядоченную строку значений параметров POST-запроса
function getReqParams(){
    $reqparams = "";
    ksort($_POST);
    foreach ($_POST as $param => $valuep) {
        $reqparams = "$reqparams|$valuep";
    }
    return substr($reqparams,1);
}

//Извлечение цифровой подписи из заголовков запроса
function getSign(){
    $HEADERS = getallheaders();
    foreach ($HEADERS as $header => $value) {
       if ($header == 'X-Api-Signature') {
            $SIGN_REQ = $value;
       }
    }
    return $SIGN_REQ;
}

// Сортировка параметров
$Request = getReqParams();
// Пароль ishop для уведомлений магазина
$NOTIFY_PWD = "***";
// Вычисляем подпись
$reqres = checkSign($NOTIFY_PWD, $Request);

// Подпись из запроса
$SIGN_REQ = getSign();

if ($reqres == $SIGN_REQ) {
    $error = 0;
}
else $error = 151;

//Ответ
header('Content-Type: text/xml');
$xmlres = <<<XML
<?xml version="1.0"?>
<result>
<result_code>$error</result_code>
</result>
XML;
echo $xmlres;
?>
POST /qiwi-notify.php HTTP/1.1
Accept: text/xml
Content-type: application/x-www-form-urlencoded
X-Api-Signature: J4WNfNZd***V5mv2w=
Host: service.ru

command=bill&bill_id=LocalTest17&status=paid&error=0&amount=0.01&user=tel%3A%2B78000005122&prv_name=Test&ccy=RUB&comment=Some+Descriptor

Подпись уведомления отправляется в заголовке X-Api-Signature. Для формирования подписи используется механизм проверки целостности HMAC с хэш-функцией SHA1.

Алгоритм проверки подписи:

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

    {parameter1}|{parameter2}|…

    где {parameter1} – значение параметра уведомления. Все значения при проверке подписи должны трактоваться как строки.

  2. Cтроку и пароль для basic-авторизации уведомления преобразовать в байты с UTF-8.
  3. Вычислить HMAC-хэш c шифрованием SHA1:

    hash = HMAС(SHA1, Notification_password_bytes, Invoice_parameters_bytes) где:

    • Notification_password_bytes – ключ функции (байт-представление basic-пароля для уведомлений);
    • Invoice_parameters_bytes – байт-представление тела POST-запроса;
    • hash – результат хэш-функции.
  4. HMAC-хэш преобразовать из строк в байты с использованием кодировки UTF-8 и base64-преобразовать.
  5. Сравнить значение заголовка X-Api-Signature с результатом 4.

Пример реализации

Пример на языке PHP реализует авторизацию уведомлений системы QIWI Wallet с проверкой цифровой подписи. Откройте вкладку PHP справа.

Коды уведомлений

Код завершения Описание
0 Успех
5 Ошибка формата параметров запроса
13 Ошибка соединения с базой данных
150 Ошибка проверки пароля
151 Ошибка проверки подписи
300 Ошибка связи с сервером