Пользователь
0,0
рейтинг
23 октября 2013 в 12:10

Разработка → QIWI и новый протокол REST в примерах из песочницы

Приветствую.
Я являюсь давним читателем хабра и часто нахожу тут ответы на свои вопросы. Но вот так случилось, что ответа обнаружить не получилось. Причём нигде.
А задача была следующая. Реализовать новый (REST) протокол для системы QIWI. Мне пришлось потратить несколько дней, чтобы найти верное решение с помощью проб, ошибок, общений с менеджером и командой поддержки, т.к. примеров нигде нет, хотя задача не такая уж и сложная.
В данном сообщении я хочу поделиться теми примерами, которых мне так не хватало. Надеюсь, что это поможет кому-то.
Сразу скажу, что я не буду расписывать, разжевывать и объяснять подробно. Будет только основное, которое считаю необходимым. Всё же у каждого свои предпочтения и цели.
Для начала вам нужно зарегистрировать свой магазин http://ishopnew.qiwi.ru/
После регистрации в разделе Способы подключения вы найдёт пункт Новый протокол. Там можно скачать описание API нового протокола.

Для отправки запросов я использовал cURL.
Вот как это было:
$requestType = 'POST'; // Для REST запросы разного типа
$url = 'some url'; // Зависит от выполняемого действия
$parameters = array(); // Так же зависит от запроса
$loginPass = $id . ':' . $password; // ID магазина и пароль(пароль нужно получить у менеджера)
$headers = array(
    "Accept: text/json",
    "Content-Type: application/x-www-form-urlencoded; charset=utf-8"
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $loginPass);

if ($requestType != 'GET') {
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $requestType);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parameters));
}
$httpResponse = curl_exec($ch);
if (!$httpResponse) {
    // Описание ошибки, к примеру 
    echo curl_error($ch).'('.curl_errno($ch).')';
    return false;
}
$httpResponseAr = json_decode($httpResponse);
return $httpResponseAr->response;

Думаю тут всё просто и понятно.

Теперь какие операции можно осуществить.
  • Выставление счета пользователю
  • Запрос статуса счета
  • Переадресация для оплаты счета
  • Отмена неоплаченного выставленного счета
  • Возврат средств по оплаченному счету
  • Проверка статуса возврата

В документации довольно подробно всё описано. Я лишь акцентирую внимание на некоторых вещах, которые тормозили мою разработку.

Опишу отдельно для каждой операции.

1) Выставление счета пользователю
$requestType = 'PUT';
$url = 'https://w.qiwi.com/api/v2/prv/{prv_id}/bills/{bill_id}';
// {prv_id} – тут важно помнить, что это ваш ID магазина.
// {bill_id} – любое уникальное число, к примеру номер записи операции или номер счёта из базы.
$parameters = array(
	'user' => 'tel:+79999999999',
	'amount' => 0.1,
	'ccy' => 'RUB',
	'comment' => 'Оплата QIWI',
	'pay_source' => 'qw',
	'lifetime' => date('c', $timePlusHour),
	'prv_name' => 'QIWI',
);

С параметрами всё понятно.

2) Запрос статуса счета
Если счёт не был оплачен после выставления, нам нужно проверить его статус. Возможно система задержала ответ или пользователь решил оплатить его чуть позже, в таком случае можно использовать cron.
$requestType = 'GET';
$url = 'https://w.qiwi.com/api/v2/prv/{prv_id}/bills/{bill_id}'; // Аналогично выше
$parameters = array();


3) Переадресация для оплаты счета
После успешного выставления счёта нужно перенаправить пользователя на страницу оплаты. Здесь cURL не используется, просто редирект.
$url = 'https://w.qiwi.com/order/external/main.action?shop={prv_id }&transaction={bill_id}';
$url .= '&successUrl=' . $successUrl;
$url .= '&failUrl=' . $failUrl;
// {prv_id} и {bill_id} всегда постоянны для одного платежа. 
// $successUrl и $failUrl адреса ваших обработчиков успешных и неуспешных операций по оплате.


4) Отмена неоплаченного выставленного счета
Используется для отмены выставленного счёта. Если вы выставили счёт, но он не оплачен, система будет высылать на адрес, указанный в настройках магазина, POST запросы на подтверждение статуса счёта. Если вы не ответите, то в итоге придёт письмо на email, указанный в настройках магазина.
$requestType = 'PATCH';
$url = 'https://w.qiwi.com/api/v2/prv/{prv_id}/bills/{bill_id}'; // Аналогично выше
$parameters = array(
	'status' => 'rejected'
); 


5) Возврат средств по оплаченному счету
Вы можете потребовать вернуть оплаченные средства.
$requestType = 'PUT';
$url = 'https://w.qiwi.com/api/v2/prv/{prv_id}/bills/{bill_id}/refund/{refund_id}'; // Аналогично выше, только {refund_id} должен быть уникален
$parameters = array(
	'amount' => $amount
); 


6) Проверка статуса возврата
Так же нужно проверять статус возврата по запросу, описанному выше.
$requestType = 'GET';
$url = 'https://w.qiwi.com/api/v2/prv/{prv_id}/bills/{bill_id}/refund/{refund_id}'; // Аналогично выше, только {refund_id} должен быть уникален и совпадать с указанным выше
$parameters = array(); 


Ответ сервера подробно описан в документации.

Так же вам нужно будет создать два обработчика POST запросов, про которые я писал в 4 пункте. В запросе будут отправлены несколько параметров, которые нужно будет обработать.
  1. bill_id=BILL-1
  2. status=paid
  3. error=0
  4. amount=1.00
  5. user=tel%3A%2B79031811737
  6. prv_name=TEST
  7. ccy=RUB
  8. comment=test
  9. command=bill

В зависимости от того, на какой адрес пришёл запрос, вы должны проверить и решить, что делать с платежом. То ли зачислить деньги, если платёж прошёл и запрос успешен.То ли уменьшить баланс, если деньги были зачислены, но платёж оказался неудачен.

И конечно отдельное негодование хочется выразить по поводу тестирования. Система QIWI не имеет тестового режима или тестовой площадки, поэтому вам придётся использовать свой кошелёк и проводить платежи, к примеру, по 10 копеек.

Надеюсь, данным сообщением я хоть немного помог тем, кто собирается использовать новый протокол в своём проекте. Ведь он обещает возможность получать оплату со всех стран, где есть QIWI.
Александр @nechin
карма
4,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

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

  • +1
    Система QIWI не имеет тестового режима или тестовой площадки


    Это не так. Свяжитесь с саппортом.
    Когда я их прикручивал, надо было специально просить, что бы включили в боевом режиме.
    Хотя, возможно, что-то и поменялось.
    • +1
      Страница FAQ
      Раздел: Настройка подключения
      Вопрос: Есть ли у QIWI Кошелька тестовый сервер?
      Ответ: Нет, тестового сервера нет.
      А так же читайте там же ответы ниже: «Как такового тестового режима не существует.»
    • 0
      Про отсутствие тестового подтверждаю.
      Мне пришлось лепить свой эмулятор сервиса для тестов.
  • 0
    Не понял насчёт п2. Смысл проверять статус по крону если уведомление о смене статуса счёта всё равное прийдёт? Насчёт адресов для сообщений от сервиса — почему их два? Я использовал один, на него приходят все уведомления? И ещё одно уточнение — в настройках нигде нет пункта для указания адреса для уведомлений для REST протокола. В данный момент указание адреса для уведомлений задаётся написанием соответствующего письма менеджеру, о чём и гласит надпись на странице ishop.qiwi.ru/protocolRest.action
    • 0
      Не понял насчёт п2. Смысл проверять статус по крону если уведомление о смене статуса счёта всё равное прийдёт?
      Уведомление приходит через определённый интервал. Об этом написано в руководстве. Использование крона добровольная операция. Допустим если вам нужно завершить операцию быстрее, чем система пришлёт вам уведомление.

      Насчёт адресов для сообщений от сервиса — почему их два? Я использовал один, на него приходят все уведомления?
      Вы можете использовать и один адрес. Два для простоты. Один для успешного уведомления, другой для не успешного.

      И ещё одно уточнение
      Да, в данный момент указание адреса для уведомлений нужно задавать через менеджера.
  • 0
    А пункт «4.2. Авторизация при уведомлениях на сервер провайдера» не реализовывали?
    Интересует алгоритм проверки X-Api-Signature
    • 0
      Нет, данный способ не реализовывался.
    • 0
      Пробовал, умаялся с проверкой зашифрованой подписи. Так не смог :(
      начал с такого :)
      $Sig = base64_encode(hash_hmac('sha1', $keys, $password));
      и перепробовал разные комбинации подставлял shop_id, api_id, password для api, password для магазина, к сожалению ничего не вышло.
      • 0
        Буквально недавно озадачился этим же, ну и решение ниже
            public function notify() {
                if (!empty($_SERVER['HTTP_X_API_SIGNATURE'])) {
                    ksort($_POST);
                    $Invoice_parameters_byte = implode('|', $_POST);
                    $Notification_password_byte = $this->getNotifyKey(); // секретная подпись получения от киви
                    $sign = hash_hmac('sha1', $Invoice_parameters_byte, $Notification_password_byte, true);
                    if (strcmp($_SERVER['HTTP_X_API_SIGNATURE'], base64_encode($sign))===0) {
                        return true;
                    }
                }
                return false;
            }
        

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.