четверг, 10 июля 2008 г.

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

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

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

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

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

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

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

Название XML-интерфейса Что делает
X1 описание выписывает счет другому пользователю WebMoney от вашего WMID
X2 описание выполняет перевод с вашего кошелька
X3 описание получает историю транзакций по кошельку
X4 описание получает историю исходящих (выписанных вами) счетов
X5 описание завершает входящий перевод с протекцией
X6 описание отправляет сообщение по внутренней WM-почте
X7 описание производит авторизацию пользователя Keeper Classic на вашем сайте
X8 описание проверяет существование в системе WMID/кошелька; получает WMID, соответствующий кошельку
X9 описание получает текущий баланс на вашем кошельке
X10 описание получает историю входящих (выписанных вам) счетов
X11 описание получает аттестационную информацию заданного WMID

Все интерфейсы требуют наличия персонального аттестата. Кроме того, некоторые интерфейсы перед началом использования нужно активировать, отправив на 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, однако мы поступим проще. Формировать тело запроса будем прямо в строке скрипта, например:

<!--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 ДЛИНОЙ 15 ЦИФР 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-ответ function _GetAnswer($address, $xml){ // Инициализируем сеанс 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, "/home/site.ru/data/signer/WebMoneyCA.crt"); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE); // Выполняем запрос, ответ помещаем в переменную $result; $result=curl_exec($ch); return $result; }

Обратите внимание на строки:

curl_setopt($ch, CURLOPT_CAINFO, "/home/site.ru/data/signer/WebMoneyCA.crt"); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);

Чтобы (в целях безопасностии и защиты от DNS-атак) во время сеанса CURL мог проверить валидность сертификата на сервере WebMoney, мы используем аргументы CURLOPT_CAINFO и CURLOPT_SSL_VERIFYPEER. Для этого скачиваем корневой сертификат WebMoney отсюда: www.wmcert.com/Cert/WebMoneyCA.crt, заливаем его в любой каталог на сервере (можно в созданный ранее /home/site.ru/data/signer/), указываем путь до него в CURLOPT_CAINFO.

Будьте внимательны! Если вы скачиваете сертификат через Internet Explorer, то он автоматически переименуется и сохранится как WebMoneyCA.cer. Не забудьте в этом случае прописать правильный путь:

curl_setopt($ch, CURLOPT_CAINFO, "/home/site.ru/data/signer/WebMoneyCA.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"; $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";

Функция _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 содержит следующий код:

<!--php // wmxml.inc.php - файл с функциями // БЛОК ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ $Global_WMID="ваш_wmid"; // Ваш WMID $Path_Folder = "/home/site.ru/data/signer/"; // Путь к директории, в которой лежит .kwm $Path_Signer = "/home/site.ru/data/signer/wmsigner"; // Путь к WMSigner $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"; // ФУНКЦИЯ ФОРМИРУЕТ УНИКАЛЬНЫЙ УВЕЛИЧИВАЮЩИЙСЯ 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&#92;004&#92;r&#92;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&#92;004&#92;r&#92;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){ // Инициализируем сеанс 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, "/home/site.ru/data/signer/WebMoneyCA.crt"); 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> </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, по которому выполняется перевод.

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

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

// ИНТЕРФЕЙС X2. ОТПРАВКА ПЕРЕВОДА. // На выходе: массив ['retval'=>код выполнения, 'retdesc'=>описание результата, 'date'=>дата и время] function _WMXML2 ($tranid,$purse,$rpurse,$amount,$period,$pcode,$desc,$wminvid) { 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> </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.

Генерируем уникальный номер запроса $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> </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:

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

Этот код должен выполнить перевод 0.01 WM без протекции, с примечанием "тестовый товар & тестовая услуга", с кошелька_отправителя на кошелек_получателя.

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



Комментариев нет: