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

XML-интерфейсы WebMoney. Часть 3. X1, X3, X4, X9, X14, X16.

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

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

Интерфейс X1. Выписывание счёта.
Интерфейс X3. Получение истории операций.
Интерфейс X4. Проверка выписанных счетов.
Интерфейс X9. Получение балансов по кошелькам.
Интерфейс X14. Бескомиссионный возврат перевода.
Интерфейс X16. Создание кошелька.

Эта статья - последняя в серии материалов об XML-интерфейсах WebMoney. Все базовые навыки вы уже получили, однако мне хотелось бы детально рассмотреть ещё несколько наиболее используемых интерфейсов, которые могут пригодиться вам в работе. Напомним, ранее мы научились работать с WMSigner (модулем цифровой подписи под Unix-системы) и формировать подпись произвольной строки с помощью этого модуля и ключей Keeper Classic. Затем мы разобрались, как получать такую подпись программно в PHP и как генерировать возрастающий уникальный параметр reqn, необходимый для работы большинства интерфейсов. Наконец, мы написали PHP-функции для использования 4-х XML интерфейсов. Сегодня мы добавим в коллекцию ещё 6.

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

Интерфейс X1. Выписывание счёта.

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

Интерфейс целесообразно применять в тех случаях, когда вы хотите получить оплату за товар\услугу и когда есть необходимость сделать так, чтобы покупатель мог оплатить её только со своего WMID и только через Кипер. В других случаях лучше использовать стандартное средство приема WM-платежей WM Merchant.

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

<w3s.request> <reqn></reqn> <wmid></wmid> <sign></sign> <invoice> <orderid></orderid> <customerwmid></customerwmid> <storepurse></storepurse> <amount></amount> <desc></desc> <address></address> <period></period> <expiration></expiration> </invoice> </w3s.request>

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

  • reqn - номер запроса, всякий раз должен быть больше предыдущего (в рамках данного отдельно взятого интерфейса);
  • wmid - ваш WMID;
  • sign - подпись запроса, сформированная из параметров: orderid + customerwmid + storepurse + amount + desc + address + period + expiration + reqn;
  • invoice\orderid - номер счёта, назначаемый вами;
  • invoice\customerwmid - WMID, на который выставляется счёт;
  • invoice\storepurse - номер вашего кошелька, на который поступят средства от оплаты счёта;
  • invoice\amount - сумма счёта;
  • invoice\desc - описание счёта;
  • invoice\address - адрес доставки счёта, маловажное поле;
  • invoice\period - срок протекции в днях;
  • invoice\expiration - срок действия счёта в днях.

Формат ответа сервера WebMoney следующий:

<w3s.response> <reqn></reqn> <retval></retval> <retdesc></retdesc> <invoice id="n1" ts="n2"> <orderid></orderid> <customerwmid></customerwmid> <storepurse></storepurse> <amount></amount> <desc></desc> <address></address> <period></period> <expiration></expiration> <state>0</state> <datecrt></datecrt> <dateupd></dateupd> </invoice> </w3s.response>

В ответе нас, прежде всего, интересует поле <retval> (eсли оно равно 0, то счёт был выставлен успешно, в противном случае retval будет содержать код ошибки, расшифровку которой нужно смотреть в поле <retdesc>). Кроме этого, крайне важным является атрибут id поля <invoice>, в нем содержится уникальный номер выставленного счёта в единой базе данных WebMoney. По нему мы в дальнейшем сможем проверять состояние оплаты этого счёта. Кроме того, будем сохранять дату создания счёта из поля <datecrt>. Остальные поля дублируют соответствующие параметры запроса, а поле <state>, в котором указывается код текущего состояния оплаты счёта, вообще всегда содержит 0 (это означает, что счёт ещё не оплачен - и это понятно, ведь он только что выписан).

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

// ИНТЕРФЕЙС X1. ВЫПИСКА СЧЕТА. // На выходе: массив ['retval'=>код выполнения, 'retdesc'=>описание результата, // 'date'=>дата и время, 'wminvid'=>уникальный номер счёта] function _WMXML1 ($orderid,$wmid,$purse,$amount,$desc,$address,$period,$expiration) { global $Global_WMID, $XML_addr; $reqn=_GetReqn(); $desc=trim($desc); $address=trim($address); $amount=floatval($amount); $rsign=_GetSign($orderid.$wmid.$purse.$amount.$desc.$address.$period.$expiration.$reqn); $address=htmlspecialchars($address, ENT_QUOTES); $desc=htmlspecialchars($desc, ENT_QUOTES); $address=iconv("CP1251", "UTF-8", $address); $desc=iconv("CP1251", "UTF-8", $desc); $xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <invoice> <orderid>$orderid</orderid> <customerwmid>$wmid</customerwmid> <storepurse>$purse</storepurse> <amount>$amount</amount> <desc>$desc</desc> <address>$address</address> <period>$period</period> <expiration>$expiration</expiration> </invoice> </w3s.request>"; $resxml=_GetAnswer($XML_addr[1], $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->invoice->datecrt); $result['wminvid']=strval($xmlres->invoice->attributes()->id); return $result; }

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

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

  • $orderid - номер счёта в системе учёта вашего сайта. Может быть любым целым числом длиной 32 бита, то есть от 0 до 2147483647 (отрицательные числа от 0 до -2147483647 тоже возможны, но при этом знак "-" будет отброшен сервером WebMoney автоматически). Может быть равен 0, может повторяться, но не может быть пустым. Рекомендуем указывать всякий раз уникальный, неповторяющийся $orderid и сохранять этот параметр в базе данных. Обязательный параметр.
  • $wmid - WMID получателя счёта (12 цифр). Обязательный параметр.
  • $purse - номер вашего кошелька, на который поступят средства от оплаты счёта. Определяет также и валюту перевода. Кошелёк должен быть из числа тех, что принадлежат вашему WMID, фигурирующему в поле <wmid> XML-запроса. Обязательный параметр.
  • $amount - сумма счёта. В качестве разделителя дробной части используйте точку, а не запятую. Незначащие нули в конце должны отсутствовать (например, 10.5 - верно, 10.50 - вызовет ошибку). Обязательный параметр.
  • $desc - описание счёта (например, описание товара\услуги, за который выставляется счёт), до 255 символов без пробелов в начале и конце. Допускаются любые символы, в том числе русские буквы. $desc желательно передавать в функцию в кодировке Win1251. Обязательный параметр.
  • $address - адрес доставки счёта. WM-счета содеражат поле "Адрес", куда обычно вставляется URL с http://, по которому плательщик может впоследствие перейти и скачать оплаченный товар, либо посмотреть инструкцию о товаре, его описание и т.д. Данный параметр можно не использовать, оставлять пустым.
  • $period - количество дней протекции (от 0 до 255). Если здесь указана цифра, кроме 0, то получатель счёта при его оплате должен будет обязательно установить код протекции сделки, который будет действовать указанное количество дней. Если вы хотите, чтобы получатель счёта оплачивал без протекции, то устанавливайте эту переменную в 0. Обязательный параметр.
  • $expiration - количество дней, в течение которых счёт будет действителей (от 0 до 255). Если здесь указана цифра, кроме 0, то получатель счёта сможет оплатить его только до истечения установленного периода времени. Если переменная установлена в 0, то срок действия счёта будет неограниченным, и его можно будет оплатить в любое время. Обязательный параметр.

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

$reqn=_GetReqn();

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

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

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

$rsign=_GetSign($orderid.$wmid.$purse.$amount.$desc.$address.$period.$expiration.$reqn);

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

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

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

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

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

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

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

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

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

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

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

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

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

$xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <invoice> <orderid>$orderid</orderid> <customerwmid>$wmid</customerwmid> <storepurse>$purse</storepurse> <amount>$amount</amount> <desc>$desc</desc> <address>$address</address> <period>$period</period> <expiration>$expiration</expiration> </invoice> </w3s.request>";

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

$resxml=_GetAnswer($XML_addr[1], $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 (содержит расшифровку результата), invoice\datecrt (содержит дату и время создания счёта в системе WebMoney). Также вытаскиваем атрибут id свойства invoiсe (напомним, он содержит уникальный номер только что выписанного счёта в глобальной базе данных WebMoney). Сохраняем эти переменные в массив $result.

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

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

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

return $result;

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

// test.php - скрипт для тестирования include("wmxml.inc.php"); $orderid="11"; $wmid="wmid_получателя_счёта"; // укажите! $purse="пополняемый_кошелёк"; // укажите! $amount="0.05"; $desc="тестовый счёт"; $address="http://test.ru"; $period="1"; $expiration="2"; $r=_WMXML1($orderid,$wmid,$purse,$amount,$desc,$address,$period,$expiration); echo "Результат (0 - успешно) - ".$r['retval']."<br>"; echo "Расшифровка - ".$r['retdesc']."<br>"; echo "Дата и время - ".$r['date']."<br>"; echo "Номер счёта в WebMoney - ".$r['wminvid']."<br>";

ВНИМАНИЕ! Настоятельно рекомендуем вам сохранять в своей базе данных уникальные номера, присвоенные счетам системой WebMoney (то, что на выходе нашей функции содержится в $result['wminvid']), и в дальнейшем при проверке состояния оплаты того или иного счёта с помощью интерфейса X4 оперировать именно с этими номерами. Они всегда уникальны и никогда не повторяются. Это поможет избежать проблем.

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

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

На наш взгляд, это самый сложный XML-интерфейс из всех. Он нуждается в некоторых пояснениях, которые мы и приведем ниже.

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

<w3s.request> <reqn></reqn> <wmid></wmid> <sign></sign> <getoperations> <purse></purse> <wmtranid></wmtranid> <tranid></tranid> <wminvid></wminvid> <orderid></orderid> <datestart></datestart> <datefinish></datefinish> </getoperations> </w3s.request>

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

  • reqn - номер запроса, всякий раз должен быть больше предыдущего (в рамках данного отдельно взятого интерфейса);
  • wmid - ваш WMID;
  • sign - подпись запроса, сформированная из параметров: purse + reqn;
  • getoperations\purse - номер вашего кошелька, по которому вы хотите получить историю транзакций;
  • getoperations\wmtranid - номер транзакции в системе WebMoney;
  • getoperations\tranid - номер транзакции в системе учёта отправителя;
  • getoperations\wminvid - номер счёта (в системе WebMoney), по которому выполнялась транзакция;
  • getoperations\orderid - номер счёта (в системе учёта вашего сайта);
  • getoperations\datestart - минимальная дата и время выполнения транзакции;
  • getoperations\datefinish - максимальная дата и время выполнения транзакции.

Формат ответа сервера WebMoney следующий:

<w3s.response> <reqn></reqn> <retval></retval> <retdesc></retdesc> <operations cnt="n"> <operation id="n1" ts="n2"> <pursesrc></pursesrc> <pursedest></pursedest> <amount></amount> <comiss></comiss> <opertype></opertype> <tranid></tranid> <wminvid></wminvid> <orderid></orderid> <period></period> <desc></desc> <datecrt></dateupd> <dateupd></dateupd> </operation> <operation>...</operation> </operations> </w3s.response>

В ответе нас, прежде всего, интересует поле <retval> (eсли оно равно 0, то история получена успешно, в противном случае retval будет содержать код ошибки, расшифровку которой нужно смотреть в поле <retdesc>). Также нас будет интересовать атрибут cnt поля <operations>, в котором содержится количество операций, попавших в выборку. Кроме того, мы "уложим" в структуру массивов полученную выборку транзакций. Мы детально опишем всё это ниже, когда будем рассматривать работу функции.

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

// ИНТЕРФЕЙС X3. ПОЛУЧЕНИЕ ИСТОРИИ ОПЕРАЦИЙ. // На выходе: массив ['retval'=>код выполнения, 'retdesc'=>описание результата, // 'cnt'=>количество операций в выборке, 'operations'=>массив с операциями] function _WMXML3 ($purse,$wmtranid,$tranid,$wminvid,$orderid,$datestart,$datefinish) { global $Global_WMID, $XML_addr; $reqn=_GetReqn(); $rsign=_GetSign($purse.$reqn); $xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <getoperations> <purse>$purse</purse> <wmtranid>$wmtranid</wmtranid> <tranid>$tranid</tranid> <wminvid>$wminvid</wminvid> <orderid>$orderid</orderid> <datestart>$datestart</datestart> <datefinish>$datefinish</datefinish> </getoperations> </w3s.request>"; $resxml=_GetAnswer($XML_addr[3], $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['cnt']=strval($xmlres->operations->attributes()->cnt); if($result['cnt']>0) { // В элементе $result['operations'] формируем элементы, // каждый из которых является // массивом с параметрами операции foreach ($xmlres->operations->operation as $operation) { // определяем тип операции (входящая, исходящая) // и кошелёк корреспондента $pursesrc=strval($operation->pursesrc); $pursedest=strval($operation->pursedest); if($pursesrc==$purse) { $type="out"; $corrpurse=$pursedest; } elseif($pursedest==$purse) { $type="in"; $corrpurse=$pursesrc; } $result['operations'][strval($operation->attributes()->id)] = Array ( 'tranid'=>strval($operation->tranid), 'wminvid'=>strval($operation->wminvid), 'orderid'=>strval($operation->orderid), 'type'=>$type, 'corrpurse'=>$corrpurse, 'corrwmid'=>strval($operation->corrwm), 'amount'=>floatval($operation->amount), 'comiss'=>floatval($operation->comiss), 'rest'=>floatval($operation->rest), 'protection'=>strval($operation->opertype), 'desc'=>iconv("UTF-8", "CP1251", strval($operation->desc)), 'datecrt'=>strval($operation->datecrt) ); } } return $result; }

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

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

  • $purse - номер вашего кошелька, по которому вы хотите получить историю переводов. Обязательный параметр.
  • $wmtranid - уникальный номер операции в системе WebMoney. Целое положительное число. Необязательный параметр.
  • $tranid - уникальный номер операции в системе учёта отправителя. Целое положительное число. Необязательный параметр.
  • $wminvid - уникальный номер счёта в системе WebMoney, по которому осуществлялась операция. Целое положительное число. Необязательный параметр.
  • $orderid - номер счёта (во внутренней системе учёта вашего сайта), по которому осуществлялась операция. Целое положительное число. Необязательный параметр.
  • $datestart - минимальная дата и время операции в формате ГГГГММДД ЧЧ:ММ:СС. Переводы, проведенные раньше $datestart, в выборку не попадут. Обязательный параметр.
  • $datefinish - максимальная дата и время операции в формате ГГГГММДД ЧЧ:ММ:СС. Переводы, проведенные позднее $datefinish, в выборку не попадут.

Теперь давайте разбираться, что тут к чему. Переменные: $purse (пойдет в поле getoperations\purse XML-запроса), $datestart (пойдет в поле getoperations\datestart XML-запроса) и $datefinish (пойдет в поле getoperations\datefinish XML-запроса) - являются обязательными! Если вы не зададите какое-либо из этих полей, интерфейс выдаст ошибку. Таким образом, интерфейс X3 всегда должен знать, по какому кошельку и за какой период времени запрашивается история операций. Если вам вдруг захочется получить полную историю за всё время существования кошелька, то задайте, например, $datestart="19700101 00:00:00" и $datestart="20990101 00:00:00".

Что касается 4-х остальных переменных: $wmtranid (пойдет в поле getoperations\wmtranid XML-запроса), $tranid (пойдет в поле getoperations\tranid XML-запроса), $wminvid (пойдет в поле getoperations\wminvid XML-запроса), $orderid (пойдет в поле getoperations\orderid XML-запроса) - то они являются необязательными. Если задана какая-либо из них, то она сужает выборку до одной операции. Например, если задана переменная $wmtranid, то из истории будет выбрана только одна(!) операция, имеющая указанный номер, однако лишь при условии, что она была осуществлена с указанного кошелька $purse и в указанный промежуток времени $datestart - $datefinish. То же касается и $tranid, $wminvid, $orderid ($orderid, врочем, не является уникальным параметром, поэтому может ограничивать выборку не одной, а несколькими транзакциями). Таким образом, если вы хотите получить информацию об одном конкретном переводе, и знаете какой-либо из его параметров, то вы можете применить данный приём - передать в функцию соответствующую переменную. Следите при этом, чтобы $datestart и $datefinish охватывали искомую транзакцию по времени; если не знаете, когда точно проводилась искомая транзакция - укажите временной отрезок с запасом, например $datestart="19700101 00:00:00" и $datestart="20990101 00:00:00".

Где же взять эти номера транзакций и счетов?

Уникальный номер операции в системе WebMoney ($wmtranid):

  • передаётся вашему серверу при оплате через WM Merchant в форме оповещения о платеже;
  • может быть получена от интерфейса X2 при создании исходящего перевода;

Уникальный номер операции в системе учёта отправителя ($tranid):

  • назначается вами самостоятельно при создании исходящего перевода в интерфейсе X2;

Уникальный номер (в базе данных WebMoney) WM-счёта, который был оплачен посредством искомой транзакции ($wminvid):

  • может быть получен от интерфейса X1 при выписке счёта;
  • может быть получен из истории выписанных счетов с помощью интерфейса X4;
  • передаётся вашему серверу при оплате через WM Merchant в форме оповещения о платеже, т.к. при оплате через WM Merchant тоже, незаметно для покупателя и продавца, создаётся счёт;

Номер (в системе учёта выставителя) WM-счёта, который был оплачен посредством искомой транзакции ($orderid):

  • назначается вами самостоятельно при выписке счёта в интерфейсе X1;
  • может быть получен из истории выписанных счетов с помощью интерфейса X4;
  • может быть получен от интерфейса X2 при оплате по счёту с соответствующим wminvid;

Резюммируя, каждая транзакция в системе WebMoney характеризуется 4 параметрами - глобальным и внутренним номером транзакции (wmtranid и tranid соответственно), глобальным и внутренним номером WM-счёта, ставшего первопричиной транзакции (wminvid и orderid соответственно); причем, ненулевым всегда является только wmtranid, остальные параметры могут отсутствовать. Зная о переводе хотя бы один из этих его параметров, с помощью интерфейса X3 вы можете запросить информацию конретно об этом переводе.

Вернёмся к рассмотрению функции.

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

$reqn=_GetReqn();

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

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

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

$xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <getoperations> <purse>$purse</purse> <wmtranid>$wmtranid</wmtranid> <tranid>$tranid</tranid> <wminvid>$wminvid</wminvid> <orderid>$orderid</orderid> <datestart>$datestart</datestart> <datefinish>$datefinish</datefinish> </getoperations> </w3s.request>";

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

$resxml=_GetAnswer($XML_addr[3], $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 (содержит расшифровку результата), а также атрибут cnt свойства operations, в котором содержится количество операций, вошедших в выборку. Сохраняем эти переменные в массив $result.

$result['retval']=strval($xmlres->retval); $result['retdesc']=iconv("UTF-8", "CP1251", strval($xmlres->retdesc)); $result['cnt']=strval($xmlres->operations->attributes()->cnt);

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

Далее, если cnt больше 0, т.е. в выборке есть хотя бы одна операция, переходим к сохранению информации о транзакциях. Эта информация содержится внутри одинаковых блоков XML-ответа <operation>...</operation>. Пробегаем блоки в цикле и, применяя парсинг XML к нужным полям и атрибутам, формируем массив, где ключами элементов делаем уникальные номера транзакций в системе WebMoney (атрибут id полей <operation>), а значениями элементов делаем вложенные ассоциативные массивы, в которых, в свою очередь, ключи элементов - это обозначения параметров транзакции, а значения элементов - соответствующие этим параметрам значения. Сформированный таким образом "массив в массиве" сохраняем внутрь элемента operations выходного массива $result:

if($result['cnt']>0) { // В элементе $result['operations'] формируем элементы, каждый из которых является // массивом с параметрами операции foreach ($xmlres->operations->operation as $operation) { // определяем тип операции (входящая, исходящая) // и кошелёк корреспондента $pursesrc=strval($operation->pursesrc); $pursedest=strval($operation->pursedest); if($pursesrc==$purse) { $type="out"; $corrpurse=$pursedest; } elseif($pursedest==$purse) { $type="in"; $corrpurse=$pursesrc; } $result['operations'][strval($operation->attributes()->id)] = Array ( 'tranid'=>strval($operation->tranid), 'wminvid'=>strval($operation->wminvid), 'orderid'=>strval($operation->orderid), 'type'=>$type, 'corrpurse'=>$corrpurse, 'corrwmid'=>strval($operation->corrwm), 'amount'=>floatval($operation->amount), 'comiss'=>floatval($operation->comiss), 'rest'=>floatval($operation->rest), 'protection'=>strval($operation->opertype), 'desc'=>iconv("UTF-8", "CP1251", strval($operation->desc)), 'datecrt'=>strval($operation->datecrt) ); } }

Рассмотрим детальнее некоторые фрагменты этого кода.

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

$pursesrc=strval($operation->pursesrc); $pursedest=strval($operation->pursedest); if($pursesrc==$purse) { $type="out"; $corrpurse=$pursedest; } elseif($pursedest==$purse) { $type="in"; $corrpurse=$pursesrc; }

То есть, если наш кошелёк является получателем, то транзакция входящая. Если отправителем - транзакция исходящая. В первом случае кошелёк нашего корреспондента - это кошелёк-отправитель, а во втором - это кошелёк-получатель. Сразу же сохраняем эти сведения о типе транзакции и кошельке корреспондента в переменные $type и $corrpurse.

Далее, как я уже говорил выше, мы сохраняем информацию о транзакциях в однотипные массивы, один массив на одну транзакцию:

$result['operations'][strval($operation->attributes()->id)] = Array ( 'tranid'=>strval($operation->tranid), 'wminvid'=>strval($operation->wminvid), 'orderid'=>strval($operation->orderid), 'type'=>$type, 'corrpurse'=>$corrpurse, 'corrwmid'=>strval($operation->corrwm), 'amount'=>floatval($operation->amount), 'comiss'=>floatval($operation->comiss), 'rest'=>floatval($operation->rest), 'protection'=>strval($operation->opertype), 'desc'=>iconv("UTF-8", "CP1251", strval($operation->desc)), 'datecrt'=>strval($operation->datecrt) );

Элементы массивов обозначают следующее:

  • tranid - назначенный номер операции;
  • wminvid - глобальный номер WM-счёта, по которому проводилась транзакция;
  • orderid - назначенный номер WM-счёта, по которому проводилась транзакция;
  • type - тип транзакции (входящая, исходящая), который мы определили ранее;
  • corrpurse - кошелёк корреспондента, определили ранее;
  • corrwmid - WMID корреспондента;
  • amount - сумма транзакции;
  • comiss - комиссия системы WebMoney за данную транзакцию (для входящих транзакций - всегда 0);
  • rest - остаток на нашем кошельке после транзакции;
  • protection - была ли протекция (0 - протекция уже снята, либо транзакция без протекции; 4 - протекция есть и она не снята; 12 - протекция есть и транзакция вернулась);
  • desc - примечание платежа;
  • datecrt - дата создания транзакции.

Впрочем, X3 даёт нам ещё больше информации, и вы, в зависимости от своих потребностей, можете дополнить приведенную выше "выемку" из XML-ответа, либо, наоборот, сократить её.

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

return $result;

Чтобы было лучше понятно, ещё раз посмотрим на содержимое массива $result (его можно привести в читабельный вид с помощью функции print_r(), например):

Array ( [retval] => код_выполнения [retdesc] => описание_результата [сnt] => количество_операций_в_выборке [operation] => Array ( [номер_операции] => Array ( [tranid] => назначенный № операции [wminvid] => № счета [orderid] => назначенный № счета [type] => тип [corrpurse] => кошелёк корр-та [corrwmid] => wmid корр-та [amount] => сумма [comiss] => комиссия [rest] => остаток [protection] => протекция [desc] => примечание [datecrt] => дата ) [номер_операции] => Array ( [tranid] => назначенный № операции [wminvid] => № счета [orderid] => назначенный № счета [type] => тип [corrpurse] => кошелёк корр-та [corrwmid] => wmid корр-та [amount] => сумма [comiss] => комиссия [rest] => остаток [protection] => протекция [desc] => примечание [datecrt] => дата ) ... ) )

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

$purse="ваш_кошелёк"; // укажите! $wmtranid=""; $tranid=""; $wminvid=""; $orderid=""; $datestart="20080830 00:00:00"; $datefinish="20080831 00:00:00"; $r=_WMXML3($purse,$wmtranid,$tranid,$wminvid,$orderid,$datestart,$datefinish); echo "Результат (0 - успешно) - ".$r['retval']."<br>"; echo "Расшифровка - ".$r['retdesc']."<br>"; echo "Количество - ".$r['cnt']."<br>"; echo "<table border=1><tr> <th>wmtranid</th> <th>tranid</th> <th>wminvid</th> <th>orderid</th> <th>тип</th> <th>кошелёк корр-та</th> <th>wmid корр-та</th> <th>сумма</th> <th>коммисия</th> <th>остаток</th> <th>протекция</th> <th>примечание</th> <th>дата</th> </tr>"; while(list($key,$val)=each($r['operations'])) { echo " <tr> <td>$key</td> <td>".$val['tranid']."</th> <td>".$val['wminvid']."</td> <td>".$val['orderid']."</td> <td>".$val['type']."</td> <td>".$val['corrpurse']."</td> <td>".$val['corrwmid']."</td> <td>".$val['amount']."</td> <td>".$val['comiss']."</td> <td>".$val['rest']."</td> <td>".$val['protection']."</td> <td>".$val['desc']."</td> <td>".$val['datecrt']."</td> </tr>"; } echo "</table>";

В этом примере мы получили и вывели в таблице полную историю операций за 30-е августа 2008 года.

Интерфейс X4. Проверка выписанных счетов.

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

Интерфейс довольно сложный, но очень похож на рассмотренный выше X3. "Поведение" этого интерфейса тоже во многом зависит от того, какие именно входные параметры он получает в XML-запросе пользователя.

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

<w3s.request> <reqn></reqn> <wmid></wmid> <sign></sign> <getoutinvoices> <purse></purse> <wminvid></wminvid> <orderid></orderid> <datestart></datestart> <datefinish></datefinish> </getoutinvoices> </w3s.request>

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

  • reqn - номер запроса, всякий раз должен быть больше предыдущего (в рамках данного отдельно взятого интерфейса);
  • wmid - ваш WMID;
  • sign - подпись запроса, сформированная из параметров: purse + reqn;
  • getoutinvoices\purse - номер вашего кошелька, по которому вы хотите получить историю выписанных счетов;
  • getoutinvoices\wminvid - номер счёта в системе WebMoney;
  • getoutinvoices\orderid - номер счёта в системе учёта вашего сайта;
  • getoutinvoices\datestart - минимальная дата и время выписки счёта;
  • getoutinvoices\datefinish - максимальная дата и время выписки счёта.

Формат ответа сервера WebMoney следующий:

<w3s.response> <reqn></reqn> <retval></retval> <retdesc></retdesc> <outinvoices cnt="n" > <outinvoice id="n1" ts="n2"> <orderid></orderid> <customerwmid></customerwmid> <storepurse></storepurse> <amount></amount> <desc></desc> <address></address> <period></period> <expiration></expiration> <state></state> <datecrt></datecrt> <dateupd></dateupd> <wmtranid></wmtranid> </outinvoice> <outinvoice>...</outinvoice> </outinvoices> </w3s.response>

В ответе нас, прежде всего, интересует поле <retval> (eсли оно равно 0, то история счетов получена успешно, в противном случае retval будет содержать код ошибки, расшифровку которой нужно смотреть в поле <retdesc>). Также нас будет интересовать атрибут cnt поля <outinvoices>, в котором содержится количество счетов, попавших в выборку. Кроме того, мы "уложим" в структуру массивов полученную выборку счетов, а именно их уникальные номера в базе данных WebMoney (атрибуты id полей <outinvoice>) и состояния оплаты (поля <state>). Мы детально опишем всё это ниже, когда будем рассматривать работу функции.

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

// ИНТЕРФЕЙС X4. ПРОВЕРКА ВЫПИСАННЫХ СЧЕТОВ. // На выходе: массив ['retval'=>код выполнения, 'retdesc'=>описание результата, // 'cnt'=>количество счетов вошедших в выборку, 'invoices'=>массив со счетами] function _WMXML4 ($purse,$wminvid,$orderid,$datestart,$datefinish) { global $Global_WMID, $XML_addr; $reqn=_GetReqn(); $rsign=_GetSign($purse.$reqn); $xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <getoutinvoices> <purse>$purse</purse> <wminvid>$wminvid</wminvid> <orderid>$orderid</orderid> <datestart>$datestart</datestart> <datefinish>$datefinish</datefinish> </getoutinvoices> </w3s.request>"; $resxml=_GetAnswer($XML_addr[4], $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['cnt']=strval($xmlres->outinvoices->attributes()->cnt); if($result['cnt']>0) { // В элементе $result['invoices'] формируем массив // [номер счёта в WM] = состояние оплаты foreach ($xmlres->outinvoices->outinvoice as $invoice) { $wminvid=strval($invoice->attributes()->id); $state=strval($invoice->state); $result['invoices'][$wminvid]=$state; } } return $result; }

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

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

  • $purse - номер вашего кошелька, по которому вы хотите получить историю выписанных (исходящих) счетов. Напомним, что счета в системе WebMoney выставляются "от имени" конкретного кошелька, вот именно этот свой кошелёк и необходимо указать в данной переменной. Обязательный параметр.
  • $wminvid - уникальный номер счёта в системе WebMoney, присвоенный ему во время выписки. Целое положительное число. Необязательный параметр.
  • $orderid - номер счёта во внутренней системе учёта вашего сайта. Этот номер вы сами присваиваете счёту при выписке (см. интерфейс X1). Целое положительное число. Необязательный параметр.
  • $datestart - минимальная дата и время выписки счёта в формате ГГГГММДД ЧЧ:ММ:СС. Счета, выставленные раньше $datestart, в выборку не попадут. Обязательный параметр.
  • $datefinish - максимальная дата и время выписки счёта в формате ГГГГММДД ЧЧ:ММ:СС. Счета, выставленные позднее $datefinish, в выборку не попадут. Обязательный параметр.

Здесь всё очень похоже на интерфейс X3. Переменные: $purse (пойдет в поле getoutinvoices\purse XML-запроса), $datestart (пойдет в поле getoutinvoices\datestart XML-запроса) и $datefinish (пойдет в поле getoutinvoices\datefinish XML-запроса) - являются обязательными! Если вы не зададите какое-либо из этих полей, интерфейс выдаст ошибку. Отсюда вывод: интерфейс X4 всегда должен знать, по какому кошельку и за какой период времени запрашивается история исходящих счетов. Если вам вдруг захочется получить полную историю за всё время существования кошелька, то задайте, например, $datestart="19700101 00:00:00" и $datestart="20990101 00:00:00".

Переменные: $wminvid (пойдет в поле getoutinvoices\wminvid XML-запроса) и $orderid (пойдет в поле getoutinvoices\orderid XML-запроса) - являются необязательными. Если обе эти переменные не заданы, то выбираются все счета по кошельку за указанный промежуток времени - так, как это описано в предыдущем абзаце. Если задана переменная $wminvid, то в выборку попадёт только один счёт, имеющий именно такой уникальный номер в базе данных WebMoney, однако лишь при условии, что он был выписан с указанного кошелька $purse и в указанный промежуток времени $datestart - $datefinish. Если задана переменная $orderid, то в выборку попадут счета, имеющие именно такой внутренний номер в учетной системе вашего сайта и удовлетворяющие условиям, что они были выписаны с указанного кошелька $purse и в указанный промежуток времени $datestart - $datefinish. Поскольку внутренний номер в вашей учетной системе - это неуникальное поле (иными словами, вы могли выписать несколько счетов с одинаковым orderid), то в такой выборке может оказаться не один счёт, а несколько. Если в getoutinvoices\orderid будет передан 0, то интерфейс посчитает, что orderid вообще не передан и является пустым. Наконец, если заданы одновременно и переменная $wminvid, и переменная $orderid, то $orderid будет проигнорирован интерфейсом.

Отсюда ещё один вывод: $wminvid и $orderid, если заданы, сужают выборку и, как правило, ограничивают её одним единственным счётом. Откуда можно узнать wminvid и orderid конкретного интересующего нас счёта, мы уже рассказывали, когда говорили об интерфейсе X3. Повторим.

Уникальный номер (в базе данных WebMoney) WM-счёта ($wminvid):

  • может быть получен от интерфейса X1 при выписке счёта;
  • может быть получен из истории операций с помощью интерфейса X3;
  • передаётся вашему серверу при оплате через WM Merchant в форме оповещения о платеже, т.к. при оплате через WM Merchant тоже, незаметно для покупателя и продавца, создаётся счёт;

Номер (в системе учёта выставителя) WM-счёта ($orderid):

  • назначается вами самостоятельно при выписке счёта в интерфейсе X1;
  • может быть получен из истории операций с помощью интерфейса X3;
  • может быть получен от интерфейса X2 при оплате по счёту с соответствующим wminvid;

Всё это может показаться вам слишком сложным, однако на самом деле вам важно лишь определиться, каким именно образом вы будете использовать интерфейс X4. Как правило, единственная задача, которая стоит перед разработчиком при использовании X4 - автоматически проверить состояние оплаты выписанных ранее счетов. Для этого есть два пути:

  1. Путь первый. Робот на вашем сайте запускается с определённой периодичностью и запрашивает информацию по всем счетам за определённый промежуток времени. В этом случае в функцию передаются переменные $purse, $datestart, $datefinish ($wminvid и $orderid не передаются). Значения $datestart и $datefinish устанавливайте в зависимости от ваших конкретных задач и условий. Например, если ваш сайт выписывает счета со сроком действия 2 дня, то и временной отрезок при их проверке в X4 также имеет смысл ограничить последними 2 днями. Просматривая выборку в цикле, "вытаскивайте" состояния оплаты счетов и выполняйте необходимые действия.
  2. Путь второй. После выписки счёта покупателю вы предоставляете ему специальную ссылку или даёте возможность нажать на специальную кнопку, в результате чего покупатель сам инициирует вызов интерфейса X4. Запрашивается информацию по данному конкретному счёту. В этом случае вы передаёте в функцию одну из переменных $wminvid или $orderid (в зависимости от того, как вы учитываете и идентифицируете у себя выписанные счета), а также $purse, $datestart, $datefinish. В полученной выборке будет присутствовать только один искомый счёт. "Вытаскивайте" состояние его оплаты и, если счёт оплачен, отгружайте товар покупателю.
Как правило, разработчики используют оба способа параллельно.

О том, какие бывают состояния оплаты счёта и как их определить, я расскажу ниже. Вернёмся к рассмотрению функции.

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

$reqn=_GetReqn();

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

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

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

$xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <getoutinvoices> <purse>$purse</purse> <wminvid>$wminvid</wminvid> <orderid>$orderid</orderid> <datestart>$datestart</datestart> <datefinish>$datefinish</datefinish> </getoutinvoices> </w3s.request>";

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

$resxml=_GetAnswer($XML_addr[4], $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 (содержит расшифровку результата), а также атрибут cnt свойства outinvoices, в котором содержится количество счетов, вошедших в выборку. Сохраняем эти переменные в массив $result.

$result['retval']=strval($xmlres->retval); $result['retdesc']=iconv("UTF-8", "CP1251", strval($xmlres->retdesc)); $result['cnt']=strval($xmlres->outinvoices->attributes()->cnt);

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

Далее, если cnt больше 0, т.е. в выборке есть хотя бы один счёт, переходим к сохранению информации о счетах. Нас, напомню, интересует состояние их оплаты. Информация о счетах содержится внутри одинаковых блоков XML-ответа <outinvoice>...</outinvoice>. Пробегаем эти блоки в цикле и формируем массив, где ключами элементов делаем уникальные номера счетов в системе WebMoney (атрибут id полей <outinvoice>), а значениями элементов делаем соответствующие этим счетам состояния их оплаты (поля <state>). Сформированный массив сохраняем внутрь элемента invoices выходного массива $result:

if($result['cnt']>0) { // В элементе $result['invoices'] формируем массив [номер счёта в WM] = состояние оплаты foreach ($xmlres->outinvoices->outinvoice as $invoice) { $wminvid=strval($invoice->attributes()->id); $state=strval($invoice->state); $result['invoices'][$wminvid]=$state; } }

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

return $result;

Чтобы было лучше понятно, ещё раз посмотрим на содержимое массива $result (его можно привести в читабельный вид с помощью функции print_r(), например):

Array ( [retval] => код_выполнения [retdesc] => описание_результата [сnt] => количество_счетов_в_выборке [invoices] => Array ( [номер_счёта] => состояние оплаты [номер_счёта] => состояние оплаты [номер_счёта] => состояние оплаты ... ) )

Что касается состояния оплаты, то оно по каждому счёту может иметь одно из следующих значений: 0 - не оплачен, 1 - оплачен с протекцией, 2 - оплачен окончательно, 3 - отказ от оплаты. "Оплачен окончательно" (2) означает, что протекция перевода по счёту уже снята, либо счёт был выставлен и оплачен вообще без протекции.

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

// test.php - скрипт для тестирования include("wmxml.inc.php"); $purse="ваш_кошелёк"; // укажите! $wminvid=""; $orderid=""; $datestart="20080830 00:00:00"; $datefinish="20080831 00:00:00"; $r=_WMXML4($purse,$wminvid,$orderid,$datestart,$datefinish); echo "Результат (0 - успешно) - ".$r['retval']."<br>"; echo "Расшифровка - ".$r['retdesc']."<br>"; echo "Количество - ".$r['cnt']."<br>"; while(list($key,$val)=each($r['invoices'])) { echo "* У счёта ".$key." состояние оплаты ".$val."<br>"; }

В этом примере мы получили полную историю счетов, выписанных 30-го августа 2008 года.

Завершая разговор об X4, хотим заметить, что приведенный пример функции _WMXML4() во многом является лишь демонстративным. В вашем конкретном случае может понадобиться получение "на выходе" более расширенной информации, либо структурирование её в ином виде. Не сомневаемся, что вы сможете адаптировать функцию под свои нужды. Главное - понять, как устроен интерфейс.

Интерфейс X9. Получение балансов по кошелькам.

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

X9 особенно полезен для автоматических обменных пунктов, сайтов, выплачивающих "WM-бонусы" и других проектов, в которых посетитель должен видеть текущие денежные резервы сервиса.

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

<w3s.request> <reqn></reqn> <wmid></wmid> <sign></sign> <getpurses> <wmid></wmid> </getpurses> </w3s.request>

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

  • reqn - номер запроса, всякий раз должен быть больше предыдущего (в рамках данного отдельно взятого интерфейса);
  • wmid - ваш WMID, которым подписывается запрос;
  • sign - подпись запроса, сформированная из параметров: getpurses\wmid+reqn;
  • getpurses\wmid - WMID, по кошелькам которого необходимо проверить балансы. Дело в том, что данный интерфейс поддерживает доверенности, т.е. вы можете проверить балансы на кошельках чужого WMID, если владелец этого WMID дал вам соответствующую доверенность на сайте security.webmoney.ru. Запрос в этом случае вы всё равно должны подписывать своим WMID, но в поле getpurses\wmid записать WMID проверяемый. В приведенном ниже примере функции мы будем проверять балансы на собственном WMID. Если же вы захотите проверить балансы по доверенности, вам нужно будет немного видоизменить функцию.

Формат ответа сервера WebMoney следующий:

<w3s.response> <reqn></reqn> <retval></retval> <retdesc></retdesc> <purses cnt="n"> <purse id="n"> <pursename></pursename> <amount></amount> </purse> <purse> ... </purse> </purses> </w3s.response>

Что нас интересует в ответе? Во-первых, поле <retval> (если оно равно 0, то балансы получены успешно, в противном случае retval будет содержать код ошибки, расшифровку которой нужно смотреть в поле <retdesc>). Во-вторых, поля <pursename> и <amount>, содержащие соответственно номера кошельков и их балансы.

Как вы уже поняли, запросить остаток по одному конкретному кошельку, к сожалению, нельзя. Ответ возвращает балансы сразу всех кошельков.

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

// ИНТЕРФЕЙС X9. ПОЛУЧЕНИЕ БАЛАНСА // На выходе: массив ['retval'=>код выполнения, 'retdesc'=>описание результата, // 'purses'=>массив балансов] function _WMXML9 () { global $Global_WMID, $XML_addr; $reqn=_GetReqn(); $rsign=_GetSign($Global_WMID.$reqn); $xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <getpurses> <wmid>$Global_WMID</wmid> </getpurses> </w3s.request>"; $resxml=_GetAnswer($XML_addr[9], $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)); if($result['retval']==0 && $result['retval']!==false) { // Формируем массив [номер кошелька] = баланс foreach ($xmlres->purses->purse as $purse) { $pursename=strval($purse->pursename); $amount=floatval($purse->amount); $result['purses'][$pursename]=$amount; } } return $result; }

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

Функция не получает никаких входных параметров.

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

$reqn=_GetReqn();

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

$rsign=_GetSign($Global_WMID.$reqn);

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

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

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

$resxml=_GetAnswer($XML_addr[9], $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 (содержит расшифровку результата). Сохраняем эти переменные в массив $result.

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

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

Если retval равен 0, то можно перейти к сохранению балансов по кошелькам. Номера кошельков и их балансы содержатся внутри одинаковых блоков XML-ответа <purse>...</purse> в <pursename> и <amount> соответственно. Пробегаем эти блоки в цикле и формируем ассоциативный массив, где ключами элементов делаем номера кошельков, а значениями элементов делаем соответствующие этим кошелькам балансы. Сформированный массив сохраняем внутрь элемента purses выходного массива $result:

if($result['retval']==0 && $result['retval']!==false) { // Формируем массив [номер кошелька] = баланс foreach ($xmlres->purses->purse as $purse) { $pursename=strval($purse->pursename); $amount=floatval($purse->amount); $result['purses'][$pursename]=$amount; } }

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

return $result;

Чтобы было лучше понятно, ещё раз посмотрим на содержимое массива $result (его можно привести в читабельный вид с помощью функции print_r(), например):

Array ( [retval] => код_выполнения [retdesc] => описание_результата [purses] => Array ( [номер_кошелька] => баланс [номер_кошелька] => баланс [номер_кошелька] => баланс ... ) )

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

// test.php - скрипт для тестирования include("wmxml.inc.php"); $r=_WMXML9(); echo "Результат (0 - успешно) - ".$r['retval']."<br>"; echo "Расшифровка - ".$r['retdesc']."<br>"; while(list($key,$val)=each($r['purses'])) { echo "* На кошельке ".$key." ".$val." WM<br>"; }

Интерфейс X14. Бескомиссионный возврат перевода.

С помощью этого интерфейса вы можете в течение 30 дней сделать возврат полученных WM-средств отправителю, не потеряв при этом комиссию системы 0.8%. Интерфейс будет очень полезен для обменных пунктов, интернет-магазинов и других сервисов в случае необходимости произвести возврат клиенту ошибочного платежа. Полное описание интерфейса находится здесь. Если Вы являетесь владельцем аттестата продавца и используете merchant.webmoney.ru, то использовать X14 вы можете без дополнительной регистрации. В противном случае, необходимо включить интерфейс путем обращения в службу поддержку WMID 941977853154.

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

<w3s.request> <reqn></reqn> <wmid></wmid> <sign></sign> <trans> <inwmtranid></inwmtranid> <amount></amount> <moneybackphone></moneybackphone> </trans> </w3s.request>

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

  • reqn - номер запроса, всякий раз должен быть больше предыдущего (в рамках данного отдельно взятого интерфейса);
  • wmid - ваш WMID;
  • sign - подпись запроса, сформированная из параметров: reqn+trans\inwmtranid+trans\amount
  • trans\inwmtranid - уникальный номер возвращаемой транзакции (в системе WebMoney);
  • trans\amount - сумма возвращаемой транзакции.
  • trans\moneybackphone - телефон клиента в сервисе WebMoney Check.

Обратите, внимание на параметр moneybackphone. Дело в том, что перед совершением возврата очень важно понять, каким именно способом переводил WM ваш контрагент. Если он платил вам с WM-карты или из сервиса WebMoney Check, то такой платеж на ваш кошелек поступил со служебного кошелька R000000000001, U000000000001, Z000000000001 и т.д. На эти кошельки делать возврат нельзя! Что же делать?

Для возврата платежа, совершенного с WM-карты, нужно сначала узнать у контрагента его номер мобильного телефона, после чего указать этот номер в параметре moneybackphone - тогда WM зачислятся контрагенту на его WebMoney Чек. Если же платеж на ваш кошелек был совершен с самого WebMoney Чека, то параметр moneybackphone можно не указывать - вебмани в этом случае всегда будут возвращены на WebMoney Чек отправителя.

Как узнать, что возвращаемая транзакция была совершена с WM-карты или Чека? Если транзакция производилась через WebMoney Merchant, то помимо служебного кошелька отправителя (R000000000001, U000000000001, Z000000000001 и т.д.) есть и другие признаки. Так, в "форме оповещения о платеже" вы получаете непустой параметр LMI_PAYMER_NUMBER, если оплата с WM-карты, или непустой параметр LMI_WMCHECK_NUMBER, если оплата с WebMoney Чека. В ответе на Х18 об этом сигнализирует непустой параметр paymer_number.

Итак, параметр moneybackphone в запросе X14 нужен для указания телефона контрагента, если исходная транзакция на ваш кошелек производилась с WM-карты.

Но вернемся к интерфейсу Х14.

Формат ответа сервера WebMoney можно посмотреть в описании интерфейса. В ответе нас интересуют: поле <retval> (eсли оно равно 0, то возврат произведён успешно, в противном случае retval будет содержать код ошибки, расшифровку которой нужно смотреть в поле <retdesc> или всё в том же описании интерфейса), а также атрибут id поля <operation> (содержит номер транзакции возврата) и поле <datecrt> (дата и время создания транзакции возврата).

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

// ИНТЕРФЕЙС X14. БЕСКОМИССИОННЫЙ ВОЗВРАТ. // На выходе: массив ['retval'=>код выполнения, 'retdesc'=>описание результата, // 'date'=>дата и время, 'wmtranid_ret'=>номер транзакции возврата] function _WMXML14 ($wmtranid,$amount,$moneybackphone) { global $Global_WMID, $XML_addr; $reqn=_GetReqn(); $amount=floatval($amount); $rsign=_GetSign($reqn.$wmtranid.$amount); $xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <trans> <inwmtranid>$wmtranid</inwmtranid> <amount>$amount</amount> <moneybackphone>$moneybackphone</moneybackphone> </trans> </w3s.request>"; $resxml=_GetAnswer($XML_addr[14], $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['wmtranid_ret']=strval($xmlres->operation->attributes()->id); $result['date']=strval($xmlres->operation->datecrt); return $result; }

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

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

  • $wmtranid - уникальный номер транзакции (в базе данных WebMoney), которая возвращается. Целое число. Обязательный параметр.
  • $amount - сумма возвращаемой транзакции. Можно указать полную сумму исходной транзакции, а можно возвращать частями. Возвращать частями можно много раз, пока сумма возвратов не станет равной сумме исходной транзакции. Обязательный параметр.
  • $moneybackphone - телефон контрагента (указывается, если возвращаемая транзакция производилась с WM-карты). Подробнее этот параметр мы рассмотрели выше.

Напомним, откуда мы можем получить значение $wmtranid:

  • передаётся вашему серверу при оплате через WM Merchant в форме оповещения о платеже;
  • может быть получен из истории операций с помощью интерфейса X3.

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

$reqn=_GetReqn();

У $amount удаляем незначащие нули, если они есть:

$amount=floatval($amount);

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

$rsign=_GetSign($reqn.$wmtranid.$amount);

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

$xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <trans> <inwmtranid>$wmtranid</inwmtranid> <amount>$amount</amount> <moneybackphone>$moneybackphone</moneybackphone> </trans> </w3s.request>";

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

$resxml=_GetAnswer($XML_addr[14], $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 (содержит расшифровку результата), атрибут id свойства operation (содержит уникальный номер только что созданной транзакции возврата в базе данных WebMoney), свойство operation\datecrt (содержит дату и время выполнения транзакции возврата). Сохраняем эти переменные в массив $result.

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

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

При возврате ЧАСТИ суммы исходной транзакции (когда $amount меньше суммы исходной транзакции) - на сервере WebMoney срабатывает защита от случайного "задвоения". Она состоит в том, что в течение получаса нельзя сделать еще один возврат ТАКОЙ ЖЕ суммы $amount. Например, если сумма исходной транзакции - 1.00, и вы делаете возврат $amount = 0.2, то повторный возврат 0.2 будет возможен только через полчаса, а до тех пор интерфейс будет отдавать код ошибки retval = 104.

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

return $result;

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

// test.php - скрипт для тестирования include("wmxml.inc.php"); $wmtranid="128150624"; $amount="0.5"; $r=_WMXML14($wmtranid,$amount); echo "Результат (0 - успешно) - ".$r['retval']."<br>"; echo "Расшифровка - ".$r['retdesc']."<br>"; echo "Номер - ".$r['wmtranid_ret']."<br>"; echo "Дата - ".$r['date']."<br>"; ?>

Отметим, что примечание операции возврата, совершенной интерфейсом X14, всегда будет иметь следующий вид: "Moneyback transaction: номер возвращаемой транзакции. (примечание возвращаемой транзакции)", и изменить его нельзя.

Интерфейс X16. Создание кошелька.

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

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

<w3s.request> <reqn></reqn> <wmid></wmid> <sign></sign> <createpurse> <wmid></wmid> <pursetype></pursetype> <desc></desc> </createpurse> </w3s.request>

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

  • reqn - номер запроса, всякий раз должен быть больше предыдущего (в рамках данного отдельно взятого интерфейса);
  • wmid - ваш WMID;
  • sign - подпись запроса, сформированная из параметров: createpurse\wmid+createpurse\pursetype+reqn
  • createpurse\wmid - WMID, в рамках которого мы хотим создать новый кошелёк. По идее, здесь можно было бы указать не только свой, но и чужой WMID, однако, данный интерфейс не поддерживает доверие, поэтому создавать кошелёк можно только в своем WMID. По этой причине и в wmid, и в createpurse\wmid должен значиться один и тот же WMID - ваш. В общем, зачем этот параметр включен разработчиками в состав XML-запроса - осталось неясным;
  • createpurse\pursetype - тип создаваемого кошелька;
  • createpurse\desc - название кошелька, которое будет отображаться в Keeper Classic или Keeper Light.

Формат ответа сервера WebMoney можно посмотреть в описании интерфейса. В ответе нас интересуют поля <retval> (eсли оно равно 0, то кошелёк создан успешно, в противном случае retval будет содержать код ошибки, расшифровку которой нужно смотреть в поле <retdesc> или всё в том же описании интерфейса) и <pursename>. В последнем содержится номер созданного кошелька.

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

// ИНТЕРФЕЙС X16. СОЗДАНИЕ КОШЕЛЬКА. // На выходе: массив ['retval'=>код выполнения, 'retdesc'=>описание результата, // 'purse'=>номер кошелька] function _WMXML16 ($type,$desc) { global $Global_WMID, $XML_addr; $reqn=_GetReqn(); $rsign=_GetSign($Global_WMID.$type.$reqn); $desc=trim($desc); $desc=htmlspecialchars($desc, ENT_QUOTES); $desc=iconv("CP1251", "UTF-8", $desc); $xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <createpurse> <wmid>$Global_WMID</wmid> <pursetype>$type</pursetype> <desc>$desc</desc> </createpurse> </w3s.request>"; $resxml=_GetAnswer($XML_addr[16], $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['purse']=strval($xmlres->purse->pursename); return $result; }

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

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

  • $type - тип кошелька (1 буква - Z, R, U и т.д.). Обязательный параметр.
  • $desc - название кошелька. Допускаются любые символы, в том числе русские буквы. $desc желательно передавать в функцию в кодировке Win1251. Обязательный параметр.

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

$reqn=_GetReqn();

У $desc убираем лишние пробелы в начале и конце:

$desc=trim($desc);

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

$rsign=_GetSign($Global_WMID.$type.$reqn);

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

$desc=htmlspecialchars($desc, ENT_QUOTES);

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

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

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

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

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

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

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

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

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

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

$xml=" <w3s.request> <reqn>$reqn</reqn> <wmid>$Global_WMID</wmid> <sign>$rsign</sign> <createpurse> <wmid>$Global_WMID</wmid> <pursetype>$type</pursetype> <desc>$desc</desc> </createpurse> </w3s.request>";

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

$resxml=_GetAnswer($XML_addr[16], $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 (содержит расшифровку результата), purse\pursename (содержит номер созданного кошелька, включая первую "сигнальную" букву, т.е. в формате буква+12 цифр). Сохраняем эти переменные в массив $result.

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

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

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

return $result;

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

// test.php - скрипт для тестирования include("wmxml.inc.php"); $type="U"; $desc="тестовый кошелёк"; $r=_WMXML16($type,$desc); echo "Результат (0 - успешно) - ".$r['retval']."<br>"; echo "Расшифровка - ".$r['retdesc']."<br>"; echo "Номер кошелька - ".$r['purse']."<br>";

В заключение ещё раз приведём ссылку на файл с функциями всех 10 XML-интерфейсов WebMoney, которые мы рассмотрели в статьях на оВебМани.Ру. Вот он. Файл готов к работе, вы можете включать его в свои программы и использовать.

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

4.09.2008

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

   Что нового почитать?
В обновленных Киперах появились регулярные платежи 04.08.16
Обновилась вся линейка мобильных Киперов (iOS, Android, Windows Phone, MacOs X и BlackBerry OS 10), а также браузерный Keeper Standard.Главное новшест...
Получить быстрый заём теперь можно и в WMR 04.08.16
На сервисе Debt работает функция быстрого займа. Робот по специальному алгоритму, на основании уровня аттестата, BL и других показателей определяет су...
Вышел новый WinPro 3.9.9.7 29.07.16
Несмотря на то, что Кипер WinPro (Кипер под Windows) - самая функциональная версия из всей линейки Киперов, пользуется ей не так много юзеров WebMoney...
Возможно ли вернуть WM после оплаты или перевода? 29.07.16
Возможно ли вернуть WM после их перечисления (перевода) или оплаты в интернет-магазине?
Как выводить вебмани в 2016 году 14.06.16 [3]
С одной стороны, возникшая (надеюсь временно) проблема с выводом WebMoney на рублевые карты и банковские счета не столь уж и большая, ибо все остальны
WebMoney.UA запустила массовые выплаты с кошельков на карты 09.06.16
На сайте webmoney.ua представлена новая услуга - Массовые выплаты. Её суть заключается в том, что вы можете делать зачисления со своего WMU кошелька н...
Как привязать аккаунт соцсети к Keeper Standard 31.05.16
В Keeper Standard добавлена возможность прикрепить аккаунт в социальной сети (Facebook, Вконтакте, Одноклассниках и еще десятке других). После прикреп...
Увидит ли получатель перевода мои данные? 31.05.16
ВОПРОС: Если я переведу деньги со своего кошелька на кошелек другого человека, увидит ли он мое имя? Или будет виден только номер моего кошелька?

   Кофейня (форум)
оплатить paypal, плачу вмз 12.08.16
Произвол арбитража 27.06.16
Как найти автора статей? 24.06.16

   p2p
Меняют 25550 UAH на 1000 WMZ (курс:25.55) 27.08.16
Меняют 10000 UAH на 10050 WMU (курс:-0.5%) 27.08.16
Меняют 25550 UAH на 1000 WMZ (курс:25.55) 27.08.16

   WebMoney TOP
Зарегистрирован WmChange.in.ua Обмен, ввод, вывод webmoney...
Зарегистрирован Obmenu Быстро, безопасно и по хорошему курсу совершить обмен следующих видов электронных валют: Webmoney (W...
Зарегистрирован webmoneycredits Мониторинг кредитных автоматов, займы в WMZ и WMR...

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


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