Здравствуйте. Имеется магазин на сайте, в котором при нажатии на кнопку Оформить должна вычитаться стоимость товаров с баланса учетной записи пользователя, но [U]из баланса вычитается не стоимость, а количество товаров[/U]. ([B]скрин 255[/B])
Я так понимаю, что в функции/процедуре, которая выполняет изменение баланса после покупки товаров необходимо просто подставить переменную стоимости вместо количества.
[S]Также есть проблема связанная с округлением, которая видна на [B]скриншоте 255[/B]. Эта проблема проявляется, [U]когда указано большое кол-во товара и в параметрах товара выставлен коэффициент единицы измерения[/U], который мне нужен - 10, 100 или 1000. При единице - всё хорошо.[/S]
[SIZE=16pt]Вопросы:[/SIZE]
1) Где и на что в коде нужно поменять переменную количество на стоимость? Я пытался найти интуитивно, где выполняется вычитание из общего баланса суммы оформленного товара - не вышло, мои начальные знания java и PL/SQL мне не помогли. Моё предположение, что это где-то происходит в [B]function makeOrder[/B].
2) [B]Неактуально[/B] [S]Как мне сделать округление стоимости? В админке выставил округление базовой цены до 1, но ничего не изменилось.[/S]
[SIZE=16pt]Полный код файла class.php, где происходят все операции компонента:[/SIZE]
Я так понимаю, что в функции/процедуре, которая выполняет изменение баланса после покупки товаров необходимо просто подставить переменную стоимости вместо количества.
[S]Также есть проблема связанная с округлением, которая видна на [B]скриншоте 255[/B]. Эта проблема проявляется, [U]когда указано большое кол-во товара и в параметрах товара выставлен коэффициент единицы измерения[/U], который мне нужен - 10, 100 или 1000. При единице - всё хорошо.[/S]
[SIZE=16pt]Вопросы:[/SIZE]
1) Где и на что в коде нужно поменять переменную количество на стоимость? Я пытался найти интуитивно, где выполняется вычитание из общего баланса суммы оформленного товара - не вышло, мои начальные знания java и PL/SQL мне не помогли. Моё предположение, что это где-то происходит в [B]function makeOrder[/B].
2) [B]Неактуально[/B] [S]Как мне сделать округление стоимости? В админке выставил округление базовой цены до 1, но ничего не изменилось.[/S]
[SIZE=16pt]Полный код файла class.php, где происходят все операции компонента:[/SIZE]
Скрытый текст |
|---|
| [CODE]<? use \Bitrix\Main, \Bitrix\Main\Loader, \Bitrix\Main\Error, \Bitrix\Main\Type\DateTime, \Bitrix\Main\Localization\Loc, \Bitrix\Iblock, \Bitrix\Iblock\Component\ElementList, Bitrix\Main\Context, Bitrix\Currency\CurrencyManager, Bitrix\Sale\Order, Bitrix\Sale\Basket, Bitrix\Sale\Delivery, Bitrix\Sale\PaySystem, Bitrix\Sale; use xPaw\SourceQuery\SourceQuery; if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die(); /** * @global CUser $USER * @global CMain $APPLICATION * @global CIntranetToolbar $INTRANET_TOOLBAR */ Loc::loadMessages(__FILE__); if (!\Bitrix\Main\Loader::includeModule('iblock')) { ShowError(Loc::getMessage('IBLOCK_MODULE_NOT_INSTALLED')); return; } if (!\Bitrix\Main\Loader::includeModule('sale')) { ShowError(Loc::getMessage('IBLOCK_MODULE_NOT_INSTALLED')); return; } if (!\Bitrix\Main\Loader::includeModule('catalog')) { ShowError(Loc::getMessage('IBLOCK_MODULE_NOT_INSTALLED')); return; } class CurrencyCalculator extends CBitrixComponent { const balanceItemID = 71; public function __construct($component = null) { parent::__construct($component); global $USER; $this->user = $USER; } public function executeComponent(){ try{ /* $rsUser = CUser::GetByID($this->user->GetID()); $arUser = $rsUser->Fetch(); echo "<pre>"; print_r($arUser); echo "</pre>"; exit;*/ $this->getUserInfo(); $this->getUserBalance(); $this->getUserCurrencyItems(); $this->getProducts(); $this->arResult['STEAM_ID'] = $this->getSteamId(); if(isset($_POST["buy"]) || isset($_POST["cash"])){ $this->getUserBasket(); $this->makeOrder(isset($_POST["cash"])); } if(isset($_REQUEST["history"]) && $_REQUEST["history"] == 'balance'){ $this->getBalanceHistory(); } # if(isset($_REQUEST["history"]) && empty($_REQUEST["history"])){ $this->getBuyHistory(); # } if(isset($_REQUEST["inv_id"]) && $this->arResult['STEAM_ID']){ $this->updateBalance(); }else{ $this->includeComponentTemplate(); } }catch (Exception $e) { var_dump($e->getMessage()); return; } } public function checkPay(){ $url = "https://auth.robokassa.ru/Merchant/WebService/Service.asmx/OpState?"; $url .= "MerchantLogin=Okyes_Shop"; $url .= "&InvoiceID=".$this->order->getId(); $url .= "&Signature=".md5("Okyes_Shop:".$this->order->getId().":SnL0RKiEI47tYdYZ8u1D"); $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { $xml = new \SimpleXMLElement($response); $xml = simplexml_load_string($xml->asXML()); return $xml; } } public function updateBalance(){ $this->order = Sale\Order::load(intval($_REQUEST["inv_id"])); if($this->order){ $paymentCollection = $this->order->getPaymentCollection(); if($paymentCollection[0]->getField("PAID") == "N"){ $status = $this->checkPay(); if($status->State->Code == '100'){ $paymentCollection[0]->setPaid("Y"); $this->order->setField("STATUS_ID", "F"); $this->order->save(); \CSaleUserAccount::UpdateAccount( $this->order->getField("USER_ID"), $this->order->getPrice(), "RUB", "Пополнение баланса", $this->order->getId() ); dump("пополнили"); } } } } /* * Корзина покупателя */ public function getUserBasket(){ $this->basket = Sale\Basket::loadItemsForFUser(Sale\Fuser::getId(), Bitrix\Main\Context::getCurrent()->getSite()); } public function cleanBasket(){ $this->basketItems = $this->basket->getBasketItems(); foreach($this->basketItems as $item){ $this->basket->getItemById($item->getId())->delete(); } $this->basket->save(); } public function checkPostFields(){ if(!isset($_POST["CURRENCY"]) || empty($_POST["CURRENCY"])){ throw new Exception('Не выбран ни один товар'); } // определим товары в запросе $arIDs = []; foreach($_POST["CURRENCY"] as $k => $cur){ if(intval($cur) > 0){ $arIDs[$k] = $cur; } } if(empty($arIDs)){ LocalRedirect("/store/"); // throw new Exception('Не указано количество товаров для покупки'); } // запросим данные по товарам $rs_element = \CIBlockElement::getList( [], ["IBLOCK_ID" => $this->arParams["IBLOCK_ID"], "ID" => array_keys($arIDs)], false, false, [] ); $this->arItems = []; $totalPrice = 0; while($result = $rs_element->Fetch()){ $data = $result; $data["PRICES"] = CCatalogProduct::GetOptimalPrice($result["ID"], 1, $this->user->GetUserGroupArray(), "N"); $data["PRODUCT"] = CCatalogProduct::GetByID($result["ID"]); $res = CCatalogMeasureRatio::getList( [], ['IBLOCK_ID'=>$this->arParams["IBLOCK_ID"],'PRODUCT_ID'=>$result["ID"]], false, false, [] )->Fetch(); $data["MEASURE"] = $res; $data["BASKET_BUY_QUANTITY"] = $arIDs[$result["ID"]]; $totalPrice = $totalPrice + ($arIDs[$result["ID"]] * $data["PRICES"]["RESULT_PRICE"]["DISCOUNT_PRICE"] * $data["MEASURE"]["RATIO"]); $this->arItems[] = $data; } if(floatval($totalPrice) > floatval($this->arResult["USER_BALANCE"]["CURRENT_BUDGET"])) throw new Exception('Недостаточно средств для покупки'); } public function createBasket(){ foreach($this->arItems as $item){ Add2BasketByProductID($item["ID"], $item["BASKET_BUY_QUANTITY"]); } $this->basket = Sale\Basket::loadItemsForFUser(Sale\Fuser::getId(), Bitrix\Main\Context::getCurrent()->getSite()); $this->basketItems = $this->basket->getBasketItems(); } public function encrieseBalance(){ if(intval($_POST["amount"]) > 0) Add2BasketByProductID(self::balanceItemID, intval($_POST["amount"])); $this->basket = Sale\Basket::loadItemsForFUser(Sale\Fuser::getId(), Bitrix\Main\Context::getCurrent()->getSite()); $this->basketItems = $this->basket->getBasketItems(); } private function giveItemsToClient() { $items = [ 'credits-rpg' => 'sm_give_rpg_credits {steamid} {count}', 'silver' => 'sm_give_shop_silver {steamid} {count}', 'gold' => 'sm_give_shop_gold {steamid} {count}', 'vip-1-month' => 'sm_give_vip {steamid} {count}', ]; $count = $this->getItemsCount($items); if (empty($count)) { return; } $steamid = $this->getSteamId(); if (!$steamid) { return; } /* require_once 'libs/php-rcon/SourceQuery/bootstrap.php'; $Query = new SourceQuery(); try { $Query->Connect('46.174.50.33', '27225', 5, SourceQuery::SOURCE); $Query->SetRconPassword('whiv42hsc2ibmsapo6dq9m4hsvorw5qk'); foreach ($items as $key => $value) { if (!array_key_exists($key, $count)) { continue; } $amount = $count[$key]; if ($key == 'vip-1-month') { $amount *= 43200; } $buffers = [ 'search' => ['{steamid}', '{count}'], 'replace' => ['"'.$steamid.'"', $amount], ]; $cmd = str_replace($buffers['search'], $buffers['replace'], $value); $Query->Rcon($cmd); } } catch (Exception $e) { var_dump($e->getMessage()); } finally { $Query->Disconnect( ); } */ try { require_once 'libs/php-rcon/SourceQuery/bootstrap.php'; $Query = new SourceQuery(); $Query->Connect('46.174.50.33', '27225', 5, SourceQuery::SOURCE); $Query->SetRconPassword('whiv42hsc2ibmsapo6dq9m4hsvorw5qk'); foreach ($items as $key => $value) { if (!array_key_exists($key, $count)) { continue; } $amount = $count[$key]; if ($key == 'vip-1-month') { $amount *= 43200; } global $DB; $sql = "INS ERT INTO `give_priv` (`auth`, `type`, `amount`) VALUES ('".$steamid."', '".$key."', '".$amount."');"; $res = $DB->Query($sql); $Query->Rcon("sm_give_priv \"".$steamid."\""); } } catch (Exception $e) { var_dump($e->getMessage()); // print_r($e->getTraceAsString().PHP_EOL); } finally { $Query->Disconnect( ); } } private function getSteamId() { $arRes = CUser::GetByID($this->user->GetID()); $arUser = $arRes->Fetch(); // var_dump($arUser); if ($arUser && isset($arUser["UF_STEAM_ID"])) { return $arUser["UF_STEAM_ID"]; } return false; } private function getItemsCount($items) { $result = []; foreach ($this->arItems as $item) { if (isset($item['CODE']) && array_key_exists($item['CODE'], $items) && !empty($item['BASKET_BUY_QUANTITY'])) { $result[$item['CODE']] = $item['BASKET_BUY_QUANTITY']; } } return $result; } public function makeOrder($check = false){ $this->cleanBasket(); if(!$check){ $this->checkPostFields(); $this->createBasket(); }else{ $this->encrieseBalance(); } $currencyCode = CurrencyManager::getBaseCurrency(); $this->order = Bitrix\Sale\Order::create(Context::getCurrent()->getSite(), $this->user->GetID()); $this->order->setPersonTypeId(1); $this->order->setField('CURRENCY', $currencyCode); $this->order->setBasket($this->basket); $paymentCollection = $this->order->getPaymentCollection(); $payment = $paymentCollection->createItem( \Bitrix\Sale\PaySystem\Manager::getObjectById($check ? 3 : 1) ); $payment->setField("SUM", $this->order->getPrice()); $payment->setField("CURRENCY", $this->order->getCurrency()); $payment->setField("PAID", $check ? "N" : "Y"); $rs = $this->order->save(); if($rs->isSuccess()){ $result["ORDER_ID"] = $rs->getId(); $order = Sale\Order::load($rs->getId()); if(!$check){ $bSuccessPayment = CSaleUserAccount::Pay($this->user->GetID(),$order->getPrice(),$order->getCurrency(),$order->getId(),False); $this->giveItemsToClient(); LocalRedirect($GLOBALS["APPLICATION"]->GetCurPage()); }else{ $mrh_login = "Okyes_Shop"; $mrh_pass1 = "WZG91C2hXsGA1bg0FQrH"; $inv_id = $rs->getId(); $inv_desc = "Пополнение баланса на сумму ".$order->getPrice()." руб."; $out_summ = $order->getPrice(); $IsTest = 0; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://auth.robokassa.ru/Merchant/WebService/Service.asmx/CalcOutSumm?MerchantLogin='.$mrh_login.'&IncCurrLabel=YandexMerchantQiwiR&IncSum='.$out_summ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $data = curl_exec($ch); curl_close($ch); //convert the XML result into array $array_data = json_decode(json_encode(simplexml_load_string($data)), true); if($array_data['OutSum']) $out_summ = $array_data['OutSum']; $crc = md5("$mrh_login:$out_summ:$inv_id:$mrh_pass1"); $propertyCollection = $order->getPropertyCollection(); $somePropValue = $propertyCollection->getItemByOrderPropertyId(1); $somePropValue->setValue($crc); $order->save(); ob_end_clean(); ?> <ht ml> <fo rm id='pay_submit' action='https://merchant.roboxchange.com/Index.aspx' method=POST> <input type=hidden name=MerchantLogin value='<?=$mrh_login?>'> <input type=hidden name=OutSum value='<?=$out_summ?>'> <input type=hidden name=InvoiceID value='<?=$inv_id?>'> <input type=hidden name=IncCurrLabel value='YandexMerchantQiwiR'> <input type=hidden name=Description value='<?=$inv_desc?>'> <input type=hidden name=SignatureValue value='<?=$crc?>'> <input type=hidden name=IsTest value='<?=$IsTest?>'> <input type=submit val ue='Pay' style="display:none"> </form> <sc ript> window.onl oad = function () { document.getElementById("pay_submit").submit() } </sc ript> </html> <? exit; } }else{ $result["ERROR"] = array( "TYPE" => "DELIVERY_NOT_SELECTED", "CODE" => "DELIVERY_ID", "DESCRIPTION" => "Ошибка оформления заказа: ".print_r($rs->getErrors()) ); } } public function prepareFilter(){ $filter = []; $filter["IBLOCK_ID"] = $this->arParams["IBLOCK_ID"]; if(intval($filter["IBLOCK_ID"]) < 1){ throw new Exception('Не указан инфоблок.'); } $filter["IBLOCK_SECTION_ID"] = $this->arParams["CURRENCY_SECTION_ID"]; if(intval($filter["IBLOCK_SECTION_ID"]) < 1){ throw new Exception('Не указан раздел с валютой.'); } $filter["ACTIVE"] = "Y"; if(!empty($GLOBALS[$this->arParams["FILTER_NAME"]])) $arFilter = array_merge($GLOBALS[$this->arParams["FILTER_NAME"]], $filter); else $arFilter = $filter; return $arFilter; } public function getBasePriceID(){ $rs_price = CCatalogGroup::GetList( [], ["BASE" => "Y"], false,false, [] )->Fetch(); if($rs_price){ $this->basePrice = $rs_price; }else{ throw new Exception('Базовая цена не найдена.'); } } public function getProducts(){ $this->arResult["ITEMS"] = []; $arFilter = $this->prepareFilter(); $obCache = new CPHPCache; $life_time = $this->arParams["CACHE_TIME"] >= 0 ? $this->arParams["CACHE_TIME"] : 30*60*60; $cache_id = md5(serialize($arFilter)); $cache = Bitrix\Main\Data\Cache::createInstance(); if ($cache->initCache($life_time, $cache_id, "/catalog/calculator/")) { $arValues = $cache->getVars(); $arItems = $arValues["ITEMS"]; }elseif ($cache->startDataCache()){ $arItems = []; $rs_element = CIBlockElement::GetList( [], $arFilter, false, false, [] ); $this->getBasePriceID(); while($result = $rs_element->GetNextElement()){ $data = $result->GetFields(); $data["PROPERTIES"] = $result->GetProperties(); $data["PRICES"] = CCatalogProduct::GetOptimalPrice($data["ID"], 1, $this->user->GetUserGroupArray(), "N"); $data["PRODUCT"] = CCatalogProduct::GetByID($data["ID"]); $res = CCatalogMeasureRatio::getList( [], ['IBLOCK_ID'=>$this->arParams["IBLOCK_ID"],'PRODUCT_ID'=>$data["ID"]], false, false, [] )->Fetch(); $data["MEASURE"] = $res; $arItems[] = $data; } $cache->endDataCache(["ITEMS" => $arItems]); } $this->arResult["ITEMS"] = $arItems; } public function getUserInfo(){ $rs_user = CUser::GetByID($this->user->GetID())->Fetch(); $this->arResult["USER"] = $rs_user; } public function getUserBalance(){ $rs_balance = CSaleUserAccount::GetList( array(), array("USER_ID" => $this->arResult["USER"]["ID"]), false, false, array("CURRENT_BUDGET", "CURRENCY") )->Fetch(); $rs_balance["CURRENT_BUDGET_FORMAT"] = number_format($rs_balance["CURRENT_BUDGET"], 2, ",", " ")." руб."; $this->arResult["USER_BALANCE"] = $rs_balance; } /* * */ public function getUserCurrencyItems(){ $db_sales = CSaleOrder::GetList(array("DATE_INSERT" => "ASC"), array("USER_ID" => $this->user->GetID(),"!STATUS_ID" => "F")); $currencyItems = array(); while ($ar_sales = $db_sales->Fetch()){ $order = Sale\Order::load($ar_sales["ID"]); $basketItems = $order->getBasket()->getBasketItems(); foreach($basketItems as $item){ if($item->getProductId() == self::balanceItemID) continue; $amount = $currencyItems[$item->getProductId()]["AMOUNT"] + $item->getQuantity(); $currencyItems[$item->getProductId()] = array( "AMOUNT" => $amount, "NAME" => $item->getField("NAME") ); } } $this->arResult["USER_CURRENCIES"] = $currencyItems; } /* * */ public function getBalanceHistory(){ $rsOrder = CSaleOrder::GetList(array('ID' => 'ASC'), array('USER_ID' => $this->user->GetID(),'BASKET_PRODUCT_ID' => self::balanceItemID)); $this->arResult["BALANCE_HISTORY"] = array(); while($result = $rsOrder->Fetch()){ $this->arResult["BALANCE_HISTORY"][] = $result; } $rs_status = CSaleStatus::GetList(); $this->arResult["STATUSES"] = array(); while($result = $rs_status->Fetch()){ $this->arResult["STATUSES"][$result["ID"]] = $result["NAME"]; } } /* * */ public function getBuyHistory(){ $rsOrder = CSaleOrder::GetList(array('ID' => 'ASC'), array('USER_ID' => $this->user->GetID(), '!BASKET_PRODUCT_ID' => self::balanceItemID)); $this->arResult["BUY_HISTORY"] = array(); while($result = $rsOrder->Fetch()){ $order = Sale\Order::load($result["ID"]); $basketItems = $order->getBasket()->getBasketItems(); $items = array(); foreach($basketItems as $item){ if($item->getProductId() == self::balanceItemID) continue; $items[] = array( "NAME" => $item->getField("NAME"), "AMOUNT" => $item->getQuantity() ); } $result["ITEMS"] = $items; $this->arResult["BUY_HISTORY"][$result["ID"]] = $result; } } }[/CODE] |