о WebMoney
Информационный портал о WebMoney
  
  
подписка  
реклама здесь 
обратная связь 
  Материалы      Вопросы и ответы     Курс обучения      Файлы
 Кофейня      WebMoney TOP      p2p      WM-Клуб      Гид   

XML-интерфейсы WebMoney. Часть 2. X2, X6, X8, X11.

© Никита Сенченко

<<XML-интерфейсы WebMoney. Часть 1. WMSigner.

XML-интерфейсы
Начало работы
Интерфейс X2. Отправка переводов.
Интерфейс X6. Отправка сообщений.
Интерфейс X8. Определение принадлежности кошелька.
Интерфейс X11. Получение аттестационной информации.

В первой статье мы познакомились с модулем аутентификации WMSigner и создали php-функции для работы c ним и получения электронной подписи. На данный момент у нас есть: установленный на сервере, настроенный и работающий WMSigner, а также скрипт с функциями wmxml.inc.php.

Теперь можно переходить непосредственно к изучению XML-интерфейсов WebMoney.

XML-интерфейсы

Как мы уже говорили, XML-интерфейсы WebMoney - это "язык", на котором ваш сайт может "общаться" с сервером WebMoney от вашего имени и отдавать ему команды на совершение тех или иных действий. Использование XML-интерфейсов позволяет автоматизировать все процессы на вашем сайте, связанные с WebMoney. А именно:

Название XML-интерфейса Что делает Куда обращается
X1 описание выписывает счет другому пользователю WebMoney от вашего WMID на специальный сервер w3s.webmoney.ru
X2 описание выполняет перевод с вашего кошелька на специальный сервер w3s.webmoney.ru
X3 описание получает историю транзакций по кошельку на специальный сервер w3s.webmoney.ru
X4 описание получает историю исходящих (выписанных вами) счетов на специальный сервер w3s.webmoney.ru
X5 описание завершает входящий перевод с протекцией на специальный сервер w3s.webmoney.ru
X6 описание отправляет сообщение по внутренней WM-почте на специальный сервер w3s.webmoney.ru
X7 описание производит авторизацию пользователя Keeper Classic на вашем сайте на специальный сервер w3s.webmoney.ru
X8 описание проверяет существование в системе WMID/кошелька; получает WMID, соответствующий кошельку на специальный сервер w3s.webmoney.ru
X9 описание получает текущий баланс на вашем кошельке на специальный сервер w3s.webmoney.ru
X10 описание получает историю входящих (выписанных вам) счетов на специальный сервер w3s.webmoney.ru
X11 описание получает аттестационную информацию заданного WMID на сервер Центра Аттестации passport.webmoney.ru
X12 описание импортирует выписку по кошельку в 1С Предприятие ---
X13 описание возвращает перевод с протекцией (по коду или по времени) отправителю на специальный сервер w3s.webmoney.ru
X14 описание возвращает перевод отправителю (в течение 14 дней) без потери комиссии на специальный сервер w3s.webmoney.ru
X15 описание управляет настройками доверия (то, что в ручном режиме делается на security.webmoney.ru) на специальный сервер w3s.webmoney.ru
X16 описание создает кошельки на специальный сервер w3s.webmoney.ru
X17 описание оперирует с арбитражными контрактами на сервер Арбитража arbitrage.webmoney.ru
X18 описание получает детали платежа WebMoney Merchant на сервер WM Merchant merchant.webmoney.ru
X19 описание проверяет соответствие данных из аттестата на сервер Центра Аттестации passport.webmoney.ru

Почти все интерфейсы требуют наличия персонального аттестата. Кроме того, некоторые интерфейсы перед началом использования нужно активировать, отправив на WMID техподдержки 941977853154 запрос с указанием: url сайта, IP-адреса сервера, краткой информации о вашем веб-проекте, в каких целях будет использоваться интерфейс.

Начало работы

Все XML-интерфейсы работают по следующему принципу:

  1. Вы формируете на своем сайте XML-пакет, содержащий параметры запроса (например: "отправить сообщение с текстом text пользователю wmid"). В запрос вы вставляете также электронную подпись XML-пакета, сформированную модулем WMSigner. Это позволяет посылать запросы только от имени вашего WMID.
  2. Сформированный XML-пакет направляете серверу WebMoney методом POST.
  3. Сервер WebMoney расшифровывает подпись вашего XML-запроса и убеждается, что запрос прислали именно вы. Таким образом, никто кроме вас не сможет, например, от вашего имени списать деньги с вашего кошелька. Но и вы не сможете списать деньги с чужого кошелька от лица его владельца.
  4. Если валидность подписи установлена и запрос составлен верно, то сервер WebMoney выполняет запрос и отвечает вам XML-пакетом, содержащим результаты выполнения запроса (например: "успешно отправил сообщение с текстом text пользователю wmid и датировал датой date").
  5. Разбираете (парсите) ответ так, как вам это нужно.

Итак, нам нужно выполнить 3 действия: сформировать XML-запрос, отправить его серверу WebMoney и получить ответ, разобрать XML-ответ. Сформировать. Отправить и получить. Разобрать.

Формировать запрос можно любым методом, главное, чтобы сформированный XML-пакет отвечал требованиям стандарта XML. Можно воспользоваться функциями DOM/DOM XML для PHP, однако мы поступим проще. Формировать тело запроса будем прямо в строке скрипта, например:

// некий xml-пакет записываем в переменную $xml $xml=" <root_element> <elem id='1'> <param1>...</param1> <param2>...</param2> </elem> </root_element> ";

При рассмотрении конкретных интерфейсов мы увидим, что почти все они требуют обязательного указания в XML-запросе поля <reqn> с уникальным номером запроса. Причем, каждый новый запрос должен содержать reqn больший, чем в предыдущем запросе. Сам reqn должен быть целым числом и иметь до 15 цифр. Для генерации такого номера удобно использовать функцию, основанную на текущей отметке времени, которая, как известно, постоянно растет и никогда не повторяется. Чтобы два запроса, отправленные в одну секунду, не получили одинаковый reqn, будем брать эту отметку с точностью до микросекунд.

Поместим такую функцию в наш wmxml.inc.php:

// ФУНКЦИЯ ФОРМИРУЕТ УНИКАЛЬНЫЙ УВЕЛИЧИВАЮЩИЙСЯ REQN function _GetReqn(){ $time=microtime(); $int=substr($time,11); $flo=substr($time,2,5); return $int.$flo; };

Внимание! Не начинайте экспериментировать с XML-интерфейсами WebMoney без этой функции! Если вы хотя бы раз передадите большой reqn (например, 777777777777777), то в дальнейшем не сможете передавать reqn, который будет меньше этого. В такой ситуации вам придется либо изобретать функцию, генерирующую постоянно растущий reqn больше 777777777777777, либо писать в тех. поддержку с просьбой обнулить для вас счетчик reqn.

Итак, как сформировать пакет - понятно. Теперь его нужно передать серверу WebMoney. Делать это нужно методом POST. Есть несколько вариантов реализации. Мы воспользуемся библиотекой libcurl (CURL). Как правило, она включена в сборку PHP даже на недорогих виртуальных хостингах. Проверить, включена ли поддержка CURL на вашем сервере, можно с помощью функции phpinfo() или так: echo function_exists("curl_init");.

Напишем функцию _GetAnswer(), которая будет отправлять на сервер WebMoney XML-пакет с запросом и получать ответ. Включим функцию в наш модульный файл wmxml.inc.php.

// ОТПРАВКА POST-ЗАПРОСА ЧЕРЕЗ CURL // На входе: URL для отправки и содержимое XML-запроса. На выходе: XML-ответ от WebMoney function _GetAnswer($address, $xml){ global $Path_Certs; // Инициализируем сеанс CURL $ch = curl_init($address); // В выводе CURL http-заголовки не нужны curl_setopt($ch, CURLOPT_HEADER, 0); // Возвращать результат, а не выводить его в браузер curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // Метод http-запроса - POST curl_setopt($ch, CURLOPT_POST,1); // Что передаем? curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); // Проверяем корневой сертификат сервера WebMoney curl_setopt($ch, CURLOPT_CAINFO, $Path_Certs); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE); // Выполняем запрос, ответ помещаем в переменную $result; $result=curl_exec($ch); return $result; }

Чтобы (в целях безопасностии и защиты от DNS-атак) во время сеанса CURL мог проверить валидность сертификата на сервере WebMoney, мы используем аргументы CURLOPT_CAINFO и CURLOPT_SSL_VERIFYPEER. Для этого скачиваем файл с корневыми сертификатами, которые используются на серверах WebMoney, заливаем его в любой каталог на своём сервере (например, /home/site.ru/data/certs/). Путь к файлу прописываем в переменной $Path_Certs нашей библиотеки wmxml.inc.php:

// путь к файлу с корневыми сертификатами $Path_Certs="/home/site.ru/data/certs/WMunited.cer";

На вход функции _GetAnswer() подается не только XML-пакет с запросом, но и URL на сервере WebMoney, куда нужно передавать этот пакет. Для каждого интерфейса URL свой, отдельный. Создадим в файле wmxml.inc.php массив с адресами всех интерфейсов для удобства:

$XML_addr[1]="https://w3s.webmoney.ru/asp/XMLInvoice.asp"; $XML_addr[2]="https://w3s.webmoney.ru/asp/XMLTrans.asp"; $XML_addr[3]="https://w3s.webmoney.ru/asp/XMLOperations.asp"; $XML_addr[4]="https://w3s.webmoney.ru/asp/XMLOutInvoices.asp"; $XML_addr[5]="https://w3s.webmoney.ru/asp/XMLFinishProtect.asp"; ... и т.д.

Функция _GetAnswer() получает ответ от сервера WebMoney и возвращает его на выходе:

$result=curl_exec($ch); return $result;

Переходим к последнему этапу. Ответ имеет вид XML-пакета. Нам нужно прочитать из него те поля, которые нам нужны, то есть разобрать (отпарсить) XML. Сделать это можно любым XML-разборщиком PHP: DOM XML, libxml, XML expat parsers и др. Автор этой статьи привык работать с простой и удобной библиотекой SimpleXML (поддерживается только в PHP5, но не в PHP4), поэтому все примеры в статье будут написаны с использованием функций именно этой библиотеки. Вы можете ко мне присоединиться, либо выбрать другое средство разбора XML, которое вам по душе.

На данный момент наш модульный файл wmxml.inc.php содержит следующий код:

// wmxml.inc.php - файл с функциями // БЛОК КОНСТАНТ $Global_WMID="XXXXXXXXXXXX"; // Ваш WMID $Path_Folder = "/home/site.ru/data/signer/"; // Путь к директории, в которой лежит .kwm $Path_Signer = "/home/site.ru/data/signer/wmsigner"; // Путь к WMSigner $Path_Certs="/home/site.ru/data/certs/WMunited.cer"; // путь к файлу с корневыми сертификатами // URL интерфейсов $XML_addr[1]="https://w3s.webmoney.ru/asp/XMLInvoice.asp"; $XML_addr[2]="https://w3s.webmoney.ru/asp/XMLTrans.asp"; $XML_addr[3]="https://w3s.webmoney.ru/asp/XMLOperations.asp"; $XML_addr[4]="https://w3s.webmoney.ru/asp/XMLOutInvoices.asp"; $XML_addr[5]="https://w3s.webmoney.ru/asp/XMLFinishProtect.asp"; $XML_addr[6]="https://w3s.webmoney.ru/asp/XMLSendMsg.asp"; $XML_addr[7]="https://w3s.webmoney.ru/asp/XMLClassicAuth.asp"; $XML_addr[8]="https://w3s.webmoney.ru/asp/XMLFindWMPurse.asp"; $XML_addr[9]="https://w3s.webmoney.ru/asp/XMLPurses.asp"; $XML_addr[10]="https://w3s.webmoney.ru/asp/XMLInInvoices.asp"; $XML_addr[11]="https://passport.webmoney.ru/asp/XMLGetWMPassport.asp"; $XML_addr[13]="https://w3s.webmoney.ru/asp/XMLRejectProtect.asp"; $XML_addr[14]="https://w3s.webmoney.ru/asp/XMLTransMoneyback.asp"; $XML_addr[151]="https://w3s.webmoney.ru/asp/XMLTrustList.asp"; $XML_addr[152]="https://w3s.webmoney.ru/asp/XMLTrustList2.asp"; $XML_addr[153]="https://w3s.webmoney.ru/asp/XMLTrustSave2.asp"; $XML_addr[16]="https://w3s.webmoney.ru/asp/XMLCreatePurse.asp"; $XML_addr[171]="https://arbitrage.webmoney.ru/xml/X17_CreateContract.aspx"; $XML_addr[172]="https://arbitrage.webmoney.ru/xml/X17_GetContractInfo.aspx"; $XML_addr[18]="https://merchant.webmoney.ru/conf/xml/XMLTransGet.asp"; $XML_addr[19]="https://passport.webmoney.ru/XML/XMLCheckUser.aspx"; // ФУНКЦИЯ ФОРМИРУЕТ УНИКАЛЬНЫЙ УВЕЛИЧИВАЮЩИЙСЯ REQN function _GetReqn(){ $time=microtime(); $int=substr($time,11); $flo=substr($time,2,5); return $int.$flo; }; // ФУНКЦИЯ ФОРМИРОВАНИЯ ПОДПИСИ // На входе: строка для подписи. На выходе: строка с результатом подписывания function _GetSign($inStr) { global $Path_Folder, $Path_Signer; chdir($Path_Folder); $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "r") ); $process = proc_open($Path_Signer, $descriptorspec, $pipes); fwrite($pipes[0], "$inStr\004\r\n"); fclose($pipes[0]); $s = fgets($pipes[1], 133); fclose($pipes[1]); $return_value = proc_close($process); return $s; } // АЛЬТЕРНАТИВНАЯ ФУНКЦИЯ ПОДПИСИ ДЛЯ PHP НИЖЕ 4.3.0 // На входе: строка для подписи. На выходе: строка с результатом подписывания function _GetSign2($inStr){ global $Path_Folder, $Path_Signer; chdir($Path_Folder); $PlanStr = "$inStr\004\r\n"; $fp = popen($Path_Signer, "r+"); fwrite($fp,$PlanStr); $s = fgets($fp, 133); pclose($fp); return $s; } // ОТПРАВКА POST-ЗАПРОСА ЧЕРЕЗ CURL // На входе: URL для отправки и содержимое XML-запроса. На выходе: XML-ответ от WebMoney function _GetAnswer($address, $xml){ global $Path_Certs; // Инициализируем сеанс CURL $ch = curl_init($address); // В выводе CURL http-заголовки не нужны curl_setopt($ch, CURLOPT_HEADER, 0); // Возвращать результат, а не выводить его в браузер curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); // Метод http-запроса - POST curl_setopt($ch, CURLOPT_POST,1); // Что передаем? curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); // Проверяем корневой сертификат сервера WebMoney curl_setopt($ch, CURLOPT_CAINFO, $Path_Certs); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE); // Выполняем запрос, ответ помещаем в переменную $result; $result=curl_exec($ch); return $result; }

Ниже мы познакомимся с некоторыми XML-интерфейсами WebMoney. Надеюсь, вы поймете смысл того, что мы делаем, и сможете наладить работу с остальными интерфейсами самостоятельно.

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

Интерфейс X2. Отправка переводов.

С помощью этого интерфейса вы можете переводить средства со своего кошелька. Полное описание интерфейса находится здесь. Интерфейс требует включения путем обращения в службу поддержку WMID 941977853154.

Наш XML-запрос должен выглядеть так:

<w3s.request> <reqn></reqn> <wmid></wmid> <sign></sign> <trans> <tranid></tranid> <pursesrc></pursesrc> <pursedest></pursedest> <amount></amount> <period></period> <pcode></pcode> <desc></desc> <wminvid></wminvid> <onlyauth></onlyauth> </trans> </w3s.request>

Что означают параметры:

  • reqn - номер запроса, всякий раз должен быть больше предыдущего;
  • wmid - ваш WMID;
  • sign - подпись запроса, сформированная из параметров: reqn + tranid + pursesrc + pursedest + amount + period + pcode + desc + wminvid;
  • tranid - уникальный номер перевода;
  • pursesrc - номер вашего кошелька, с которого выполняется перевод;
  • pursedest - номер кошелька, на который выполняется перевод;
  • amount - сумма перевода;
  • period - срок протекции в днях;
  • pcode - код протекции;
  • desc - примечание перевода;
  • wminvid - номер счета в системе WebMoney, по которому выполняется перевод;
  • onlyauth - признак, который определяет, будет ли выполнен перевод, если получатель запрещает входящие переводы.

Формат ответа сервера WebMoney можно посмотреть в описании интерфейса. Нас интересует, фактически, только одно поле ответа - <retval>. Если оно равно 0, то запрос выполнен успешно. В противном случае, оно будет содержать код ошибки, расшифровку которой можно посмотреть в том же описании.

Приведем теперь полностью функцию, которая реализует работу с интерфейсом X2 и добавим её в wmxml.inc.php:

// ИНТЕРФЕЙС X2. ОТПРАВКА ПЕРЕВОДА. // На выходе: массив ['retval'=>код выполнения, 'retdesc'=>описание результата, 'date'=>дата и время] function _WMXML2 ($tranid,$purse,$rpurse,$amount,$period,$pcode,$desc,$wminvid,$onlyauth) { global $Global_WMID, $XML_addr; $reqn=_GetReqn(); $desc=trim($desc); $pcode=trim($pcode); $amount=floatval($amount); $rsign=_GetSign($reqn.$tranid.$purse.$rpurse.$amount.$period.$pcode.$desc.$wminvid); $pcode=htmlspecialchars($pcode, ENT_QUOTES); $desc=htmlspecialchars($desc, ENT_QUOTES); $pcode=iconv("CP1251", "UTF-8", $pcode); $desc=iconv("CP1251", "UTF-8", $desc); $xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <trans> <tranid>$tranid</tranid> <pursesrc>$purse</pursesrc> <pursedest>$rpurse</pursedest> <amount>$amount</amount> <period>$period</period> <pcode>$pcode</pcode> <desc>$desc</desc> <wminvid>$wminvid</wminvid> <onlyauth>$onlyauth</onlyauth> </trans> </w3s.request>"; $resxml=_GetAnswer($XML_addr[2], $xml); // echo $resxml; $xmlres = simplexml_load_string($resxml); if(!$xmlres) { $result['retval']=1000; $result['retdesc']="Не получен XML-ответ"; return $result; } $result['retval']=strval($xmlres->retval); $result['retdesc']=iconv("UTF-8", "CP1251", strval($xmlres->retdesc)); $result['date']=strval($xmlres->operation->datecrt); return $result; }

Разберем, что происходит в этой функции.

Функция получает переменные:

  • $tranid - номер транзакции в системе учета вашего сайта. Может быть любым целым числом длиной 32 бита, то есть от 0 до 2147483647 (отрицательные числа от 0 до -2147483647 тоже возможны, хотя официальным описанием это запрещено). $tranid не должен повторяться более одного раза. Вам нужно организовать сохранение предыдущего $tranid на вашем сайте, например, в базе данных и увеличивать его всякий раз при создании очередной транзакции.
  • $purse - ваш кошелек, с которого списываются средства. Кошелек должен быть из числа тех, что принадлежат вашему WMID, фигурирующему в поле <wmid> XML-запроса.
  • $rpurse - кошелек получателя средств.
  • $amount - сумма перевода. В качестве разделителя дробной части используйте точку, а не запятую. Незначащие нули в конце должны отсутствовать (например, 10.5 - верно, 10.50 - вызовет ошибку).
  • $period - количество дней протекции. Если перевод без протекции, то устанавливайте в 0.
  • $pcode - код протекции до 255 символов без пробелов в начале и конце. Допускаются любые символы, в том числе русские буквы. Если $period=0 (то есть перевод без протекции), то $pcode обязательно должен быть пустым. $pcode желательно передавать в функцию в кодировке Win1251.
  • $desc - примечание к переводу до 255 символов без пробелов в начале и конце. Допускаются любые символы, в том числе русские буквы. $desc желательно передавать в функцию в кодировке Win1251.
  • $wminvid - номер счета в системе WebMoney, по которому выполняется перевод. Если перевод не по счету, то поле должно быть равно 0.
  • $onlyauth - если это поле равно 0, то перевод выполнится даже в том случае, если получатель запретил (в настройках своего WM Keeper) прием входящих переводов от неавторизованных корреспондентов и наш WMID окажется неавторизованным. Если это поле равно 1, то перевод выполнится только в том случае, если получатель разрешил переводы от неавторизованных, либо если наш WMID авторизован отправителем.

Примечание. Запрет на прием платежей от неавторизованных корреспондентов обычно устанавливают продавцы, которые используют автоматизированный прием WebMoney посредством WM Merchant и хотят избежать поступления на кошельки прямых переводов, которые не ожидаются ("в обход" WM Merchant), чтобы не искать их потом вручную. Из этих соображений, для соблюдения бизнес-этики, рекомендуем передавать интерфейсу всегда onlyauth=1.

Генерируем уникальный номер запроса $reqn с помощью функции _GetReqn():

$reqn=_GetReqn();

Выполняем некоторые преобразования, чтобы избежать ошибок. У $desc и $pcode убираем лишние пробелы в начале и конце. У $amount удаляем незначащие нули, если они есть. Этого требует описание интерфейса.

$desc=trim($desc); $pcode=trim($pcode); $amount=floatval($amount);

Получаем подпись XML-пакета с помощью функции _GetSign(). На вход функции подаем строку, полученную в результате склейки параметров, как это предусмотрено в описании интерфейса. Параметры должны склеиваться именно в таком порядке, как это указано ниже. Значения всех параметров при формировании строки подписи обязательно должны быть в кодировке Win1251! Поэтому - внимание! - если функция _WMXML2(), с которой мы сейчас работаем, получила переменные $desс или $pcode в кодировке, отличной от Win1251, то их нужно сперва перекодировать. Остальные параметры содержат всегда только цифры и английские буквы, поэтому для них кодировка никакой роли не играет.

$rsign=_GetSign($reqn.$tranid.$purse.$rpurse.$amount.$period.$pcode.$desc.$wminvid);

Теперь преобразуем специальные символы ("<", "&" и др.) в html-сущности. Если этого не сделать, то при попадании в $desc или $pcode таких символов WebMoney наш запрос не примет и вернет ошибку "A name was started with an invalid character". Обратите внимание, что при формировании строки подписи переменные $desc и $pcode пребывали в своем первозданном виде, со всеми спецсимволами, а преобразование мы выполняем уже после получения подписи. Преобразовать спецсимволы в PHP можно с помощью функции htmlspecialchars():

$pcode=htmlspecialchars($pcode, ENT_QUOTES); $desc=htmlspecialchars($desc, ENT_QUOTES);

Но это еще не всё. $desc и $pcode могут содержать русские символы. Например, в $desc может быть такой текст: "тестовый товар & тестовая услуга". И здесь нужно понимать, как подготовить $desc и $pcode для передачи в составе XML-пакета. Дело в том, что содержимое полученного от вас XML сервер WebMoney попытается прочитать так, будто он пришел в кодировке Unicode. Если сервер встретит в пакете русские символы в другой кодировке, то вернет ошибку: "An invalid character was found in text content" ("Обнаружен ошибочный символ"). Для того чтобы этого не произошло, нам нужно принудительно перекодировать $desc и $pcode в UTF-8 и уже в таком виде включать их в XML-запрос.

Сделать преобразование кодировок можно с помощью функции iconv() из одноименного расширения PHP:

$pcode=iconv("CP1251", "UTF-8", $pcode); $desc=iconv("CP1251", "UTF-8", $desc);

То же самое, но с помощью функции mb_convert_encoding() из расширения mbstring:

$pcode=mb_convert_encoding($pcode, "UTF-8", "windows-1251"); $desc=mb_convert_encoding($desc, "UTF-8", "windows-1251");

Можно даже преобразовать не в UTF-8, а в html-сущности, это тоже сработает:

$pcode=mb_convert_encoding($pcode, "HTML-ENTITIES","windows-1251"); $desc=mb_convert_encoding($desc, "HTML-ENTITIES","windows-1251");

Если же iconv и mbstring вашим сервером не поддерживаются, то могу предложить еще один вариант. Оставьте $desc и $pcode в кодировке Win1251, а в начале XML-запроса вставляйте заголовок <?xml version='1.0' encoding='windows-1251'?>. Он укажет, что данные в пакете переданы в Win1251, и сервер WebMoney обработает их именно в этой кодировке. То есть пакет будет начинаться так:

$xml=" <?xml version='1.0' encoding='windows-1251'?>
<w3s.request>
...

Правда, хотя на момент написания этих строк такой вариант работал нормально, не могу поручиться, что он будет работать всегда, поскольку точная логика обработки XML-пакета сервером WebMoney не известна, и не ясно, будет ли всегда сервер учитывать заголовок XML-запроса.

Понятно, что если переменные $desc и $pcode были переданы в функцию _WMXML2(), уже пребывая в кодировке UTF-8, то никаких преобразований делать не нужно.

Наконец, формируем XML-пакет с запросом:

$xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <trans> <tranid>$tranid</tranid> <pursesrc>$purse</pursesrc> <pursedest>$rpurse</pursedest> <amount>$amount</amount> <period>$period</period> <desc>$desc</desc> <wminvid>$wminvid</wminvid> <onlyauth>$onlyauth</onlyauth> </trans> </w3s.request>";

Отправляем запрос на сервер WebMoney и получаем от него ответ с помощью функции _GetAnswer(). На вход функции подаем URL интерфейса X2 из глобального массива $XML_addr, а также пакет XML-запроса, сформированный только что:

$resxml=_GetAnswer($XML_addr[2], $xml);

Для отладки и поиска ошибок может потребоваться прочитать XML-ответ "в чистом виде". Тогда просто раскомментируйте следующую строку:

// echo $resxml;

Вызовом функции simplexml_load_string() из библиотеки SimpleXML создаем на основе XML-ответа, полученного от WebMoney, объект. Параметры XML-ответа становятся свойствами объекта, и мы сможем легко получать к ним доступ.

$xmlres = simplexml_load_string($resxml);

Если $xmlres не создан, значит, мы по какой-то причине не получили ответ от WebMoney. Тогда прерываем работу функции:

if(!$xmlres) { $result['retval']=1000; $result['retdesc']="Не получен XML-ответ"; return $result; }

Читаем следующие свойства объекта: retval (содержит результат выполнения запроса; если перевод на кошелек выполнен успешно, то retval равен 0), retdesc (содержит расшифровку результата), operation/datecrt (содержит дату и время создания транзакции в системе WebMoney в случае успешного перевода, либо дату и время последнего успешного перевода в случае ошибки). Сохраняем эти переменные в массив $result.

$result['retval']=strval($xmlres->retval); $result['retdesc']=iconv("UTF-8", "CP1251", strval($xmlres->retdesc)); $result['date']=strval($xmlres->operation->datecrt);

Обратите внимание, что содержимое поля <retdesc> мы перекодировали из UTF-8 в Win1251. Дело в том, что XML-ответ от WebMoney приходит в кодировке Windows1251, но SimpleXML при помещении XML-данных в объект принудительно превратил их в Юникод. Такая вот у него особенность. А так как <retdesc> - это строка, и теоретически она может содержать русские символы, то при выемке её из объекта мы возвращаем ей "родную" кодировку. Хотя, в общем, это не обязательно и зависит от ваших нужд и задач.

На выходе функция _WMXML2() возвращает массив $result:

return $result;

Теперь осталось только проверить, как работает то, что мы написали. Создадим скрипт для тестов test.php:

// test.php - скрипт для тестирования include("wmxml.inc.php"); $tranid="1"; $purse="кошелек_отправитель"; $rpurse="кошелек_получатель"; $amount="0.10"; $period="0"; $pcode=""; $desc="тестовый товар & тестовая услуга"; $wminvid="0"; $onlyauth="1"; $r=_WMXML2($tranid,$purse,$rpurse,$amount,$period,$pcode,$desc,$wminvid,$onlyauth); echo "Результат (0 - успешно) - ".$r['retval']."<br>"; echo "Расшифровка - ".$r['retdesc']."<br>"; echo "Дата и время - ".$r['date']."<br>";

Этот код должен выполнить перевод 0.10 WM без протекции; с примечанием "тестовый товар & тестовая услуга"; с кошелька_отправителя на кошелек_получателя; при условии, что соблюдены ограничения на прием переводов, установленные получателем (onlyauth=1).

Естественно, на кошельке-отправителе $purse должно быть достаточно средств для совершения перевода.

Интерфейс X6. Отправка сообщений.

С помощью этого интерфейса вы можете отправить сообщение по внутренней WM-почте. Полное описание интерфейса находится здесь. Интерфейс требует включения путем обращения в службу поддержку WMID 941977853154.

Наш XML-запрос должен выглядеть так:

<w3s.request> <reqn></reqn> <wmid></wmid> <sign></sign> <message> <receiverwmid></receiverwmid> <msgsubj></msgsubj> <msgtext></msgtext> </message> </w3s.request>

Что означают параметры:

  • reqn - номер запроса, всякий раз должен быть больше предыдущего;
  • wmid - ваш WMID;
  • sign - подпись запроса, сформированная из параметров: receiverwmid + reqn + msgtext + msgsubj ;
  • receiverwmid - WMID получателя сообщения;
  • msgsubj - тема сообщения;
  • msgtext - текст сообщения.

Формат ответа сервера WebMoney можно посмотреть в описании интерфейса. Нас интересует, фактически, только одно поле ответа - <retval>. Если оно равно 0, то запрос выполнен успешно. В противном случае, оно будет содержать код ошибки.

Приведем теперь полностью функцию, которая реализует работу с интерфейсом X6 и добавим её в wmxml.inc.php:

// ИНТЕРФЕЙС X6. ОТПРАВКА СООБЩЕНИЯ. // На выходе: массив ['retval'=>код выполнения, 'retdesc'=>описание результата, 'date'=>дата и время] function _WMXML6 ($wmid,$msg,$subj) { global $Global_WMID, $XML_addr; $reqn=_GetReqn(); $msg=trim($msg); $subj=trim($subj); $msg=str_replace ("\r", "", $msg); $rsign=_GetSign($wmid.$reqn.$msg.$subj); $msg=htmlspecialchars($msg, ENT_QUOTES); $subj=htmlspecialchars($subj, ENT_QUOTES); $msg=iconv("CP1251", "UTF-8", $msg); $subj=iconv("CP1251", "UTF-8", $subj); $xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <message> <receiverwmid>$wmid</receiverwmid> <msgsubj>$subj</msgsubj> <msgtext>$msg</msgtext> </message> </w3s.request>"; $resxml=_GetAnswer($XML_addr[6], $xml); // echo $resxml; $xmlres = simplexml_load_string($resxml); if(!$xmlres) { $result['retval']=1000; $result['retdesc']="Не получен XML-ответ"; return $result; } $result['retval']=strval($xmlres->retval); $result['retdesc']=iconv("UTF-8", "CP1251", strval($xmlres->retdesc)); $result['date']=strval($xmlres->message->datecrt); return $result; }

Разберем, что происходит в этой функции.

Функция получает переменные:

  • $wmid - WMID получателя сообщения.
  • $msg - текст сообщения до 1024 символов без пробелов в начале и конце.
  • $subj - тема сообщения до 255 символов без пробелов в начале и конце. Может быть пустой. Переносы строк не допускаются. Тема отображается только у пользователей Keeper Light.

Генерируем уникальный номер запроса $reqn с помощью функции _GetReqn():

$reqn=_GetReqn();

Выполняем некоторые преобразования, чтобы избежать ошибок. У $msg и $subj убираем лишние пробелы в начале и конце.

$msg=trim($msg); $subj=trim($subj);

В качестве переноса строк в тексте сообщения допускается использовать только \n. Поскольку высока вероятность попадания в $msg переноса строк, обозначенного \r\n, то удалим из текста \r:

$msg=str_replace ("\r", "", $msg);

Получаем подпись XML-пакета с помощью функции _GetSign(). На вход функции подаем строку, полученную в результате склейки параметров, как это предусмотрено в описании интерфейса. Параметры должны склеиваться именно в таком порядке, как это указано ниже. Значения всех параметров при формировании строки подписи обязательно должны быть в кодировке Win1251! Поэтому - внимание! - если функция _WMXML6(), с которой мы сейчас работаем, получила переменные $msg или $subj в кодировке, отличной от Win1251, то их нужно сперва перекодировать. Остальные параметры содержат всегда только цифры, поэтому для них кодировка никакой роли не играет.

$rsign=_GetSign($wmid.$reqn.$msg.$subj);

Теперь преобразуем специальные символы ("<", "&" и др.) в html-сущности. Если этого не сделать, то при попадании в $msg или $subj таких символов WebMoney наш запрос не примет и вернет ошибку "A name was started with an invalid character". Обратите внимание, что при формировании строки подписи переменные $msg и $subj пребывали в своем первозданном виде, со всеми спецсимволами, а преобразование мы выполняем уже после получения подписи. Преобразовать спецсимволы в PHP можно с помощью функции htmlspecialchars():

$msg=htmlspecialchars($msg, ENT_QUOTES); $subj=htmlspecialchars($subj, ENT_QUOTES);

Но это еще не всё. $msg и $subj могут содержать русские символы. Например, в $msg может быть такой текст: "привет & пока!". И здесь нужно понимать, как подготовить $msg и $subj для передачи в составе XML-пакета. Дело в том, что содержимое полученного от вас XML сервер WebMoney попытается прочитать так, будто он пришел в кодировке Unicode. Если сервер встретит в пакете русские символы в другой кодировке, то вернет ошибку: "An invalid character was found in text content" ("Обнаружен ошибочный символ"). Для того чтобы этого не произошло, нам нужно принудительно перекодировать $msg и $subj в UTF-8 и уже в таком виде включать их в XML-запрос.

Сделать преобразование кодировок можно с помощью функции iconv() из одноименного расширения PHP:

$msg=iconv("CP1251", "UTF-8", $msg); $subj=iconv("CP1251", "UTF-8", $subj);

То же самое, но с помощью функции mb_convert_encoding() из расширения mbstring:

$msg=mb_convert_encoding($msg, "UTF-8", "windows-1251"); $subj=mb_convert_encoding($subj, "UTF-8", "windows-1251");

Можно даже преобразовать не в UTF-8, а в html-сущности, это тоже сработает:

$msg=mb_convert_encoding($msg, "HTML-ENTITIES","windows-1251"); $subj=mb_convert_encoding($subj, "HTML-ENTITIES","windows-1251");

Если же iconv и mbstring вашим сервером не поддерживаются, то могу предложить еще один вариант. Оставьте $msg и $subj в кодировке Win1251, а в начале XML-запроса вставляйте заголовок <?xml version='1.0' encoding='windows-1251'?>. Он укажет, что данные в пакете переданы в Win1251, и сервер WebMoney обработает их именно в этой кодировке. То есть пакет будет начинаться так:

$xml=" <?xml version='1.0' encoding='windows-1251'?>
<w3s.request>
...

Правда, хотя на момент написания этих строк такой вариант работал нормально, не могу поручиться, что он будет работать всегда, поскольку точная логика обработки XML-пакета сервером WebMoney не известна, и не ясно, будет ли всегда сервер учитывать заголовок XML-запроса.

Понятно, что если переменные $msg и $subj были переданы в функцию _WMXML6(), уже пребывая в кодировке UTF-8, то никаких преобразований делать не нужно.

Наконец, формируем XML-пакет с запросом:

$xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <message> <receiverwmid>$wmid</receiverwmid> <msgsubj>$subj</msgsubj> <msgtext>$msg</msgtext> </message> </w3s.request>";

Отправляем запрос на сервер WebMoney и получаем от него ответ с помощью функции _GetAnswer(). На вход функции подаем URL интерфейса X6 из глобального массива $XML_addr, а также пакет XML-запроса, сформированный только что:

$resxml=_GetAnswer($XML_addr[6], $xml);

Для отладки и поиска ошибок может потребоваться прочитать XML-ответ "в чистом виде". Тогда просто раскомментируйте следующую строку:

// echo $resxml;

Вызовом функции simplexml_load_string() из библиотеки SimpleXML создаем на основе XML-ответа, полученного от WebMoney, объект. Параметры XML-ответа становятся свойствами объекта, и мы сможем легко получать к ним доступ.

$xmlres = simplexml_load_string($resxml);

Если $xmlres не создан, значит, мы по какой-то причине не получили ответ от WebMoney. Тогда прерываем работу функции:

if(!$xmlres) { $result['retval']=1000; $result['retdesc']="Не получен XML-ответ"; return $result; }

Читаем следующие свойства объекта: retval (содержит результат выполнения запроса; если сообщение отправлено успешно, то retval равен 0), retdesc (содержит расшифровку результата), message/datecrt (содержит дату и время отправки сообщения). Сохраняем эти переменные в массив $result.

$result['retval']=strval($xmlres->retval); $result['retdesc']=iconv("UTF-8", "CP1251", strval($xmlres->retdesc)); $result['date']=strval($xmlres->message->datecrt);

Обратите внимание, что содержимое поля <retdesc> мы перекодировали из UTF-8 в Win1251. Дело в том, что XML-ответ от WebMoney приходит в кодировке Windows1251, но SimpleXML при помещении XML-данных в объект принудительно превратил их в Юникод. Такая вот у него особенность. А так как <retdesc> - это строка, и теоретически она может содержать русские символы, то при выемке её из объекта мы возвращаем ей "родную" кодировку. Хотя, в общем, это не обязательно и зависит от ваших нужд и задач.

На выходе функция _WMXML6() возвращает массив $result:

return $result;

Теперь осталось только проверить, как работает то, что мы написали. Создадим скрипт для тестов test.php:

// test.php - скрипт для тестирования include("wmxml.inc.php"); $wmid="wmid_получателя"; $msg="<b>тест1</b> тест2 <q>тест3</q>"; $subj="тестовая тема"; $r=_WMXML6($wmid,$msg,$subj); echo "Результат (0 - успешно) - ".$r['retval']."<br>"; echo "Расшифровка - ".$r['retdesc']."<br>"; echo "Дата и время - ".$r['date']."<br>";

Этот код должен выполнить отправку сообщения с текстом из трех строк и темой "тестовая тема" на WMID получателя.

Не забывайте, что в тексте сообщения можно использовать теги <b>...</b> (выделяет текст между тегами жирным), <i>...</i> (выделяет текст курсивом), <u>...</u> (делает текст подчеркнутым), <s>...</s> (делает текст перечеркнутым), <q>...</q> (помечает текст как цитату). Таким образом, текст из нашего примера:

$msg="<b>тест1</b> тест2 <q>тест3</q>";

поступит в Кипер получателя в следующем виде:

тест1
тест2
> тест3

Интерфейс X8. Определение принадлежности кошелька.

Один из наиболее простых интерфейсов. С его помощью можно установить, существует ли в WebMoney определенный WMID или кошелек, а также определить, какому WMID принадлежит кошелек. Полное описание интерфейса находится здесь. Интерфейс требует включения путем обращения в службу поддержку WMID 941977853154.

Наш XML-запрос должен выглядеть так:

<w3s.request> <reqn></reqn> <wmid></wmid> <sign></sign> <testwmpurse> <wmid></wmid> <purse></purse> </testwmpurse> </w3s.request>

Что означают параметры:

  • reqn - номер запроса, всякий раз должен быть больше предыдущего;
  • wmid - ваш WMID;
  • sign - подпись запроса, сформированная из параметров: testwmpurse\wmid + testwmpurse\purse
  • testwmpurse\wmid - WMID, который мы хотим проверить;
  • testwmpurse\purse - номер кошелька, который мы хотим проверить.

Формат ответа сервера:

<w3s.response> <reqn></reqn> <retval></retval> <retdesc></retdesc> <testwmpurse> <wmid available="" themselfcorrstate="" newattst=""></wmid> <purse merchant_active_mode="" merchant_allow_cashier=""></purse> </testwmpurse> </w3s.response>

В ответе от сервера WebMoney нас будут интересовать, прежде всего, поля <retval>, <wmid>, <purse>.

  1. Мы хотим проверить, существует ли в системе определенный WMID.
    Передаем в запросе только <wmid>, а <purse> оставляем пустым. Если WMID существует, получаем в ответе retval=1. Если не существует, то retval=0.
  2. Мы хотим проверить, существует ли в системе определенный кошелек, и установить, какому WMID он принадлежит.
    Передаем в запросе только <purse>, а <wmid> оставляем пустым. В случае успешного нахождения кошелька получаем в ответе retval=1, а также заполненные поля <wmid> и <purse> (в поле <wmid> содержится WMID, которому принадлежит указанный кошелек). В случае, если указанный кошелек не существует в системе, получим retval=0.
  3. Мы хотим проверить, принадлежит ли определенный кошелек определенному WMID.
    Передаем в запросе и <purse>, и <wmid>. Если кошелек принадлежит WMID, то получим в ответе retval=1. Также в ответе будет присутствовать <purse> и <wmid>, которые мы передавали. Если кошелек не принадлежит WMID, то получаем ответ с retval=1, но без поля <purse>.

Приведем теперь полностью функцию, которая реализует работу с интерфейсом X8 и добавим её в wmxml.inc.php:

// ИНТЕРФЕЙС X8. ОПРЕДЕЛЕНИЕ ПРИНАДЛЕЖНОСТИ КОШЕЛЬКА. // На выходе: массив ['wmid'=>wmid, 'purse'=>кошелек, 'avaliable'=>запрет на входящие переводы, 'newattst'=>аттестат, 'merchant_active_mode'=>включенность кошелька в WM Merchant, 'merchant_allow_cashier'=>включенность опции *прием из терминалов* в WM Merchant, 'messpermiit'=>запрет на входящие сообщения от НЕ корреспондентов, 'invpermit'=>запрет на входящие счета от НЕ коррексондентов, 'paypermit'=>запрет на входящие переводы от НЕ корреспондентов, 'retval'=>код выполнения, 'retdesc'=>описание результата] function _WMXML8 ($wmid,$purse) { global $Global_WMID, $XML_addr; $reqn=_GetReqn(); $rsign=_GetSign($wmid.$purse); $xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <testwmpurse> <wmid>$wmid</wmid> <purse>$purse</purse> </testwmpurse> </w3s.request>"; $resxml=_GetAnswer($XML_addr[8], $xml); // echo $resxml; $xmlres = simplexml_load_string($resxml); if(!$xmlres) { $result['retval']=1000; $result['retdesc']="Не получен XML-ответ"; return $result; } $result['wmid']=strval($xmlres->testwmpurse->wmid); $result['purse']=strval($xmlres->testwmpurse->purse); $result['avaliable']=strval($xmlres->testwmpurse->wmid->attributes()->available); $result['newattst']=strval($xmlres->testwmpurse->wmid->attributes()->newattst); $result['merchant_active_mode']=strval($xmlres->testwmpurse->purse->attributes()->merchant_active_mode); $result['merchant_allow_cashier']=strval($xmlres->testwmpurse->purse->attributes()->merchant_allow_cashier); $result['retval']=strval($xmlres->retval); $result['retdesc']=iconv("UTF-8", "CP1251", strval($xmlres->retdesc)); $themselfcorrstate=decbin(strval($xmlres->testwmpurse->wmid->attributes()->themselfcorrstate)); if(strlen($themselfcorrstate)<2) $messpermit=0; else $messpermit=substr($themselfcorrstate, -2, 1); if(strlen($themselfcorrstate)<3) $invpermit=0; else $invpermit=substr($themselfcorrstate, -3, 1); if(strlen($themselfcorrstate)<4) $paypermit=0; else $paypermit=substr($themselfcorrstate, -4, 1); $result['messpermit']=$messpermit; $result['invpermit']=$invpermit; $result['paypermit']=$paypermit; return $result; }

Разберем, что происходит в этой функции.

Функция получает переменные:

  • $wmid - WMID для проверки. Может быть пустым. Если пустой - проверяется существование кошелька.
  • $purse - кошелек для проверки. Может быть пустым. Если пустой - проверяется существование WMID.

Генерируем уникальный номер запроса $reqn с помощью функции _GetReqn():

$reqn=_GetReqn();

Получаем подпись XML-пакета с помощью функции _GetSign(). На вход функции подаем строку, полученную в результате склейки $wmid и $purse.

$rsign=_GetSign($wmid.$purse);

Формируем XML-пакет с запросом:

$xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <testwmpurse> <wmid>$wmid</wmid> <purse>$purse</purse> </testwmpurse> </w3s.request>";

Отправляем запрос на сервер WebMoney и получаем от него ответ с помощью функции _GetAnswer(). На вход функции подаем URL интерфейса X8 из глобального массива $XML_addr, а также пакет XML-запроса, сформированный только что:

$resxml=_GetAnswer($XML_addr[8], $xml);

Для отладки и поиска ошибок может потребоваться прочитать XML-ответ "в чистом виде". Тогда просто раскомментируйте следующую строку:

// echo $resxml;

Вызовом функции simplexml_load_string() из библиотеки SimpleXML создаем на основе XML-ответа, полученного от WebMoney, объект. Параметры XML-ответа становятся свойствами объекта, и мы сможем легко получать к ним доступ.

$xmlres = simplexml_load_string($resxml);

Если $xmlres не создан, значит, мы по какой-то причине не получили ответ от WebMoney. Тогда прерываем работу функции:

if(!$xmlres) { $result['retval']=1000; $result['retdesc']="Не получен XML-ответ"; return $result; }

Читаем следующие свойства объекта: retval (содержит результат выполнения), retdesc (содержит расшифровку результата), testwmpurse/wmid, testwmpurse/purse. Сохраняем эти переменные в массив $result.

$result['wmid']=strval($xmlres->testwmpurse->wmid); $result['purse']=strval($xmlres->testwmpurse->purse); $result['retval']=strval($xmlres->retval); $result['retdesc']=strval(iconv("UTF-8", "CP1251", $xmlres->retdesc));

Обратите внимание, что содержимое поля <retdesc> мы перекодировали из UTF-8 в Win1251. Дело в том, что XML-ответ от WebMoney приходит в кодировке Windows1251, но SimpleXML при помещении XML-данных в объект принудительно превратил их в Юникод. Такая вот у него особенность. А так как <retdesc> - это строка, и теоретически она может содержать русские символы, то при выемке её из объекта мы возвращаем ей "родную" кодировку. Хотя, в общем, это не обязательно и зависит от ваших нужд и задач.

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

  • атрибут available поля testwmpurse/wmid - показывает, запретила ли Система WebMoney входящие транзакции на данный WMID. Такой запрет может быть связан, например, с наложением на WMID блокировки (блокировка может быть наложена Арбитражем или роботом безопасности). Значение -1 этого атрибута означает, что кошелек не найден, либо возникла системная ошибка. Значение 1 означает, что входящие переводы запрещены. Значение 0 означает, что входящие переводы не запрещены.
  • атрибут newattst поля testwmpurse/wmid - содержит код аттестата данного WMID. Код 100 означает аттестат псевдонима, 110 - формальный аттестат, 120 - начальный аттестат, 130 - песональный аттестат, 135 - аттестат продавца, 136 - аттестат Capitaller, 140 - аттестат разработчика, 150 - аттестат регистратора, 190 - аттестат сервиса, 170 - аттестат Гаранта, 300 - аттестат Оператора.
  • атрибут merchant_active_mode поля testwmpurse/purse - показывает, включен ли данный кошелек в сервисе автоматизированного приема платежей WM Merchant. 1 - включен, 0 - не включен.
  • атрибут merchant_allow_cashier поля testwmpurse/purse - показывает, включена ли у данного кошелька опция "принимать платежи из терминалов" в сервисе автоматизированного приема платежей WM Merchant. 1 - включена, 0 - не включена.

Читаем эти атрибуты помощью функций SimpleXML. Сохраняем их в массив $result:

$result['avaliable']=strval($xmlres->testwmpurse->wmid->attributes()->available); $result['newattst']=strval($xmlres->testwmpurse->wmid->attributes()->newattst); $result['merchant_active_mode']=strval($xmlres->testwmpurse->purse->attributes()->merchant_active_mode); $result['merchant_allow_cashier']=strval($xmlres->testwmpurse->purse->attributes()->merchant_allow_cashier);

Есть еще атрибут themselfcorrstate у поля testwmpurse/wmid. Он позволяет определить, запретил ли владелец данного WMID получение входящих переводов, счетов, WM-сообщений от неавторизованных пользователей (включение и отключение таких запретов производится в настройках WM Keeper Classic и Light; неавторизованный пользователь - такой, которого не добавили в список Корреспондентов).

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

$themselfcorrstate=decbin(strval($xmlres->testwmpurse->wmid->attributes()->themselfcorrstate));

Примеры такого двоичного значения: 0001, 0010, 0011 и т.д.

2-й бит справа показывает, запретил ли владелец WMID получать от неавторизованных пользователей WM-сообщения (1 - запретил, 0 - не запретил). 3-й бит справа показывает, запретил ли владелец WMID получать от неавторизованных пользователей WM-счета (1 - запретил, 0 - не запретил). 4-й бит справа показывает, запретил ли владелец WMID получать от неавторизованных пользователей WM-переводы (1 - запретил, 0 - не запретил).

Чтобы оперелить все эти значения - прочитаем и запишем эти 3 интересующих нас бита в переменные $messpermit, $invpermit, $paypermit. Потом поместим переменные в массив $result:

if(strlen($themselfcorrstate)<2) $messpermit=0; else $messpermit=substr($themselfcorrstate, -2, 1); if(strlen($themselfcorrstate)<3) $invpermit=0; else $invpermit=substr($themselfcorrstate, -3, 1); if(strlen($themselfcorrstate)<4) $paypermit=0; else $paypermit=substr($themselfcorrstate, -4, 1); $result['messpermit']=$messpermit; $result['invpermit']=$invpermit; $result['paypermit']=$paypermit;

Таким образом, в $result['messpermit'] содержится информации о запрете входящих WM-сообщений (1 - запрещены, 0 - не запрещены); в $result['invpermit'] содержится информации о запрете входящих WM-счетов (1 - запрещены, 0 - не запрещены); в $result['messpermit'] содержится информации о запрете входящих WM-переводов (1 - запрещены, 0 - не запрещены).

Зачем нам могут понадобится все эти характеристики? Вообще говоря, в 99% случаев они не понадобятся :-) Однако, данная информация пригодится тем сервисам, которые совершают WM-переводы в пользу своих клиентов (вручную из Кипера или с помощью интерфейса X2). В первую очередь, речь идет об обменных пунктах. Эта информация позволяет превентивно определить, можно ли совершать перевод на данный кошелек, или этого делать не стоит.

Например, если X8 показал, что WMID получателя заблокирован на входящие транзакции (avaliable не равен 0), то нужно воздержаться от совершения WM-перевода в его сторону. Так нужно поступить и в том случае, если кошелек-получатель подключен к WM Merchant'у (merchant_active_mode=1) и/или он настроен на прием платежей из терминалов ((merchant_allow_cashier=1). Это говорит о том, что получатель является продавцом и не ожидает каких-либо входящих переводов, кроме платежей из WM Merchant'а, разрешение на прием которых он дал самолично. Есть большая вероятность, что такой продавец никогда вручную не проверяет входящие платежи на свой кошелек, а потому прямой перевод, проведенный мимо WM Merchant'а, он может "потерять". Не делать прямые переводы на такой кошелек - это хороший тон и своего рода соблюдение бизнес-этики, которая избавит получателя от головной боли.

Примечание.
Исходя из тех же соображений, которые были изложены выше, мы рекомендуем в интерфейсе X2 всегда включать параметр onlyauth. Если вы в X2 устанавливаете onlyauth=1, то перевод будет успешно совершён только в том случае, когда вы "имеете право" переводить WM своему получателю. При этом как раз и проверяются многие из тех характеристик, которые мы только что рассмотрели в интерфейсе X8. В частности, при включенном onlyauth=1 в интерфейсе X2 перевод НЕ будет выполнен, если сработает хотя бы одно из следующих условий:
  • WMID получателя заблокирован Системой на входящие транзакции (в X8 об этом сигнализирует атрибут available не равный 0);
  • Кошелек получателя включен в WM Merchant (в X8 об этом сигнализирует атрибут merchant_active_mode равный 1);
  • У кошелька получателя в WM Merchant включена опция "принимать платежи из терминалов" (в X8 об этом сигнализирует атрибут merchant_allow_cashier равный 1);
  • Владелец WMID получателя запретил входящие переводы от неавторизованных пользователей (в X8 об этом сигнализирует атрибут themselfcorrstate, если у него 4-й бит справа равен 1) и при этом отправитель у получателя не авторизован.
  • На выходе функция _WMXML8() возвращает массив $result:

    return $result;

    Теперь осталось только проверить, как работает то, что мы написали. Создадим скрипт для тестов test.php:

    // test.php - скрипт для тестирования include("wmxml.inc.php"); $wmid="wmid_для_проверки"; $purse="кошелек_для_проверки"; $r=_WMXML8($wmid,$purse); if($wmid!="" && $purse=="") { if($r['retval']==1) echo "WMID $wmid существует"; if($r['retval']==0) echo "WMID $wmid НЕ существует"; } elseif($wmid=="" && $purse!="") { if($r['retval']==1) echo "Кошелек $purse существует и принадлежит WMID ".$r['wmid']; if($r['retval']==0) echo "Кошелек $purse НЕ существует"; } elseif($wmid!="" && $purse!="") { if($r['retval']==1 && $r['wmid']!="" && $r['purse']!="") echo "ДА, кошелек $purse принадлежит WMID $wmid"; if($r['retval']==1 && $r['wmid']!="" && $r['purse']=="") echo "НЕТ, кошелек $purse НЕ принадлежит WMID $wmid"; if($r['retval']==0) echo "WMID $wmid не существует. Проверка невозможна."; } echo "<br>======<br>Дополнительные характеристики:<br>"; echo "WMID заблокирован (1 - да) - ".$r['avaliable']."<br>"; echo "Код аттестата - ".$r['newattst']."<br>"; echo "Кошелек включен на WM Merchant (1 - включен) - ".$r['merchant_active_mode']."<br>"; echo "Кошелек принимает платежи из терминалов (1 - да) - ".$r['merchant_allow_cashier']."<br>"; echo "Владелец WMID запретил входящие сообщения (1 - да) - ".$r['messpermit']."<br>"; echo "Владелец WMID запретил входящие счета (1 - да) - ".$r['invpermit']."<br>"; echo "Владелец WMID запретил входящие переводы (1 - да) - ".$r['paypermit']."<br>";

    Интерфейс X11. Получение аттестационной информации.

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

    Наш XML-запрос должен выглядеть так:

    <request> <wmid></wmid> <passportwmid></passportwmid> <sign></sign> <params> <dict></dict> <info></info> <mode></mode> </params> </request>

    Что означают параметры:

    • wmid - ваш WMID. Этот параметр является необязательным.
    • passportwmid - WMID, информацию по которому нужно получить.
    • sign - подпись запроса, сформированная из параметров wmid + passportwmid. Подпись в данном интерфейсе является необязательной.
    • dict - отображение в ответе опорного словаря (1 - отображается, 0 - не отображается);
    • info - отображение в ответе паспортных данных и контактной информации владельца WMID (1 - отображаются, 0 - не отображаются);
    • mode - указывает, проверять ли установку доверенности от проверяемого WMID к WMID, подписавшему запрос (1 - проверять, 0 - не проверять).

    Формат ответа сервера WebMoney можно посмотреть в описании интерфейса. Ответ дает нам исчерпывающую информацию об аттестате проверяемого WMID, паспортных данных, местонахождении, контактной информации, организационно-правовом статусе, банковских реквизитах и т.д. Однако, интерфейс возвращает только ту информацию, которую сам владелец аттестата открыл для публичного просмотра, т.е. к скрытым полям интерфейс доступа не дает (если, конечно, у вашего WMID нет доверенности от проверяемого WMID на просмотр аттестационной информации).

    Забегая вперед, скажем, что интерфейс X11 отличается от всех остальных, поскольку:

    • не требует формирования подписи;
    • не требует передачи уникального номера запроса reqn;
    • XML-ответ содержит значимую информацию не в самих элементах, а в их атрибутах.

    Формирование подписи в запросе необходимо лишь в случае если WMID, подписывающий запрос, является доверенным идентификатором для проверяемого аттестата. Установка доверительных отношений производится на сайте центра аттестации. Доверенные WMID могут просматривать все персональные данные владельца аттестата, даже если их видимость была заблокирована владельцем аттестата. Если доверительных отношений между проверяемым WMID и WMID, подписавшим запрос нет, то в запросе можно указать лишь параметр passportwmid, а sign и wmid оставить пустыми.

    Приведем теперь полностью функцию, которая реализует работу с интерфейсом X11 и добавим её в wmxml.inc.php:

    // ИНТЕРФЕЙС X11. ПОЛУЧЕНИЕ ИНФОРМАЦИИ ИЗ АТТЕСТАТА. // На выходе: массив ['att'=>код аттестата, 'recalled'=>флаг отзыва аттестата, 'retval'=>код выполнения, 'retdesc'=>описание результата, 'wmids'=>список прикрепленных к аттестату WMID] function _WMXML11 ($wmid) { global $XML_addr; $xml=" <request> <wmid></wmid> <passportwmid>$wmid</passportwmid> <sign></sign> <params> <dict>1</dict> <info>1</info> <mode>0</mode> </params> </request>"; $resxml=_GetAnswer($XML_addr[11], $xml); // echo $resxml; $xmlres = simplexml_load_string($resxml); if(!$xmlres) { $result['att']=0; $result['retval']=1000; $result['retdesc']="Не получен XML-ответ"; return $result; } if(!$xmlres->certinfo->attestat->row) { $result['att']=0; $result['retval']=1001; $result['retdesc']="Информация об аттестате не получена. Возможно, неверно указан WMID."; return $result; } $result['att']=strval($xmlres->certinfo->attestat->row->attributes()->tid); $result['recalled']=strval($xmlres->certinfo->attestat->row->attributes()->recalled); $result['retval']=strval($xmlres->attributes()->retval); foreach ($xmlres->certinfo->wmids->row as $row) { $wmids[]=strval($row->attributes()->wmid); } $result['wmids']=$wmids; return $result; }

    Разберем, что происходит в этой функции.

    Функция получает единственную переменную $wmid. В ней мы передаем WMID, информацию о котором нужно получить.

    Формируем XML-пакет с запросом:

    $xml=" <request> <wmid></wmid> <passportwmid>$wmid</passportwmid> <sign></sign> <params> <dict>1</dict> <info>1</info> <mode>0</mode> </params> </request>";

    Мы уже обращали ваше внимание, что поля <wmid> и <sign> в этом интерфейсе являются необязательными, поэтому мы их в запросе не указываем, подпись пакета функцией _GetSign() не формируем. Кроме того, в X11 нет поля <reqn> с уникальным номером запроса, поэтому функция _GetReqn() также не задействована.

    Отправляем запрос на сервер WebMoney и получаем от него ответ с помощью функции _GetAnswer(). На вход функции подаем URL интерфейса X11 из глобального массива $XML_addr, а также пакет XML-запроса, сформированный только что:

    $resxml=_GetAnswer($XML_addr[11], $xml);

    Для отладки и поиска ошибок может понадобиться прочитать XML-ответ "в чистом виде". Тогда просто раскомментируйте следующую строку:

    // echo $resxml;

    Вызовом функции simplexml_load_string() из библиотеки SimpleXML создаем на основе XML-ответа, полученного от WebMoney, объект. Параметры XML-ответа становятся свойствами объекта, и мы сможем легко получать к ним доступ.

    $xmlres = simplexml_load_string($resxml);

    Если $xmlres не создан, значит, мы по какой-то причине не получили ответ от WebMoney. Тогда прерываем работу функции:

    if(!$xmlres) { $result['att']=0; $result['retval']=1000; $result['retdesc']="Не получен XML-ответ"; return $result; }

    Если ответ получен, но в нем нет информации об аттестате - прерываем работу функции. Вероятнее всего, это говорит о том, что на вход функции был подан неверный или несуществующий WMID:

    if(!$xmlres->certinfo->attestat->row) { $result['att']=0; $result['retval']=1001; $result['retdesc']="Информация об аттестате не получена. Возможно, неверно указан WMID."; return $result; }

    Если же всё в порядке и ошибок нет, то осталось прочитать нужные элементы объекта и отдать их на выход функции _WMXML11(). Как вы понимаете, выходных данных может быть много, и они могут быть самыми разными - от фамилии владельца WMID, до даты его рождения. Но для простоты мы прочитаем только 4 элемента XML-ответа:

    • атрибут tid поля certinfo/attestat/row - содержит код аттестата. Код 100 означает аттестат псевдонима, 110 - формальный аттестат, 120 - начальный аттестат, 130 - песональный аттестат, 135 - аттестат продавца, 136 - аттестат Capitaller, 140 - аттестат разработчика, 150 - аттестат регистратора, 190 - аттестат сервиса, 170 - аттестат Гаранта, 300 - аттестат Оператора.
    • атрибут recalled поля certinfo/attestat/row - содержит информацию об отзыве аттестата. Если атрибут равен 1, то аттестат данного WMID отозван.
    • атрибут retval корневого элемента - содержит код выполнения запроса. Если равен 0, то запрос выполнен успешно. В противном случае, атрибут будет содержать код ошибки, расшифровку которой можно посмотреть в полном описании интерфейса.
    • поля certinfo/wmids/row - содержат информацию о всех WMID, прикрепленных к аттестату пользователя. Этих полей может быть несколько - по количеству WMID, прикрепленных к аттестату. Знать эту информацию в некоторых случаях может быть полезно, поэтому мы заставим нашу функцию отдавать её. Сами номера прикрепленных WMID содержатся в атрибутах wmid полей certinfo/wmids/row. Нужно просмотреть их в цикле.

    Читаем эти данные с помощью функций SimpleXML. Сохраняем их в массив $result:

    $result['att']=strval($xmlres->certinfo->attestat->row->attributes()->tid); $result['recalled']=strval($xmlres->certinfo->attestat->row->attributes()->recalled); $result['retval']=strval($xmlres->attributes()->retval); foreach ($xmlres->certinfo->wmids->row as $row) { $wmids[]=strval($row->attributes()->wmid); } $result['wmids']=$wmids;

    На выходе функция _WMXML11() возвращает массив $result:

    return $result;

    Теперь осталось только проверить, как работает то, что мы написали. Создадим скрипт для тестов test.php:

    // test.php - скрипт для тестирования include("wmxml.inc.php"); $wmid="здесь_запрашиваемый_wmid"; $r=_WMXML11($wmid); echo "Результат (0 - успешно) - ".$r['retval']."<br>"; echo "Расшифровка - ".$r['retdesc']."<br>"; echo "Код аттестата - ".$r['att']."<br>"; echo "Флаг отзыва (1 - отозван) - ".$r['recalled']."<br>"; echo "Прикрепленные WMID - "; while(list($k,$v)=each($r['wmids'])) echo $v.", ";

    В этой статье мы рассказали о 4-х XML-интерфейсах: X2, X6, X8, X11. Наш файл с функциями wmxml.inc.php выглядит теперь так. В следующей, заключительной статье цикла мы познакомим вас с интерфейсом X7 и расскажем о том, как организовать на вашем сайте авторизацию пользователей при помощи Кипера.

    Обсудить этот материал

    17.08.2007

    Внимание! Все права на данный материал принадлежат сайту owebmoney.ru. Копирование материала разрешено с обязательным указанием гиперссылки на http://owebmoney.ru.

       Что нового почитать?
    Мой номер телефона утерян и не подлежит восстановлению. Как быть? 06.10.16 [3]
    ВОПРОС: Долго не пользовался своей симкой. Номер заблокирован, восстановлению не подлежит. Как востановить доступ к кошельку?
    Автомобилистам на заметку: как оплатить штраф по WM 04.10.16
    Сегодня мы хотим напомнить о возможностях, которые существуют в WebMoney для оплаты штрафов ГАИ и дорожных сборов. Если неприятность всё же произошла ...
    На WebMoney Merchant можно принимать Биткоины 30.09.16 [5]
    Если вы на вашем сайте принимаете WebMoney и делаете это через WebMoney Merchant, то для вас есть хорошая новость. Теперь с вами смогут рассчитаться т...
    Муравей-бот отвечает на вопросы о WebMoney в Telegram 27.09.16
    WebMoney запустил интеллектуального бота-помощника для мессенджера Telegram. Он постарается понять ваш вопрос и дать на него ответ.Для начала, разбере...
    Автоплатежи помогут не забыть об оплате 27.09.16
    В WebMoney Keeper, а также в личный кабинет Telepay добавлена опция автоплатежа для 3х крупнейших мобильных операторов России: Билайна, МТС и Мегафона...
    Новая библиотека для платформы .Net 14.09.16
    Разработчикам будет полезно узнать, что выпущена новая версия библиотеки для работы с XML-интерфейсами WebMoney для платформы Microsoft .Net.В ней реа...
    WebMoney пришла в Молдову 14.09.16 [1]
    WebMoney предоставила возможность работы с кошельком, номинированным в молдавских леях. Однако, кошелек этот не совсем обычный.Во-первых, кошелек созд...
    В обновленных Киперах появились регулярные платежи 04.08.16
    Обновилась вся линейка мобильных Киперов (iOS, Android, Windows Phone, MacOs X и BlackBerry OS 10), а также браузерный Keeper Standard.Главное новшест...

       Кофейня (форум)
    Вчера на форуме вебмани обосрал вебмани, седне лок 09.12.16
    Проблема с Кипером WinPro версии 3.9.9.8 01.12.16
    Работает ли корректно в данный момент Х19? 30.11.16

       p2p
    Меняют 10000 UAH на 24700 Qiwi (курс:2.47) 10.12.16
    Меняют 10000 UAH на 25000 Яндекс.Д (курс:2.5) 10.12.16
    Меняют 26300 UAH на 1000 WMZ (курс:26.3) 09.12.16

       WebMoney TOP
    Зарегистрирован Обмен24 Ввод/Вывод WebMoney, ЯД, QIWI на Privat24, СберБанк, АльфаБанк, ТКСБ и другие. Быстрая обработка зая...
    Зарегистрирован Green Cash Обменный пункт WebMoney в Москве. Ввод/вывод WebMoney на выгодных условиях. Работаем 7 дней в неделю...
    Зарегистрирован Bestchange.ee Ввод и вывод WM в Эстонии и Европе. Карты (чеки Paymer), высылаем на e-mail. Оплату принимаем на бан...

       WM-Клуб
    Присоединился Василий Галанов
    Присоединился Евгений Кудрявцев
    Присоединился Николай Бирюк


     
    Все права на материалы, опубликованные на owebmoney.ru, охраняются в соответствии с законом об авторском праве. Разрешено копирование без согласования при условии указания гиперссылки на сайт (без атрибута nofollow и сокрытий) непосредственно до\после материала.