BxCreditsModule.php 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  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_DIRECTION_IN', 'in');
  12. define('BX_CREDITS_DIRECTION_OUT', 'out');
  13. define('BX_CREDITS_ORDER_TYPE_SINGLE', 'single'); //--- one-time payment
  14. define('BX_CREDITS_ORDER_TYPE_RECURRING', 'recurring'); //--- recurring payment (subscription)
  15. class BxCreditsModule extends BxBaseModGeneralModule
  16. {
  17. function __construct(&$aModule)
  18. {
  19. parent::__construct($aModule);
  20. }
  21. public function actionGetProfiles()
  22. {
  23. $sTerm = bx_get('term');
  24. $a = BxDolService::call('system', 'profiles_search', array($sTerm), 'TemplServiceProfiles');
  25. echoJson($a);
  26. }
  27. public function actionCheckout()
  28. {
  29. $iBuyerId = bx_get_logged_profile_id();
  30. if(!$iBuyerId)
  31. return echoJson(array('code' => 1, 'msg' => _t('_bx_credits_err_unknown_buyer')));
  32. $aData = $this->_oConfig->getCheckoutData();
  33. if(empty($aData) || !is_array($aData))
  34. return echoJson(array('code' => 2, 'msg' => _t('_bx_credits_err_incorrect_data')));
  35. $iSellerId = (int)$aData['seller'];
  36. $fAmount = (float)$aData['amount'];
  37. $fBalance = (float)$this->_oDb->getProfile(array('type' => 'balance', 'id' => $iBuyerId));
  38. if($fAmount > $fBalance)
  39. return echoJson(array('code' => 3, 'msg' => _t('_bx_credits_err_low_balance')));
  40. $sOrder = $this->_oConfig->getOrder();
  41. $sInfo = '_bx_credits_txt_history_info_checkout';
  42. $sData = serialize(array(
  43. 'conversion' => $this->_oConfig->getConversionRateUse(),
  44. 'precision' => $this->_oConfig->getPrecision()
  45. ));
  46. $this->updateProfileBalance($iBuyerId, $iSellerId, -$fAmount, $sOrder, $sInfo, $sData);
  47. $this->updateProfileBalance($iSellerId, $iBuyerId, $fAmount, $sOrder, $sInfo, $sData);
  48. bx_alert($this->getName(), 'checkout', 0, false, array(
  49. 'seller' => $iSellerId,
  50. 'buyer' => $iBuyerId,
  51. 'amount' => $fAmount,
  52. 'order' => $sOrder
  53. ));
  54. return echoJson(array(
  55. 'code' => 0,
  56. 'redirect' => bx_append_url_params($aData['return_data_url'], array('o' => $sOrder, 'c' => $aData['custom']))
  57. ));
  58. }
  59. public function serviceGetSafeServices()
  60. {
  61. return array (
  62. 'GetBlockBundles' => '',
  63. 'GetBlockOrders' => '',
  64. 'GetBlockHistory' => '',
  65. );
  66. }
  67. public function serviceGetCheckoutUrl()
  68. {
  69. return $this->_oConfig->getCheckoutUrl();
  70. }
  71. public function serviceValidateCheckout($iSeller, $iBuyer, $fAmount, $sOrder)
  72. {
  73. $fAmount = (float)$fAmount;
  74. $aOut = $this->_oDb->getHistory(array('type' => 'row_by', 'by' => array('first_pid' => $iBuyer, 'direction' => BX_CREDITS_DIRECTION_OUT, 'order' => $sOrder)));
  75. if(empty($aOut) || !is_array($aOut) || (int)$aOut['second_pid'] != (int)$iSeller)
  76. return false;
  77. $aDataOut = unserialize($aOut['data']);
  78. if($this->_oConfig->convertM2C($fAmount, $aDataOut['conversion'], $aDataOut['precision']) != (float)$aOut['amount'])
  79. return false;
  80. $aIn = $this->_oDb->getHistory(array('type' => 'row_by', 'by' => array('first_pid' => $iSeller, 'direction' => BX_CREDITS_DIRECTION_IN, 'order' => $sOrder)));
  81. if(empty($aIn) || !is_array($aIn) || (int)$aIn['second_pid'] != (int)$iBuyer)
  82. return false;
  83. $aDataIn = unserialize($aIn['data']);
  84. if($this->_oConfig->convertM2C($fAmount, $aDataIn['conversion'], $aDataIn['precision']) != (float)$aIn['amount'])
  85. return false;
  86. return true;
  87. }
  88. public function serviceGetBlockCheckout()
  89. {
  90. $oBuyer = BxDolProfile::getInstance();
  91. if(!$oBuyer)
  92. return MsgBox(_t('_bx_credits_err_unknown_buyer'));
  93. $iSeller = (int)bx_get('seller');
  94. $oSeller = BxDolProfile::getInstance($iSeller);
  95. if(!$oSeller)
  96. return MsgBox(_t('_bx_credits_err_unknown_seller'));
  97. $fAmountM = (float)bx_get('amount');
  98. $fAmountC = $this->_oConfig->convertM2C($fAmountM);
  99. $aData = array(
  100. 'seller' => $iSeller,
  101. 'currency' => array(
  102. 'code' => bx_process_input(bx_get('currency_code')),
  103. 'sign' => bx_process_input(bx_get('currency_sign')),
  104. ),
  105. 'amountm' => $fAmountM,
  106. 'amountc' => $fAmountC
  107. );
  108. $iItemsCount = (int)bx_get('items_count');
  109. for($i = 0; $i < $iItemsCount; $i++) {
  110. $aData['items'][] = array(
  111. 'title' => bx_process_input(bx_get('item_title_' . $i)),
  112. 'quantity' => (int)bx_get('item_quantity_' . $i)
  113. );
  114. }
  115. $this->_oConfig->setCheckoutData(array(
  116. 'seller' => $iSeller,
  117. 'amount' => $fAmountC,
  118. 'custom' => bx_process_input(bx_get('custom')),
  119. 'return_data_url' => bx_process_input(bx_get('return_data_url')),
  120. ));
  121. return $this->_oTemplate->getBlockCheckout($oBuyer, $oSeller, $aData);
  122. }
  123. public function serviceGetMenuItemAddonAmount()
  124. {
  125. $iProfileId = bx_get_logged_profile_id();
  126. if(!$iProfileId)
  127. return '';
  128. return array(
  129. 'unit' => $this->_oTemplate->getUnit(),
  130. 'value' => $this->convertC2S($this->_oDb->getProfile(array('type' => 'balance', 'id' => $iProfileId)), false)
  131. );
  132. }
  133. /**
  134. * @page service Service Calls
  135. * @section bx_credits Credits
  136. * @subsection bx_credits-page_blocks Page Blocks
  137. * @subsubsection bx_credits-get_block_bundles get_block_bundles
  138. *
  139. * @code bx_srv('bx_credits', 'get_block_bundles'); @endcode
  140. *
  141. * Get page block with bundles
  142. *
  143. * @see BxCreditsModule::serviceGetBlockBundles
  144. */
  145. /**
  146. * @ref bx_credits-get_block_bundles "get_block_bundles"
  147. */
  148. public function serviceGetBlockBundles()
  149. {
  150. return $this->_oTemplate->getBlockBundles();
  151. }
  152. /**
  153. * @page service Service Calls
  154. * @section bx_credits Credits
  155. * @subsection bx_credits-page_blocks Page Blocks
  156. * @subsubsection bx_credits-get_block_orders_note get_block_orders_note
  157. *
  158. * @code bx_srv('bx_credits', 'get_block_orders_note', [...]); @endcode
  159. *
  160. * Get page block with a notice for orders usage.
  161. *
  162. * @return HTML string with block content to display on the site.
  163. *
  164. * @see BxCreditsModule::serviceBlockLicensesNote
  165. */
  166. /**
  167. * @ref bx_credits-get_block_orders_note "get_block_orders_note"
  168. */
  169. public function serviceGetBlockOrdersNote()
  170. {
  171. return MsgBox(_t('_bx_credits_page_block_content_orders_common_note'));
  172. }
  173. /**
  174. * @page service Service Calls
  175. * @section bx_credits Credits
  176. * @subsection bx_credits-page_blocks Page Blocks
  177. * @subsubsection bx_credits-block_orders get_block_orders
  178. *
  179. * @code bx_srv('bx_credits', 'get_block_orders', [...]); @endcode
  180. *
  181. * Get page block with a list of orders purchased by currently logged member.
  182. *
  183. * @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.
  184. *
  185. * @see BxCreditsModule::serviceBlockLicenses
  186. */
  187. /**
  188. * @ref bx_credits-get_block_orders "get_block_orders"
  189. */
  190. public function serviceGetBlockOrders($sType = 'common')
  191. {
  192. return $this->_getBlockOrders($sType);
  193. }
  194. /**
  195. * @page service Service Calls
  196. * @section bx_credits Credits
  197. * @subsection bx_credits-page_blocks Page Blocks
  198. * @subsubsection bx_credits-get_block_history get_block_history
  199. *
  200. * @code bx_srv('bx_credits', 'get_block_history', [...]); @endcode
  201. *
  202. * Get page block with a list of all changes with credits.
  203. *
  204. * @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.
  205. *
  206. * @see BxCreditsModule::serviceGetBlockHistory
  207. */
  208. /**
  209. * @ref bx_credits-get_block_history "get_block_history"
  210. */
  211. public function serviceGetBlockHistory($sType = 'common')
  212. {
  213. return $this->_getBlockHistory($sType);
  214. }
  215. /**
  216. * @page service Service Calls
  217. * @section bx_credits Credits
  218. * @subsection bx_credits-payments Payments
  219. * @subsubsection bx_credits-get_payment_data get_payment_data
  220. *
  221. * @code bx_srv('bx_credits', 'get_payment_data', [...]); @endcode
  222. *
  223. * Get an array with module's description. Is needed for payments processing module.
  224. *
  225. * @return an array with module's description.
  226. *
  227. * @see BxCreditsModule::serviceGetPaymentData
  228. */
  229. /**
  230. * @ref bx_credits-get_payment_data "get_payment_data"
  231. */
  232. public function serviceGetPaymentData()
  233. {
  234. $CNF = &$this->_oConfig->CNF;
  235. $oPermalink = BxDolPermalinks::getInstance();
  236. $aResult = $this->_aModule;
  237. $aResult['url_browse_order_common'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_ORDERS_COMMON'], array('filter' => '{order}'));
  238. $aResult['url_browse_order_administration'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_ORDERS_ADMINISTRATION'], array('filter' => '{order}'));
  239. return $aResult;
  240. }
  241. /**
  242. * @page service Service Calls
  243. * @section bx_credits Credits
  244. * @subsection bx_credits-payments Payments
  245. * @subsubsection bx_credits-get_cart_item get_cart_item
  246. *
  247. * @code bx_srv('bx_credits', 'get_cart_item', [...]); @endcode
  248. *
  249. * Get an array with prodict's description. Is used in Shopping Cart in payments processing module.
  250. *
  251. * @param $iItemId product's ID.
  252. * @return an array with prodict's description. Empty array is returned if something is wrong.
  253. *
  254. * @see BxCreditsModule::serviceGetCartItem
  255. */
  256. /**
  257. * @ref bx_credits-get_cart_item "get_cart_item"
  258. */
  259. public function serviceGetCartItem($iItemId)
  260. {
  261. $CNF = &$this->_oConfig->CNF;
  262. if(!$iItemId)
  263. return array();
  264. $aItem = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iItemId));
  265. if(empty($aItem) || !is_array($aItem))
  266. return array();
  267. return array (
  268. 'id' => $aItem[$CNF['FIELD_ID']],
  269. 'author_id' => $this->_oConfig->getAuthor(),
  270. 'name' => $aItem[$CNF['FIELD_NAME']],
  271. 'title' => _t($aItem[$CNF['FIELD_TITLE']]),
  272. 'description' => $this->_oConfig->getBundleDescription($aItem),
  273. 'url' => $this->_oConfig->getBundleUrl($aItem),
  274. 'price_single' => $aItem[$CNF['FIELD_PRICE']],
  275. 'price_recurring' => '',
  276. 'period_recurring' => 1,
  277. 'period_unit_recurring' => '',
  278. 'trial_recurring' => ''
  279. );
  280. }
  281. /**
  282. * @page service Service Calls
  283. * @section bx_credits Credits
  284. * @subsection bx_credits-payments Payments
  285. * @subsubsection bx_credits-get_cart_items get_cart_items
  286. *
  287. * @code bx_srv('bx_credits', 'get_cart_items', [...]); @endcode
  288. *
  289. * Get an array with prodicts' descriptions by seller. Is used in Manual Order Processing in payments processing module.
  290. *
  291. * @param $iSellerId seller ID.
  292. * @return an array with prodicts' descriptions. Empty array is returned if something is wrong or seller doesn't have any products.
  293. *
  294. * @see BxCreditsModule::serviceGetCartItems
  295. */
  296. /**
  297. * @ref bx_credits-get_cart_items "get_cart_items"
  298. */
  299. public function serviceGetCartItems($iAuthorId)
  300. {
  301. $CNF = &$this->_oConfig->CNF;
  302. $iAuthorId = $this->_oConfig->getAuthor();
  303. $aItems = $this->_oDb->getBundle(array('type' => 'all', 'active' => 1));
  304. $aResult = array();
  305. foreach($aItems as $aItem)
  306. $aResult[] = array(
  307. 'id' => $aItem[$CNF['FIELD_ID']],
  308. 'author_id' => $iAuthorId,
  309. 'name' => $aItem[$CNF['FIELD_NAME']],
  310. 'title' => _t($aItem[$CNF['FIELD_TITLE']]),
  311. 'description' => $this->_oConfig->getBundleDescription($aItem),
  312. 'url' => $this->_oConfig->getBundleUrl($aItem),
  313. 'price_single' => $aItem[$CNF['FIELD_PRICE']],
  314. 'price_recurring' => '',
  315. 'period_recurring' => 1,
  316. 'period_unit_recurring' => '',
  317. 'trial_recurring' => ''
  318. );
  319. return $aResult;
  320. }
  321. /**
  322. * @page service Service Calls
  323. * @section bx_credits Credits
  324. * @subsection bx_credits-payments Payments
  325. * @subsubsection bx_credits-register_cart_item register_cart_item
  326. *
  327. * @code bx_srv('bx_credits', 'register_cart_item', [...]); @endcode
  328. *
  329. * Register a processed single time payment inside the Credits module. Is called with payment processing module after the payment was registered there.
  330. *
  331. * @param $iClientId client ID.
  332. * @param $iSellerId seller ID
  333. * @param $iItemId item ID.
  334. * @param $iItemCount the number of purchased items.
  335. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  336. * @param $sLicense license number genereted with payment processing module for internal usage
  337. * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
  338. *
  339. * @see BxCreditsModule::serviceRegisterCartItem
  340. */
  341. /**
  342. * @ref bx_credits-register_cart_item "register_cart_item"
  343. */
  344. public function serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
  345. {
  346. return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_SINGLE);
  347. }
  348. /**
  349. * @page service Service Calls
  350. * @section bx_credits Credits
  351. * @subsection bx_credits-payments Payments
  352. * @subsubsection bx_credits-register_subscription_item register_subscription_item
  353. *
  354. * @code bx_srv('bx_credits', 'register_subscription_item', [...]); @endcode
  355. *
  356. * Register a processed subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was registered there.
  357. *
  358. * @param $iClientId client ID.
  359. * @param $iSellerId seller ID
  360. * @param $iItemId item ID.
  361. * @param $iItemCount the number of purchased items.
  362. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  363. * @param $sLicense license number genereted with payment processing module for internal usage
  364. * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
  365. *
  366. * @see BxCreditsModule::serviceRegisterSubscriptionItem
  367. */
  368. /**
  369. * @ref bx_credits-register_subscription_item "register_subscription_item"
  370. */
  371. public function serviceRegisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
  372. {
  373. return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_RECURRING);
  374. }
  375. /**
  376. * @page service Service Calls
  377. * @section bx_credits Credits
  378. * @subsection bx_credits-payments Payments
  379. * @subsubsection bx_credits-reregister_cart_item reregister_cart_item
  380. *
  381. * @code bx_srv('bx_credits', 'reregister_cart_item', [...]); @endcode
  382. *
  383. * Reregister a single time payment inside the Credits module. Is called with payment processing module after the payment was reregistered there.
  384. *
  385. * @param $iClientId client ID.
  386. * @param $iSellerId seller ID
  387. * @param $iItemIdOld old item ID.
  388. * @param $iItemIdNew new item ID.
  389. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  390. * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
  391. *
  392. * @see BxCreditsModule::serviceReregisterCartItem
  393. */
  394. /**
  395. * @ref bx_credits-reregister_cart_item "reregister_cart_item"
  396. */
  397. public function serviceReregisterCartItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
  398. {
  399. return array();
  400. }
  401. /**
  402. * @page service Service Calls
  403. * @section bx_credits Credits
  404. * @subsection bx_credits-payments Payments
  405. * @subsubsection bx_credits-reregister_subscription_item reregister_subscription_item
  406. *
  407. * @code bx_srv('bx_credits', 'reregister_subscription_item', [...]); @endcode
  408. *
  409. * Reregister a subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was reregistered there.
  410. *
  411. * @param $iClientId client ID.
  412. * @param $iSellerId seller ID
  413. * @param $iItemIdOld old item ID.
  414. * @param $iItemIdNew new item ID.
  415. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  416. * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
  417. *
  418. * @see BxCreditsModule::serviceReregisterSubscriptionItem
  419. */
  420. /**
  421. * @ref bx_credits-reregister_subscription_item "reregister_subscription_item"
  422. */
  423. public function serviceReregisterSubscriptionItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
  424. {
  425. return array();
  426. }
  427. /**
  428. * @page service Service Calls
  429. * @section bx_credits Credits
  430. * @subsection bx_credits-payments Payments
  431. * @subsubsection bx_credits-unregister_cart_item unregister_cart_item
  432. *
  433. * @code bx_srv('bx_credits', 'unregister_cart_item', [...]); @endcode
  434. *
  435. * Unregister an earlier processed single time payment inside the Credits module. Is called with payment processing module after the payment was unregistered there.
  436. *
  437. * @param $iClientId client ID.
  438. * @param $iSellerId seller ID
  439. * @param $iItemId item ID.
  440. * @param $iItemCount the number of purchased items.
  441. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  442. * @param $sLicense license number genereted with payment processing module for internal usage
  443. * @return boolean value determining where the payment was unregistered or not.
  444. *
  445. * @see BxCreditsModule::serviceUnregisterCartItem
  446. */
  447. /**
  448. * @ref bx_credits-unregister_cart_item "unregister_cart_item"
  449. */
  450. public function serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
  451. {
  452. return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_SINGLE);
  453. }
  454. /**
  455. * @page service Service Calls
  456. * @section bx_credits Credits
  457. * @subsection bx_credits-payments Payments
  458. * @subsubsection bx_credits-unregister_subscription_item unregister_subscription_item
  459. *
  460. * @code bx_srv('bx_credits', 'unregister_subscription_item', [...]); @endcode
  461. *
  462. * Unregister an earlier processed subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was unregistered there.
  463. *
  464. * @param $iClientId client ID.
  465. * @param $iSellerId seller ID
  466. * @param $iItemId item ID.
  467. * @param $iItemCount the number of purchased items.
  468. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  469. * @param $sLicense license number genereted with payment processing module for internal usage
  470. * @return boolean value determining where the subscription was unregistered or not.
  471. *
  472. * @see BxCreditsModule::serviceUnregisterSubscriptionItem
  473. */
  474. /**
  475. * @ref bx_credits-unregister_subscription_item "unregister_subscription_item"
  476. */
  477. public function serviceUnregisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
  478. {
  479. return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_RECURRING);
  480. }
  481. /**
  482. * @page service Service Calls
  483. * @section bx_credits Credits
  484. * @subsection bx_credits-payments Payments
  485. * @subsubsection bx_credits-cancel_subscription_item cancel_subscription_item
  486. *
  487. * @code bx_srv('bx_credits', 'cancel_subscription_item', [...]); @endcode
  488. *
  489. * Cancel an earlier processed subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was canceled there.
  490. *
  491. * @param $iClientId client ID.
  492. * @param $iSellerId seller ID
  493. * @param $iItemId item ID.
  494. * @param $iItemCount the number of purchased items.
  495. * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
  496. * @return boolean value determining where the subscription was canceled or not.
  497. *
  498. * @see BxCreditsModule::serviceCancelSubscriptionItem
  499. */
  500. /**
  501. * @ref bx_credits-cancel_subscription_item "cancel_subscription_item"
  502. */
  503. public function serviceCancelSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
  504. {
  505. return true;
  506. }
  507. public function serviceGetProfileBalance($iProfileId = 0)
  508. {
  509. return $this->getProfileBalance($iProfileId);
  510. }
  511. public function serviceUpdateProfileBalance($iFirstPid, $fAmount, $iSecondPid = 0, $sOrder = '', $sInfo = '')
  512. {
  513. if(empty($sInfo))
  514. $sInfo = '_bx_credits_txt_history_info_service';
  515. return $this->updateProfileBalance($iFirstPid, $iSecondPid, $fAmount, $sOrder, $sInfo);
  516. }
  517. /**
  518. * Delete all content by profile
  519. * @param $iProfileId profile id
  520. * @return number of deleted items
  521. */
  522. public function serviceDeleteEntitiesByAuthor ($iProfileId)
  523. {
  524. $this->_oDb->deleteProfile(array('id' => $iProfileId));
  525. $this->_oDb->deleteHistory(array('first_pid' => $iProfileId));
  526. }
  527. /*
  528. * Common methods
  529. */
  530. public function convertC2S($fCredits, $bWithUnit = true)
  531. {
  532. $sResult = '';
  533. if($bWithUnit)
  534. $sResult .= $this->_oTemplate->getUnit();
  535. $iPrecision = $this->_oConfig->getPrecision();
  536. $sResult .= sprintf("%01." . $iPrecision . "f", round((float)$fCredits, $iPrecision));
  537. return $sResult;
  538. }
  539. public function getProfileBalance($iProfileId = 0)
  540. {
  541. if(empty($iProfileId))
  542. $iProfileId = bx_get_logged_profile_id();
  543. if(empty($iProfileId))
  544. return 0;
  545. return (float)$this->_oDb->getProfile(array('type' => 'balance', 'id' => $iProfileId));
  546. }
  547. public function updateProfileBalance($iFirstPid, $iSecondPid, $fAmount, $sOrder = '', $sInfo = '', $sData = '')
  548. {
  549. $CNF = &$this->_oConfig->CNF;
  550. if(empty($sOrder))
  551. $sOrder = $this->_oConfig->getOrder();
  552. if(empty($sData))
  553. $sData = serialize(array(
  554. 'conversion' => $this->_oConfig->getConversionRateUse(),
  555. 'precision' => $this->_oConfig->getPrecision()
  556. ));
  557. if(!$this->_oDb->updateProfileBalance($iFirstPid, $fAmount))
  558. return false;
  559. $fAmountAbs = abs($fAmount);
  560. $sDirection = $fAmount > 0 ? BX_CREDITS_DIRECTION_IN : BX_CREDITS_DIRECTION_OUT;
  561. $this->_oDb->insertHistory(array(
  562. 'first_pid' => $iFirstPid,
  563. 'second_pid' => $iSecondPid,
  564. 'amount' => $fAmountAbs,
  565. 'direction' => $sDirection,
  566. 'order' => $sOrder,
  567. 'data' => $sData,
  568. 'info' => $sInfo,
  569. 'date' => time()
  570. ));
  571. bx_alert($this->getName(), 'update_balance', 0, false, array(
  572. 'first_pid' => $iFirstPid,
  573. 'second_pid' => $iSecondPid,
  574. 'amount' => $fAmountAbs,
  575. 'direction' => $sDirection,
  576. 'order' => $sOrder,
  577. ));
  578. $oSecondProfile = BxDolProfile::getInstanceMagic($iSecondPid);
  579. sendMailTemplate($CNF['ETEMPLATE_' . strtoupper($sDirection)], 0, $iFirstPid, array(
  580. 'second_profile_name' => $oSecondProfile->getDisplayName(),
  581. 'amount' => $fAmountAbs,
  582. ));
  583. return true;
  584. }
  585. public function processGrant($iProfileId, $fAmount, $sMessage = '')
  586. {
  587. $CNF = &$this->_oConfig->CNF;
  588. $oProfile = BxDolProfile::getInstance($iProfileId);
  589. if(!$oProfile)
  590. return array('code' => 1, 'msg' => '_bx_credits_err_profile_not_found');
  591. $sInfo = '_bx_credits_txt_history_info_grant';
  592. if(!$this->updateProfileBalance($iProfileId, 0, $fAmount, '', $sInfo))
  593. return array('code' => 2, 'msg' => '_bx_credits_err_cannot_update_balance');
  594. sendMailTemplate($CNF['ETEMPLATE_GRANTED'], 0, $iProfileId, array(
  595. 'amount' => $fAmount,
  596. 'message' => $sMessage
  597. ));
  598. bx_alert($this->getName(), 'granted', 0, false, array(
  599. 'profile' => $iProfileId,
  600. 'amount' => $fAmount,
  601. ));
  602. return array('code' => 0);
  603. }
  604. public function processWithdrawRequest($iProfileId, $fAmount, $sMessage = '')
  605. {
  606. $CNF = &$this->_oConfig->CNF;
  607. if(empty($iProfileId))
  608. $iProfileId = bx_get_logged_profile_id ();
  609. if(empty($iProfileId))
  610. return array('code' => 1, 'msg' => '_bx_credits_err_login_required');
  611. $oProfile = BxDolProfile::getInstance($iProfileId);
  612. if(!$oProfile)
  613. return array('code' => 1, 'msg' => '_bx_credits_err_login_required');
  614. $fBalance = $this->getProfileBalance($iProfileId);
  615. if($fAmount > $fBalance)
  616. return array('code' => 2, 'msg' => '_bx_credits_err_low_balance');
  617. $aResult = array('code' => 3, 'msg' => '_bx_credits_err_cannot_send');
  618. $oEmailTemplates = BxDolEmailTemplates::getInstance();
  619. if(!$oEmailTemplates)
  620. return $aResult;
  621. $fRate = $this->_oConfig->getConversionRateWithdraw();
  622. $aTemplateVars = array(
  623. 'profile_link' => $oProfile->getUrl(),
  624. 'profile_name' => $oProfile->getDisplayName(),
  625. 'amount' => $fAmount,
  626. 'rate' => $fRate,
  627. 'message' => $sMessage,
  628. );
  629. $aTemplate = $oEmailTemplates->parseTemplate($CNF['ETEMPLATE_WITHDRAW_REQUESTED'], $aTemplateVars);
  630. if(!$aTemplate)
  631. return $aResult;
  632. $sEmail = $this->_oConfig->getWithdrawEmail();
  633. if(!sendMail($sEmail, $aTemplate['Subject'], $aTemplate['Body'], 0, array(), BX_EMAIL_SYSTEM, 'html', false, array(), false))
  634. return $aResult;
  635. bx_alert($this->getName(), 'withdraw_requested', 0, $iProfileId, array(
  636. 'profile' => $iProfileId,
  637. 'amount' => $fAmount,
  638. 'rate' => $fRate
  639. ));
  640. return array('code' => 0);
  641. }
  642. public function processWithdrawConfirm($iProfileId, $fAmount, $sMessage = '')
  643. {
  644. $CNF = &$this->_oConfig->CNF;
  645. $oProfile = BxDolProfile::getInstance($iProfileId);
  646. if(!$oProfile)
  647. return array('code' => 1, 'msg' => '_bx_credits_err_profile_not_found');
  648. $fBalance = $this->getProfileBalance($iProfileId);
  649. if($fAmount > $fBalance)
  650. return array('code' => 2, 'msg' => '_bx_credits_err_low_balance');
  651. $sInfo = '_bx_credits_txt_history_info_withdraw';
  652. if(!$this->updateProfileBalance($iProfileId, 0, -$fAmount, '', $sInfo))
  653. return array('code' => 3, 'msg' => '_bx_credits_err_cannot_update_balance');
  654. sendMailTemplate($CNF['ETEMPLATE_WITHDRAW_SENT'], 0, $iProfileId, array(
  655. 'amount' => $fAmount,
  656. 'message' => $sMessage
  657. ));
  658. bx_alert($this->getName(), 'withdraw_sent', 0, false, array(
  659. 'profile' => $iProfileId,
  660. 'amount' => $fAmount,
  661. ));
  662. return array('code' => 0);
  663. }
  664. /*
  665. * Internal methods
  666. */
  667. protected function _serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
  668. {
  669. $CNF = &$this->_oConfig->CNF;
  670. $aItem = $this->serviceGetCartItem($iItemId);
  671. if(empty($aItem) || !is_array($aItem))
  672. return array();
  673. $aBundle = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iItemId));
  674. if(empty($aBundle) || !is_array($aBundle))
  675. return array();
  676. $iTrial = 0;
  677. $sDuration = '';
  678. $sAction = 'register';
  679. if($sType == BX_CREDITS_ORDER_TYPE_RECURRING && isset($CNF['FIELD_DURATION_RECURRING'], $CNF['FIELD_TRIAL_RECURRING'])) {
  680. $iTrial = $aBundle[$CNF['FIELD_TRIAL_RECURRING']];
  681. $sDuration = $aBundle[$CNF['FIELD_DURATION_RECURRING']];
  682. if($this->_oDb->isOrderByPbo($iClientId, $iItemId, $sOrder))
  683. $sAction = 'prolong';
  684. }
  685. if(!$this->_oDb->{$sAction . 'Order'}($iClientId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType, $sDuration, $iTrial))
  686. return array();
  687. $sInfo = '_bx_credits_txt_history_info_purchase';
  688. $fAmount = (float)$aBundle[$CNF['FIELD_AMOUNT']] + (float)$aBundle[$CNF['FIELD_BONUS']];
  689. if(!$this->updateProfileBalance($iClientId, 0, $fAmount, '', $sInfo))
  690. return array();
  691. bx_alert($this->getName(), 'order_' . $sAction, 0, false, array(
  692. 'profile_id' => $iClientId,
  693. 'bundle_id' => $iItemId,
  694. 'product_id' => $iItemId, //--- Alias for 'bundle_id'
  695. 'count' => $iItemCount,
  696. 'order' => $sOrder,
  697. 'license' => $sLicense,
  698. 'type' => $sType,
  699. 'duration' => $sDuration,
  700. 'trial' => $iTrial
  701. ));
  702. $oClient = BxDolProfile::getInstanceMagic($iClientId);
  703. $oSeller = BxDolProfile::getInstanceMagic($iSellerId);
  704. $sSellerUrl = $oSeller->getUrl();
  705. $sSellerName = $oSeller->getDisplayName();
  706. sendMailTemplate($CNF['ETEMPLATE_PURCHASED'], 0, $iClientId, array(
  707. 'client_name' => $oClient->getDisplayName(),
  708. 'bundle_name' => $aBundle[$CNF['FIELD_NAME']],
  709. 'bundle_title' => _t($aBundle[$CNF['FIELD_TITLE']]),
  710. 'bundle_url' => $this->_oConfig->getBundleUrl($aBundle),
  711. 'vendor_url' => $sSellerUrl,
  712. 'vendor_name' => $sSellerName,
  713. 'order' => $sOrder,
  714. 'license' => $sLicense,
  715. 'notes' => _t('_bx_credits_txt_purchased_note', $sSellerUrl, $sSellerName),
  716. ));
  717. return $aItem;
  718. }
  719. protected function _serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
  720. {
  721. $CNF = &$this->_oConfig->CNF;
  722. $aBundle = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iItemId));
  723. if(empty($aBundle) || !is_array($aBundle))
  724. return false;
  725. if(!$this->_oDb->unregisterOrder($iClientId, $iItemId, $sOrder, $sLicense, $sType))
  726. return false;
  727. $fAmount = (float)$aBundle[$CNF['FIELD_AMOUNT']] + (float)$aBundle[$CNF['FIELD_BONUS']];
  728. $aProfile = $this->_oDb->getProfile(array('type' => 'id', 'id' => $iClientId));
  729. if(!empty($aProfile) && is_array($aProfile))
  730. $this->_oDb->updateProfile(array('balance' => (float)$aProfile['balance'] - $fAmount), array('id' => $aProfile['id']));
  731. bx_alert($this->getName(), 'order_unregister', 0, false, array(
  732. 'profile_id' => $iClientId,
  733. 'bundle_id' => $iItemId,
  734. 'product_id' => $iItemId, //--- Alias for 'bundle_id'
  735. 'count' => $iItemCount,
  736. 'order' => $sOrder,
  737. 'license' => $sLicense,
  738. 'type' => $sType,
  739. ));
  740. return true;
  741. }
  742. protected function _getBlockOrders($sType)
  743. {
  744. $CNF = &$this->_oConfig->CNF;
  745. $sGrid = $CNF['OBJECT_GRID_ORDERS_' . strtoupper($sType)];
  746. $oGrid = BxDolGrid::getObjectInstance($sGrid);
  747. if(!$oGrid)
  748. return '';
  749. return array(
  750. 'content' => $oGrid->getCode(),
  751. 'menu' => $CNF['OBJECT_MENU_MANAGE_SUBMENU']
  752. );
  753. }
  754. protected function _getBlockHistory($sType)
  755. {
  756. $CNF = &$this->_oConfig->CNF;
  757. $sGrid = $CNF['OBJECT_GRID_HISTORY_' . strtoupper($sType)];
  758. $oGrid = BxDolGrid::getObjectInstance($sGrid);
  759. if(!$oGrid)
  760. return '';
  761. return array(
  762. 'content' => $oGrid->getCode(),
  763. 'menu' => $CNF['OBJECT_MENU_MANAGE_SUBMENU']
  764. );
  765. }
  766. }
  767. /** @} */