BxCreditsModule.php 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup Credits Credits
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. define('BX_CREDITS_TRANSFER_TYPE_PURCHASE', 'purchase');
  12. define('BX_CREDITS_TRANSFER_TYPE_CHECKOUT', 'checkout');
  13. define('BX_CREDITS_TRANSFER_TYPE_CANCELLATION', 'cancellation');
  14. define('BX_CREDITS_TRANSFER_TYPE_GRANT', 'grant');
  15. define('BX_CREDITS_TRANSFER_TYPE_SEND', 'send');
  16. define('BX_CREDITS_TRANSFER_TYPE_WITHDRAW', 'withdraw');
  17. define('BX_CREDITS_TRANSFER_TYPE_SERVICE', 'service');
  18. define('BX_CREDITS_DIRECTION_IN', 'in');
  19. define('BX_CREDITS_DIRECTION_OUT', 'out');
  20. define('BX_CREDITS_ORDER_TYPE_SINGLE', 'single'); //--- one-time payment
  21. define('BX_CREDITS_ORDER_TYPE_RECURRING', 'recurring'); //--- recurring payment (subscription)
  22. class BxCreditsModule extends BxBaseModGeneralModule
  23. {
  24. function __construct(&$aModule)
  25. {
  26. parent::__construct($aModule);
  27. }
  28. public function actionGetProfiles()
  29. {
  30. $sTerm = bx_get('term');
  31. $a = BxDolService::call('system', 'profiles_search', array($sTerm), 'TemplServiceProfiles');
  32. echoJson($a);
  33. }
  34. public function actionCheckBundleName()
  35. {
  36. $CNF = &$this->_oConfig->CNF;
  37. $sName = bx_process_input(bx_get('name'));
  38. if(empty($sName))
  39. return echoJson(array());
  40. $sResult = '';
  41. $iId = (int)bx_get('id');
  42. if(!empty($iId)) {
  43. $aBundle = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iId));
  44. if(strcmp($sName, $aBundle[$CNF['FIELD_NAME']]) == 0)
  45. $sResult = $sName;
  46. }
  47. echoJson(array(
  48. 'name' => !empty($sResult) ? $sResult : $this->_oConfig->getBundleName($sName)
  49. ));
  50. }
  51. public function actionCheckout()
  52. {
  53. $iBuyerId = bx_get_logged_profile_id();
  54. if(!$iBuyerId)
  55. return echoJson(['code' => 1, 'msg' => _t('_bx_credits_err_unknown_buyer')]);
  56. $aData = $this->_oConfig->getCheckoutData();
  57. if(empty($aData) || !is_array($aData))
  58. return echoJson(['code' => 2, 'msg' => _t('_bx_credits_err_incorrect_data')]);
  59. $fConversion = $this->_oConfig->getConversionRateUse();
  60. $iPrecision = $this->_oConfig->getPrecision();
  61. $iSellerId = (int)$aData['seller'];
  62. $fAmount = (float)$aData['amount'];
  63. $aCustomData = $this->_oConfig->deconstructCheckoutCustomData($aData['custom']);
  64. $aPpOrders = BxDolPayments::getInstance()->getPendingOrdersInfo(['id' => (int)$aCustomData[1]]);
  65. if(!empty($aPpOrders) && is_array($aPpOrders)) {
  66. $aPpOrder = reset($aPpOrders);
  67. if(!empty($aPpOrder) && is_array($aPpOrder) && ((int)$aPpOrder['seller_id'] != $iSellerId || $this->_oConfig->convertM2C((float)$aPpOrder['amount'], $fConversion, $iPrecision) != $fAmount))
  68. return echoJson(['code' => 3, 'msg' => _t('_bx_credits_err_incorrect_data')]);
  69. }
  70. $fBalance = (float)$this->_oDb->getProfile(['type' => 'balance', 'id' => $iBuyerId]);
  71. if($fAmount > $fBalance)
  72. return echoJson(['code' => 4, 'msg' => _t('_bx_credits_err_low_balance')]);
  73. $sOrder = $this->_oConfig->getOrder();
  74. $sInfo = '_bx_credits_txt_history_info_checkout';
  75. $sData = serialize([
  76. 'conversion' => $fConversion,
  77. 'precision' => $iPrecision
  78. ]);
  79. $this->updateProfileBalance($iBuyerId, $iSellerId, -$fAmount, BX_CREDITS_TRANSFER_TYPE_CHECKOUT, $sOrder, $sInfo, $sData);
  80. $this->updateProfileBalance($iSellerId, $iBuyerId, $fAmount, BX_CREDITS_TRANSFER_TYPE_CHECKOUT, $sOrder, $sInfo, $sData);
  81. bx_alert($this->getName(), 'checkout', 0, false, [
  82. 'seller' => $iSellerId,
  83. 'buyer' => $iBuyerId,
  84. 'amount' => $fAmount,
  85. 'order' => $sOrder
  86. ]);
  87. return echoJson([
  88. 'code' => 0,
  89. 'redirect' => bx_append_url_params($aData['return_data_url'], ['o' => $sOrder, 'c' => $aData['custom']])
  90. ]);
  91. }
  92. public function actionSubscribe()
  93. {
  94. $iBuyerId = bx_get_logged_profile_id();
  95. if(!$iBuyerId)
  96. return echoJson(array('code' => 1, 'msg' => _t('_bx_credits_err_unknown_buyer')));
  97. $aData = $this->_oConfig->getCheckoutData();
  98. if(empty($aData) || !is_array($aData))
  99. return echoJson(array('code' => 2, 'msg' => _t('_bx_credits_err_incorrect_data')));
  100. $iSellerId = (int)$aData['seller'];
  101. $fAmount = (float)$aData['amount'];
  102. $fBalance = (float)$this->_oDb->getProfile(array('type' => 'balance', 'id' => $iBuyerId));
  103. if($fAmount > $fBalance)
  104. return echoJson(array('code' => 3, 'msg' => _t('_bx_credits_err_low_balance')));
  105. $sUnique = $this->_oConfig->getOrder(9);
  106. $sCustomer = 'bx_cus_' . $sUnique;
  107. $sSubscription = 'bx_sub_' . $sUnique;
  108. bx_alert($this->getName(), 'subscribe', 0, false, array(
  109. 'seller' => $iSellerId,
  110. 'buyer' => $iBuyerId,
  111. 'amount' => $fAmount,
  112. 'trial' => $aData['trial'],
  113. 'customer' => $sCustomer,
  114. 'subscription' => $sSubscription
  115. ));
  116. return echoJson(array(
  117. 'code' => 0,
  118. 'redirect' => bx_append_url_params($aData['return_data_url'], array(
  119. 'cs' => $sCustomer,
  120. 'sb' => $sSubscription,
  121. 'tr' => $aData['trial'],
  122. 'c' => $aData['custom']
  123. ))
  124. ));
  125. }
  126. public function serviceGetSafeServices()
  127. {
  128. return array (
  129. 'GetBlockBundles' => '',
  130. 'GetBlockOrders' => '',
  131. 'GetBlockHistory' => '',
  132. );
  133. }
  134. public function serviceGetCheckoutUrl()
  135. {
  136. return $this->_oConfig->getCheckoutUrl();
  137. }
  138. public function serviceValidateCheckout($iSeller, $iBuyer, $fAmount, $sOrder)
  139. {
  140. $fAmount = (float)$fAmount;
  141. $aOut = $this->_oDb->getHistory(array('type' => 'row_by', 'by' => array('first_pid' => $iBuyer, 'direction' => BX_CREDITS_DIRECTION_OUT, 'order' => $sOrder)));
  142. if(empty($aOut) || !is_array($aOut) || (int)$aOut['second_pid'] != (int)$iSeller)
  143. return false;
  144. $aDataOut = unserialize($aOut['data']);
  145. if($this->_oConfig->convertM2C($fAmount, $aDataOut['conversion'], $aDataOut['precision']) != (float)$aOut['amount'])
  146. return false;
  147. $aIn = $this->_oDb->getHistory(array('type' => 'row_by', 'by' => array('first_pid' => $iSeller, 'direction' => BX_CREDITS_DIRECTION_IN, 'order' => $sOrder)));
  148. if(empty($aIn) || !is_array($aIn) || (int)$aIn['second_pid'] != (int)$iBuyer)
  149. return false;
  150. $aDataIn = unserialize($aIn['data']);
  151. if($this->_oConfig->convertM2C($fAmount, $aDataIn['conversion'], $aDataIn['precision']) != (float)$aIn['amount'])
  152. return false;
  153. return true;
  154. }
  155. public function serviceGetBlockCheckout()
  156. {
  157. $oBuyer = BxDolProfile::getInstance();
  158. if(!$oBuyer)
  159. return MsgBox(_t('_bx_credits_err_unknown_buyer'));
  160. $iSeller = (int)bx_get('seller');
  161. $oSeller = BxDolProfile::getInstance($iSeller);
  162. if(!$oSeller)
  163. return MsgBox(_t('_bx_credits_err_unknown_seller'));
  164. $fAmountM = (float)bx_get('amount');
  165. $fAmountC = $this->_oConfig->convertM2C($fAmountM);
  166. $aData = array(
  167. 'seller' => $iSeller,
  168. 'currency' => array(
  169. 'code' => bx_process_input(bx_get('currency_code')),
  170. 'sign' => bx_process_input(bx_get('currency_sign')),
  171. ),
  172. 'amountm' => $fAmountM,
  173. 'amountc' => $fAmountC
  174. );
  175. $iItemsCount = (int)bx_get('items_count');
  176. for($i = 0; $i < $iItemsCount; $i++) {
  177. $aData['items'][] = array(
  178. 'title' => bx_process_input(bx_get('item_title_' . $i)),
  179. 'quantity' => (int)bx_get('item_quantity_' . $i)
  180. );
  181. }
  182. $this->_oConfig->setCheckoutData(array(
  183. 'seller' => $iSeller,
  184. 'amount' => $fAmountC,
  185. 'custom' => bx_process_input(bx_get('custom')),
  186. 'return_data_url' => bx_process_input(bx_get('return_data_url')),
  187. ));
  188. return $this->_oTemplate->getBlockCheckout($oBuyer, $oSeller, $aData);
  189. }
  190. public function serviceGetPopupSubscribe($aData)
  191. {
  192. $oBuyer = BxDolProfile::getInstance();
  193. if(!$oBuyer)
  194. return array('msg' => _t('_bx_credits_err_unknown_buyer'));
  195. $iSeller = (int)$aData['seller'];
  196. $oSeller = BxDolProfile::getInstance($iSeller);
  197. if(!$oSeller)
  198. return array('msg' => _t('_bx_credits_err_unknown_seller'));
  199. $fAmountM = (float)$aData['amount'];
  200. $fAmountC = $this->_oConfig->convertM2C($fAmountM);
  201. $aData = array_merge($aData, array(
  202. 'amountm' => $fAmountM,
  203. 'amountc' => $fAmountC
  204. ));
  205. $this->_oConfig->setCheckoutData(array(
  206. 'seller' => $iSeller,
  207. 'amount' => $fAmountC,
  208. 'trial' => (int)$aData['trial'] > 0,
  209. 'custom' => bx_process_input($aData['custom']),
  210. 'return_data_url' => bx_process_input($aData['return_data_url']),
  211. ));
  212. return $this->_oTemplate->getPopupSubscribe($oBuyer, $oSeller, $aData);
  213. }
  214. public function serviceGetMenuItemAddonAmount()
  215. {
  216. $iProfileId = bx_get_logged_profile_id();
  217. if(!$iProfileId)
  218. return '';
  219. return array(
  220. 'unit' => $this->_oTemplate->getUnit(),
  221. 'value' => $this->convertC2S($this->_oDb->getProfile(array('type' => 'balance', 'id' => $iProfileId)), false)
  222. );
  223. }
  224. /**
  225. * @page service Service Calls
  226. * @section bx_credits Credits
  227. * @subsection bx_credits-page_blocks Page Blocks
  228. * @subsubsection bx_credits-get_block_bundles get_block_bundles
  229. *
  230. * @code bx_srv('bx_credits', 'get_block_bundles'); @endcode
  231. *
  232. * Get page block with bundles
  233. *
  234. * @see BxCreditsModule::serviceGetBlockBundles
  235. */
  236. /**
  237. * @ref bx_credits-get_block_bundles "get_block_bundles"
  238. */
  239. public function serviceGetBlockBundles()
  240. {
  241. return $this->_oTemplate->getBlockBundles();
  242. }
  243. /**
  244. * @page service Service Calls
  245. * @section bx_credits Credits
  246. * @subsection bx_credits-page_blocks Page Blocks
  247. * @subsubsection bx_credits-get_block_orders_note get_block_orders_note
  248. *
  249. * @code bx_srv('bx_credits', 'get_block_orders_note', [...]); @endcode
  250. *
  251. * Get page block with a notice for orders usage.
  252. *
  253. * @return HTML string with block content to display on the site.
  254. *
  255. * @see BxCreditsModule::serviceBlockLicensesNote
  256. */
  257. /**
  258. * @ref bx_credits-get_block_orders_note "get_block_orders_note"
  259. */
  260. public function serviceGetBlockOrdersNote()
  261. {
  262. return MsgBox(_t('_bx_credits_page_block_content_orders_common_note'));
  263. }
  264. /**
  265. * @page service Service Calls
  266. * @section bx_credits Credits
  267. * @subsection bx_credits-page_blocks Page Blocks
  268. * @subsubsection bx_credits-block_orders get_block_orders
  269. *
  270. * @code bx_srv('bx_credits', 'get_block_orders', [...]); @endcode
  271. *
  272. * Get page block with a list of orders purchased by currently logged member.
  273. *
  274. * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  275. *
  276. * @see BxCreditsModule::serviceBlockLicenses
  277. */
  278. /**
  279. * @ref bx_credits-get_block_orders "get_block_orders"
  280. */
  281. public function serviceGetBlockOrders($sType = 'common')
  282. {
  283. return $this->_getBlockOrders($sType);
  284. }
  285. /**
  286. * @page service Service Calls
  287. * @section bx_credits Credits
  288. * @subsection bx_credits-page_blocks Page Blocks
  289. * @subsubsection bx_credits-get_block_history get_block_history
  290. *
  291. * @code bx_srv('bx_credits', 'get_block_history', [...]); @endcode
  292. *
  293. * Get page block with a list of all changes with credits.
  294. *
  295. * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
  296. *
  297. * @see BxCreditsModule::serviceGetBlockHistory
  298. */
  299. /**
  300. * @ref bx_credits-get_block_history "get_block_history"
  301. */
  302. public function serviceGetBlockHistory($sType = 'common')
  303. {
  304. return $this->_getBlockHistory($sType);
  305. }
  306. /**
  307. * @page service Service Calls
  308. * @section bx_credits Credits
  309. * @subsection bx_credits-payments Payments
  310. * @subsubsection bx_credits-get_payment_data get_payment_data
  311. *
  312. * @code bx_srv('bx_credits', 'get_payment_data', [...]); @endcode
  313. *
  314. * Get an array with module's description. Is needed for payments processing module.
  315. *
  316. * @return an array with module's description.
  317. *
  318. * @see BxCreditsModule::serviceGetPaymentData
  319. */
  320. /**
  321. * @ref bx_credits-get_payment_data "get_payment_data"
  322. */
  323. public function serviceGetPaymentData()
  324. {
  325. $CNF = &$this->_oConfig->CNF;
  326. $oPermalink = BxDolPermalinks::getInstance();
  327. $aResult = $this->_aModule;
  328. $aResult['url_browse_order_common'] = bx_absolute_url($oPermalink->permalink($CNF['URL_ORDERS_COMMON'], array('filter' => '{order}')));
  329. $aResult['url_browse_order_administration'] = bx_absolute_url($oPermalink->permalink($CNF['URL_ORDERS_ADMINISTRATION'], array('filter' => '{order}')));
  330. return $aResult;
  331. }
  332. /**
  333. * @page service Service Calls
  334. * @section bx_credits Credits
  335. * @subsection bx_credits-payments Payments
  336. * @subsubsection bx_credits-get_cart_item get_cart_item
  337. *
  338. * @code bx_srv('bx_credits', 'get_cart_item', [...]); @endcode
  339. *
  340. * Get an array with prodict's description. Is used in Shopping Cart in payments processing module.
  341. *
  342. * @param $iItemId product's ID.
  343. * @return an array with prodict's description. Empty array is returned if something is wrong.
  344. *
  345. * @see BxCreditsModule::serviceGetCartItem
  346. */
  347. /**
  348. * @ref bx_credits-get_cart_item "get_cart_item"
  349. */
  350. public function serviceGetCartItem($iItemId)
  351. {
  352. $CNF = &$this->_oConfig->CNF;
  353. if(!$iItemId)
  354. return array();
  355. $aItem = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iItemId));
  356. if(empty($aItem) || !is_array($aItem))
  357. return array();
  358. return array (
  359. 'id' => $aItem[$CNF['FIELD_ID']],
  360. 'author_id' => $this->_oConfig->getAuthor(),
  361. 'name' => $aItem[$CNF['FIELD_NAME']],
  362. 'title' => _t($aItem[$CNF['FIELD_TITLE']]),
  363. 'description' => $this->_oConfig->getBundleDescription($aItem),
  364. 'url' => $this->_oConfig->getBundleUrl($aItem),
  365. 'price_single' => $aItem[$CNF['FIELD_PRICE']],
  366. 'price_recurring' => '',
  367. 'period_recurring' => 1,
  368. 'period_unit_recurring' => '',
  369. 'trial_recurring' => ''
  370. );
  371. }
  372. /**
  373. * @page service Service Calls
  374. * @section bx_credits Credits
  375. * @subsection bx_credits-payments Payments
  376. * @subsubsection bx_credits-get_cart_items get_cart_items
  377. *
  378. * @code bx_srv('bx_credits', 'get_cart_items', [...]); @endcode
  379. *
  380. * Get an array with prodicts' descriptions by seller. Is used in Manual Order Processing in payments processing module.
  381. *
  382. * @param $iSellerId seller ID.
  383. * @return an array with prodicts' descriptions. Empty array is returned if something is wrong or seller doesn't have any products.
  384. *
  385. * @see BxCreditsModule::serviceGetCartItems
  386. */
  387. /**
  388. * @ref bx_credits-get_cart_items "get_cart_items"
  389. */
  390. public function serviceGetCartItems($iSellerId)
  391. {
  392. $CNF = &$this->_oConfig->CNF;
  393. $iAuthorId = $this->_oConfig->getAuthor();
  394. if($iSellerId != $iAuthorId && !BxDolAcl::getInstance()->isMemberLevelInSet([MEMBERSHIP_ID_ADMINISTRATOR], $iSellerId))
  395. return array();
  396. $aItems = $this->_oDb->getBundle(array('type' => 'all', 'active' => 1));
  397. $aResult = array();
  398. foreach($aItems as $aItem)
  399. $aResult[] = array(
  400. 'id' => $aItem[$CNF['FIELD_ID']],
  401. 'author_id' => $iAuthorId,
  402. 'name' => $aItem[$CNF['FIELD_NAME']],
  403. 'title' => _t($aItem[$CNF['FIELD_TITLE']]),
  404. 'description' => $this->_oConfig->getBundleDescription($aItem),
  405. 'url' => $this->_oConfig->getBundleUrl($aItem),
  406. 'price_single' => $aItem[$CNF['FIELD_PRICE']],
  407. 'price_recurring' => '',
  408. 'period_recurring' => 1,
  409. 'period_unit_recurring' => '',
  410. 'trial_recurring' => ''
  411. );
  412. return $aResult;
  413. }
  414. /**
  415. * @page service Service Calls
  416. * @section bx_credits Credits
  417. * @subsection bx_credits-payments Payments
  418. * @subsubsection bx_credits-register_cart_item register_cart_item
  419. *
  420. * @code bx_srv('bx_credits', 'register_cart_item', [...]); @endcode
  421. *
  422. * Register a processed single time payment inside the Credits module. Is called with payment processing module after the payment was registered there.
  423. *
  424. * @param $iClientId client ID.
  425. * @param $iSellerId seller ID
  426. * @param $iItemId item ID.
  427. * @param $iItemCount the number of purchased items.
  428. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  429. * @param $sLicense license number genereted with payment processing module for internal usage
  430. * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
  431. *
  432. * @see BxCreditsModule::serviceRegisterCartItem
  433. */
  434. /**
  435. * @ref bx_credits-register_cart_item "register_cart_item"
  436. */
  437. public function serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
  438. {
  439. return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_SINGLE);
  440. }
  441. /**
  442. * @page service Service Calls
  443. * @section bx_credits Credits
  444. * @subsection bx_credits-payments Payments
  445. * @subsubsection bx_credits-register_subscription_item register_subscription_item
  446. *
  447. * @code bx_srv('bx_credits', 'register_subscription_item', [...]); @endcode
  448. *
  449. * Register a processed subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was registered there.
  450. *
  451. * @param $iClientId client ID.
  452. * @param $iSellerId seller ID
  453. * @param $iItemId item ID.
  454. * @param $iItemCount the number of purchased items.
  455. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  456. * @param $sLicense license number genereted with payment processing module for internal usage
  457. * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
  458. *
  459. * @see BxCreditsModule::serviceRegisterSubscriptionItem
  460. */
  461. /**
  462. * @ref bx_credits-register_subscription_item "register_subscription_item"
  463. */
  464. public function serviceRegisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
  465. {
  466. return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_RECURRING);
  467. }
  468. /**
  469. * @page service Service Calls
  470. * @section bx_credits Credits
  471. * @subsection bx_credits-payments Payments
  472. * @subsubsection bx_credits-reregister_cart_item reregister_cart_item
  473. *
  474. * @code bx_srv('bx_credits', 'reregister_cart_item', [...]); @endcode
  475. *
  476. * Reregister a single time payment inside the Credits module. Is called with payment processing module after the payment was reregistered there.
  477. *
  478. * @param $iClientId client ID.
  479. * @param $iSellerId seller ID
  480. * @param $iItemIdOld old item ID.
  481. * @param $iItemIdNew new item ID.
  482. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  483. * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
  484. *
  485. * @see BxCreditsModule::serviceReregisterCartItem
  486. */
  487. /**
  488. * @ref bx_credits-reregister_cart_item "reregister_cart_item"
  489. */
  490. public function serviceReregisterCartItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
  491. {
  492. return array();
  493. }
  494. /**
  495. * @page service Service Calls
  496. * @section bx_credits Credits
  497. * @subsection bx_credits-payments Payments
  498. * @subsubsection bx_credits-reregister_subscription_item reregister_subscription_item
  499. *
  500. * @code bx_srv('bx_credits', 'reregister_subscription_item', [...]); @endcode
  501. *
  502. * Reregister a subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was reregistered there.
  503. *
  504. * @param $iClientId client ID.
  505. * @param $iSellerId seller ID
  506. * @param $iItemIdOld old item ID.
  507. * @param $iItemIdNew new item ID.
  508. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  509. * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
  510. *
  511. * @see BxCreditsModule::serviceReregisterSubscriptionItem
  512. */
  513. /**
  514. * @ref bx_credits-reregister_subscription_item "reregister_subscription_item"
  515. */
  516. public function serviceReregisterSubscriptionItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
  517. {
  518. return array();
  519. }
  520. /**
  521. * @page service Service Calls
  522. * @section bx_credits Credits
  523. * @subsection bx_credits-payments Payments
  524. * @subsubsection bx_credits-unregister_cart_item unregister_cart_item
  525. *
  526. * @code bx_srv('bx_credits', 'unregister_cart_item', [...]); @endcode
  527. *
  528. * Unregister an earlier processed single time payment inside the Credits module. Is called with payment processing module after the payment was unregistered there.
  529. *
  530. * @param $iClientId client ID.
  531. * @param $iSellerId seller ID
  532. * @param $iItemId item ID.
  533. * @param $iItemCount the number of purchased items.
  534. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  535. * @param $sLicense license number genereted with payment processing module for internal usage
  536. * @return boolean value determining where the payment was unregistered or not.
  537. *
  538. * @see BxCreditsModule::serviceUnregisterCartItem
  539. */
  540. /**
  541. * @ref bx_credits-unregister_cart_item "unregister_cart_item"
  542. */
  543. public function serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
  544. {
  545. return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_SINGLE);
  546. }
  547. /**
  548. * @page service Service Calls
  549. * @section bx_credits Credits
  550. * @subsection bx_credits-payments Payments
  551. * @subsubsection bx_credits-unregister_subscription_item unregister_subscription_item
  552. *
  553. * @code bx_srv('bx_credits', 'unregister_subscription_item', [...]); @endcode
  554. *
  555. * Unregister an earlier processed subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was unregistered there.
  556. *
  557. * @param $iClientId client ID.
  558. * @param $iSellerId seller ID
  559. * @param $iItemId item ID.
  560. * @param $iItemCount the number of purchased items.
  561. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  562. * @param $sLicense license number genereted with payment processing module for internal usage
  563. * @return boolean value determining where the subscription was unregistered or not.
  564. *
  565. * @see BxCreditsModule::serviceUnregisterSubscriptionItem
  566. */
  567. /**
  568. * @ref bx_credits-unregister_subscription_item "unregister_subscription_item"
  569. */
  570. public function serviceUnregisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
  571. {
  572. return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_RECURRING);
  573. }
  574. /**
  575. * @page service Service Calls
  576. * @section bx_credits Credits
  577. * @subsection bx_credits-payments Payments
  578. * @subsubsection bx_credits-cancel_subscription_item cancel_subscription_item
  579. *
  580. * @code bx_srv('bx_credits', 'cancel_subscription_item', [...]); @endcode
  581. *
  582. * Cancel an earlier processed subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was canceled there.
  583. *
  584. * @param $iClientId client ID.
  585. * @param $iSellerId seller ID
  586. * @param $iItemId item ID.
  587. * @param $iItemCount the number of purchased items.
  588. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  589. * @return boolean value determining where the subscription was canceled or not.
  590. *
  591. * @see BxCreditsModule::serviceCancelSubscriptionItem
  592. */
  593. /**
  594. * @ref bx_credits-cancel_subscription_item "cancel_subscription_item"
  595. */
  596. public function serviceCancelSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
  597. {
  598. return true;
  599. }
  600. public function serviceGetProfileBalance($iProfileId = 0)
  601. {
  602. return $this->getProfileBalance($iProfileId);
  603. }
  604. public function serviceUpdateProfileBalance($iFirstPid, $fAmount, $iSecondPid = 0, $sOrder = '', $sInfo = '')
  605. {
  606. if(empty($sInfo))
  607. $sInfo = '_bx_credits_txt_history_info_service';
  608. return $this->updateProfileBalance($iFirstPid, $iSecondPid, $fAmount, BX_CREDITS_TRANSFER_TYPE_SERVICE, $sOrder, $sInfo);
  609. }
  610. public function serviceMakePayment($iBuyerPid, $fAmount, $iSellerPid, $sOrder = '')
  611. {
  612. $sInfo = '_bx_credits_txt_history_info_checkout';
  613. if(!$this->updateProfileBalance($iBuyerPid, $iSellerPid, -$fAmount, BX_CREDITS_TRANSFER_TYPE_CHECKOUT, $sOrder, $sInfo))
  614. return false;
  615. if(!$this->updateProfileBalance($iSellerPid, $iBuyerPid, $fAmount, $sOrder, BX_CREDITS_TRANSFER_TYPE_CHECKOUT, $sInfo)) {
  616. $this->updateProfileBalance($iBuyerPid, 0, $fAmount, BX_CREDITS_TRANSFER_TYPE_CANCELLATION, $sOrder, '_bx_credits_txt_history_info_cancellation');
  617. return false;
  618. }
  619. return true;
  620. }
  621. /**
  622. * Delete all content by profile
  623. * @param $iProfileId profile id
  624. * @return number of deleted items
  625. */
  626. public function serviceDeleteEntitiesByAuthor ($iProfileId)
  627. {
  628. $this->_oDb->deleteProfile(array('id' => $iProfileId));
  629. $this->_oDb->deleteHistory(array('first_pid' => $iProfileId));
  630. }
  631. /*
  632. * Common methods
  633. */
  634. public function convertC2S($fCredits, $bWithUnit = true)
  635. {
  636. $sResult = '';
  637. if($bWithUnit)
  638. $sResult .= $this->_oTemplate->getUnit();
  639. $iPrecision = $this->_oConfig->getPrecision();
  640. $sResult .= sprintf("%01." . $iPrecision . "f", round((float)$fCredits, $iPrecision));
  641. return $sResult;
  642. }
  643. public function getProfileBalance($iProfileId = 0)
  644. {
  645. if(empty($iProfileId))
  646. $iProfileId = bx_get_logged_profile_id();
  647. if(empty($iProfileId))
  648. return 0;
  649. return (float)$this->_oDb->getProfile(array('type' => 'balance', 'id' => $iProfileId));
  650. }
  651. public function getProfileBalanceCleared($iProfileId = 0)
  652. {
  653. if(empty($iProfileId))
  654. $iProfileId = bx_get_logged_profile_id();
  655. if(empty($iProfileId))
  656. return 0;
  657. $fCleared = (float)$this->_oDb->getHistory(['type' => 'cleared', 'profile' => $iProfileId]);
  658. $fSpent = (float)$this->_oDb->getHistory(['type' => 'spent', 'profile' => $iProfileId]);
  659. return $fCleared > $fSpent ? $fCleared - $fSpent : 0;
  660. }
  661. public function updateProfileBalance($iFirstPid, $iSecondPid, $fAmount, $sType, $sOrder = '', $sInfo = '', $sData = '')
  662. {
  663. $CNF = &$this->_oConfig->CNF;
  664. if(empty($sOrder))
  665. $sOrder = $this->_oConfig->getOrder();
  666. if(empty($sData))
  667. $sData = serialize(array(
  668. 'conversion' => $this->_oConfig->getConversionRateUse(),
  669. 'precision' => $this->_oConfig->getPrecision()
  670. ));
  671. if(!$this->_oDb->updateProfileBalance($iFirstPid, $fAmount))
  672. return false;
  673. $fAmountAbs = abs($fAmount);
  674. $sDirection = $fAmount > 0 ? BX_CREDITS_DIRECTION_IN : BX_CREDITS_DIRECTION_OUT;
  675. $iHistoryId = $this->_oDb->insertHistory([
  676. 'first_pid' => $iFirstPid,
  677. 'second_pid' => $iSecondPid,
  678. 'amount' => $fAmountAbs,
  679. 'type' => $sType,
  680. 'direction' => $sDirection,
  681. 'order' => $sOrder,
  682. 'data' => $sData,
  683. 'info' => $sInfo,
  684. 'date' => time()
  685. ]);
  686. if(!$iHistoryId)
  687. return false;
  688. bx_alert($this->getName(), 'update_balance', 0, false, array(
  689. 'first_pid' => $iFirstPid,
  690. 'second_pid' => $iSecondPid,
  691. 'amount' => $fAmountAbs,
  692. 'type' => $sType,
  693. 'direction' => $sDirection,
  694. 'order' => $sOrder,
  695. ));
  696. $oSecondProfile = BxDolProfile::getInstanceMagic($iSecondPid);
  697. sendMailTemplate($CNF['ETEMPLATE_' . strtoupper($sDirection)], 0, $iFirstPid, array(
  698. 'second_profile_name' => $oSecondProfile->getDisplayName(),
  699. 'amount' => $fAmountAbs,
  700. ));
  701. return $iHistoryId;
  702. }
  703. public function processGrant($iUserId, $iProfileId, $fAmount, $sMessage = '')
  704. {
  705. $CNF = &$this->_oConfig->CNF;
  706. $oProfile = BxDolProfile::getInstance($iProfileId);
  707. if(!$oProfile)
  708. return ['code' => 2, 'msg' => '_bx_credits_err_profile_not_found'];
  709. $sInfo = '_bx_credits_txt_history_info_grant';
  710. $iHistoryId = $this->updateProfileBalance($iProfileId, 0, $fAmount, BX_CREDITS_TRANSFER_TYPE_GRANT, '', $sInfo);
  711. if(!$iHistoryId)
  712. return ['code' => 3, 'msg' => '_bx_credits_err_cannot_update_balance'];
  713. sendMailTemplate($CNF['ETEMPLATE_GRANTED'], 0, $iProfileId, [
  714. 'amount' => $fAmount,
  715. 'message' => $sMessage
  716. ]);
  717. bx_alert($this->getName(), 'granted', 0, false, [
  718. 'profile' => $iProfileId,
  719. 'amount' => $fAmount,
  720. ]);
  721. return ['code' => 0, 'id' => $iHistoryId];
  722. }
  723. public function processSend($iUserId, $iProfileId, $fAmount, $sMessage = '')
  724. {
  725. $CNF = &$this->_oConfig->CNF;
  726. $fAmountAvail = $this->getProfileBalance($iUserId);
  727. if($fAmount > $fAmountAvail)
  728. return ['code' => 1, 'msg' => '_bx_credits_err_low_balance'];
  729. $oProfile = null;
  730. if(!$iProfileId || !($oProfile = BxDolProfile::getInstance($iProfileId)))
  731. return ['code' => 2, 'msg' => '_bx_credits_err_profile_not_found'];
  732. $sOrder = $this->_oConfig->getOrder();
  733. $sInfo = !empty($sMessage) ? $sMessage : '_bx_credits_txt_history_info_send';
  734. $iHistoryId = $this->updateProfileBalance($iUserId, $iProfileId, -$fAmount, BX_CREDITS_TRANSFER_TYPE_SEND, $sOrder, $sInfo);
  735. if(!$iHistoryId)
  736. return ['code' => 3, 'msg' => '_bx_credits_err_cannot_update_balance'];
  737. if(!$this->updateProfileBalance($iProfileId, $iUserId, $fAmount, BX_CREDITS_TRANSFER_TYPE_SEND, $sOrder, $sInfo)) {
  738. $sInfo = '_bx_credits_txt_history_info_cancellation';
  739. $iHistoryId = $this->updateProfileBalance($iUserId, 0, $fAmount, BX_CREDITS_TRANSFER_TYPE_CANCELLATION, $sOrder, $sInfo);
  740. return ['code' => 3, 'id' => $iHistoryId, 'msg' => '_bx_credits_err_cannot_update_balance'];
  741. }
  742. $oUser = BxDolProfile::getInstance($iUserId);
  743. sendMailTemplate($CNF['ETEMPLATE_RECEIVED'], 0, $iProfileId, [
  744. 'performer_id' => $iUserId,
  745. 'performer_name' => $oUser->getDisplayName(),
  746. 'performer_link' => $oUser->getUrl(),
  747. 'amount' => $fAmount,
  748. 'order' => $sOrder,
  749. 'message' => $sMessage
  750. ]);
  751. bx_alert($this->getName(), 'sent', 0, $iUserId, [
  752. 'performer' => $iUserId,
  753. 'profile' => $iProfileId,
  754. 'amount' => $fAmount,
  755. 'order' => $sOrder,
  756. ]);
  757. return ['code' => 0, 'id' => $iHistoryId];
  758. }
  759. public function processWithdrawRequest($iUserId, $iProfileId, $fAmount, $sMessage = '')
  760. {
  761. $CNF = &$this->_oConfig->CNF;
  762. if(empty($iProfileId))
  763. $iProfileId = bx_get_logged_profile_id ();
  764. if(empty($iProfileId))
  765. return ['code' => 1, 'msg' => '_bx_credits_err_login_required'];
  766. $oProfile = BxDolProfile::getInstance($iProfileId);
  767. if(!$oProfile)
  768. return ['code' => 1, 'msg' => '_bx_credits_err_login_required'];
  769. $fBalanceCleared = $this->getProfileBalanceCleared($iProfileId);
  770. if($fAmount > $fBalanceCleared)
  771. return ['code' => 2, 'msg' => '_bx_credits_err_low_balance'];
  772. if($fAmount < ($iWithdrawMinimum = (int)getParam($CNF['PARAM_WITHDRAW_MINIMUM'])))
  773. return ['code' => 3, 'msg' => _t('_bx_credits_err_withdraw_minimum', $iWithdrawMinimum)];
  774. $fBalance = $this->getProfileBalance($iProfileId);
  775. if(($fBalance - $fAmount) < ($iWithdrawRemaining = (int)getParam($CNF['PARAM_WITHDRAW_REMAINING'])))
  776. return ['code' => 4, 'msg' => _t('_bx_credits_err_withdraw_remaining', $iWithdrawRemaining)];
  777. $aResult = ['code' => 5, 'msg' => '_bx_credits_err_cannot_send'];
  778. $fRate = $this->_oConfig->getConversionRateWithdraw();
  779. $aTemplateVars = [
  780. 'profile_link' => $oProfile->getUrl(),
  781. 'profile_name' => $oProfile->getDisplayName(),
  782. 'amount' => $fAmount,
  783. 'rate' => $fRate,
  784. 'message' => $sMessage,
  785. 'confirm_url' => bx_absolute_url(BxDolPermalinks::getInstance()->permalink($CNF['URL_HISTORY_ADMINISTRATION']))
  786. ];
  787. $aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate($CNF['ETEMPLATE_WITHDRAW_REQUESTED'], $aTemplateVars);
  788. if(!$aTemplate)
  789. return $aResult;
  790. $sEmail = $this->_oConfig->getWithdrawEmail();
  791. if(!sendMail($sEmail, $aTemplate['Subject'], $aTemplate['Body'], 0, [], BX_EMAIL_SYSTEM, 'html', false, [], true))
  792. return $aResult;
  793. bx_alert($this->getName(), 'withdraw_requested', 0, $iProfileId, [
  794. 'profile' => $iProfileId,
  795. 'amount' => $fAmount,
  796. 'rate' => $fRate
  797. ]);
  798. return ['code' => 0];
  799. }
  800. public function processWithdrawConfirm($iUserId, $iProfileId, $fAmount, $sMessage = '')
  801. {
  802. $CNF = &$this->_oConfig->CNF;
  803. $oProfile = BxDolProfile::getInstance($iProfileId);
  804. if(!$oProfile)
  805. return ['code' => 1, 'msg' => '_bx_credits_err_profile_not_found'];
  806. $fBalance = $this->getProfileBalance($iProfileId);
  807. if($fAmount > $fBalance)
  808. return ['code' => 2, 'msg' => '_bx_credits_err_low_balance'];
  809. $sInfo = '_bx_credits_txt_history_info_withdraw';
  810. $iHistoryId = $this->updateProfileBalance($iProfileId, 0, -$fAmount, BX_CREDITS_TRANSFER_TYPE_WITHDRAW, '', $sInfo);
  811. if(!$iHistoryId)
  812. return ['code' => 3, 'msg' => '_bx_credits_err_cannot_update_balance'];
  813. sendMailTemplate($CNF['ETEMPLATE_WITHDRAW_SENT'], 0, $iProfileId, [
  814. 'amount' => $fAmount,
  815. 'message' => $sMessage
  816. ]);
  817. bx_alert($this->getName(), 'withdraw_sent', 0, $iUserId, [
  818. 'performer' => $iUserId,
  819. 'profile' => $iProfileId,
  820. 'amount' => $fAmount,
  821. ]);
  822. return ['code' => 0, 'id' => $iHistoryId];
  823. }
  824. public function processClearing()
  825. {
  826. $CNF = &$this->_oConfig->CNF;
  827. $aItems = $this->_oDb->getHistory(['type' => 'clearing', 'clearing' => $this->_oConfig->getWithdrawClearing()]);
  828. if(empty($aItems) || !is_array($aItems))
  829. return;
  830. $iNow = time();
  831. foreach($aItems as $aItem) {
  832. $this->_oDb->updateHistory([$CNF['FIELD_H_CLEARED'] => $iNow], [$CNF['FIELD_H_ID'] => $aItem['id']]);
  833. //TODO: Some action(s) related to clearing can be performed here.
  834. }
  835. }
  836. /*
  837. * Internal methods
  838. */
  839. protected function _serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
  840. {
  841. $CNF = &$this->_oConfig->CNF;
  842. $aItem = $this->serviceGetCartItem($iItemId);
  843. if(empty($aItem) || !is_array($aItem))
  844. return array();
  845. $aBundle = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iItemId));
  846. if(empty($aBundle) || !is_array($aBundle))
  847. return array();
  848. $iTrial = 0;
  849. $sDuration = '';
  850. $sAction = 'register';
  851. if($sType == BX_CREDITS_ORDER_TYPE_RECURRING && isset($CNF['FIELD_DURATION_RECURRING'], $CNF['FIELD_TRIAL_RECURRING'])) {
  852. $iTrial = $aBundle[$CNF['FIELD_TRIAL_RECURRING']];
  853. $sDuration = $aBundle[$CNF['FIELD_DURATION_RECURRING']];
  854. if($this->_oDb->isOrderByPbo($iClientId, $iItemId, $sOrder))
  855. $sAction = 'prolong';
  856. }
  857. if(!$this->_oDb->{$sAction . 'Order'}($iClientId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType, $sDuration, $iTrial))
  858. return array();
  859. $sInfo = '_bx_credits_txt_history_info_purchase';
  860. $fAmount = ((float)$aBundle[$CNF['FIELD_AMOUNT']] + (float)$aBundle[$CNF['FIELD_BONUS']]) * $iItemCount;
  861. if(!$this->updateProfileBalance($iClientId, 0, $fAmount, BX_CREDITS_TRANSFER_TYPE_PURCHASE, '', $sInfo))
  862. return array();
  863. bx_alert($this->getName(), 'order_' . $sAction, 0, false, array(
  864. 'profile_id' => $iClientId,
  865. 'bundle_id' => $iItemId,
  866. 'product_id' => $iItemId, //--- Alias for 'bundle_id'
  867. 'count' => $iItemCount,
  868. 'order' => $sOrder,
  869. 'license' => $sLicense,
  870. 'type' => $sType,
  871. 'duration' => $sDuration,
  872. 'trial' => $iTrial
  873. ));
  874. $oClient = BxDolProfile::getInstanceMagic($iClientId);
  875. $oSeller = BxDolProfile::getInstanceMagic($iSellerId);
  876. $sSellerUrl = $oSeller->getUrl();
  877. $sSellerName = $oSeller->getDisplayName();
  878. sendMailTemplate($CNF['ETEMPLATE_PURCHASED'], 0, $iClientId, array(
  879. 'client_name' => $oClient->getDisplayName(),
  880. 'bundle_name' => $aBundle[$CNF['FIELD_NAME']],
  881. 'bundle_title' => _t($aBundle[$CNF['FIELD_TITLE']]),
  882. 'bundle_url' => $this->_oConfig->getBundleUrl($aBundle),
  883. 'vendor_url' => $sSellerUrl,
  884. 'vendor_name' => $sSellerName,
  885. 'order' => $sOrder,
  886. 'license' => $sLicense,
  887. 'notes' => _t('_bx_credits_txt_purchased_note', $sSellerUrl, $sSellerName),
  888. ));
  889. return $aItem;
  890. }
  891. protected function _serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
  892. {
  893. $CNF = &$this->_oConfig->CNF;
  894. $aBundle = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iItemId));
  895. if(empty($aBundle) || !is_array($aBundle))
  896. return false;
  897. if(!$this->_oDb->unregisterOrder($iClientId, $iItemId, $sOrder, $sLicense, $sType))
  898. return false;
  899. $fAmount = (float)$aBundle[$CNF['FIELD_AMOUNT']] + (float)$aBundle[$CNF['FIELD_BONUS']];
  900. $aProfile = $this->_oDb->getProfile(array('type' => 'id', 'id' => $iClientId));
  901. if(!empty($aProfile) && is_array($aProfile))
  902. $this->_oDb->updateProfile(array('balance' => (float)$aProfile['balance'] - $fAmount), array('id' => $aProfile['id']));
  903. bx_alert($this->getName(), 'order_unregister', 0, false, array(
  904. 'profile_id' => $iClientId,
  905. 'bundle_id' => $iItemId,
  906. 'product_id' => $iItemId, //--- Alias for 'bundle_id'
  907. 'count' => $iItemCount,
  908. 'order' => $sOrder,
  909. 'license' => $sLicense,
  910. 'type' => $sType,
  911. ));
  912. return true;
  913. }
  914. protected function _getBlockOrders($sType)
  915. {
  916. $CNF = &$this->_oConfig->CNF;
  917. $sGrid = $CNF['OBJECT_GRID_ORDERS_' . strtoupper($sType)];
  918. $oGrid = BxDolGrid::getObjectInstance($sGrid);
  919. if(!$oGrid)
  920. return '';
  921. return array(
  922. 'content' => $oGrid->getCode(),
  923. 'menu' => $CNF['OBJECT_MENU_MANAGE_SUBMENU']
  924. );
  925. }
  926. protected function _getBlockHistory($sType)
  927. {
  928. $CNF = &$this->_oConfig->CNF;
  929. $sGrid = $CNF['OBJECT_GRID_HISTORY_' . strtoupper($sType)];
  930. $oGrid = BxDolGrid::getObjectInstance($sGrid);
  931. if(!$oGrid)
  932. return '';
  933. return array(
  934. 'content' => $oGrid->getCode(),
  935. 'menu' => $CNF['OBJECT_MENU_MANAGE_SUBMENU']
  936. );
  937. }
  938. }
  939. /** @} */