Введение
Мы уже рассказывали о сервисе автоматического приема платежей WebMoney Merchant. Напомним, он позволяет организовать прием WM-платежей на сайте без участия человека. Однако, у интернет-бизнесменов часто возникает необходимость автоматизировать другие операции со своими WebMoney-кошельками. Например, автоматически отправлять покупателю сообщение по внутренней WM-почте, делать выплаты по партнерской программе или выплачивать выигрыши в онлайн-играх, запрашивать баланс своих кошельков, проверять правильность введенного пользователем WM-идентификатора и т.д.
Любая автоматизация упрощает жизнь, позволяет не отвлекаться на рутину, избежать человеческих ошибок. Еще Генри Форд понял, что там, где людей можно заменить роботами, - это нужно делать обязательно.
WebMoney в этом смысле дает нам отличнейшие и не имеющие аналогов инструменты. Почти все процессы, происходящие на вашем web-сервисе и связанные с WebMoney, можно авторматизировать, сделать моментальными, заставить их работать круглые сутки и без какого-либо вашего вмешательства. Для этого нужно всего лишь "научить" ваш сайт "общаться" с сервером WebMoney и отдавать ему команды.
Этот язык общения и команд описывается специальными правилами, которые называются XML-интерфейсами. Данным материалом мы открываем цикл статей, в которых научим вас использовать XML-интерфейсы WebMoney во благо вашего интернет-бизнеса. Немного терпения, немного практики веб-программирования - и через некоторое время работать за вас будут уже роботы. А освободившееся время предлагаю уделить любви или спорту, либо тому и другому сразу :-)
Что понадобится для работы?
Итак, первый вопрос на повестке дня - что нужно знать и уметь, чтобы разобраться в XML-интерфейсах? Безусловно, нужно уметь программировать на одном из серверных языков (PHP, ASP, Perl и т.д.) На каком уровне? Пожалуй, на среднем или даже ниже среднего. Там, где ваших знаний будет не хватать - вам помогут примеры, которыми наш материал будет обильно сдобрен.
Гораздо важнее, чтобы вы понимали: как устроено дерево каталогов на сервере, что такое права доступа к файлам, что такое FTP и shell, как передается информация между серверами в интернете, что такое методы POST и GET, наконец, что такое XML. Конечно, мы будем давать комментарии некоторым понятиям, но тем, кто всё это уже знает, - будет намного проще.
Все программные примеры мы будем приводить на языке PHP. Платформа - ОС FreeBSD. Сегодня это наиболее распространенная "связка". Информацию по работе с WMSigner на платформе .Net вы сможете найти на сайте www.wmsigner.com
Важное замечание! Для работы XML-интерфейсов нужен персональный аттестат. Если у вас его еще нет - поспешите получить. Для первой статьи (которую вы сейчас читаете) аттестат не понадобится, а вот для следующих уже будет нужен.
Еще одно замечание перед тем, как мы начнем. При работе с XML-интерфейсами могут использоваться ключи Keeper Classic или сертификаты Keeper Light - на ваш выбор. Результат один и тот же, но вот конкретная реализация немного отличается. Мы будем демонстрировать реализацию XML-интерфейсов на примерах с ключами Keeper Classic. Тот, кто пользуется Лайтом, как вариант, может зарегистрировать новый WMID в Keeper Classic и присоединить его к своему аттестату.
Установка WMSigner
В этой статье нам предстоит познакомиться с модулем аутентификации WMSigner. Он понадобится для работы XML-интерфейсов.
Отыщите ваш файл ключей .kwm. Как вы знаете, он был создан при регистрации Keeper Classic. Отыскали? Теперь вспомните код доступа к файлу ключей. И то, и другое нам понадобится. Те, кто не смог найти файл или вспомнить код доступа - войдите в Кипер и нажмите Инструменты - Параметры программы - Безопасность - Сохранить ключи в файл, сохраните файл ключей, назначьте пароль доступа. И больше их не теряйте.
Файл .kwm имеет размер 164 байта. В нем содержится закрытый ключ пользователя WebMoney. Информация шифруется закрытым ключем, передается в таком виде на сервер WebMoney, где расшифровывается открытым ключем. Так WebMoney проверяет авторство информации и убеждается в том, что она передана верно, без искажений. Это принцип ассиметричного шифрования.
При работе с Keeper Classiс сообщения, посылаемые к WebMoney, шифрует сам Кипер. В случае с XML-интерфейсами обмен информацией происходит по принципу "сервер-сервер", а не "Кипер-сервер", а в качестве шифровальщика выступает модуль WMSigner.
Скомпилируем WMSigner на сервере. Для этого скачаем последнюю версию WMSigner (на момент написания статьи это версия 2.0) отсюда, например, в zip-архиве. Распакуем содержимое архива и зальем его по FTP в любое место на сервере.
Приступим к компиляции. Для этого нам понадобится доступ к shell.
Примечание! Для доступа к серверной консоли (shell) рекомендуем использовать программу putty. Доступ к shell должен быть предоставлен вашим хостинг-провайдером. Если провайдер не предоставил доступ, попросите его скомпилировать модуль WMSigner за вас. Напомним основные shell-команды в FreeBSD, которые, возможно, понадобятся вам для работы: cd каталог - переход в заданный каталог; для перехода в каталог на уровень выше набирайте cd .. ; ls - просмотр содержимого текущего каталога; pwd - просмотр пути к текущему каталогу.
Войдем в shell, с помощью команды cd доберемся до каталога, куда мы только что залили исходники WMSigner'а. Наберем в командной строке:
$ make
Через пару секунд компиляция завершена. В том же каталоге появился файл wmsigner. Все файлы и подкаталоги с исходниками WMSigner'а теперь можно удалить, они своё отработали и нам больше не понадобятся.
Прежде чем двигаться дальше, давайте разберемся со структурой каталогов на сервере. Пусть на нашем условном сервере файлы, доступные через web, лежат в каталоге /home/site.ru/data/htdocs/. Там же будут находиться и php-скрипты, работающие с XML-интерфейсами. Из соображений безопасности очень желательно разместить WMSigner таким образом, чтобы он не был недоступен из web'a. Поэтому создадим, например, каталог /home/site.ru/data/signer/. Сделать это можно через FTP или shell.
Если по какой-то причине у вас нет возможности создавать каталоги выше директории web-документов, то вы можете создать подкаталог /home/site.ru/data/htdocs/что-то/, где вместо "что-то" - директория с очень сложным именем, чтобы его было тяжело определить методом подбора. Кроме того, обязательно поместите в эту директорию файл .htaccess, запрещающий web-доступ к содержимому директории. В противном случае, ваши секретные файлы, которые будут находиться в этом каталоге, могут быть скачаны злоумышленником прямо с вашего сайта. Приводим текст файла .htaccess для такого случая. Он состоит всего из 2-х строк:
Order Allow,Deny Deny from All
Скопируем WMSigner в только что созданную директорию /home/site.ru/data/signer/
Поместим в тот же каталог файл ключей .kwm.
Создадим в той же директории /home/site.ru/data/signer/ файл wmsigner.ini с 3 строками текста:
ваш WMID код доступа к ключам путь к файлу .kwm
Пусть, наш WMID - 123456789012, код доступа - akwru3kdn, а файл ключей называется 123456789012.kwm. Тогда содержимое wmsigner.ini должно быть таким:
123456789012 akwru3kdn 123456789012.kwm
Либо таким:
123456789012 akwru3kdn /home/site.ru/data/signer/123456789012.kwm
Итак, в каталоге /home/site.ru/data/signer/ находится 3 файла: модуль подписи wmsigner, файл ключей .kwm, файл wmsigner.ini. Если они попадут в руки злоумышленника, он сможет подключиться к вашим кошелькам. Поэтому эти файлы нужно тщательно беречь. И именно поэтому мы не стали помещать их в каталог с web-документами, откуда они могли быть скачаны кем-угодно прямо с вашего сайта, а разместили их выше в древе каталогов сервера.
Примечание! 123456789012.kwm может находиться и в другой директории, лежать отдельно от wmsigner.ini и wmsigner. Вам всего лишь нужно прописать правильный путь к нему в wmsigner.ini. Однако, где бы ни находился .kwm, вы должны помнить, что он содержит секретный ключ, и применять к нему меры защиты, в том числе те, которые мы описали выше. Wmsigner и wmsigner.ini должны обязательно находиться в одном каталоге.
Наконец, установим правильные атрибуты на файлы wmsigner, wmsigner.ini и 123456789012.kwm. Сделать это можно из FTP-менеджера (Total Commander, FAR и др.), либо через shell. Для wmsigner нужно разрешить выполнение. Для wmsigner.ini и 123456789012.kwm будет достаточным разрешение только на чтение и только владельцем. Для установки таких прав доступа через shell перейдите в каталог /home/site.ru/data/signer/ и выполните там команды:
$ chmod 111 wmsigner $ chmod 400 wmsigner.ini $ chmod 400 123456789012.kwm
Тестирование WMSigner в shell
Перейдем к тестированию. Чтобы убедиться в работоспособности скомилированного только что модуля WMSigner, дадим ему на вход строку, которую он должен подписать. На выходе получим строку, сформированную в результате подписывания входной строки вашим закрытым ключем. Формат входной строки такой: строка_для_подписывания �04rn
Примечание! Даже при подаче одинаковой входной строки, строка подписи будет каждый раз разная, так как при ее формировании используется текущая метка времени.
Продемонстрируем. В shell'e перейдем в каталог /home/site.ru/data/signer/ и выполним команду:
$ echo -ne "TestString123�04rn" | ./wmsigner
Если в ответ получена длинная цифр и букв - значит всё в порядке, wmsigner работает правильно. Если получена ошибка - значит что-то не так. Перечень возможных ошибок:
- Error 20 - Невозможно загрузить конфигурационный файл wmsigner.ini. Возможно, он отсутствует в той же директории, что и wmsigner.
- !LoadKeys Error 2 - Невозможно загрузить файл ключей. Возможно, он отсутстует по тому пути, который указан в wmsigner.ini, или имеет другое название.
- Error -3 - Код доступа неверный. Возможно, Вы используете пароль на вход в Кипер, а не код доступа.
- Error -4 - Не задан WMID.
- Error -5 - Не задан код доступа.
- Error -6 - Не задан файл ключей.
Что происходит при формировании строки подписи? 1) wmsigner ищет файл wmsigner.ini в том же каталоге, где лежит он сам; 2) wmsigner берет из wmsigner.ini WMID, код доступа и путь к файлу .kwm; 3) wmsigner обращается к файлу kwm, чтобы подписать строку.
Тестирование WMSigner в PHP
Теперь то же самое сделаем из PHP. Создадим файл wmxml.inc.php, куда будем складывать все функции, необходимые нам для работы с XML-интерфейсами WebMoney. Этот файл будем вызывать ("инклудить") из наших php-скриптов там, где это нужно. Первой функцией, которую мы создаем в wmxml.inc.php, будет функция _GetSign(). Она будет делать то же самое, что мы только что проделали через shell: получать на вход строку для подписи, вызывать WMSigner, получать результаты его работы и отдавать на выходе строку с результатом подписывания.
array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "r") ); $process = proc_open($Path_Signer, $descriptorspec, $pipes); fwrite($pipes[0], "$inStr�04rn"); fclose($pipes[0]); $s = fgets($pipes[1], 133); fclose($pipes[1]); $return_value = proc_close($process); return $s; } ?>
Создадим также скрипт test.php, подключающий wmxml.inc.php и вызывающий функцию _GetSign():
Оба файла поместим в каталог web-документов /home/site.ru/data/htdocs/, запустим test.php. Если строка с подписью отобразилась, значит всё работает нормально.
Теперь остановимся и обратим внимание на два момента. Момент первый. Зачем эта строка в функции _GetSign():
chdir($Path_Folder);
Дело в том, что когда запускается скрипт test.php, то текущим рабочим каталогом является каталог, в котором находится сам скрипт, то есть /home/site.ru/data/htdocs/. Вызваный функцией _GetSign() WMSigner находит в своем каталоге wmsigner.ini, считывает из него путь к ключам 123456789012.kwm и пытается найти его начиная от текущего рабочего каталога, то есть по адресу /home/site.ru/data/htdocs/123456789012.kwm. Там он его, естественно, не обнаруживает.
Для того, чтобы WMSigner правильно нашел файл ключей, мы с помощью php-функции chdir() принудительно установливаем в качестве текущего каталога директорию, в которой находится 123456789012.kwm. Директорию эту мы заранее прописываем в переменную $Path_Folder.
Другой вариант решения вопроса: в wmsigner.ini сразу прописывать полный путь к файлу .kwm начиная от корня сервера (см. пример). Тогда WMSigner будет всегда точно знать, где ему искать .kwm. В этом случае вызов chdir($Path_Folder) можно не использовать.
Момент второй - это использованная php-функция proc_open() . Она появилась в PHP версии 4.3.0. Если у вас установлен PHP более старой версии, вы можете применять php-функцию popen() . C ней пользовательская функция формирования подписи _GetSign() будет выглядеть так:
// АЛЬТЕРНАТИВНАЯ ФУНКЦИЯ ПОДПИСИ ДЛЯ PHP НИЖЕ 4.3.0 // На входе: строка для подписи. На выходе: строка с результатом function _GetSign($inStr){ global $Path_Folder, $Path_Signer; chdir($Path_Folder); $PlanStr = "$inStr�04rn"; $fp = popen($Path_Signer, "r+"); fwrite($fp,$PlanStr); $s = fgets($fp, 133); pclose($fp); return $s; }
Примечание! Проверить доступность той или иной функции в вашей сборке PHP можно стандартной php-функцией function_exists(), например: function_exists("proc_open"). Если получаем в ответ TRUE ("1"), то функция proc_open() доступна.
Вызовы WMSigner с опциями командной строки
Мы познакомились со стандратным вызовом модуля WMSigner, когда "на вход" ему подается только строка для подписи, а все остальные данные модуль пытается отыскать самостоятельно. Напомним, как ведет себя WMSigner "по умолчанию": 1) ищет файл wmsigner.ini в своем каталоге; 2) читает из wmsigner.ini WMID, код доступа и путь к файлу .kwm; 3) обращается к файлу .kwm, чтобы сформировать подпись.
Как видим, никакой особой гибкости и адаптируемости под нужды программиста здесь нет. Однако, на самом деле, так шаблонно WMSigner ведет себя только "по умолчанию", и с помощью параметров командной строки можно полностью управлять его поведением.
Вот какие опции поддерживаются:
-i [ini-path] -- путь к ini-файлу;
-w [wmid] -- WMID;
-p [password] -- код доступа;
-k [key-path] -- путь к файлу ключей;
-K64 [key-base64] -- ключ (содержимое файла .kwm) в base64 закодированном виде;
-s [sign] -- строка для подписи.
Приведем пример. Для этого снова зайдем через shell в каталог /home/site.ru/data/signer/, где лежит wmsigner. Напомню, раньше мы делали стандартный вызов:
$ echo -ne "TestString123�04rn" | ./wmsigner
Но мы можем, например, передать ему на вход параметр -i и указать путь к ini-файлу. В следующем примере wmsigner получает команду искать не wmsigner.ini, а my.ini в той же директории, где лежит он сам:
$ echo -ne "TestString123�04rn" | ./wmsigner -i my.ini
А так wmsigner будет искать не wmsigner.ini, а /home/site.ru/trulala.goaway (обратите внимание, что конфигурационный ini-файл может иметь расширение, отличное от "ini" или даже вообще не иметь расширения!):
$ echo -ne "TestString123�04rn" | ./wmsigner -i /home/site.ru/trulala.goaway
Но использовать ini-файл вообще не обязательно. Можно передать все три необходимых параметра - WMID, код доступа и путь к ключам - прямо на вход модуля аутентификации, вот так:
$ echo -ne "TestString123�04rn" | ./wmsigner -w 123456789012 -p akwru3kdn -k 123456789012.kwm
Но и это еще не всё. Можно вообще не держать файл .kwm на сервере, а передавать на вход WMSigner'у ключ в кодировке Base64, интерпретирующей байтовую информацию в ввиде последовательности простых символов, через опцию командной строки -K64:
$ echo -ne "TestString123�04rn" | ./wmsigner -w 123456789012 -p akwru3kdn -K64 здесь_длинная_ последовательность_символов_в_кодировке_base64
Для полноты картины продемонстрируем, как сконвертировать бинарный файл .kwm в кодировку Base64. Это можно сделать с помощью такого php-кода:
В переменную $b64 запишется содержимое нашего файла 123456789012.kwm, кодированное в Base64.
Такой подход при работе с WMSigner, когда все необходимые параметры передаются ему через командную строку, имеет много преимуществ. Мы можем хранить ini-файл и файл ключей в любом месте на сервере, где нам только заблагорассудится. Можем давать им произвольные названия. Можем вообще не хранить эти файлы на сервере, а вместо этого "вшивать" wmid, код доступа и ключ прямо в код программы. Можем держать их в базе данных. Можем применять дополнительное шифрование и другие методы защиты.
Возвращаясь к нашей функции формирования подписи _GetSign(), вызов wmsigner с опциями командной строки отразиться только на одной строке php-кода:
$process = proc_open($Path_Signer." -опция параметр -опция параметр ...", $descriptorspec, $pipes);
То есть видоизмененная функция _GetSign будет выглядеть, например, так:
array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "r") ); $process = proc_open($Path_Signer." -w 123456789012 -p akwru3kdn -k 123456789012.kwm", $descriptorspec, $pipes); fwrite($pipes[0], "$inStr�04rn"); fclose($pipes[0]); $s = fgets($pipes[1], 133); fclose($pipes[1]); $return_value = proc_close($process); return $s; } ?>
На этом всё. В ближайшие дни читайте следующую статью, в которой мы перейдем к изучению непосредственно самих XML-интерфейсов WebMoney. Скомпилированный и настроенный WMSigner, а также функция _GetSign() нам в этом пригодятся.
Спасибо автору Никите Сенченко (owebmoney.ru)
|