Обработчик платежной системы Робокасса для тестирования

Модератор
#
Обработчик платежной системы Робокасса для тестирования
Инструкции - http://www.robokassa.ru/Doc/Ru/Interface.aspx

1. В код настроек типовой дин. страницы корзины добавляем
// ------------------------------------------------
// Обработка уведомления об оплате от ROBOKASSA
// должно быть только в настройках типовой дин. страницы
// ------------------------------------------------
if (isset($_REQUEST['SignatureValue'])
// для отличия от SuccessURL/FailURL
&& !isset($_REQUEST['Culture']))
{
   // Получаем ID заказа
   $order_id = to_int($_REQUEST['InvId']);

   $order_row = $shop->GetOrder($order_id);

   if ($order_row)
   {
      // Вызов обработчика платежной системы
      $shop->ExecSystemsOfPayHandler($order_row['shop_system_of_pay_id']);
   }
   
   exit();
}
// ------------------------------------------------

2. В код типовой дин. страницы корзины добавляем
// ------------------------------------------------
// Обработка уведомления об оплате от ROBOKASSA
// ------------------------------------------------
if (isset($_REQUEST['SignatureValue']) && isset($_REQUEST['Culture']))
{
   // Получаем ID заказа
   $order_id = to_int($_REQUEST['InvId']);

   $order_row = $shop->GetOrder($order_id);

   if ($order_row)
   {
      // Вызов обработчика платежной системы
      $shop->ExecSystemsOfPayHandler($order_row['shop_system_of_pay_id']);
   }
}
// ------------------------------------------------

3. Обновляем обработчик платежной системы:
<?php
/* Оплата через ROBOKASSA  */
class system_of_pay_handler
{
   /* Логин в системе ROBOKASSA */
   var $mrh_login = "mylogin";

   /* Пароль #1 - Используется интерфейсом инициализации оплаты */
   var $mrh_pass1 = "1234567a";

   // регистрационная информация (пароль #2)
   // registration info (password #2)
   var $mrh_pass2 = "98765432a";

   /* язык */
   var $culture = "ru";

   /* предлагаемая валюта платежа
   default payment e-currency
   Доступные валюты: http://merchant.roboxchange.com/Handler/Xml/CurrList.ashx
   */
   var $in_curr = "YandexMerchantOceanR";

   /* Код валюты в магазине HostCMS, которая была указана при регистрации магазина*/
   var $robokassa_currency = 1;

   /* Определяем коэффициент перерасчета при оплате ROBOKASSA */
   var $coefficient = 1;
   
   /**
    * Обработка статуса оплаты
    *
    */
   function ProcessResult()
   {
      /* Информация о заказе */
      $order_id = to_int($_REQUEST['InvId']);

      if (!$order_id)
      {
         return false;
      }

      $shop = & singleton('shop');

      $order_row = $shop->GetOrder($order_id);

      if (!$order_row)
      {
         return false;
      }

      $shop_row = $shop->GetShop($order_row['shop_shops_id']);

      // Сумма от Robokassa
      $out_summ = to_str($_REQUEST["OutSum"]);
      
      // Хэш от Robokassa
      $crc = to_str($_REQUEST["SignatureValue"]);

      /* Сумма заказа в валюте магазина HostCMS */
      $order_sum = sprintf("%.6f", $shop->GetOrderSum($order_id) * $this->coefficient);
      
      if ($out_summ == $order_sum)
      {
         // Для ResultURL используется mrh_pass2!
         $my_crc = md5("$out_summ:$order_id:{$this->mrh_pass2}");

         /* Устанавливаем параметры */
         $param['id'] = $order_row['shop_order_id'];
         $param['shop_shops_id'] = $order_row['shop_shops_id'];
      }
      else
      {
         // Суммы не совпали
         $my_crc = '';
      }

      /* Сравниваем хэши */
      if (mb_strtoupper($my_crc) == mb_strtoupper($crc))
      {
         /* Проверка прошла успешно!
         Добавляем комментарий */
         $param['system_information'] = "Товар оплачен через ROBOKASSA.\n";

         // Обновляем информацию о заказе
         $shop->InsertOrder($param);

         // Изменяем статус оплаты ПОСЛЕ ОБНОВЛЕНИЯ ИНФОРМАЦИ, генерируем ссылки для эл.товаров, списываем товары
         $shop->SetOrderPaymentStatus($order_id);
         
         // Проводки по партнерской программе
         $affiliate = & singleton('affiliate');
         $affiliate->AcceptAffiliatePlanForSiteUsers($order_row['site_users_id'], $order_id);
      }
      else
      {
         $param['system_information'] = 'ROBOKASSA хэш не совпал!';
         
         // Обновляем информацию о заказе
         $shop->InsertOrder($param);
      }

      // Отправку письма об оплате делаем только после вставки информации об оплате
      if (mb_strtoupper($my_crc) == mb_strtoupper($crc))
      {
         $structure = & singleton('Structure');
         $structure_row = $structure->GetStructureItem(to_int($shop_row['structure_id']));

         $lib = new lib();
         $LA = $lib->LoadLibPropertiesValue(to_int($structure_row['lib_id']), to_int($structure_row['structure_id']));

         $order_row = $shop->GetOrder($order_id);

         if (trim(to_str($order_row['shop_order_account_number'])) != '')
         {
            $shop_order_account_number = trim(to_str($order_row['shop_order_account_number']));
         }
         else
         {
            $shop_order_account_number = $order_id;
         }
         
         // Отправляем письмо администратору о подтверждении платежа
         $shop->SendMailAboutOrder($order_row['shop_shops_id'], $order_id, $order_row['site_users_id'],
         to_str($LA['xsl_letter_to_admin']),
         to_str($LA['xsl_letter_to_user']),
         $order_row['shop_order_users_email'],
         array(
         'admin-content-type' => 'html',
         'user-content-type' => 'html',
         'admin-subject' => sprintf($GLOBALS['MSG_shops']['shop_order_confirm_admin_subject'], $shop_order_account_number, $shop_row['shop_shops_name'], $order_row['shop_order_date_of_pay']),
         'user-subject' => sprintf($GLOBALS['MSG_shops']['shop_order_confirm_user_subject'], $shop_order_account_number, $shop_row['shop_shops_name'], $order_row['shop_order_date_of_pay']),
         'email_from_admin' => $order_row['shop_order_users_email']));
         
         // http://www.robokassa.ru/Doc/Ru/Interface.aspx#223
         // 3. Оповещение об оплате (ResultURL)
         // Факт успешности сообщения магазину об исполнении операции определяется по результату, возвращаемому обменному пункту. Результат должен содержать "OKnMerchantInvId", т.е. для счета #5 должен быть возвращен текст "OK5".
         echo "OK{$order_id}\n";
      }
      else
      {
          echo "bad sign\n";
      }
   }

   /* Вывод сообщения об успешности/неуспешности оплаты */
   function ShowResultMessage()
   {
      /* Информация о заказе */
      $order_id = to_int($_REQUEST['InvId']);

      if (!$order_id)
      {
         return false;
      }

      $shop = & singleton('shop');

      $order_row = $shop->GetOrder($order_id);

      if (!$order_row)
      {
         return false;
      }

      $shop_row = $shop->GetShop($order_row['shop_shops_id']);

      // Хэш1 от Robokassa
      $crc = to_str($_REQUEST["SignatureValue"]);
      
      // Сумма от Robokassa
      $out_summ = to_str($_REQUEST["OutSum"]);
      
      /* Сумма заказа в валюте магазина HostCMS */
      $order_sum = $shop->GetOrderSum($order_id) * $this->coefficient;
      $order_sum = sprintf("%.6f", $order_sum);
      
      if ($out_summ == $order_sum)
      {
         // Для SuccessURL и FailURL используется mrh_pass1!
         $my_crc = md5("$out_summ:$order_id:{$this->mrh_pass1}");
      }
      else
      {
         $my_crc = '';
      }

      /* Сравниваем хэши */
      if (mb_strtoupper($my_crc) == mb_strtoupper($crc))
      {
         if ($order_row['shop_order_status_of_pay'] == 1)
         {
            $status = "оплачен";
         }
         else
         {
            $status = "не оплачен";
         }
         ?><h1>Заказ <?php echo $status?></h1>
         <p>Заказ <strong>№ <?php echo $order_row['shop_order_account_number']?></strong> <?php echo $status?>.</p>
         <?php
      }
      else
      {
         ?><p>Хэш не совпал!</p><?php
      }
   }

   /**
    * Отображает стартовую страницу для оплаты через ROBOKASSA.
    *
    */
   function ShowPurseRequest()
   {
      $shop = & singleton('shop');
      
      /* ID платежной системы берем из сессии */
      $system_of_pay_id = to_int($_SESSION['system_of_pay_id']);
      $row_system_of_pay = $shop->GetSystemOfPay($system_of_pay_id);
      
      if ($row_system_of_pay)
      {
         $shop_id = $row_system_of_pay['shop_shops_id'];
      }
      else
      {
         return false;
      }

      /* Получаем id текущего пользователя сайта */
      if (class_exists('SiteUsers'))
      {
         /* Получаем id текущего пользователя сайта */
         $SiteUsers = & singleton('SiteUsers');
         $site_users_id = $SiteUsers->GetCurrentSiteUser();
      }
      else
      {
         $site_users_id = false;
      }

      // статус платежа, по умолчанию 0
      $order_row['status_of_pay'] = 0 ;

      // дата платежа, по умолчанию пустая строка
      $order_row['date_of_pay'] = '';

      $order_row['description'] = to_str($_SESSION['description']);

      // описание и системная информация, по умолчанию пустая строка
      if (to_str($_SESSION['shop_coupon_text']) != '')
      {
         $order_row['description'] .= "Купон на скидку: ".to_str($_SESSION['shop_coupon_text'])."\n";
      }

      if (!isset($_SESSION['last_order_id']))
      {
         $_SESSION['last_order_id'] = 0;
      }

      // Если заказ еще не был оформлен
      if ($_SESSION['last_order_id'] == 0)
      {
         /* Оформляем заказ */
         $order_id = $shop->ProcessOrder($shop_id, $site_users_id, $system_of_pay_id, $order_row);
      }
      else
      {
         $order_id = $_SESSION['last_order_id'];
      }

      if ($order_id > 0)
      {
         if (!class_exists('SiteUsers'))
         {
            /* Класс пользователей сайта не существует, дописываем информацию о заказчике
            в поле shop_order_description из текущей сессии */
            if ($order_row)
            {
               /* Описание заказчика */
               $order_row['description'] .= "Информация о заказчике:\n"
               ."Имя: ".to_str($_SESSION['site_users_name'])."\n"
               ."Фамилия: ".to_str($_SESSION['site_users_surname'])."\n"
               ."Отчество: ".to_str($_SESSION['site_users_patronymic'])."\n"
               ."E-Mail: ".to_str($_SESSION['site_users_email'])."\n"
               ."Телефон: ".to_str($_SESSION['site_users_phone'])."\n"
               ."Факс: ".to_str($_SESSION['site_users_fax'])."\n"
               ."Адрес: ".to_str($_SESSION['full_address'])."\n";

               /* Дополнительная информация о заказе */
               $order_row['system_information'] = to_str($_SESSION['system_information']);

               /* Обязательно добавляем идентификатор! */
               $order_row['id'] = $order_id;

               $shop->InsertOrder($order_row);
            }
         }

         $order_row = $shop->GetOrder($order_id);

         if ($order_row)
         {
            $this->PrintOrder($order_id);
         }

         $shop_row = $shop->GetShop($shop_id);

         if ($_SESSION['last_order_id'] == 0)
         {
            $structure = & singleton('Structure');
            $structure_row = $structure->GetStructureItem(to_int($shop_row['structure_id']));

            $lib = new lib();
            $LA = $lib->LoadLibPropertiesValue(to_int($structure_row['lib_id']), to_int($structure_row['structure_id']));

            $date_str = date("d.m.Y H:i:s");

            if (trim(to_str($order_row['shop_order_account_number'])) != '')
            {
               $shop_order_account_number = trim(to_str($order_row['shop_order_account_number']));
            }
            else
            {
               $shop_order_account_number = $order_id;
            }

            /* Отправляем письмо заказчику */
            $shop->SendMailAboutOrder($shop_id,
            $order_id,
            $site_users_id,
            to_str($LA['xsl_letter_to_admin']),
            to_str($LA['xsl_letter_to_user']),
            $order_row['shop_order_users_email'],
            array('admin-content-type' => 'html',
            'user-content-type' => 'html',
            'admin-subject' => sprintf($GLOBALS['MSG_shops']['shop_order_admin_subject'], $shop_order_account_number, $shop_row['shop_shops_name'], $date_str),
            'user-subject' => sprintf($GLOBALS['MSG_shops']['shop_order_user_subject'], $shop_order_account_number, $shop_row['shop_shops_name'], $date_str),
            'email_from_admin' => $order_row['shop_order_users_email']));
         }

         // Сохраняем ID последнего оформленного заказа ТОЛЬКО ПОСЛЕ ОТПРАВКИ ПИСЬМА
         $_SESSION['last_order_id'] = $order_id;
      }
      else
      {
         switch ($order_id)
         {
            case -1:
               {
                  ?><div id="error">Ошибка вставки заказа в базу данных. Обратитесь к администратору.</div><?php
                  break;
               }
            case -2:
               {
                  ?><div id="error">Ошибка - не найден магазин. Обратитесь к администратору.</div><?php
                  break;
               }
            case -3:
               {
                  ?><div id="error">Ошибка - корзина пуста. Добавьте товар в корзину и оформите заказ.</div><?php
                  break;
               }
         }
      }
   }

   /**
    * Метод, запускающий выполнение обработчика
    */
   function Execute()
   {
      /* Пользователь перешел на страницу с уведомлением о статусе заказа */
      if (isset($_REQUEST['InvId']) && isset($_REQUEST['Culture']))
      {
         $this->ShowResultMessage();
         return true;
      }
      
      /* Пришло подтверждение оплаты, обработаем его */
      if (isset($_REQUEST['InvId']))
      {
         $this->ProcessResult();
         return true;
      }

      /* Иначе оформляем заказ и отображаем стартовую страницу для оплаты через WebMoney */
      $this->ShowPurseRequest();
   }

   /**
    * Метод для отображения формы заказа для печати.
    *
    * @param int $order_id идентификатор заказа
    */
   function PrintOrder($order_id)
   {
      $shop = & singleton('shop');

      $order_row = $shop->GetOrder($order_id);
      if (!$order_row)
      {
         return false;
      }

      if ($order_row)
      {
         $shop_row = $shop->GetShop($order_row['shop_shops_id']);

         /* Сумма заказа в валюте магазина HostCMS (далее пересчитывается в валюту) */
         $order_sum = $shop->GetOrderSum($order_id) * $this->coefficient;

         /* Валюта магазина HostCMS */
         $shop_currency_id = $shop_row['shop_currency_id'];

         $currency_row = $shop->GetCurrency($shop_currency_id);
         
         /* Получаем коэффициент пересчета в валюту ROBOKASSA */
         $currency_coefficient = $shop->GetCurrencyCoefficientToShopCurrency($shop_currency_id, $this->robokassa_currency);
         $robokassa_sum = round($order_sum * $currency_coefficient, 2);

         // Описание заказа
         $inv_desc = "Оплата счета N {$order_row['shop_order_account_number']}";

         // build CRC value
         $crc = md5("{$this->mrh_login}:$order_sum:$order_id:{$this->mrh_pass1}");

         // Тестовый - http://test.robokassa.ru/Index.aspx
         // Рабочий - https://merchant.roboxchange.com/Index.aspx

         ?>
         <h1>Оплата через систему ROBOKASSA</h1>
         
         <p>
         <a href="http://www.robokassa.ru/" target="_blank">
         <img src="http://www.robokassa.ru/Images/logo.gif" border="0" alt="Система электронных платежей">
         </a>
         </p>
         
         <p>Сумма к оплате составляет <strong><?php echo $order_sum?> <?php echo $currency_row['shop_currency_name']?></strong></p>
         
         <p>Для оплаты нажмите кнопку "Оплатить".</p>
         
         <p style="color: rgb(112, 112, 112);">
         Внимание! Нажимая &laquo;Оплатить&raquo; Вы подтверждаете передачу контактных данных на сервер ROBOKASSA для оплаты.
         </p>

         <form action="http://test.robokassa.ru/Index.aspx" method="POST">
            <input type="hidden" name="MrchLogin" value="<?php echo $this->mrh_login?>">
            <input type="hidden" name="OutSum" value="<?php echo $robokassa_sum?>">
            <input type="hidden" name="InvId" value="<?php echo $order_id?>">
            <input type="hidden" name="Desc" value="<?php echo $inv_desc?>">
            <input type="hidden" name="SignatureValue" value="<?php echo $crc?>">
            <input type="hidden" name="IncCurrLabel" value="<?php echo $this->in_curr?>">
            <input type="hidden" name="Culture" value="<?php echo $this->culture?>">
            <input type="submit" value="Оплатить">
         </form>
         <?php
      }
   }

   /**
    * Изменение статуса заказа. Позволяет пользователю внедрять собственные
    * обработчики при изменении статуса.
    *
    * @param array $param массив атрибутов
    * - $param['shop_order_id'] идентификатор заказа
    * - $param['prev_order_row'] информация о предыдущем состоянии заказа (доступно не всегда)
    * - $param['action'] выполняемое действие над заказом, может принимать значения:
    * edit (редактирование заказа), cancel (отмена заказа),
    * status (изменение статуса заказа), delete (удаление заказа),
    * edit_item (редактирование товара в заказе), delete_item (удаление товара в заказе)
    */
   function ChangeStatus($param = array())
   {
      // Если произошло изменение статуса
      if (isset($param['action']) && in_array($param['action'], array('status', 'edit')))
      {
         $shop_order_id = to_int($param['shop_order_id']);

         $shop = & singleton('shop');

         $order_row = $shop->GetOrder($shop_order_id);

         // Получаем информацию о магазине
         $shop_id = to_int($order_row['shop_shops_id']);

         $shop_row = $shop->GetShop($shop_id);

         $structure = & singleton('Structure');
         $structure_row = $structure->GetStructureItem(to_int($shop_row['structure_id']));

         $lib = new lib();
         $LA = $lib->LoadLibPropertiesValue(to_int($structure_row['lib_id']), to_int($structure_row['structure_id']));

         if ($order_row)
         {
            $DateClass = new DateClass();
            $date_str = $DateClass->datetime_format($order_row['shop_order_date_time']);
         }
         else
         {
            $date_str = '';
         }

         // Если предыдущий статус заказа был 1, то меняем тему на подтверждение
         if (to_int($order_row['shop_order_status_of_pay']) == 1)
         {
            $admin_subject = $GLOBALS['MSG_shops']['shop_order_confirm_admin_subject'];
            $user_subject = $GLOBALS['MSG_shops']['shop_order_confirm_user_subject'];
         }
         else
         {
            $admin_subject = $GLOBALS['MSG_shops']['shop_order_admin_subject'];
            $user_subject = $GLOBALS['MSG_shops']['shop_order_user_subject'];
         }

         $not_paid = isset($param['prev_order_row']) && $param['prev_order_row']['shop_order_status_of_pay'] == 0;
         
         // Письмо отправляем только при установке статуса активности для заказа
         if (to_int($order_row['shop_order_status_of_pay']) == 1 && $not_paid)
         {
            if (trim(to_str($order_row['shop_order_account_number'])) != '')
            {
               $shop_order_account_number = trim(to_str($order_row['shop_order_account_number']));
            }
            else
            {
               $shop_order_account_number = $shop_order_id;
            }

            /* Отправляем письмо заказчику */
            $shop->SendMailAboutOrder($shop_id,
            $shop_order_id,
            $order_row['site_users_id'],
            to_str($LA['xsl_letter_to_admin']),
            to_str($LA['xsl_letter_to_user']),
            $order_row['shop_order_users_email'],
            array('admin-content-type' => 'html',
            'user-content-type' => 'html',
            'admin-subject' => sprintf($admin_subject, $shop_order_account_number, $shop_row['shop_shops_name'], $date_str),
            'user-subject' => sprintf($user_subject, $shop_order_account_number, $shop_row['shop_shops_name'], $date_str),
            'email_from_admin' => $order_row['shop_order_users_email']));
         }
      }
   }
}
?>
#
Re: Обработчик платежной системы Робокасса для тестирования
О, я попробую, скоро отпишусь.
#
Re: Обработчик платежной системы Робокасса для тестирования
Ткните носом - куда добавлять обработчик платежной системы?

hostcmsfiles\shop\pay\
а через веб-интерфейс...

Интернет-магазин - Список интернет-магазинов - Платежные системы
но тут только список вариантов оплаты...
#
Re: Обработчик платежной системы Робокасса для тестирования
Sizam4ik писал(а):
но тут только список вариантов оплаты…
- создайте новый обработчик через меню "Платежная система" -> "Добавить". И сделайте его активным.
#
Re: Обработчик платежной системы Робокасса для тестирования
"Не удалось установить связь с магазином для передачи ему информации об оплате. Через минуту будет произведена повторная попытка."
- после оплаты.
Какие должны быть параметры
Result URL:
[используется для оповещения о платеже, если метод отсылки - email, то email-адрес]    
Метод отсылки данных по Result URL:


И прочие ?
http://www.aiventa.ru
Модератор
#
Re: Обработчик платежной системы Робокасса для тестирования
hell0men,
Адрес корзины на Вашем сайте, например, http://www.site.ru/shop/cart/
#
Re: Обработчик платежной системы Робокасса для тестирования
Именно так и стоит. А GET|POST?
http://www.aiventa.ru
Модератор
#
Re: Обработчик платежной системы Робокасса для тестирования
hell0men,
Там из $_REQUEST берется, можно POST поставить. Если не получится, уточните проблему у Робокассы.
#
Re: Обработчик платежной системы Робокасса для тестирования
Я и GET и POST попробовал, проблема в следующем:
     
"Не удалось установить связь с магазином для передачи ему информации об оплате. Через минуту будет произведена повторная попытка." - после оплаты.
Адреса такие же как в системе WebMoney.
http://www.aiventa.ru
Модератор
#
Re: Обработчик платежной системы Робокасса для тестирования
HostCMS писал(а):
Если не получится, уточните проблему у Робокассы.
Авторизация