PHP-библиотека для работы с API Яндекс.Денег. Вывод сообщений пользователю в веб-приложениях Используйте для сравнения с булевыми значениями строгое сравнение

Всем привет!

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

В мире unix, существует немыслимое множество способов передать команду или сообщение от демона к веб-скрипту и наборот. Но сейчас я хочу рассказать только про очереди сообщений — «System V IPC Messages Queues».

Должно быть, вам в детстве мама уже рассказывала о том, что очереди очереди могут быть как в реализации System V IPC, так и в реализации Posix. Я же хочу затронуть тему только System V, как близкую мне лично. А тему posix, по возможности, буду стараться избегать.

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

На этом вводная часть заканчивается, переходим к практике.

Отправляем сообщения

queue-send.php

Принимаем сообщения

queue-receive.php

Давайте запустим по очереди сперва файл queue-send.php , а затем queue-receive.php .

U% php queue-send.php send 4 messages u% php queue-receive.php type: 1 type: 1, msgtype: 1, message: s:15:"message, type 1"; type: 1, msgtype: 1, message: s:15:"message, type 1"; type: 2 type: 2, msgtype: 2, message: s:15:"message, type 2"; type: 3 type: 3, msgtype: 3, message: s:15:"message, type 3";

Можно заметить, что сообщения были сгруппированы, и сперва было выведено 2 сообщения первого типа, а затем все остальные.
Если же, мы бы указали получать сообщения типа 0, то получили бы все сообщения вне зависимости от типа.

While (msg_receive($queue, $i, $msgtype, 4096, $message, false, MSG_IPC_NOWAIT)) { // ...

Так же, тут стоит заметить ещё одну особенность очереди: если мы уберём константу MSG_IPC_NOWAIT, уберём из скрипта лишнее, и запустим в одном терминале файл queue-receive.php , а в другом будем периодически запускать файл queue-send.php , то мы увидим как демон может эффективно использовать очередь, ожидая из неё задания.

queue-receive-wait.php

Собственно на этом всё самое интересное про очереди я уже рассказал. Ещё есть функции получения статистики очереди, удаление и проверка на существование очереди.

Давайте теперь попробуем написать демона слушающего очередь:
queue-daemon.php

    САМОВОЛЬНИЧАТЬ, самовольничаю, самовольничаешь, несовер. (разг.). Поступать самовольно, вести себя самовольно. Толковый словарь Ушакова. Д.Н. Ушаков. 1935 1940 … Толковый словарь Ушакова

    САМОВОЛЬНИЧАТЬ, аю, аешь; несовер. (разг.). Поступать самовольно. Толковый словарь Ожегова. С.И. Ожегов, Н.Ю. Шведова. 1949 1992 … Толковый словарь Ожегова

    Несов. неперех. разг. Поступать по своему желанию, по своей прихоти. Толковый словарь Ефремовой. Т. Ф. Ефремова. 2000 … Современный толковый словарь русского языка Ефремовой

    Самовольничать, самовольничаю, самовольничаем, самовольничаешь, самовольничаете, самовольничает, самовольничают, самовольничая, самовольничал, самовольничала, самовольничало, самовольничали, самовольничай, самовольничайте, самовольничающий,… … Формы слов

    самовольничать - самов ольничать, аю, ает … Русский орфографический словарь

    самовольничать - (I), самово/льничаю, чаешь, чают … Орфографический словарь русского языка

    Аю, аешь; нсв. Разг. Поступать по своему желанию, по собственной прихоти, не спрашивая разрешения у кого л. С. в гостях. С. на работе. Самовольничай у себя дома. ◁ Самовольничанье, я; ср. Без самовольничанья, пожалуйста, а то уволю! … Энциклопедический словарь

    самовольничать - аю, аешь; нсв.; разг. см. тж. самовольничанье Поступать по своему желанию, по собственной прихоти, не спрашивая разрешения у кого л. Самово/льничать в гостях. Самово/льничать на работе. Самовольничай у себя дома … Словарь многих выражений

Мне давно хотелось попробовать что-нибудь новенькое, и вот, когда на работе предложили написать примеры использования API Яндекс.Денег на разных языках, я с удовольствием принял это предложение-challenge. Так как чаще всего подобный функционал используют в приложениях на различных хостингах, то было принято волевое решение первым делом попробовать написать сие на PHP. Причем API до этого я даже не видел; более того, никакого опыта работы с PHP, кроме как лабораторной в ВУЗе, у меня не было. Дело обещало быть интересным.

Выбор окружения

Первое, с чем я столкнулся: разрабатывать и деплоить тут же на хостинг не очень удобно. И я решил скачать какой-нибудь джентльменский набор для web-разработчика. Из студенческих времен в памяти маячило название Denwer. Попробовал, но быстро отказался от него. Он живет какой-то своей жизнью, и когда я пытался настроить его, переписав что-нибудь в conf-файле Apache, он затирал или не затирал это по своему усмотрению, не давая все настроить руками. То есть получилось, что не я его настраивал, а он меня. Напомнило «если б я имел коня - это был бы номер...». В итоге я его, конечно, победил, но решил при этом найти более простой WAMP-server. Хочу отметить, что Denwer хороший продукт и ничего против я не имею, но читать факи и мануалы по нему мне не захотелось.

Нашел страничку со списком WAMP"ов в вики и стал перебирать их. Основными критерием для выбора были поддерживаемость проекта, чтобы версия сборки была более-менее свежей, и простота установки/запуска. В итоге смело могу рекомендовать The Uniform Server . Он не требует установки (только распаковать архив), при запуске висит в трее и запускается легким нажатием =). Самовольничать он не стал, и я остановился на нем.

Аутентификация OAuth

Почитал инструкции , скачал документацию , оголил шашку и помчался в бой. Но в бою я был быстро повержен OAuth-аутентификацией. OAuth - это способ получить доступ к какому-либо сервису/аккаунту пользователя без ввода и хранения его логина и пароля в своем приложении. Пришло к нам это от создателя твиттера и выглядит примерно так: мы делаем запрос к сервису (в нашем случае – к Яндекс.Деньгам), пользователь вводит на сервере Яндекс.Денег свой логин/пароль и дает нашему приложению разрешения пользоваться его аккаунтом. После этого сервер Яндекс.Денег делает редирект на наше приложение, и мы получаем временный код, время жизни которого очень мало. Затем посредством еще одного запроса к Яндекс.Деньгам меняем этот временный код на постоянный токен пользователя и дальше для нас, как для дембеля, все дороги открыты.

Правда, пока я проходил OAuth-аутентификацию, наткнулся на проблему безопасности. Попробовал обращаться к серверу Яндекс.Денег, но PHP стал грязно ругаться и говорить что-то про сертификаты. Порыскал немного в интернете и понял, что нужно, чтобы наше приложение проверяло SSL-сертификат сервера. Хотелось сделать хорошо, чтобы гарантировать пользователям безопасность, и я продолжил поиски. Но вменяемых примеров реализации проверки сертификата сервера в рунете почти нет. Расскажу по порядку.

Сначала нужно было прописать проверку сертификатов в коде при отправке запросов. Как заставить cURL, которым я пользуюсь, отправлять запросы с проверкой сертификата? Начал искать и был поражен тем, что самый популярный совет при ошибках сертификатов: ОТКЛЮЧИТЬ проверку. И это предлагают на куче сайтов и форумов (к примеру, ). Ужас, в общем. Вот код, который чаще всего предлагают:

Curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

Запомните его, дети, и никогда не пишите. «А теперь, сынок, повторим все те плохие слова, которые ты должен забыть». Слава богу, что в англоязычном интернете не все так плохо и я нашел такую ссылочку , которая все объяснила. Сделал, как там написано, и все заработало.

Затем нужно было сохранить публичный сертификат Яндекс.Денег у себя, чтобы было с чем сравнивать при отправке запросов. Я вроде не совсем отсталый, но тем не менее мне это показалось довольно непростым. Может, вам в будущем поможет при работе с SSL. Заходим на нужный сайт через https, тыкаем в сертификаты и экспортируем. Но их там 3, какой из них нужен? «Возьми с полки пирожок; их там два, возьми средний». Оказывается, нужно экспортировать сертификат центра сертификации (корневой) и промежуточный (Яндекса). Конечный сертификат меняется раз в год и, если впишем его в цепочку и забудем поменять, когда он протухнет, то все в нашем приложении поломается. Поэтому экспортируем только указанные 2 сертификата и просто сохраняем их в один текстовый файл (скриншот). В моей библиотеке он фигурирет как ym.crt .

После этого запросы у меня заработали. Ура! Дальнейшее было делом техники. В документации все было понятно; собственно, поэтому я ее фактически и закопипастил в документацию кода. Оговорюсь еще, что писал я ее как объектную; на мой взгляд, с объектами работать хорошо и удобно.

Шифрование

Еще были небольшие трудности с шифрованием. Сначала сохранение/восстановление токенов пользователей было реализовано стандартной PHP-библиотекой Mcrypt. Но, как выяснилось, с ней есть проблемы. Например, из экзамплов, взятых в мануале, сразу заработала только одна deprecated-функция. Остальные функции плевали на мое желание заставить их работать, и лишь говорили что-то о неудачной инициализации модуля. Надо было разбираться. Затем выяснилось, что хостеры не очень жалуют эту библиотеку. Спросил у поддержки своего хостера , почему при создании сайта на PHP 5.3 нет модуля Mcrypt. Мне ответили (дословно): «Он годами глючил в 5.2 - автоматом не внесли в 5.3 как модуль, о котором вспоминают раз в пять лет, а проблемы с ним были». Других удобных стандартных библиотек с реализацией симметричного шифрования я в PHP не нашел (есть библиотека OpenSSL, но она не совсем для этого). После этого библиотеку шифрования я решил сменить на , которая является открытой и поддерживает популярный алгоритм AES. Она заработала сразу и без проблем.

Функционал и примеры использования

Также для «тренировки на кошках», а точнее — тестирования и отладки, были написаны вызовы функций библиотеки, которые я впоследствии облагородил версткой для приятного глазу вида, наполнил комментариями и обозвал примерами использования библиотеки.

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

  • OAuth-авторизация пользователя;
  • безопасность работы (поддерживается проверка цепочки сертификатов);
  • удобство работы (response"ы сервера представлены в виде объектов) и быстрый старт;
  • относительно безопасное и простое решение хранения токенов пользователей с использованием шифрования и без использования БД. Реализацию этого решения вы сможете легко переписать под свои хранилища.
Сама библиотека представляет собой файл цепочки сертификатов ym.crt и файл ym.php , который содержит:
  • программный интерфейс IYandexMoney;
  • главный класс YandexMoney (реализация интерфейса);
  • класс-перечисление с правами доступа (scope);
  • вспомогательные классы (response-объекты вывода результатов запросов к API).
В комплект библиотеки приложены 2 файла, которые реализуют шифрование: Rijndael.php и AES.php. Данные файлы взяты из библиотеки . Они нужны на случай, если вы будете использовать методы сохранения и восстановления токенов.
Внимание: использует PHP версии 5, а также стандартную библиотеку cUrl для http-запросов.

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

YandexMoney::authorize(Consts::CLIENT_ID, "account-info operation-history", Consts::REDIRECT_URL); // затем на странице редиректа инициировать создание объекта и получение токена $ym = new YandexMoney(Consts::CLIENT_ID, Consts::CERTIFICATE_CHAIN_PATH); $token = $ym->receiveOAuthToken($_GET["code"], Consts::REDIRECT_URL);
При создании объекта $ym ему передается идентификатор приложения и абсолютный путь на сервере к цепочке сертификатов (файл ym.crt). И то, и другое обычно прописывается в константах в каком-нибудь модуле (consts.php в наших примерах).
Ну и покажем, как получить информацию о счете пользователя. Таким же образом создаем объект и затем вызываем метод, передав ему токен пользователя:

$ym = new YandexMoney(Consts::CLIENT_ID, Consts::CERTIFICATE_CHAIN_PATH); $accountInfoResponse = $ym->accountInfo($token); echo "Номер счета: " . $accountInfoResponse->getAccount() . "\n"; echo "Баланс: " . $accountInfoResponse->getBalance() . "\n"; echo "Код валюты: " . $accountInfoResponse->getCurrency() . "\n";
Информация о счете получена.

Примерно так же обстоят дела и с другими вызовами.

В итоге, библиотеку решили назвать громким именем SDK и выложить на