[EVO] Костыли для личного кабинета пользователя

Сильно не пинайте только начинаю разбираться в modx api, так что мои костыли для TSVshop не претендуют на нобелевскую премию, хотя может кому и пригодятся…
Всегда готов выслушать замечания и предложения.

В качестве интернет магазина используется TSVshop
Для авторизации стандартный WebLogin/WebSignup

Очень много букв и кода

1) Создал таблицу где будет хранится баланс пользователя: user_balance(id, user_id, balance, date)
2) С помощью робокассы сочинил простой сниппет
<?php
if($mod == 'pay'){
	// регистрационная информация (логин, пароль #1)
	$mrh_login = "";
	$mrh_pass1 = "";
	// номер заказа
	$inv_id = 0;
	// описание заказа
	$inv_desc = "Пополнение счета ROBOKASSA";
	// сумма заказа
	$def_sum = "100";
	// тип товара
	$shp_item = 2;
	// Пользователь ИД
	$shp_user_id = $_SESSION['webInternalKey'];
	// язык
	$culture = "ru";
	// кодировка
	$encoding = "utf-8";
	// формирование подписи
	$crc  = md5("$mrh_login::$inv_id:$mrh_pass1:ShpItem=$shp_item:ShpUserId=$shp_user_id");
	// HTML-страница с кассой
	print "<html><script language=JavaScript ".
		  "src='https://auth.robokassa.ru/Merchant/PaymentForm/FormFLS.js?".
		  "MerchantLogin=$mrh_login&DefaultSum=$def_sum&InvoiceID=$inv_id".
		  "&Description=$inv_desc&SignatureValue=$crc&shpItem=$shp_item".
			"&shpUserId=$shp_user_id".
		  "&Culture=$culture&Encoding=$encoding'></script></html>";
}

if($mod == 'balance'){
	$u_id = $_SESSION['webInternalKey'];
	function get_user_balance($user_id) {
		global $modx;
		$user_balance_table = $modx->getFullTableName('user_balance');
		$res_balance = $modx->db->select("id,balance,date", $user_balance_table, 'user_id = "' . $user_id . '"');
		$user_balance = $modx->db->getRow($res_balance);
		return (int)$user_balance['balance']; 
	}
	echo "Ваш баланс составляет:". get_user_balance($u_id) ." руб.";
}
?>

Данный снипет умеет делать всего 2 вещи: mod =`pay` — выводит блок для ввода суммы платежа и mod = `balance` — выводит текущий баланс пользователя.

3) Так же с помощью робокассы сочинил скрипт для зачислению средст пользователю(от лавливает ответ робокасссы)

<?php
require_once('../manager/includes/protect.inc.php');
// Загрузка конфигурации
if (!$rt = @include_once '../manager/includes/config.inc.php') {
    exit('Невозможно загрузить конфигурационный файл!');
}
// Установка режима MODx API
define('MODX_API_MODE', true);
// Инициализация парсера
if (!$rt2 = @include_once(MODX_MANAGER_PATH.'/includes/document.parser.class.inc.php')) {
    exit('Невозможно загрузить парсер!'); 
}
$modx = new DocumentParser;
// Включение доступа к базе данных MODx
$modx->db->connect();
// Включение доступа к основным параметрам MODx
$modx->getSettings();
////////////////////////////////////
// регистрационная информация (пароль #2)
$mrh_pass2 = "";
//установка текущего времени
$tm=getdate(time()+9*3600);
$date="$tm[year]-$tm[mon]-$tm[mday] $tm[hours]:$tm[minutes]:$tm[seconds]";
//Разбор ответа
$out_summ = $_REQUEST["OutSum"];
$inv_id = $_REQUEST["InvId"];
$shp_item = $_REQUEST["ShpItem"];
$shp_user_id = $_REQUEST["ShpUserId"];
$crc = $_REQUEST["SignatureValue"];
// Подготовка сигнатуры
$crc = strtoupper($crc);
// Составляем свою сигнатуру
$my_crc = strtoupper(md5("$out_summ:$inv_id:$mrh_pass2:ShpItem=$shp_item:ShpUserId=$shp_user_id"));
// Сравнение сигнатур
if ($my_crc !=$crc)
{
  echo "bad sign\n";
  exit();
}
// запись в базу информации о проведенной операции
global $modx; 
// Получение текущего баланса
$user_balance_table = $modx->getFullTableName('user_balance');
$res = $modx->db->select("id,balance,date", $user_balance_table, 'user_id = "' . $shp_user_id . '"');
$user_old_balance = $modx->db->getRow($res);
//Переводим в число
$user_old_balance = (int)$user_old_balance['balance'];
$out_summ = (int)$out_summ;
//Суммируем текущий баланс и пополнение
$user_new_balance = $user_old_balance + $out_summ;
//Записываем в базу обновленный баланс	
$res_update_balance = $modx->db->update(array('balance' => $user_new_balance), $user_balance_table, 'user_id = "' . $shp_user_id . '"' );  
//Проверяем записалось ли в базу
if($res_update_balance) { 
	echo "OK$inv_id\n"; 
	} else {  
	echo 'NO DB UPDATE';  
}
?>


На данном этапе мы научились зачислять денежки на счет пользователя, но остается проблема: при регистрации нового пользователя необходимо в таблице user_balance присвоить юзеру нулевой баланс. Небольшой плагин решает эту проблему:

function get_user_id() {
	global $modx;
	if(isset($_POST['username'])){
		$username = $_POST['username'];
		$user_table = $modx->getFullTableName('web_users');
		$res_user_id = $modx->db->select("id", $user_table, 'username = "'.$username.'"');
		$user_id = $modx->db->getRow($res_user_id);
		return (int)$user_id['id']; 
	} else {
		return false; }
}

function insert_user_balance() {
	if(get_user_id() != false) {
		global $modx;
		$user_table = $modx->getFullTableName('user_balance');
		$dbTable = array();
        $dbTable['user_id'] = $modx->db->escape(get_user_id());
        $dbTable['balance'] = 0;
        $dbQuery = $modx->db->insert($dbTable, $user_table );
	}
}

return insert_user_balance();

Повесил этот плагин на событие OnWebSaveUser.

На следующем этапе предстоит запретить оформление заказа если у пользователя не достаточно средств на личном счете, для этого использовал плагин на событии TSVshopOnTplCartRender
Код плагина:
global $modx;	
$u_id = $_SESSION['webInternalKey'];
function get_user_balance($user_id) {
	global $modx;
	$user_balance_table = $modx->getFullTableName('user_balance');
	$res_balance = $modx->db->select("id,balance,date", $user_balance_table, 'user_id = "' . $user_id . '"');
	$user_balance = $modx->db->getRow($res_balance);
	return (int)$user_balance['balance']; 
}

function get_session() {
	if(isset($_COOKIE['tsvshop'])) {
		$sess = $_COOKIE['tsvshop'];
		return (int)$_SESSION[$sess]['result']['total'];
	} else {
		return false;}
}

if(get_session() != false) {
	$user_balance = get_user_balance($u_id);
	$total_price = 	get_session();
	if($user_balance < $total_price) {
		$tpl = mb_eregi_replace('%--form--%(.*)%--fend--%', "На вашем счету недостаточно средст! Пополните пожалуйста ваш баланс!", $tpl);
		$modx->event->output($tpl);
		} else {
		$tpl = preg_replace('/(%--.*?--%)/' ,"", $tpl);  
		$modx->event->output($tpl);
	}
}

В данном плагине пришлось очень сильно поизврашаться, что бы спрятать форму оформления заказа от пользователя, я обернул чанк в метки %--form--% и %--fend--% и регуляркой вырезаю этот кусок.

Ну и напоследок сниппет для обновления баланса пользователя после покупки вызывается до снипета [!TSVshop? &act=`finish`!]

Код сниппета:
<?php
$user_id = $_SESSION['tsvshopfin']['result']['userid'];
$out_summ = $_SESSION['tsvshopfin']['result']['total'];
global $modx;
// Получение текущего баланса
$user_balance_table = $modx->getFullTableName('user_balance');
$res = $modx->db->select("id,balance,date", $user_balance_table, 'user_id = "' . $user_id . '"');
$user_old_balance = $modx->db->getRow($res);

//Вычитаем из текущего баланса сумму покупки
$user_new_balance = (int)$user_old_balance['balance'] - (int)$out_summ;

//Записываем в базу обновленный баланс	
$res_update_balance = $modx->db->update(array('balance' => $user_new_balance), $user_balance_table, 'user_id = "' . $user_id . '"' );
if($res_update_balance) {  
	echo "Ваш баланс составляет: ".$user_new_balance;
	} else {  
	echo 'ERROR! NO DB UPDATE!';  
}
$_SESSION['tsvshopfin']['result']['userbalance'] = $user_new_balance;
?>


В итоге решение получилось очень извращенным, но при этом ни один файл модуля TSVShop не пострадал =)))

Повторяюсь, сильно не пинайте. Данное извращение постепенно будет приведено в человеческий вид.

1 комментарий

avatar
Да мы все тут на костылях :) Молодец.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.