<?php
class createBill {
	/* логин (id) магазина */
	public $login = 'xxx';

	/* пароль для магазина */
	public $password = 'yyy';

	/* идентификатор пользователя (номер телефона) */
	public $user; // string

	/* сумма, на которую выставляется счет (разделитель «.») */
	public $amount; // string

	/* комментарий к счету, который увидит пользователь (максимальная длина 255 байт) */
	public $comment; // string

	/* уникальный идентификатор счета (максимальная длина 30 байт) */
	public $txn; // string

	/* время действия счета в секундах, в течение которого счет будет храниться в системе QIWI и будет доступен для оплаты */
	public $lifetime_sec = 3888000; //45 суток

	/* отправить оповещение пользователю (1 - уведомление SMS-сообщением, 2 - уведомление звонком, 0 - не оповещать).
	Уведомления доступны только магазинам, зарегистрированным по схеме "Именной кошелек".
	Для магазинов, зарегистрированных по схеме "Прием платежей", уведомления заблокированы. */
	public $alarm = 0;

	/* флаг для создания нового пользователя (если он не зарегистрирован в системе) */
	public $create = false;
}

class createBillResponse {
	public $createBillResult; // int
}

class Response {
  public $updateBillResult;
}

class Param {
  public $login;
  public $password;
  public $txn;
  public $status;
}

class ServerQIWI {

public function updateBill($param_update_bill)
{   
	$shop = & singleton('shop');
   
	$order_id = $param_update_bill->txn;
   
	$order_row = $shop->GetOrder($order_id);
   
	$return_status = new Response();
      
	$return_status->updateBillResult = 300;
   
	$shop_parametres = new createBill();
     
	$txn_windows_1251 = iconv("utf-8", "windows-1251", $param_update_bill->txn);
	$password_windows_1251 = iconv("utf-8", "windows-1251", $shop_parametres->password);
      
	$password = strtoupper(md5($txn_windows_1251 . strtoupper(md5($password_windows_1251))));

	if ($shop_parametres->login == $param_update_bill->login && $param_update_bill->password == $password)
	{      
        // Заказ не найден
        if (!$order_row)
        {
           //Счет не найден
           $return_status->updateBillResult = 210;
        }
		else
		{         
			$param = array();
			/* Устанавливаем параметры */
			$param['id'] = $order_row['shop_order_id'];
			$param['shop_shops_id'] = $order_row['shop_shops_id'];
         
			$status_account_text = $this->ReferenceAccountStatus($param_update_bill->status);
        
			$param['system_information'] = $status_account_text;
         
			// Обновляем информацию о заказе
			$shop->InsertOrder($param);
         
			if ($param_update_bill->status == 60)
			{
				if($order_row['shop_order_status_of_pay'] != 1)
				{
					// Изменяем статус оплаты ПОСЛЕ ОБНОВЛЕНИЯ ИНФОРМАЦИ, генерируем ссылки для эл.товаров, списываем товары
					$shop->SetOrderPaymentStatus($order_id);
               
					// Проводки по партнерской программе
					$affiliate = & singleton('affiliate');
					$affiliate->AcceptAffiliatePlanForSiteUsers($order_row['site_users_id'], $order_id);

					$shop_row = $shop->GetShop($order_row['shop_shops_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);

					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']));
				}
			}
            
            $return_status->updateBillResult = 0;
        }
	}
	else
	{
		$return_status->updateBillResult = 150;
	}

   return $return_status;
}

	function ReferenceAccountStatus($status)
	{
			$return_code_message = "";

			switch ($status) {
				case 60:
					$return_code_message = "Заказ оплачен через QIWI Кошелек.\n";
					break;
				case 50:
					$return_code_message = "Счет выставлен.\n";
					break;
				case 52:
					$return_code_message = "Счет проводится.\n";
					break;
				case 150:
					$return_code_message = "Счет отменен(ошибка на терминале).\n";
					break;
				case 151:
					$return_code_message = "Счет отменен (ошибка авторизации: недостаточно средств на балансе, отклонен абонентом при оплате с лицевого счета оператора сотовой связи и т.п.).\n";
					break;
				case 160:
					$return_code_message = "Счет отменен.\n";
					break;
				case 161:
					$return_code_message = "Счет отменен(истекло время).\n";
					break;
				default:
					$return_code_message = "Неизвестный статус.\n";
					break;
			}
			return $return_code_message;
	}
}

/* Оплата через QIWI Кошелек */
class system_of_pay_handler
{
	public $rub_currency_id = 1;

	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()
	{
		/* Пришли данные с нашей формы "Оплата через систему QIWI Кошелек" */
		if (!isset($_POST['qiwi_payment_options']) || (isset($_POST['qiwi_payment_options']) && mb_strlen(to_str($_POST['user_qiwi'])) == 0))
		{
			/* Иначе оформляем заказ и отображаем стартовую страницу для оплаты через QIWI Кошелек */
			$this->ShowPurseRequest();
			return true;
		}
		/* Пришло подтверждение оплаты, обработаем его */
		if (isset($_POST['qiwi_payment_options']))
		{
			$order_id = to_int($_POST['order_id']);
			$this->CreateBillQiwi($order_id);
			return true;
		}

	}

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

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

		$handler_url = $this->GetHandlerUrl($order_row['shop_shops_id']);

		?>
		<h2>Оплата через систему QIWI Кошелек</h2>

		<form method="POST" action="<?php echo $handler_url?>">
			<input type="hidden" name="order_id" value="<?php echo $order_id?>">
			<table>
				<tr>
					<td class="field">Номер Вашего мобильного телефона(должен совпадать с номером в системе QIWI Кошелек в случае, если Вы там зарегистрированы) - без восьмерки, без скобок, без дефисов:</td>
					<td>
						<input type="text" size="30" maxlength="32" name="user_qiwi" value=""/>
					</td>
				</tr>
				<tr>
					<td class="field">Зарегистрировать Вас в системе QIWI Кошелек?</td>
					<td>
						<input type="checkbox" name="need_to_register_user_qiwi"/> Да
					</td>
				</tr>
				<tr>
					<td colspan="2">
						<input type="submit" name="qiwi_payment_options" value="Далее">
					</td>
				</tr>
			</table>
			<div style="clear: both;"></div>
		</form>
		<?php
	}

	/**
	 * Метод обработки данных, полученных с формы "Оплата через систему QIWI Кошелек".
	 *
	 * @param int $order_id идентификатор заказа
	 */
	function CreateBillQiwi($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_sum = $shop->GetOrderSum($order_id);

			/* Делаем перерасчет суммы в валюты, выбранные для QIWI Кошелек */
			$shop_currency_id = $shop_row['shop_currency_id'];

			/* Для RUB */
			$coefficient = $shop->GetCurrencyCoefficientToShopCurrency($shop_currency_id, $this->rub_currency_id);
			$amount = round($order_sum * $coefficient, 2);

			$params = new createBill();

			$params->user = to_str($_POST['user_qiwi']); // пользователь, которому выставляется счет
			$params->amount = $amount; // сумма
			$params->comment = "Оплата заказа №" . $order_row['shop_order_account_number'] . " интернет-магазина " . $shop_row['shop_shops_name'];
			$params->txn = to_str($order_id); // номер заказа
			$params->lifetime = date('d.m.Y H:i:s', time() + $params->lifetime_sec);

			if(isset($_POST['need_to_register_user_qiwi']))
			{
				$params->create = true;
			}

			$wsdlPath = CMS_FOLDER."hostcmsfiles/shop/pay/IShopServerWS.wsdl";
			$options = array();
			$options['classmap']['createBill'] = 'createBill';
			$options['classmap']['createBillResponse'] = 'createBillResponse';

			$client = new SoapClient($wsdlPath, $options);

			$bill_result = new createBillResponse();

			$bill_result = $client->createBill($params);

			$bill_result_text = $this->ReferenceCodeCompletion($bill_result->createBillResult);

			$param = array();
			/* Устанавливаем параметры */
			$param['id'] = $order_row['shop_order_id'];
			$param['shop_shops_id'] = $order_row['shop_shops_id'];

			$param['system_information'] = "Код ответа: ". $bill_result->createBillResult . " - " . $bill_result_text;

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

			?>
			<h2>Оплата через систему QIWI Кошелек</h2>
			<?php
			if($bill_result->createBillResult === 0)
			{
				echo $bill_result_text . ". Можете оплатить его одним из способов:<br/><ul><li>Наличными</li><li>Из QIWI Кошелька</li><li>Банковскими картами Visa, MasterCard</li><li>С лицевого счета МТС, Билайн, Мегафон</li></ul>";
	?><h1>  <a href="https://w.qiwi.ru/orders.action" target="blank">  Перейти к оплате счета</a>  </h1>	<?php
}
			else
			{
				echo "Счет не добавлен. Код ответа: ". $bill_result->createBillResult . " - " . $bill_result_text;
			}

		}
		return true;
	}

	function ReferenceCodeCompletion($code)
	{
		$return_code_message = "";

		switch ($code) {
				case 0:
					$return_code_message = "Добавление счета прошло успешно";
					break;
				case 13:
					$return_code_message = "Сервер занят, повторите запрос позже";
					break;
				case 150:
					$return_code_message = "Ошибка авторизации (неверный логин/пароль)";
					break;
				case 210:
					$return_code_message = "Счет не найден";
					break;
				case 215:
					$return_code_message = "Счет с таким txn-id уже существует";
					break;
				case 241:
					$return_code_message = "Сумма слишком мала";
					break;
				case 242:
					$return_code_message = "Превышена максимальная сумма платежа – 15 000р.";
					break;
				case 278:
					$return_code_message = "Превышение максимального интервала получения списка счетов";
					break;
				case 298:
					$return_code_message = "Агента не существует в системе";
					break;
				case 300:
					$return_code_message = "Неизвестная ошибка";
					break;
				case 330:
					$return_code_message = "Ошибка шифрования";
					break;
				case 370:
					$return_code_message = "Превышено максимальное кол-во одновременно выполняемых запросов";
					break;
				default:
					$return_code_message = "Неизвестный статус";
					break;
			}
		return $return_code_message;
	}

	/**
	 * Изменение статуса заказа. Позволяет пользователю внедрять собственные
	 * обработчики при изменении статуса.
	 *
	 * @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']));
			}
		}
	}

	function GetHandlerUrl($shop_shops_id)
	{
		$shop = & singleton('shop');
		$shop_row = $shop->GetShop($shop_shops_id);

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

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

			$handler_url = 'http://'.$site_alias.$shop_path.'cart/';
		}
		else
		{
			$handler_url = '';
		}

		return $handler_url;
	}

	function HandleSoapServer()
	{
		$wsdlPath = CMS_FOLDER . "hostcmsfiles/shop/pay/IShopClientWS.wsdl";
		$server = new SoapServer($wsdlPath, array('classmap' => array('tns:updateBill' => 'Param', 'tns:updateBillResponse' => 'Response')));
		$server->setClass("ServerQIWI");
		$server->handle();
	}
}
?>