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

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

Редактировать на GitHub

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

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

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

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

    Mobile SMS

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

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

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

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

Авторизация

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

curl "адрес сервера" \
  --header "Authorization: Basic MjMyNDQxMjM6NDUzRmRnZDQ0Mw=="

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

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

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

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

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

Запрос → PUT

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": "Text comment"
     }
  }
}
Параметр Описание Тип
user Обязательный параметр. Идентификатор номера QIWI Wallet, на который выставляется счет (в международном формате), с префиксом tel: String(20)
amount Обязательный параметр. Сумма, на которую выставляется счет. Округляется в меньшую сторону до двух десятичных знаков Number(6.2)
ccy Обязательный параметр. Идентификатор валюты (Alpha-3 ISO 4217 код). Может использоваться любая валюта, предусмотренная договором с КИВИ String(3)
comment Обязательный параметр. Комментарий к счету String(255)
lifetime Обязательный параметр. Дата/время с точностью до секунд в формате ISO 8601 (ГГГГ-ММ-ДДTчч:мм:сс). Указывается московское время. Если счет не будет оплачен до этой даты, ему присваивается финальный статус и последующая оплата станет невозможна.
Внимание! По истечении 45 суток от даты выставления счет автоматически будет переведен в финальный статус.
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",
        "ccy": "RUB",
        "status": "waiting",
        "error": 0,
        "user": "tel:+79031234567",
        "comment": "Text comment"
     }
  }
}

Ответ в случае ошибки

HTTP/1.1 500 Internal Server Error
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.ccy String Идентификатор валюты (Alpha-3 ISO 4217 код)
bill.status String Текущий статус счета
bill.error Integer Константа, всегда 0
bill.user String Копия параметра user из исходного запроса
bill.comment String Копия параметра comment из исходного запроса

<?php
//Пример реализации запроса на PHP
//Идентификатор магазина из вкладки "Данные магазина"
$SHOP_ID = "21379721";
//API ID из вкладки "Данные магазина"
$REST_ID = "62573819";
//API пароль из вкладки "Данные магазина"
$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"
);

$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

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": "Text comment"
     }
  }
}

Ответ в случае ошибки

HTTP/1.1 500 Internal Server Error
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 Нельзя изменить данные счета – он уже оплачивается или оплачен +

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

Редактировать на GitHub

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

Запрос → POST

Пример

user@server:~$ curl "https://example.com/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%26amount=1.00%26user=tel%3A%2B79031811737%26prv_name=TEST%26ccy=RUB%26comment=test%26command=bill"
Параметр Описание Тип Обяз.
bill_id Уникальный идентификатор счета в системе провайдера String +
status Текущий статус счета String +
amount Сумма, на которую выставлялся счет, округленная до двух десятичных знаков Number(6.2) +
user Номер QIWI Кошелька, на который был выставлен счет, с префиксом tel: String +
prv_name Название проекта, указанное на сайте kassa.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-авторизация

Пример уведомления с Basic-авторизацией

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

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 проекта.

Для первичного получения или смены пароля на сайте QIWI Касса, нажмите кнопку "Создать пароль и сохранить" или "Сменить пароль оповещения", соответственно.

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

Пример уведомления с подписью

POST /qiwi-notify.php HTTP/1.1
Accept: text/xml
Content-type: application/x-www-form-urlencoded
X-Api-Signature: J4WNfNZd***V5mv2w=
Host: example.com

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

Для использования этого способа авторизации уведомлений, на сайте QIWI Касса достаточно активировать флаг "Использовать HMAC подпись вместо basic-авторизации".

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

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

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

    {parameter1}|{parameter2}|…

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

  2. Строку и пароль для 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

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();
// Пароль  для уведомлений магазина
$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;
?>

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

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

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