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

	// Секретный ключ (заполняется вручную пользователем на странице настроек магазина)
	var $merchant_secret_key = "XXXXXXXXXXXXXXXX";
	
	// Валюта платежа RUR для работы или TST для тестирования системы
	//var $currencyName = "RUR";
	var $currencyName = "TST";
	
	// Код рублей
	var $intellectmoney_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->intellectmoney_currency);
		
		$im_sum = round($order_sum * $coefficient, 2);
		
		// Сравниваем хэши
		if (self::check($_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)
			{
			
				$param['system_information'] = "Товар оплачен через Platron.\n\n"
				. "Информация:\n\n"
				. "Идентификатор платежа в системе Platron: {$_POST['pg_payment_id']}\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->intellectmoney_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 ) {
		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;
	}
}
?>