Обработчик платежной системы Platron

#
Обработчик платежной системы Platron
<?php
/* Оплата через Platron */
class system_of_pay_handler
{
   // Идентифкатор магазина, с которым будет работать обработчик
   var $merchant_id = 12345;

   // Секретный ключ (заполняется вручную пользователем на странице настроек магазина)
   var $merchant_secret_key = "qwertyuiop";
   
   // Валюта платежа RUR для работы или TST для тестирования системы
   var $currencyName = "RUR";
   
   // Код рублей
   var $platron_currency = 1;
   
   // Запускаем обработчик платежной системы
   function Execute()
  {
      // Пришло подтверждение оплаты, обработаем его
      if (isset($_REQUEST['pg_order_id']))
      {
         $this->ProcessResult();
         return true;
      }

      // Иначе оформляем заказ и отображаем стартовую страницу для оплаты через Platron
      $this->ShowPurseRequest();
   }
   
   // Обработка ответа платежной системы
   function ProcessResult()
{
      // Информация о заказе
      $order_id = to_int($_REQUEST['pg_order_id']);

      if (!$order_id)
      {
         return false;
      }

      $shop = & singleton('shop');

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

      // Заказ не найден или уже оплачен
      if (!$order_row || $order_row['shop_order_status_of_pay'])
      {
         return false;
      }

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


      // Устанавливаем параметры, которые не зависят от совпадения хешей
      $param['id'] = $order_row['shop_order_id'];
      $param['shop_shops_id'] = $order_row['shop_shops_id'];
      
      $order_sum = $shop->GetOrderSum($order_id);

      // Делаем перерасчет суммы в валюту Platron
      $shop_currency_id = $shop_row['shop_currency_id'];
      
      $coefficient = $shop->GetCurrencyCoefficientToShopCurrency($shop_currency_id, $this->platron_currency);
      
      $im_sum = round($order_sum * $coefficient, 2);
      
      // Сравниваем хэши
      if (self::check(to_str($_POST['pg_sig']), "", $_POST, $this->merchant_secret_key))
      {
         if (to_int($_POST['pg_result']) == 1
         && round(to_float($_POST['pg_net_amount']), 2) == $im_sum)
         {
         
            $id_plat = to_str($_POST['pg_payment_id']);
         
            $param['system_information'] = "Товар оплачен через Platron.\n\n"
            . "Информация:\n\n"
            . "Идентификатор платежа в системе Platron: {$id_plat}\n"
            . "\n";

            // Обновляем информацию о заказе
            $shop->InsertOrder($param);
            
            // Изменяем статус оплаты ПОСЛЕ ОБНОВЛЕНИЯ ИНФОРМАЦИ, генерируем ссылки для эл.товаров, списываем товары
            $shop->SetOrderPaymentStatus($order_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']));

            $order_row = $shop->GetOrder($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'], $order_id, $shop_row['shop_shops_name'], $order_row['shop_order_date_of_pay']),
            'user-subject' => sprintf($GLOBALS['MSG_shops']['shop_order_confirm_user_subject'], $order_id, $shop_row['shop_shops_name'], $order_row['shop_order_date_of_pay']),
            'email_from_admin' => $order_row['shop_order_users_email']));
            
            $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><response/>');
            $xml->addChild('pg_salt', $_POST['pg_salt']);
            $xml->addChild('pg_status', 'ok');
            $xml->addChild('pg_description', "Оплата принята");
            $xml->addChild('pg_sig', self::makeXML("", $xml, $this->merchant_secret_key));

            header('Content-type: text/xml');
            
            print $xml->asXML();
         }
      }
      else
      {
         $param['system_information'] = 'Хэш не совпал!';
         
         // Обновляем информацию о заказе
         $shop->InsertOrder($param);         
      }
   }
   
   /**
    * Отображает стартовую страницу для оплаты через Platron.
    *
    */
   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;
               }
         }
      }
   }
   
   /**
    * Метод для отображения формы заказа для печати.
    *
    * @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']);
         
         $order_id = $order_row['shop_order_id'];

         $order_sum = $shop->GetOrderSum($order_id);

         // Делаем перерасчет суммы в валюту Platron
         $shop_currency_id = $shop_row['shop_currency_id'];

         // Получаем название валюты
         $currency_row = $shop->GetCurrency($shop_currency_id);
         
         $currency_name = $currency_row['shop_currency_name'];
         
         $coefficient = $shop->GetCurrencyCoefficientToShopCurrency($shop_currency_id, $this->platron_currency);
         
         $im_sum = round($order_sum * $coefficient, 2);
         
         // Получаем имя/фамилию/отчество заказчика
         $fio = implode(" ", array($order_row['shop_order_users_surname'], $order_row['shop_order_users_name'], $order_row['shop_order_users_patronymic']));
         
         // Получаем email заказчика
         $email = $order_row['shop_order_users_email'];

         // Информация об алиасе сайта
         $site = & singleton ('site');
         $site_alias = $site->GetCurrentAlias($shop_row['site_id']);

         /* Получаем путь к магазину */
         $Structure = & singleton('Structure');
         
         $kernel = & singleton('kernel');
         
         $shop_path = "/".$Structure->GetStructurePath($shop_row['structure_id'], 0);

         $handler_url = 'http://'.$site_alias.$shop_path.'cart/';
         
         $array_of_params = array(
            'pg_merchant_id' => $this->merchant_id,
            'pg_order_id' => $order_id,
            'pg_amount' => $im_sum,
            'pg_lifetime' => 86400,
            'pg_description' => "Оплата заказа №$order_id",
            'pg_salt' => rand(21,43433),
            'zzz' => "Перейти к оплате"
         );
         
         $sig = self::make('payment.php', $array_of_params, $this->merchant_secret_key);
         
         ?>
         <h1>Оплата через систему Platron</h1>
         <!-- Форма для оплаты через Platron -->
         <p>К оплате <strong><?php echo $im_sum . " " . $currency_name?></strong></p>
         <form method="post" action="https://www.platron.ru/payment.php">
         
            <input type="hidden" name="pg_merchant_id" value="<?php echo $array_of_params['pg_merchant_id']?>">
            <input type="hidden" name="pg_order_id" value="<?php echo $array_of_params['pg_order_id']?>">
            <input type="hidden" name="pg_amount" value="<?php echo $array_of_params['pg_amount']?>">
            <input type="hidden" name="pg_lifetime" value="<?php echo $array_of_params['pg_lifetime']?>">
            <input type="hidden" name="pg_description" value="<?php echo $array_of_params['pg_description']?>">
            <input type="hidden" name="pg_salt" value="<?php echo $array_of_params['pg_salt']?>">
            <input type="hidden" name="pg_sig" value="<?php echo $sig?>">
            
            <input name="submit" value="Перейти к оплате" type="submit"/>
         </form>
         <?php
      }
   }
   // *****************************
   //  Далее идут методы Platron'а
   // *****************************
   
   public static function getScriptNameFromUrl ( $url )
   {
      $path = parse_url($url, PHP_URL_PATH);
      $len  = strlen($path);
      if ( $len == 0  ||  '/' == $path{$len-1} ) {
         return "";
      }
      return basename($path);
   }
   
   /**
    * Get name of currently executed script (need to check signature of incoming message using self::check)
    *
    * @return string
    */
   public static function getOurScriptName ()
   {
      return self::getScriptNameFromUrl( $_SERVER['PHP_SELF'] );
   }

   /**
    * Creates a signature
    *
    * @param array $arrParams  associative array of parameters for the signature
    * @param string $strSecretKey
    * @return string
    */
   public static function make ( $strScriptName, $arrParams, $strSecretKey )
   {
      return md5( self::makeSigStr($strScriptName, $arrParams, $strSecretKey) );
   }

   /**
    * Verifies the signature
    *
    * @param string $signature
    * @param array $arrParams  associative array of parameters for the signature
    * @param string $strSecretKey
    * @return bool
    */
   public static function check ( $signature, $strScriptName, $arrParams, $strSecretKey )
   {
      return (string)$signature === self::make($strScriptName, $arrParams, $strSecretKey);
   }

   private static function makeSigStr ( $strScriptName, $arrParams, $strSecretKey )
   {
      if(isset($arrParams['pg_sig']))
      {
         unset($arrParams['pg_sig']);
      }
      
      ksort($arrParams);

      array_unshift($arrParams, $strScriptName);
      array_push   ($arrParams, $strSecretKey);
      
      return join(';', $arrParams);
   }
   
   
   /**
    * make the signature for XML
    *
    * @param string|SimpleXMLElement $xml
    * @param string $strSecretKey
    * @return string
    */
   public static function makeXML ( $strScriptName, $xml, $strSecretKey )
   {
      $arrFlatParams = self::makeFlatParamsXML($xml);
      return self::make($strScriptName, $arrFlatParams, $strSecretKey);
   }

   /**
    * Returns flat array of XML params
    *
    * @param (string|SimpleXMLElement) $xml
    * @return array
    */
   private static function makeFlatParamsXML ( $xml, $parent_name = '' )
   {
      if (!$xml instanceof SimpleXMLElement)
      {
         $xml = new SimpleXMLElement($xml);
      }

      $arrParams = array();
      $i = 0;
      foreach ($xml->children() as $tag)
      {
         $i++;
         if ('pg_sig' == $tag->getName())
            continue;
            
         /**
          * Имя делаем вида tag001subtag001
          * Чтобы можно было потом нормально отсортировать и вложенные узлы не запутались при сортировке
          */
         $name = $parent_name . $tag->getName().sprintf('%03d', $i);

         if ($tag->children())
         {
            $arrParams = array_merge($arrParams, self::makeFlatParamsXML($tag, $name));
            continue;
         }

         $arrParams += array($name => (string)$tag);
      }

      return $arrParams;
   }
}
?>


В блок

   // Идентифкатор магазина, с которым будет работать обработчик
   var $merchant_id = 12345;

   // Секретный ключ (заполняется вручную пользователем на странице настроек магазина)
   var $merchant_secret_key = "qwertyuiop";
добавьте свои данные.

В ТДС корзины традиционно встречаем запрос Platron'а:

// ------------------------------------------------
// Подготовка редиректа для Platron
// ------------------------------------------------
if (isset($_POST['pg_order_id']))
{
   // Получаем ID заказа
   $order_id = to_int($_POST['pg_order_id']);

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

   if ($order_row)
   {
      // Вызов обработчика платежной системы
      $shop->ExecSystemsOfPayHandler($order_row['shop_system_of_pay_id']);
   }
}
#
Re: Обработчик платежной системы Platron
Огромное спасибо!
#
Re: Обработчик платежной системы Platron
Где в БД хранится информация о Лицевом счете пользователя? или каждый раз он считает количество оплаченных заказов, и минусует от них приобретенные товары. Интересует подробная информация о списании денег с лицевого счет, т.к. сейчас если ставишь Доставлено или Отправлено, количество денег на лицевом счете не уменьшается.
Модератор
#
Re: Обработчик платежной системы Platron
CCron,
нужно менять флажок "Оплачено", тогда будет идти списание. Статусы из выпадающего списка отражают информационно статусы работы с заказом и на списание с лицевого счета не влияют.
#
Re: Re: Обработчик платежной системы Platron
HostCMS писал(а):
нужно менять флажок «Оплачено», тогда будет идти списание. Статусы из выпадающего списка отражают информационно статусы работы с заказом и на списание с лицевого счета не влияют.

Когда деньги приходят, открываем два окна, одно с "Оформленные заказы", второе "Транзакции Platron" смотрим что за сегодня пришло. Руками подтверждать, что "оплачено", т.е. нажимаем на лампочку, она загорается?

А когда человек что-то покупает, то нажимаем на кнопку "Оплачено", она тухнет и со счета снимаются деньги?

Есть необходимость, иметь некую цифру (всё сумму) на счете Пользователя, чтобы была возможность списывать его из другого магазина, или через операции API. Например поднятие объявлений выше других (VIP статус), увеличение лимита числа объявлений пользователя.
#
Re: Обработчик платежной системы Platron
Интересует автоматические платежи через Platron, чтобы пользователь как только оплатил объявление меняло свой статус и становилось выше других. Не понятно как сделать.

Есть идея с таблицей, где будут храниться "купоны". Пользователь покупает номер этого купона, потом вводит в личном кабинете (или редактировании объявления), проверяется его наличие и активность, меняется статус купона и приоритет объявления.

Может есть какой нибудь более простой способ?
#
Re: Обработчик платежной системы Platron
Аналогичный вопрос был, спасибо помогло!
#
Re: Обработчик платежной системы Platron
Цитата:
В ТДС корзины традиционно встречаем запрос Platron'а:
// ------------------------------------------------
// Подготовка редиректа для Platron
// ------------------------------------------------
if (isset($_POST['pg_order_id']))
{
    // Получаем ID заказа
    $order_id = to_int($_POST['pg_order_id']);

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

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

это нужно добавить в код страницы или настройки страницы?
HostDev.pw - модули для HostCMS, Telegram: @hostdev
Модератор
#
Re: Обработчик платежной системы Platron
Добавляете в код настроек типовой.
Вы только что начали читать предложение, чтение которого вы уже заканчиваете.
#
Re: Обработчик платежной системы Platron
А какую ссылку указывать для того чтобы "Платрон" сообщил магазину что платеж совершен или не совершен?
HostDev.pw - модули для HostCMS, Telegram: @hostdev
Авторизация