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

Автоматический прием WM-платежей. Сервис WebMoney Merchant.

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

Введение
Общий принцип
Подготовительные работы
Формирование заказа. Начало платежа.
Проведение платежа
Окончание покупки
Интерфейс запроса статуса платежа X18
Интерфейс регистрации заказа X22
Возврат платежей
Последние штрихи и рекомендации

Введение

Существует 3 способа автоматического приема WebMoney на сайте:

  1. Web Merchant Interface
  2. XML-интерфейс X20
  3. Выписка WM-счета с последующей проверкой оплаты (способ очень устарел). Реализуется с помощью XML-интерфейсов X1 и X3.

Я рекомендую использовать 1-й способ, так как он наиболее универсален - позволяет принимать оплату от пользователей любой версии Кипера (Classic, Light, Mini, Mobile). Кроме того, он позволяет вашему покупателю оплачивать товар/услугу не только с WM-кошелька, но и с WM-карты, WebMoney Check, с банковской карты(!), из платежных терминалов, по системе денежных переводов и т.п., без необходимости регистрации в системе WebMoney.

Поэтому в данной статье мы поговорим о Web Merchant Interface (дальше будем называть его также упрощенно - Мерчант) и рассмотрим подключение сайта к нему на конкретном примере.

Прежде, чем начать, ответим на важный вопрос: можно ли подключить прием WebMoney в автоматическом режиме, совершенно не обладая навыками программирования? Ответ таков: нет, нельзя. Ни по одному из 3-х способов. Так же, впрочем, как и в случае подключения к сайту любой другой системы электронных денег, вам нужно иметь минимальные навыки программирования.

В некоторых наиболее простых случаях возможно подключение Web Merchant Interface по этому упрощенному руководству без необходимости что-то программировать. Но при этом, хотя сам прием платежей и будет автоматизирован, их обработка все равно останется ручным трудом. А это означает, что не будет и моментальности, поэтому такой подход равносилен обычной публикации на сайте номеров своих WM-кошельков (как, кстати, до сих пор многие и поступают).

Так или иначе, в данном материале я предполагаю, что вы умеете программировать под web хотя бы на минимальном уровне. Если не умеете, то дальше можно не читать - у вас ничего не выйдет. Просто опубликуйте на сайте номера своих кошельков и принимайте платежи вручную. Либо наймите программиста.

Для демонастрации программного кода я буду использовать PHP + СУБД MySQL. Но поскольку я постараюсь сдобрить статью подробными комментариями, для вас не составит труда реализовать подключение к Web Merchant Interface на другом серверном языке, который вы знаете. Если что-то все же останется не понятым, прибегайте к техническому описанию интерфейса, которое находится здесь.

Вообще, если вы никогда не видели, как работает Web Merchant Interface, то посмотрите вот этот пример.

Общий принцип

Общий принцип работы Web Merchant Interface такой (см. рис.1). Вы формируете на своем сайте необходимую информацию о заказе (точка А) и отправляете ее сайту Мерчанта https://merchant.webmoney.ru. Одновременно с этим и ваш покупатель попадает на этот сайт для совершения платежа. Мерчант авторизует покупателя, предлагает выбрать способ оплаты, проверяет наличие нужной суммы на кошельке или WM-карте, т.е. проводит ряд необходимых идентификаций и проверок. После этого Мерчант списывает WM с кошелька или карты покупателя. В тот же момент уплаченная сумма поступает на ваш кошелек. Мерчант уведомляет ваш сайт о том, что покупка успешно произведена или о том, что возникла какая-либо ошибка (точка С).


Рис.1. Схема взаимодействия вашего сайта с Мерчантом

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

Подготовительные работы

Для использования Web Merchant Interface ваш WMID должен иметь аттестат продавца. Идем по этой ссылке и выполняем требования, необходимые для получения аттестата продавца. Впрочем, можно и без этого. Имея начальный или персональный аттестат, тоже можно принимать платежи через Web Merchant Interface. Правда, в этом случае Вы будете скованы лимитами.

Теперь на странице Настройки нужно установить некоторые опции. Для этого напротив нужного кошелька жмем "настроить". Попадаем на страницу с настройкам. Приводим ее ниже:


Рис.2. Пример заполнения настроек при подключении кошелька к Мерчанту

Что означают эти опции (см. рис.2)?

  • Торговое имя - впишите сюда название вашего сервиса, который будет оплачиваться на данный кошелек. Это торговое имя плательщик будет видеть на странице Мерчанта перед оплатой (см. рис.3). Ни на что больше оно не влияет.
  • Secret Key - запишем сюда произвольную строку из 15-20 символов, состоящую из английских букв, цифр и других символов, кроме кавычек. Для чего нужен Secret Key, я расскажу чуть позже.
  • Result URL, Success URL, Fail URL. В эти поля нужно вписать адреса 3-х страниц вашего сайта (обязательно с http:// или https:// в начале). Сами страницы мы будем программировать чуть позже, а пока разберемся, зачем они нужны.
    На Success URL покупатель будет отправлен Мерчантом в случае успешной оплаты. На Fail URL покупатель будет отправлен, если оплата по какой-то причине не произошла (например, покупатель передумал платить и нажал на кнопку отказа, либо у него оказалось недостаточно средств на кошельке). Страница Result URL - секретная, пользователь ее не видит. Она служит для "общения" сервера Мерчанта с вашим сайтом, т.е. для обмена информацией. Желательно выбирать для скрипта (файла), прописанного в Result URL, не банальное имя.
  • Рядом с Success URL и Fail URL выбираем в качестве метода вызова POST.
  • Передавать параметры в предварительном запросе - галочку ставим.
  • Позволять использовать URL, передаваемые в форме - галочку не ставим, эта опция нам не нужна.
  • Высылать оповещение об ошибке платежа на кипер - будет ли Мерчант отправлять вам по внутренней WM-почте сообщение в случае возникновения ошибки при совершении платежа пользователем. Ставим галочку, так как это полезная фишка.
  • Метод формирования контрольной подписи - выбираем SHA256. Вернемся к разговору о контрольной подписи позже.
  • Режимы - выбираем "Тестовый", так как в тестовом режиме деньги с кошелька плательщика не списываются, и это очень удобно для проведения тестовых покупок. В самом конце, когда всё будет готово, мы вернемся к данной опции и переведем ее в рабочий режим.

Жмем кнопку [Сохранить].

На скриншоте (рис.2) я устанавливал настройки для одного из своих Z-кошельков. Точно так же можно настроить и другие кошельки, в т.ч. и кошельки других типов (R, U и т.д.). Если, например, вы планируете принимать оплату за товар/услугу в WMZ и WMR на выбор покупателя, то вам нужно настроить один Z- и один R-кошелек. Настройки совершенно идентичны.

Формирование заказа. Начало платежа.

Чтобы инициировать платеж, в точке А (см. рис.1) нам нужно передать Мерчанту ряд параметров, для того чтобы Мерчант знал, какую сумму и в пользу какого продавца списывать с кошелька покупателя. Какие именно действия пользователя будут предшествовать точке А - решать вам. Но помните - к моменту, когда покупатель нажмет кнопку в точке А и перейдет на Мерчант для оплаты, вам обязательно нужно иметь информацию об этом пользователе и его покупке. Как правило, это решается одним из способов в зависимости от вашей конкретной ситуации:

  • Покупатель формирует "корзину покупок" и заполняет информацию о себе, а ваш сайт подсчитывает и сохраняет стоимость его заказа. Такой подход обычно применяется в интернет-магазинах нецифровых товаров.
  • Покупатель проходит регистрацию на сайте, входит в личный аккаунт и указывает сумму, на которую он собирается пополнить свой внутренний счет на вашем сайте. Чаще всего применяется на сайтах интернет-казино, хостинг-провайдеров.
  • Покупатель просто выбирает один товар из каталога и указывает необходимую информацию о себе. Обычно такую схему можно встретить в магазинах цифровых товаров.

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

Пусть, нам требуется продавать покупателям некие электронные товары (скажем, коды пополнения мобильных операторов) и выслать их по email после оплаты. Также договоримся для простоты, что покупатель сможет выбирать из каталога и оплачивать за раз только один товар т.е. без формирования "корзины покупок".

Очевидно, что у нас в базе данных должна быть таблица с характеристиками товаров:

Таблица goods
id id товара
tname название товара
cost стоимость товара
... ...

Покупатель выбирает товар из каталога, и попадает в точку А. Эта страница на вашем сайте (назовем ее order.php) должна содержать такую html-форму:

<form method="POST" action="https://merchant.webmoney.ru/lmi/payment.asp">
<input type="hidden" name="LMI_PAYMENT_NO" value="1">
<input type="hidden" name="LMI_PAYMENT_AMOUNT" value="0.05">
<input type="hidden" name="LMI_PAYMENT_DESC" value="код пополнения Super Mobile">
<input type="hidden" name="LMI_PAYEE_PURSE" value="Z155771820786">
<input type="hidden" name="id" value="345">
Укажите email для отправки товара: <input type="text" name="email" size="15">
<input type="submit" value="Перейти к оплате">
</form>

Будем называть это формой запроса платежа. Рассмотрим форму детальнее:

  • action - Атрибут action должен отправлять на https://merchant.webmoney.ru/lmi/payment.asp.
  • method - Должен использоваться метод посыла формы POST.
  • LMI_PAYMENT_NO - Поле, которое содержит номер заказа, покупки и т.д. Назначается вами произвольно. Можно не использовать, но мы рекомендуем всегда использовать это поле, тем более, что в некоторых случаях без нумерации покупок просто не обойтись. К тому же, передача LMI_PAYMENT_NO необходима для последующего применения интерфейса Х18. Поле может содержать только цифры. В нашем примере значение LMI_PAYMENT_NO=1
  • LMI_PAYMENT_AMOUNT - Поле, которое содержит сумму платежа. Дробная часть отделяется точкой. В нашем примере значение LMI_PAYMENT_AMOUNT=0.05.
  • LMI_PAYMENT_DESC (или LMI_PAYMENT_DESC_BASE64) - Поле, которое содержит примечание платежа. Должно содержать текст, желательно - наименование товара или услуги, которая продается. Максимальная длина - 255 символов. В нашем примере значение LMI_PAYMENT_DESC="код пополнения Super Mobile".
  • LMI_PAYEE_PURSE - Ваш кошелек, только что подключенный к Мерчанту (см. главу "Предварительные настройки"). Должен состоять из буквы (Z-, R- и т.д.) и 12 цифр. По значению этого поля Мерчант распознает, в пользу какого продавца (иначе говоря, на чей кошелек) производится платеж. В нашем примере LMI_PAYMENT_PURSE="Z155771820786".

Обращаю ваше внимание, что поля LMI_PAYMENT_NO, LMI_PAYMENT_AMOUNT, LMI_PAYMENT_DESC, LMI_PAYEE_PURSE должны называться именно так, и никак иначе. При этом поля LMI_PAYMENT_AMOUNT, LMI_PAYMENT_DESC и LMI_PAYEE_PURSE являются обязательными.

Если в LMI_PAYMENT_DESC есть кириллические символы, то они должны быть представлены в кодировке Win1251. Если это по каким-то причинам невозможно, и ваша строка представлена в кодировке UTF8, то вместо LMI_PAYMENT_DESC нужно использовать параметр LMI_PAYMENT_DESC_BASE64. В нём нужно передать вашу UTF8-строку, предварительно закодированную в base64:

<input type="hidden" name="LMI_PAYMENT_DESC_BASE64" value="<?php echo base64_encode("здесь ваше примечание платежа в кодировке UTF8");?>">

В той же форме можно передавать и свои произвольные параметры, если это необходимо. При чем, названы эти параметры могут быть как угодно, главное, чтобы они не начинались с префикса "LMI_". В нашем примере мы добавили в форму:

  • Поле id - содержит id выбранного покупателем товара. Берется из таблицы goods.
  • Поле email - покупатель указывает здесь свой email, на который он получит товар после оплаты.

После нажатия на кнопку покупатель попадает на https://merchant.webmoney.ru/lmi/payment.asp, то есть переходит на сайт Мерчанта. Одновременно с этим сайту Мерчанта, естественно, передаются и все параметры нашей формы.

Здесь есть маленький секрет. Платить на Мерчанте можно не только с кошелька, но и многими другими способами. Так вот, если изменять action "формы запроса платежа", то можно позиционировать покупателя сразу на том или ином способе оплаты на стороне Мерчанта. Ниже перечислены все возможные значения Action "формы запроса платежа" и куда они "приведут" покупателя:

  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_2 - Keeper Light;
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_3 - WebMoney-карта или чек Paymer (опция "Прием чеков Paymer.com (ВМ-карт) или WM notes" в настройках кошелька должна быть включена);
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_4 - Keeper Mobile;
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_5 - E-Num;
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_7 - оплата через платежные терминалы (только для WMU кошельков, опция "Прямой прием платежей через терминалы и банки (Украина)" в настроках кошелька должна быть включена);
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_8 - Keeper Classic;
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_9 - Keeper Mini;
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_11 - Почта РФ (только для WMR кошельков);
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_12 - Keeper для соц.сетей;
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_13 - WebMoney Check (опция "Прием платежей через терминалы, банкоматы, кассы магазинов и т.п.(WebMoney.Check)" в настройках кошелька должна быть включена);
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_14 - Денежный перевод (только для WMR кошельков, опция "Прием платежей через Системы денежных переводов" должна быть включена);
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_15 - оплата через системы интернет-банк некоторых российских банков (только для WMR кошельков, соответствующая опция в настройках кошелька должна быть включена);
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_16 - оплата банковской картой (только для WMR кошельков, опция "Прием платежей через карты российских банков" в настройках кошелька должна быть включена);
  • https://merchant.webmoney.ru/lmi/payment.asp?at=authtype_19 - оплата бонусами Сбербанка "Спасибо" (только для WMR кошельков, опция "Прием платежей через бонусные СПАСИБО "Сбербанка" в настройках кошелька должна быть включена);

Посмотрите, как это может выглядеть на практике. В примере пользователю предложили выбрать, как он хочет платить - с кошелька, через WebMoney Check или с WM-карты. В зависимости от сделанного выбора отправили пользователя по нужной "ветке" оплаты.

Прохождение платежа.

Первое, что видит покупатель, попав на сайт сервиса Мерчант:


Рис.3. Первая страница сервиса Мерчанта.

Здесь видно сумму будущего платежа, торговое имя (помните, мы заполняли его, когда подключали кошелек в главе "Подготовительные работы"?) и содержимое LMI_PAYMENT_DESC (название товара или услуги), а также LMI_PAYMENT_NO (номер покупки).

На этой же странице покупатель выбирает способ оплаты - с WebMoney-кошелька, либо через сервис WebMoney Check, с WM-карты и т.д. Для примера авторизуемся с помощью Кипера и продемонстрируем оплату с WebMoney-кошелька.


Рис.4. Страница Мерчанта с выбором кошелька.

Далее в нашем примере покупатель выбирает кошелек, с которого будет списана стоимость покупки.

После нажатия на кнопку [Платеж подтверждаю] начинается самое интересное. Мы оказываемся в точке B (см.рис.1), и сервер Мерчанта отправляет на наш Result URL форму предварительного запроса. Отправка происходит методом POST. Форма содержит такие параметры:

  • LMI_PREREQUEST, равный 1. Это индикатор предварительного запроса. Зачем он нужен, мы узнаем чуть позже.
  • LMI_PAYEE_PURSE - кошелек продавца (должен совпадать с параметром LMI_PAYEE_PURSE, переданным в order.php).
  • LMI_PAYMENT_NO - номер покупки (должен совпадать с параметром LMI_PAYEE_NO, переданным в order.php).
  • LMI_PAYMENT_AMOUNT - сумма платежа, которую оплачивает покупатель (должна совпадать с параметром LMI_PAYEE_AMOUNT, переданным в order.php).
  • LMI_PAYER_WM - WMID покупателя.
  • Ряд других менее важных "системных" параметров. Полный их список можно посмотреть здесь. Все системные параметры имеют префикс LMI_.
  • Все остальные параметры, которые мы передавали Мерчанту в точке А из формы запроса платежа. В нашем случае это id и email.

Зачем нужна эта форма? Дело в том, что еще в точке А недобросовестный покупатель может заменить значения параметров в форме запроса платежа, т.е. произвести "взлом" html-кода. Это совсем не сложный трюк. В результате Мерчанту будут переданы совсем не те значения параметров, которые нужно.

Например, в нашем примере покупатель мог бы заменить в поле LMI_PAYMENT_AMOUNT сумму платежа с 0.05 на 0.01, в результате он заплатил бы 0.01 WMZ вместо 0.05 WMZ и спокойно получил бы товар за меньшую цену. Другой вариант: подставить в форму id более дорогого товара и, таким образом, купить его дешевле.

Поэтому, в целях защиты, Мерчант как бы переспрашивает нас перед списанием средств с покупателя: "а действительно ли такой-то товар в вашем магазине стоит столько-то? а действительно ли это ваш кошелек для приема платежей?" и т.д.

В ответ на такой запрос мы должны в том же скрипте Result URL произвести все необходимые проверки и выдать Мерчанту ответ: строку "YES",если всё верно, или строку с текстом ошибки, если что-то не так. В частности, в нашем примере нужно произвести такие проверки:

  1. Проверить, существует ли товар с полученным от Мерчанта id в нашей базе данных (в таблице goods), то есть не произошла ли подмена параметра id.
  2. Проверить, совпадает ли сумма в LMI_PAYMENT_AMOUNT с реальной стоимостью товара, прописанной в нашей БД (в таблице goods), то есть не произошла ли подмена параметра LMI_PAYMENT_AMOUNT.
  3. Проверить, действительно ли кошелек получателя в LMI_PAYEE_PURSE является вашим кошельком, подключенным к Мерчанту, то есть не произошла ли подмена параметра LMI_PAYEE_PURSE.
  4. Проверить, передан ли параметр email, так как если он не передан, отправлять товар будет некуда, а значит покупку нужно прервать прямо сейчас.

Ниже приводим PHP-код, реализующий эти проверки в нашем примере. Напомню, что в качестве Result URL мы прописали скрипт test_results.php (см.рис.2). Поэтому приведенный ниже код мы помещаем в этот файл. В качестве сигнала о том, что получена именно форма предварительного запроса, используем параметр LMI_PREREQUEST, равный 1.

// Соединяемся с БД
...
// Если это форма предварительного запроса, то идем дальше...
IF($_POST['LMI_PREREQUEST']==1) {
  // 1) Проверяем, есть ли товар с таким id в базе данных.
  // Если такой товар не обнаружен, то выводим ошибку и прерываем работу скрипта.
  $q="SELECT `id`, `cost` FROM `goods` WHERE id='$_POST['id']'";
  $res=mysql_fetch_row(mysql_query($q));
  if(!$res[0] or $res[0]=="") {
    echo "ERR: НЕТ ТАКОГО ТОВАРА";
    exit;
  }
  // 2) Проверяем, не произошла ли подмена суммы.
  // Cравниваем стоимость товара в базе данных с той суммой, что передана нам Мерчантом.
  // Если сумма не совпадает, то выводим ошибку и прерываем работу скрипта.
  if(trim($res[1])!=trim($_POST['LMI_PAYMENT_AMOUNT'])) {
    echo "ERR: НЕВЕРНАЯ СУММА ".$_POST['LMI_PAYMENT_AMOUNT'];
    exit;
  }
  // 3) Проверяем, не произошла ли подмена кошелька.
  // Cравниваем наш настоящий кошелек с тем кошельком, который передан нам Мерчантом.
  // Если кошельки не совпадают, то выводим ошибку и прерываем работу скрипта.
  if(trim($_POST['LMI_PAYEE_PURSE'])!="Z155771820786") {
    echo "ERR: НЕВЕРНЫЙ КОШЕЛЕК ПОЛУЧАТЕЛЯ ".$_POST['LMI_PAYEE_PURSE'];
    exit;
  }
  // 4) Проверяем, указал ли пользователь свой email.
  // Если параметр $email пустой, то выводим ошибку и прерываем работу скрипта.
  if(!trim($_POST['email']) or trim($_POST['email'])=="") {
    echo "ERR: НЕ УКАЗАН EMAIL";
    exit;
  }
  // Если ошибок не возникло и мы дошли до этого места, то выводим YES
  echo "YES";
}

Естественно, в вашем случае набор проверок будет отличаться.

В случае, если Мерчант получил от Result URL ответ "YES", средства списываются с кошелька плательщика и тут же поступают на ваш. В случае получения другого ответа Мерчант прерывает платеж, средства с кошелька плательщика не списываются, а на экран выводится текст ошибки:


Рис.5. Мерчант получил от Result URL ошибку, прервал выполнение платежа и отобразил эту ошибку.

На этом скриншоте показано, как сработала наша проверка № 2. Очевидно, хитроумный покупатель решил нас одурачить и заплатить 0.01 WMZ вместо 0.05, изменив параметр LMI_PAYMENT_AMOUNT в форме order.php. Но мы пресекли его план. Обман не удался.

Как я только что говорил, если Мерчант получает от вас "YES", то происходит списание с кошелька. Сразу после этого мы попадаем в точку С, и Мерчант направляет тому же скрипту Result URL форму оповещения о платеже. Отправка происходит методом POST. Форма содержит такие параметры:

  • LMI_PAYMENT_NO - номер покупки, назначенный продавцом.
  • LMI_PAYEE_PURSE - кошелек продавца, на который покупатель совершил платеж.
  • LMI_PAYMENT_AMOUNT - сумма, которую заплатил покупатель.
  • LMI_PAYER_PURSE - кошелек покупателя, с которого он совершил платеж.
  • LMI_PAYER_WM - WMID покупателя.
  • LMI_PAYMER_NUMBER - номер WM-карты или чека Paymer, если была оплата WM-картой.
  • LMI_WMCHECK_NUMBER - номер телефона покупателя, если была оплата с WebMoney Check.
  • LMI_HASH - контрольная подпись. Что это такое, расскажем через минуту.
  • LMI_SYS_TRANS_DATE - дата и время совершения платежа с точностью до секунд.
  • Ряд других менее важных "системных" параметров. Полный их список можно посмотреть здесь. Все системные параметры имеют префикс LMI_.
  • Все остальные параметры, которые мы передавали Мерчанту в точке А в форме запроса платежа. В нашем случае это id и email.

Как видите, это очень похоже на форму предварительного запроса. Но есть и различия. Например, мы уже не получаем параметра LMI_PREREQUEST, зато появляется LMI_HASH и ряд других переменных.

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

Кроме того, создадим таблицу orders, куда будем записывать завершенные покупки. Это может пригодиться нам для статистики и истории.

Таблица orders
order_id id покупки. INDEX, auto_increment
id id купленного товара
odate дата покупки
purse кошелек покупателя
email email покупателя
tovar содержимое купленного товара
... ...

То, что получена именно форма оповещения о платеже, мы можем узнать по отсутствию параметра LMI_PREREQUEST. Дописываем наш test_results.php:

// Соединяемся с БД
...
// Если это форма предварительного запроса...
IF($_POST['LMI_PREREQUEST']==1) {
  ...
}
// Если нет LMI_PREREQUEST, следовательно это форма оповещения о платеже...
ELSE {
  // Выбираем из базы данных нужный товар, записываем его в переменную $tovar;
  ...
  // Вносим покупку в таблицу orders
  $q="insert into `orders` set `id`='$_POST['id']', `odate`='$_POST['LMI_SYS_TRANS_DATE']',
    `purse`='$_POST['LMI_PAYER_PURSE']', `email`='$_POST['email']', `tovar`='$tovar'";
  mysql_query($q);
  // Отправляем товар на email покупателя
  $text="Ваш товар: ".$tovar;
  mail($_POST['email'], convert_cyr_string("Ваш товар",w,k), convert_cyr_string($text,w,k),
   "From: robot@site.ru\r\nContent-Type: text/plain; charset=\"koi8-r\"");
}

Вроде бы всё? Не совсем. Дело в том, что есть вероятность того, что злоумышленник узнает адрес нашего Result URL (скрипт test_results.php) и симитирует посыл на него ложной формы оповещения о платеже. В этом случае наш Result URL будет ошибочно "думать", что получает форму от Мерчанта из точки С и что оплата за товар произведена, тогда как на самом деле никакой оплаты не поступит.

Для того, чтобы избежать этой ситуации и пресечь подобное мошенничество, нам нужно определить, кто прислал форму оповещения о платеже - Мерчант или кто-то посторонний. Для этого используется параметр LMI_HASH. И это, пожалуй, самый сложный момент.

Мерчант формирует LMI_HASH так. Сначала он склеивает в одну строку (без пробелов и разделителей) значения следующих полей:

  1. Кошелек продавца (LMI_PAYEE_PURSE);
  2. Сумма платежа (LMI_PAYMENT_AMOUNT);
  3. Внутренний номер покупки продавца (LMI_PAYMENT_NO);
  4. Флаг тестового режима (LMI_MODE);
  5. Внутренний номер счета в системе WebMoney Transfer (LMI_SYS_INVS_NO);
  6. Внутренний номер платежа в системе WebMoney Transfer (LMI_SYS_TRANS_NO);
  7. Дата и время выполнения платежа (LMI_SYS_TRANS_DATE);
  8. Secret Key;
  9. Кошелек покупателя (LMI_PAYER_PURSE);
  10. WMId покупателя (LMI_PAYER_WM).

Склейка значений происходит именно в том порядке, в котором они приведены выше. Все эти параметры, кроме 8-го, передаются Мерчантом на Result URL в той же форме оповещения о платеже.

После склейки Мерчант формирует контрольную подпись. В нашем случае мы указали в настройках (см.рис.2), что контрольная подпись будет формироваться по алгоритму SHA256.

Справка. SHA256 - алгоритм шифрования. В результате применения этого алгоритма к строке любой длины на выходе получается строка из 64 символов, которая называется "хэшем" (другие названия - "контрольная сумма", "контрольная подпись", "свёртка").
Расшифровать хэш невозможно, то есть алгоритм необратим и работает только в одном направлении. Поэтому SHA256 используется для хранения секретной информации, такой, как пароли. Например, при регистрации пользователя на форуме пароль кодируется SHA256 и полученная свертка сохраняется в базе данных. Когда пользователь авторизуется на форуме, указывая пароль, то этот пароль также кодируется SHA256, и полученная свёртка сравнивается с той, что хранится в базе. Если они совпадают, то и пароль был указан верно. Если не совпадают, то неверно.
В PHP имеется стандартная функция шифрования по алгоритму SHA256: hash("sha256",$str). В PHP должен быть подключен модуль hash (поддерживается начиная с версии PHP 5.1.2).

Полученный путем таких преобразований SHA256-хэш, состоящий из 64 символов, Мерчант и передает в переменной LMI_HASH, предварительно переведя его в верхний регистр. Наша задача такая: проделать те же самые действия, получить свой SHA256-хэш и сравнить его с LMI_HASH, полученным от Мерчанта. Если они совпадают, значит форма оповещения о платеже действительно передана нам Мерчантом.

А в чем смысл? - спросите вы. Ведь точно так же и хакер может сформировать LMI_HASH на основе ложных параметров, и передать нам эти параметры вместе с LMI_HASH. Изюминка заключается в том, что значение одного из полей, участвующих в формировании LMI_HASH - Secret Key - знаете только вы и Мерчант. И никто больше. Если ошибка будет хотя бы в одной букве Secret Key (равно как и в значении любой другой переменной, участвующей в формировании "склеенной" строки), то контрольные подписи уже не совпадут.

Давайте вернемся в начало статьи и обратим внимание на опцию "Secret Key" в настройках кошелька на рис.2. Туда мы ввели бессмысленную и длинную последовательность символов. Теперь мы знаем, где она используется. И знаем, почему желательно задавать в Secret Key строку подлинее и посложнее: так мы уменьшаем шансы ее подбора злоумышленником.

Итак, перед тем как выполнять заказ, мы должны сформировать контрольную сумму и сравнить ее с LMI_HASH. Если значния совпадают - выполняем заказ. Если не совпадают - то предполагаем, что была попытка взлома, и заказ не выполняем от греха подальше.

Следующий PHP-код демонстрирует проверку контрольной подписи:

// Задаем значение $secret_key.
// Оно должно совпадать с Secret Key, указанным нами в настройках кошелька.
$secret_key="dflsj4k!;fm3afd";
// Склеиваем строку параметров
$common_string = $_POST['LMI_PAYEE_PURSE'].$_POST['LMI_PAYMENT_AMOUNT'].$_POST['LMI_PAYMENT_NO'].
$_POST['LMI_MODE'].$_POST['LMI_SYS_INVS_NO'].$_POST['LMI_SYS_TRANS_NO'].
$_POST['LMI_SYS_TRANS_DATE'].$secret_key.$_POST['LMI_PAYER_PURSE'].$_POST['LMI_PAYER_WM'];
// Шифруем полученную строку в SHA256 и переводим ее в верхний регистр
$hash = strtoupper(hash("sha256",$common_string));
// Прерываем работу скрипта, если контрольные суммы не совпадают
if($hash!=$_POST['LMI_HASH']) exit;

Таким образом, окончательный вариант Result URL (test_results.php) будет выглядеть так:

// Соединяемся с БД
...
// ЕСЛИ ЭТО ФОРМА ПРЕДВАРИТЕЛЬНОГО ЗАПРОСА, ТО ИДЕМ ДАЛЬШЕ...
IF($_POST['LMI_PREREQUEST']==1) {
  // 1) Проверяем, есть ли товар с таким id в базе данных.
  // Если такой товар не обнаружен, то выводим ошибку и прерываем работу скрипта.
  $q="SELECT `id`, `cost` FROM `goods` WHERE id='$_POST['id']'";
  $res=mysql_fetch_row(mysql_query($q));
  if(!$res[0] or $res[0]=="") {
    echo "ERR: НЕТ ТАКОГО ТОВАРА";
    exit;
  }
  // 2) Проверяем, не произошла ли подмена суммы.
  // Cравниваем стоимость товара в базе данных с той суммой, что передана нам Мерчантом.
  // Если сумма не совпадает, то выводим ошибку и прерываем работу скрипта.
  if(trim($res[1])!=trim($_POST['LMI_PAYMENT_AMOUNT'])) {
    echo "ERR: НЕВЕРНАЯ СУММА ".$_POST['LMI_PAYMENT_AMOUNT'];
    exit;
  }
  // 3) Проверяем, не произошла ли подмена кошелька.
  // Cравниваем наш настоящий кошелек с тем кошельком, который передан нам Мерчантом.
  // Если кошельки не совпадают, то выводим ошибку и прерываем работу скрипта.
  if(trim($_POST['LMI_PAYEE_PURSE'])!="Z155771820786") {
    echo "ERR: НЕВЕРНЫЙ КОШЕЛЕК ПОЛУЧАТЕЛЯ ".$_POST['LMI_PAYEE_PURSE'];
    exit;
  }
  // 4) Проверяем, указал ли пользователь свой email.
  // Если параметр $email пустой, то выводим ошибку и прерываем работу скрипта.
  if(!trim($_POST['email']) or trim($_POST['email'])=="") {
    echo "ERR: НЕ УКАЗАН EMAIL";
    exit;
  }
  // Если ошибок не возникло и мы дошли до этого места, то выводим YES
  echo "YES";
}
// ЕСЛИ НЕТ LMI_PREREQUEST, СЛЕДОВАТЕЛЬНО ЭТО ФОРМА ОПОВЕЩЕНИЯ О ПЛАТЕЖЕ...
ELSE {
  // Задаем значение $secret_key.
  // Оно должно совпадать с Secret Key, указанным нами в настройках кошелька.
  $secret_key="dflsj4k!;fm3afd";
  // Склеиваем строку параметров
  $common_string = $_POST['LMI_PAYEE_PURSE'].$_POST['LMI_PAYMENT_AMOUNT'].$_POST['LMI_PAYMENT_NO'].
     $_POST['LMI_MODE'].$_POST['LMI_SYS_INVS_NO'].$_POST['LMI_SYS_TRANS_NO'].
     $_POST['LMI_SYS_TRANS_DATE'].$secret_key.$_POST['LMI_PAYER_PURSE'].$_POST['LMI_PAYER_WM'];
  // Шифруем полученную строку в SHA256 и переводим ее в верхний регистр
  $hash = strtoupper(hash("sha256",$common_string));
  // Прерываем работу скрипта, если контрольные суммы не совпадают
  if($hash!=$_POST['LMI_HASH']) exit;
  // Выбираем из базы данных нужный товар, записываем его в переменную $tovar;
  ...
  // Вносим покупку в таблицу orders
  $q="insert into `orders` set `id`='$_POST['id']', `odate`='$_POST['LMI_SYS_TRANS_DATE']',
    `purse`='$_POST['LMI_PAYER_PURSE']', `email`='$_POST['email']', `tovar`='$tovar'";
  mysql_query($q);
  // Отправляем товар на email покупателя
  $text="Ваш товар: ".$tovar;
  mail($_POST['email'], convert_cyr_string("Ваш товар",w,k), convert_cyr_string($text,w,k),
     "From: robot@site.ru\r\nContent-Type: text/plain; charset=\"koi8-r\"");
}

Отправляя форму оповещения о платеже, Мерчант уже не ждет от вас ответа, как в форме предварительного запроса, поскольку от вашего ответа уже ничего не зависело бы: деньги списаны с покупателя и зачислены продавцу.

Важно! Игнорирование проверок формы предварительного запроса и формы оповещения о платеже - это основная ошибка программистов, которые подключают к сайту прием WM-платежей. Это становится причиной взломов и несанкционированных покупок, среди которых самый распространенный взлом заключается в подмене хакером суммы платежа и покупки товара/услуги по значительно заниженной стоимости. Не повторяйте чужих ошибок!

Примечание. Если пользователь выбрал оплату не с Кипера, а с WM-карты или через сервис WebMoney Check, то для вас всё остается прозрачным. Приведенный выше программный код будет работать и в этих случаях тоже. Единственная разница заключается в получении от Мерчанта таких параметров как LMI_PAYMER_NUMBER (содержит номер WM-карты, с которой производилась оплата), LMI_WMCHECK_NUMBER (содержит номер телефона покупателя в сервисе WebMoney Check, с которого производилась оплата) и некоторые другие. Но эти параметры несут не более чем просто информационную нагрузку, поскольку вам как продавцу, за исключением редких случаев, абсолютно без разницы, откуда поступили деньги.
Обратите внимание, что при оплате с WM-карты Мерчант запрашивает у пользователя email, поскольку это единственный способ связи с таким пользователем. Этот email передается в параметре LMI_PAYMER_EMAIL.

Окончание покупки

Что ж, всё самое сложное позади. Осталось разобраться с Success URL и Fail URL.

После успешного платежа покупатель попадает на такую страницу:


Рис.6. Последняя страница Мерчанта после оплаты.

Это точка D схемы на рис.1. При нажатии на кнопку [Вернуться к продавцу] Мерчант перенаправляет пользователя на Success URL. Этой странице Мерчант передает форму выполненного платежа, содержащую несколько "системных" параметров (см. список), а также все остальные "несистемные" параметры, которые мы передавали Мерчанту еще в точке А в форме запроса платежа. В нашем случае это id и email. Таким образом, Мерчант как бы пропускает сквозь себя эти параметры, возвращая на выходе то, то получал на входе.

Передача Мерчантом параметров на Success URL позволяет нам внести и сюда элемент интерактивности. Например, вывести на экран какое-нибудь персонифицированное сообщение об успешном окончании покупки. Ниже приведем один из вариантов Success URL (скрипт yes.php) для нашего примера:

echo "Покупка успешно произведена. Товар номер ".$_POST['id']." выслан на ваш email ".$_POST['email'];

Важно! Ни в коем случае не выполняйте заказ в скрипте Success URL, поскольку она никак не защищена от взломов и посыла ложных форм. Так, например, если бы мы отправляли товар покупателю именно в Success URL, а не в Result URL, то злоумышленник легко мог бы отправить на Success URL форму, содержащую email и id - и мы выслали бы ему товар, не получив при этом никакой оплаты.

А что же Fail URL? На него Мерчант отправляет покупателя в следующих случаях:

  1. На какой-либо из страниц Мерчанта покупатель нажал кнопку [От платежа отказываюсь].
  2. У покупателя недостаточно средств.
  3. Мерчант не получил от Продавца "YES" в ответ на форму предварительного запроса.

Как вы уже знаете, во всех этих случаях деньги с покупателя не списывается, покупатель перенаправляется прямиком на Fail URL, а форма оповещения о платеже на Result URL не передается.

Странице Fail URL (в нашем примере это скрипт no.php) передаются такие же параметры, как и Success URL. Но, конечно, на этой странице нужно выводить совсем иной текст. Это должно быть что-то вроде "Оплата не прошла. Возможно, вы отказались от платежа или возникла другая ошибка".

Интерфейс запроса статуса платежа X18

[Данный раздел добавлен в статью 18 июля 2009 года]

Как вы могли заметить, форма оповещения о платеже отправляется Мерчантом на ваш Result URL всего 1 раз. Если в этот момент произойдет обрыв соединения, либо Мерчант не сможет "достучаться" до вашего сервера, то сигнал об успешном завершении платежа вы не получите.

Для того чтобы избежать такой ситуации на Мерчанте развернут специальный интерфейс обратной связи (он называется X18). Прибегнув к нему, вы можете запросить сервер Мерчанта о состоянии любого из своих платежей по его LMI_PAYMENT_NO и, если искомый платеж был успешно проведен, получить в ответ также его параметры. То есть здесь уже не Мерчант стучится к вам, а вы стучитесь к Мерчанту.

Интерфейс достаточно простой. На вход нужно передать XML-пакет, содержащий ваш WMID, кошелек-получатель, LMI_PAYMENT_NO искомого платежа.

Нюанс заключается в том, что вам нужно идентифицировать себя перед Мерчантом путем передачи в XML-пакете одного из следующих параметров: цифровая подпись, md5-хеш запроса или SecretKey. Если вы решите использовать первый вариант (цифровую подпись), то вам нужно делать это с помощью модуля WMSigner. Второй вариант проще: необходимо сформировать md5-хеш (должен быть представлен в верхнем регистре) строки, полученной в результате склейки параметров wmid + lmi_payee_purse + lmi_payment_no + secret_key. Третий вариант ещё проще, но небезопаснее: нужно всего лишь передать в запросе свой SecretKey, однако нужно понимать, что в случае использования незащищенного http-протокола или в результате DNS-атаки ваш SecretKey может быть перехвачен.

Приведем пример реализации интерфейса на PHP. В качестве способа идентификации будем использовать второй вариант - md5-хеш. Для корректной работы этого примера необходимо наличие PHP версии не ниже 5.0 с подключенными модулями curl и simplexml.

$lmi_payment_no="11111"; // номер платежа, состояние которого запрашивается $wmid="123456789012"; // ваш wmid $lmi_payee_purse="Z010101010101"; // ваш кошелек-получатель, на который совершался платеж $secret_key="df938jk30kdl"; // SecretKey, заданный в настройках кошелька на WM Merchant // формируем хеш: $md5=strtoupper(md5($wmid.$lmi_payee_purse.$lmi_payment_no.$secret_key)); // формируем xml-запрос // т.к. используется хеш, то 2 других метода авторизации - sign и secret_key - // оставляем пустыми $request=" <merchant.request> <wmid>$wmid</wmid> <lmi_payee_purse>$lmi_payee_purse</lmi_payee_purse> <lmi_payment_no>$lmi_payment_no</lmi_payment_no> <sign></sign> <md5>$md5</md5> <secret_key></secret_key> </merchant.request> "; // отправляем запрос с помощью curl методом POST и получаем ответ $ch = curl_init("https://merchant.webmoney.ru/conf/xml/XMLTransGet.asp"); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_POST,1); curl_setopt($ch, CURLOPT_POSTFIELDS, $request); curl_setopt($ch, CURLOPT_CAINFO, "/path/to/WMunited.cer"); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE); $result=curl_exec($ch); // разбираем xml-ответ с помощью simplexml $xmlres = simplexml_load_string($result); // смотрим результат выполнения запроса $retval=strval($xmlres->retval); // если результат равен -8, то платежа с таким номером не было if($retval==-8) echo "Платеж $lmi_payment_no не проводился!"; // если результат не равен -8 и не равен 0, то возникла ошибка при обработке запроса elseif($retval!=0) echo "Запрос составлен некорректно!"; // если результат равен 0, то платеж с таким номером проведен else { // вытаскиваем важные параметры платежа $wmtranid=strval($xmlres->operation->attributes()->wmtransid); $date=strval($xmlres->operation->operdate); $payer=strval($xmlres->operation->pursefrom); $ip=strval($xmlres->operation->IPAddress); $paymer_number=strval($xmlres->operation->paymer_number); // отображаем результаты на экране echo " Платеж $lmi_payment_no завершился успешно. Он был произведен $date с кошелька $payer. Плательщик использовал IP-адрес $ip. WM-транзакции присвоен идентификатор $wmtranid. "; }

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

curl_setopt($ch, CURLOPT_CAINFO, "/path/to/WMunited.cer");

Если вы не слишком щепетильно относитесь к формированию LMI_PAYMENT_NO и допускаете платежи с одинаковыми номерами, то при запросе интерфейса по такому LMI_PAYMENT_NO, с которым было проведено более одного платежа, интерфейс вернет информацию только об одном (последнем) платеже с данным номером. Если вы вообще не передаете LMI_PAYMENT_NO в "форме запроса платежа" (этот параметр, напомню, является необязательным), то и запросить его статус с помощью Х18 вы не сможете. Это еще один аргумент за то, чтобы всегда присваивать, сохранять на своей стороне и передавать на Мерчант номер платежа LMI_PAYMENT_NO!

Функция для работы с интерфейсом Х18 включена в библиотеку XOWM от оВебмани.Ру.

Интерфейс регистрации заказа X22

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

Например, клиент на сайте отельного брокера заказывает бронирование гостиничного номера в Новосибирске, после этого работу с сайтом он заканчивает. Менеджер звонит в гостиницу, подтверждает бронь и, используя Х22, создаёт ссылку для оплаты этого заказа. Такую ссылку можно отправить клиенту, скажем, на email. Клиент, кликнув по ней, переходит на merchant.webmoney.ru для оплаты. Таким образом, ему не нужно повторно формировать заказ\корзину на сайте.

Подробно этот полезный интерфейс рассмотрен нами в отдельной статье.

Возврат платежей

Если возникнет необходимость вернуть платеж покупателю, воспользуйтесь интерфейсом Х14. Он позволяет возвращать WM без потери комиссии системы 0.8% (тут нужно понимать, что комиссию не потеряете именно ВЫ, но вашему клиенту удержанные с него в момент платежа через Мерчант 0.8% компенсированы уже не будут).

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

Кроме того, если лень автоматизировать, можно воспользоваться страницей ручного возврата. Здесь сначала нужно найти транзакцию по её системному номеру (LMI_SYS_TRANS_NO, а не LMI_PAYMENT_NO!), а затем нажать кнопку "Вернуть отправителю". Возврат будет выполнен без потери комиссии, т.е. с вашего кошелька 0.8% от суммы возврата списаны не будут.

Последние штрихи и рекомендации

Теперь всё готово! Не забудьте перед тем, как начать принимать платежи, вернуться на страницу настроек (см.рис.2) и установить опцию Тестовый/Рабочий режимы в положение "рабочий".

В заключение приведем несколько важных рекомендаций.

  • Не пренебрегайте формой предварительного запроса и формой оповещения о платеже, которые присылает вам Мерчант. Используйте их для проверок валидности параметров платежа. Продумайте все варианты подмены и взлома, которые могут быть применены против вас - и учтите эти варианты в таких проверках.
  • Производите действия по выполнению заказа (отгрузка товара, предоставление услуги, пополнение баланса и т.д.) только в Result URL и только после успешных проверок формы оповещения о платеже. Не производите действия по выполнению заказа в Success URL.
  • Используйте в качестве Result URL скрипт со сложным названием.
Обсудить этот материал

16.05.2007. Последнее обновление - 13.08.2014

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

   Что нового почитать?
На WebMoney Merchant можно принимать Биткоины 30.09.16
Если вы на вашем сайте принимаете WebMoney и делаете это через WebMoney Merchant, то для вас есть хорошая новость. Теперь с вами смогут рассчитаться т...
Муравей-бот отвечает на вопросы о WebMoney в Telegram 27.09.16
WebMoney запустил интеллектуального бота-помощника для мессенджера Telegram. Он постарается понять ваш вопрос и дать на него ответ.Для начала, разбере...
Автоплатежи помогут не забыть об оплате 27.09.16
В WebMoney Keeper, а также в личный кабинет Telepay добавлена опция автоплатежа для 3х крупнейших мобильных операторов России: Билайна, МТС и Мегафона...
Новая библиотека для платформы .Net 14.09.16
Разработчикам будет полезно узнать, что выпущена новая версия библиотеки для работы с XML-интерфейсами WebMoney для платформы Microsoft .Net.В ней реа...
WebMoney пришла в Молдову 14.09.16
WebMoney предоставила возможность работы с кошельком, номинированным в молдавских леях. Однако, кошелек этот не совсем обычный.Во-первых, кошелек созд...
В обновленных Киперах появились регулярные платежи 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...

   Кофейня (форум)
WMZ в латвийский банк с минимальной комиссией? 03.09.16
Пополнить WMZ за наличные в Харькове 30.08.16
оплатить paypal, плачу вмз 12.08.16

   p2p
Меняют 10000 UAH на 10194 WMU (курс:-1.9%) 30.09.16
Меняют 25430 UAH на 1000 WMZ (курс:25.43) 30.09.16
Меняют 10000 UAH на 26000 WMR (курс:2.6) 30.09.16

   WebMoney TOP
Зарегистрирован Хостинг картинок Бесплатный фотохостинг картинок на котором вы можете загружать свои изображения в интернете без огра...
Зарегистрирован WMloans к нам обращаются все! WMloans – кредитный сервис, который позволяет моментально получить кредиты Webmoney без проверки зад...
Зарегистрирован WmChange.in.ua Обмен, ввод, вывод webmoney...

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


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