PageRenderTime 27ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/components/bitrix/sale.order.payment.change/class.php

https://gitlab.com/alexprowars/bitrix
PHP | 524 lines | 399 code | 75 blank | 50 comment | 70 complexity | 777204a27dc12689a207cb7a92a637b5 MD5 | raw file
  1. <?php
  2. use Bitrix\Main,
  3. Bitrix\Sale,
  4. Bitrix\Currency,
  5. Bitrix\Main\Localization\Loc,
  6. Bitrix\Main\Loader,
  7. Bitrix\Sale\PaySystem,
  8. Bitrix\Main\Application;
  9. if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
  10. Loc::loadMessages(__FILE__);
  11. /**
  12. * Class SaleAccountPay
  13. */
  14. class SaleOrderPaymentChange extends \CBitrixComponent
  15. {
  16. /** @var Main\ErrorCollection $errorCollection*/
  17. protected $errorCollection;
  18. /** @var \Bitrix\Sale\Order $order */
  19. protected $order = null;
  20. protected $isRefreshPrice = false;
  21. /**
  22. * Function checks and prepares all the parameters passed. Everything about $arParam modification is here.
  23. * @param mixed[] $params List of unchecked parameters
  24. * @return mixed[] Checked and valid parameters
  25. */
  26. public function onPrepareComponentParams($params)
  27. {
  28. $this->errorCollection = new Main\ErrorCollection();
  29. if (!isset($params["ELIMINATED_PAY_SYSTEMS"]) && !is_array($params["ELIMINATED_PAY_SYSTEMS"]))
  30. {
  31. $params["ELIMINATED_PAY_SYSTEMS"] = array();
  32. }
  33. $params['NAME_CONFIRM_TEMPLATE'] = 'confirm_template';
  34. $params["TEMPLATE_PATH"] = $this->getTemplateName();
  35. if (empty($params['NAME_CONFIRM_TEMPLATE']))
  36. {
  37. $params['NAME_CONFIRM_TEMPLATE'] = "confirm_template";
  38. }
  39. if (empty($params['ACCOUNT_NUMBER']))
  40. {
  41. $this->errorCollection->setError(new Main\Error(Loc::getMessage("SOPC_ERROR_ORDER_NOT_EXISTS")));
  42. }
  43. if (empty($params['PAYMENT_NUMBER']))
  44. {
  45. $this->errorCollection->setError(new Main\Error(Loc::getMessage("SOPC_ERROR_PAYMENT_NOT_EXISTS")));
  46. }
  47. if ($params["PATH_TO_PAYMENT"] == '')
  48. {
  49. $params["PATH_TO_PAYMENT"] = "/personal/order/payment/";
  50. }
  51. else
  52. {
  53. $params["PATH_TO_PAYMENT"] = trim($params["PATH_TO_PAYMENT"]);
  54. }
  55. if (empty($params['ALLOW_INNER']))
  56. {
  57. $params['ALLOW_INNER'] = "N";
  58. }
  59. if (empty($params['ONLY_INNER_FULL']))
  60. {
  61. $params['ONLY_INNER_FULL'] = "Y";
  62. }
  63. if (!CBXFeatures::IsFeatureEnabled('SaleAccounts'))
  64. {
  65. $params['ALLOW_INNER'] = "N";
  66. }
  67. if ($params['REFRESH_PRICES'] === "Y")
  68. {
  69. $this->isRefreshPrice = true;
  70. }
  71. else
  72. {
  73. $params['REFRESH_PRICES'] = "N";
  74. }
  75. return $params;
  76. }
  77. /**
  78. * Check Required Modules
  79. * @throws Main\SystemException
  80. * @return bool
  81. */
  82. protected function checkModules()
  83. {
  84. if (!Loader::includeModule('sale'))
  85. {
  86. $this->errorCollection->setError(new Main\Error(Loc::getMessage('SOPC_MODULE_NOT_INSTALL')));
  87. return false;
  88. }
  89. return true;
  90. }
  91. /**
  92. * Prepare data to render in new version of component.
  93. * @return void
  94. */
  95. protected function buildPaySystemsList()
  96. {
  97. global $USER;
  98. if (!$USER->IsAuthorized())
  99. {
  100. $this->errorCollection->setError(new Main\Error(Loc::getMessage('SALE_ACCESS_DENIED')));
  101. return;
  102. }
  103. $paymentCollection = $this->order->getPaymentCollection();
  104. /** @var \Bitrix\Sale\Payment $payment */
  105. if ((int)$this->arResult['PAYMENT']['ID'] > 0)
  106. {
  107. $payment = $paymentCollection->getItemById($this->arResult['PAYMENT']['ID']);
  108. }
  109. if (empty($payment))
  110. {
  111. $payment = $paymentCollection->createItem();
  112. }
  113. $paySystemList = PaySystem\Manager::getListWithRestrictions($payment);
  114. foreach ($paySystemList as $paySystemElement)
  115. {
  116. if (!in_array($paySystemElement['ID'], $this->arParams['ELIMINATED_PAY_SYSTEMS']))
  117. {
  118. if (!empty($paySystemElement["LOGOTIP"]))
  119. {
  120. $paySystemElement["LOGOTIP"] = CFile::GetFileArray($paySystemElement['LOGOTIP']);
  121. $fileTemp = CFile::ResizeImageGet(
  122. $paySystemElement["LOGOTIP"]["ID"],
  123. array("width" => "95", "height" =>"55"),
  124. BX_RESIZE_IMAGE_PROPORTIONAL,
  125. true
  126. );
  127. $paySystemElement["LOGOTIP"] = $fileTemp["src"];
  128. }
  129. if ($paySystemElement['ID'] == $this->arResult['INNER_ID'])
  130. {
  131. $innerData = $paySystemElement;
  132. }
  133. else
  134. {
  135. $this->arResult['PAYSYSTEMS_LIST'][] = $paySystemElement;
  136. }
  137. }
  138. }
  139. if (empty($this->arResult['PAYSYSTEMS_LIST']))
  140. {
  141. $this->errorCollection->setError(new Main\Error(Loc::getMessage("SOPC_EMPTY_PAY_SYSTEM_LIST")));
  142. }
  143. if ($this->arParams['ALLOW_INNER'] == 'Y' && isset($innerData))
  144. {
  145. if ((float)$this->arResult['INNER_PAYMENT_INFO']["CURRENT_BUDGET"] > 0)
  146. {
  147. $this->arResult['PAYSYSTEMS_LIST'][] = $innerData;
  148. }
  149. }
  150. }
  151. /**
  152. * Function implements all the life cycle of our component
  153. * @return void
  154. */
  155. public function executeComponent()
  156. {
  157. global $APPLICATION;
  158. $templateName = null;
  159. if ($this->checkModules() && $this->errorCollection->isEmpty())
  160. {
  161. if ($this->arParams["SET_TITLE"] !== "N")
  162. {
  163. $APPLICATION->SetTitle(Loc::getMessage('SOPC_TITLE'));
  164. }
  165. $this->prepareData();
  166. if ($this->order)
  167. {
  168. if (
  169. $this->arParams['ALLOW_INNER'] == 'Y'
  170. && (float)$this->arParams['INNER_PAYMENT_SUM'] > 0
  171. )
  172. {
  173. $result = $this->initiateInnerPay();
  174. $errorMessages = $result->getErrorMessages();
  175. if (empty($errorMessages))
  176. {
  177. die();
  178. }
  179. else
  180. {
  181. $this->errorCollection->add($result->getErrors());
  182. }
  183. }
  184. elseif ($this->arParams['AJAX_DISPLAY'] === 'Y')
  185. {
  186. if ((int)$this->arParams['NEW_PAY_SYSTEM_ID'] == (int)$this->arResult['INNER_ID']
  187. && $this->arParams['ALLOW_INNER'] === 'Y'
  188. && $this->arResult['IS_ALLOW_PAY'] === 'Y')
  189. {
  190. $this->arResult['SHOW_INNER_TEMPLATE'] = "Y";
  191. }
  192. else
  193. {
  194. $this->orderPayment();
  195. }
  196. $templateName = $this->arParams['NAME_CONFIRM_TEMPLATE'];
  197. }
  198. else
  199. {
  200. $this->buildPaySystemsList();
  201. if ($this->errorCollection->isEmpty())
  202. {
  203. $signer = new Main\Security\Sign\Signer;
  204. $this->arResult['$signedParams'] = $signer->sign(base64_encode(serialize($this->arParams)), 'sale.order.payment.change');
  205. }
  206. }
  207. }
  208. else
  209. {
  210. $this->errorCollection->setError(new Main\Error(Loc::getMessage('SOPC_ERROR_ORDER_NOT_EXISTS')));
  211. }
  212. }
  213. $this->formatResultErrors();
  214. $this->includeComponentTemplate($templateName);
  215. }
  216. /**
  217. * Move all errors to $this->arResult, if there were any
  218. * @return void
  219. */
  220. protected function formatResultErrors()
  221. {
  222. if (!$this->errorCollection->isEmpty())
  223. {
  224. /** @var Main\Error $error */
  225. foreach ($this->errorCollection->toArray() as $error)
  226. {
  227. $this->arResult['errorMessage'][] = $error->getMessage();
  228. }
  229. }
  230. }
  231. /**
  232. * Collect data for component
  233. * @throws Main\ArgumentNullException
  234. */
  235. protected function prepareData()
  236. {
  237. if ($this->arParams['ACCOUNT_NUMBER'] == '')
  238. {
  239. return;
  240. }
  241. $registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER);
  242. $orderClassName = $registry->getOrderClassName();
  243. $this->order = $orderClassName::loadByAccountNumber($this->arParams['ACCOUNT_NUMBER']);
  244. if (empty($this->order))
  245. {
  246. return;
  247. }
  248. $paymentClassName = $registry->getPaymentClassName();
  249. $paymentList = $paymentClassName::getList(
  250. array(
  251. "filter" => array("ACCOUNT_NUMBER" => $this->arParams['PAYMENT_NUMBER']),
  252. "select" => array('*')
  253. )
  254. );
  255. $this->arResult['PAYMENT'] = $paymentList->fetch();
  256. $this->arResult['IS_ALLOW_PAY'] = $this->order->isAllowPay() ? 'Y' : 'N';
  257. $this->arResult['INNER_ID'] = PaySystem\Manager::getInnerPaySystemId();
  258. if ($this->arParams['ALLOW_INNER'] == 'Y')
  259. {
  260. $this->loadInnerData();
  261. }
  262. }
  263. /**
  264. * Initiate inner payment
  265. * @return Main\Result
  266. * @throws Main\ArgumentNullException
  267. * @throws Main\ObjectNotFoundException
  268. */
  269. protected function initiateInnerPay()
  270. {
  271. $result = new Sale\Result();
  272. global $USER;
  273. if (!$USER->IsAuthorized())
  274. {
  275. $result->addError(new Main\Error(Loc::getMessage('SALE_ACCESS_DENIED')));
  276. return $result;
  277. }
  278. $budget = $this->arResult['INNER_PAYMENT_INFO']['CURRENT_BUDGET'];
  279. if ($budget <= 0)
  280. {
  281. $result->addError(new Main\Error(Loc::getMessage('SOPC_LOW_BALANCE')));
  282. return $result;
  283. }
  284. /** @var \Bitrix\Sale\Payment $payment */
  285. $paymentCollection = $this->order->getPaymentCollection();
  286. $payment = $paymentCollection->getItemById($this->arResult['PAYMENT']['ID']);
  287. $paySystemObject = PaySystem\Manager::getObjectById($this->arResult['INNER_ID'] );
  288. $sum = $payment->getSum();
  289. $paymentSum = (float)$this->arParams['INNER_PAYMENT_SUM'];
  290. if ($budget >= $sum && $paymentSum >= $sum)
  291. {
  292. $payment->setFields(array(
  293. 'PAY_SYSTEM_ID' => $paySystemObject->getField('ID'),
  294. 'PAY_SYSTEM_NAME' => $paySystemObject->getField('NAME')
  295. )
  296. );
  297. }
  298. else
  299. {
  300. $paymentSum = $paymentSum >= $budget ? $budget : $paymentSum;
  301. if ($this->arParams['ONLY_INNER_FULL'] === 'Y' && $paymentSum < $sum)
  302. {
  303. $result->addError(new Main\Error(Loc::getMessage('SOPC_LOW_BALANCE')));
  304. return $result;
  305. }
  306. $rest = $sum - $paymentSum;
  307. $payment->setField('SUM', $rest);
  308. /** @var Sale\Payment $newPayment */
  309. $payment = $paymentCollection->createItem();
  310. $paymentResult = $payment->setFields(
  311. array(
  312. 'SUM' => $paymentSum,
  313. 'CURRENCY'=> $this->order->getCurrency(),
  314. 'PAY_SYSTEM_ID' => $paySystemObject->getField('ID'),
  315. 'PAY_SYSTEM_NAME' => $paySystemObject->getField('NAME')
  316. )
  317. );
  318. if (!$paymentResult->isSuccess())
  319. {
  320. $result->addError(new Main\Error(Loc::getMessage('SOPC_LOW_BALANCE')));
  321. return $result;
  322. }
  323. }
  324. $this->order->save();
  325. $result = $paySystemObject->initiatePay($payment, null, PaySystem\BaseServiceHandler::STRING);
  326. return $result;
  327. }
  328. /**
  329. * Load user account data
  330. * @return void
  331. */
  332. protected function loadInnerData()
  333. {
  334. global $USER;
  335. if (!$USER->IsAuthorized())
  336. {
  337. $this->errorCollection->setError(new Main\Error(Loc::getMessage('SALE_ACCESS_DENIED')));
  338. return;
  339. }
  340. $accountList = CSaleUserAccount::GetList(
  341. array("CURRENCY" => "ASC"),
  342. array(
  343. "USER_ID" => (int)($USER->GetID()),
  344. "CURRENCY" => $this->order->getCurrency()
  345. ),
  346. false,
  347. false,
  348. array("ID", "CURRENT_BUDGET", "CURRENCY", "TIMESTAMP_X")
  349. );
  350. if ($account = $accountList->Fetch())
  351. {
  352. $currencyList = CCurrencyLang::GetFormatDescription($account["CURRENCY"]);
  353. $account['FORMATED_CURRENCY'] = trim(str_replace("#", "", $currencyList['FORMAT_STRING']));
  354. $this->arResult['INNER_PAYMENT_INFO'] = $account;
  355. }
  356. }
  357. /**
  358. * Ordering payment for calling in ajax callback
  359. * @return void
  360. */
  361. protected function orderPayment()
  362. {
  363. global $USER;
  364. if (!$USER->IsAuthorized())
  365. {
  366. $this->errorCollection->setError(new Main\Error(Loc::getMessage('SALE_ACCESS_DENIED')));
  367. return;
  368. }
  369. if ($this->arParams['ALLOW_INNER'] !== 'Y' && (int)$this->arParams['NEW_PAY_SYSTEM_ID'] == (int)$this->arResult['INNER_ID'])
  370. {
  371. $this->errorCollection->setError(new Main\Error(Loc::getMessage('SOPC_ERROR_ORDER_PAYMENT_SYSTEM')));
  372. return;
  373. }
  374. $paySystemObject = PaySystem\Manager::getObjectById((int)$this->arParams['NEW_PAY_SYSTEM_ID']);
  375. if (empty($paySystemObject))
  376. {
  377. $this->errorCollection->setError(new Main\Error(Loc::getMessage('SOPC_ERROR_ORDER_PAYMENT_SYSTEM')));
  378. return;
  379. }
  380. \Bitrix\Sale\DiscountCouponsManagerBase::freezeCouponStorage();
  381. /** @var \Bitrix\Sale\Payment $payment */
  382. $paymentCollection = $this->order->getPaymentCollection();
  383. $payment = $paymentCollection->getItemById($this->arResult['PAYMENT']['ID']);
  384. $paymentResult = $payment->setFields(array(
  385. 'PAY_SYSTEM_ID' => $paySystemObject->getField('ID'),
  386. 'PAY_SYSTEM_NAME' => $paySystemObject->getField('NAME')
  387. )
  388. );
  389. if (!$paymentResult->isSuccess())
  390. {
  391. \Bitrix\Sale\DiscountCouponsManagerBase::unFreezeCouponStorage();
  392. $this->errorCollection->add($paymentResult->getErrors());
  393. return;
  394. }
  395. if ($this->isRefreshPrice)
  396. {
  397. $oldOrderPrice = $this->order->getPrice();
  398. $this->order->refreshData(array('PRICE', 'PRICE_DELIVERY'));
  399. if (count($this->order->getPaymentCollection()) > 1)
  400. {
  401. $newOrderPrice = $this->order->getPrice();
  402. $paymentSum = $payment->getSum();
  403. $payment->setFieldNoDemand('SUM', $paymentSum + ($newOrderPrice - $oldOrderPrice));
  404. }
  405. }
  406. $resultSaving = $this->order->save();
  407. \Bitrix\Sale\DiscountCouponsManagerBase::unFreezeCouponStorage();
  408. if ($resultSaving->isSuccess())
  409. {
  410. if ($this->arResult['IS_ALLOW_PAY'] == 'Y')
  411. {
  412. $this->arResult = array(
  413. "ORDER_ID" => $this->order->getField("ACCOUNT_NUMBER"),
  414. "ORDER_DATE" => $this->order->getDateInsert()->toString(),
  415. "PAYMENT_ID" => $payment->getField("ACCOUNT_NUMBER"),
  416. "PAY_SYSTEM_NAME" => $payment->getField("PAY_SYSTEM_NAME"),
  417. "IS_CASH" => $paySystemObject->isCash() || $paySystemObject->getField("ACTION_FILE") === 'cash',
  418. "NAME_CONFIRM_TEMPLATE" => $this->arParams['NAME_CONFIRM_TEMPLATE']
  419. );
  420. if ($paySystemObject->getField('NEW_WINDOW') === 'Y')
  421. {
  422. if (mb_substr($this->arParams['PATH_TO_PAYMENT'], -1) !== '/')
  423. $this->arParams['PATH_TO_PAYMENT'] .= '/';
  424. $this->arResult["PAYMENT_LINK"] = $this->arParams['PATH_TO_PAYMENT'] . "?ORDER_ID=" . $this->order->getField("ACCOUNT_NUMBER") . "&PAYMENT_ID=" . $payment->getField('ACCOUNT_NUMBER');
  425. }
  426. else
  427. {
  428. if ($returnUrl = $this->arParams['RETURN_URL'])
  429. {
  430. $paySystemObject->getContext()->setUrl($returnUrl);
  431. }
  432. $paySystemBufferedOutput = $paySystemObject->initiatePay($payment, null, PaySystem\BaseServiceHandler::STRING);
  433. if ($paySystemBufferedOutput->isSuccess())
  434. {
  435. $this->arResult["TEMPLATE"] = $paySystemBufferedOutput->getTemplate();
  436. }
  437. else
  438. {
  439. $this->errorCollection->add($paySystemBufferedOutput->getErrors());
  440. }
  441. }
  442. }
  443. }
  444. else
  445. {
  446. $this->errorCollection->add($resultSaving->getErrors());
  447. }
  448. }
  449. }