Просмотр исходного кода

Ticket #259 - Subscriptions in Payment module and Chargebee integration.

AntonLV 10 лет назад
Родитель
Сommit
05c9b979ee

+ 59 - 58
modules/boonex/payment/classes/BxPaymentCart.php

@@ -33,7 +33,7 @@ class BxPaymentCart extends BxBaseModPaymentCart
         if(empty($iUserId))
         if(empty($iUserId))
             return MsgBox(_t($this->_sLangsPrefix . 'err_required_login'));
             return MsgBox(_t($this->_sLangsPrefix . 'err_required_login'));
 
 
-        $aCartInfo = $this->getInfo($iUserId, $iVendor);
+        $aCartInfo = $this->getInfo(BX_PAYMENT_TYPE_SINGLE, $iUserId, $iVendor);
         return array(
         return array(
         	'content' => $this->_oModule->_oTemplate->displayBlockCart($aCartInfo, $iVendor),
         	'content' => $this->_oModule->_oTemplate->displayBlockCart($aCartInfo, $iVendor),
         	'menu' => $this->_oModule->_oConfig->getObject('menu_cart_submenu')
         	'menu' => $this->_oModule->_oConfig->getObject('menu_cart_submenu')
@@ -56,21 +56,13 @@ class BxPaymentCart extends BxBaseModPaymentCart
 
 
     public function serviceAddToCart($iVendorId, $iModuleId, $iItemId, $iItemCount)
     public function serviceAddToCart($iVendorId, $iModuleId, $iItemId, $iItemCount)
     {
     {
-    	if($iVendorId == BX_PAYMENT_EMPTY_ID || empty($iModuleId) || empty($iItemId) || empty($iItemCount))
-            return array('code' => 1, 'message' => _t($this->_sLangsPrefix . 'err_wrong_data'));
-
-		$iClientId = $this->_oModule->getProfileId();
-        if(empty($iClientId))
-            return array('code' => 2, 'message' => _t($this->_sLangsPrefix . 'err_required_login'));
-
-        if($iClientId == $iVendorId)
-            return array('code' => 3, 'message' => _t($this->_sLangsPrefix . 'err_purchase_from_yourself'));
+    	$iClientId = $this->_oModule->getProfileId();
 
 
-        $aVendor = $this->_oModule->getVendorInfo($iVendorId);
-        if(!$aVendor['active'])
-            return array('code' => 4, 'message' => _t($this->_sLangsPrefix . 'err_inactive_vendor'));
+    	$mixedResult = $this->_checkData($iClientId, $iVendorId, $iModuleId, $iItemId, $iItemCount);
+    	if($mixedResult !== true)
+    		return $mixedResult;
 
 
-        $aVendorProviders = $this->_oModule->_oDb->getVendorInfoProviders($iVendorId);
+        $aVendorProviders = $this->_oModule->_oDb->getVendorInfoProvidersCart($iVendorId);
         if(empty($aVendorProviders))
         if(empty($aVendorProviders))
             return array('code' => 5, 'message' => _t($this->_sLangsPrefix . 'err_not_accept_payments'));
             return array('code' => 5, 'message' => _t($this->_sLangsPrefix . 'err_not_accept_payments'));
 
 
@@ -84,11 +76,11 @@ class BxPaymentCart extends BxBaseModPaymentCart
             	$sCartItems
             	$sCartItems
 			);
 			);
         else
         else
-            $sCartItems = empty($sCartItems) ? $sCartItem : $sCartItems . $this->_oModule->_oConfig->getDivider('descriptors') . $sCartItem;
+            $sCartItems = empty($sCartItems) ? $sCartItem : $sCartItems . $this->_oModule->_oConfig->getDivider('DIVIDER_DESCRIPTORS') . $sCartItem;
 
 
         $this->_oModule->_oDb->setCartItems($iClientId, $sCartItems);
         $this->_oModule->_oDb->setCartItems($iClientId, $sCartItems);
 
 
-        $aInfo = $this->getInfo($iClientId);
+        $aInfo = $this->getInfo(BX_PAYMENT_TYPE_SINGLE, $iClientId);
         $iTotalQuantity = 0;
         $iTotalQuantity = 0;
         foreach($aInfo as $aCart)
         foreach($aInfo as $aCart)
            $iTotalQuantity += $aCart['items_count'];
            $iTotalQuantity += $aCart['items_count'];
@@ -123,59 +115,68 @@ class BxPaymentCart extends BxBaseModPaymentCart
         return array('code' => 0, 'message' => _t($this->_sLangsPrefix . 'inf_successfully_deleted'));
         return array('code' => 0, 'message' => _t($this->_sLangsPrefix . 'inf_successfully_deleted'));
     }
     }
 
 
-    public function getInfo($iUserId, $iVendorId = BX_PAYMENT_EMPTY_ID, $aItems = array())
+	public function serviceSubscribe($iVendorId, $iModuleId, $iItemId, $iItemCount)
     {
     {
-        if($iVendorId != BX_PAYMENT_EMPTY_ID && !empty($aItems))
-            return $this->_getInfo($iUserId, $iVendorId, $this->_oModule->_oConfig->descriptorsM2A($aItems));
+    	$iClientId = $this->_oModule->getProfileId();
 
 
-        $aContent = $this->_parseByVendor($iUserId);
+    	$mixedResult = $this->_checkData($iClientId, $iVendorId, $iModuleId, $iItemId, $iItemCount);
+    	if($mixedResult !== true)
+    		return $mixedResult;
 
 
-        if($iVendorId != BX_PAYMENT_EMPTY_ID)
-            return isset($aContent[$iVendorId]) ? $this->_getInfo($iUserId, $iVendorId, $aContent[$iVendorId]) : array();
+        $aVendorProviders = $this->_oModule->_oDb->getVendorInfoProvidersSubscription($iVendorId);
+        if(empty($aVendorProviders))
+            return array('code' => 5, 'message' => _t($this->_sLangsPrefix . 'err_not_accept_payments'));
 
 
-        $aResult = array();
-        foreach($aContent as $iVendorId => $aVendorItems)
-            $aResult[$iVendorId] = $this->_getInfo($iUserId, $iVendorId, $aVendorItems);
+        $sCartItem = $this->_oModule->_oConfig->descriptorA2S(array($iVendorId, $iModuleId, $iItemId, $iItemCount));
 
 
-        return $aResult;
+        if(count($aVendorProviders) > 1) {
+        	//TODO: Show popup with selector and path Descriptior into it.
+        	return array('popup' => '');
+        }
+
+        $aProvider = array_shift($aVendorProviders);
+
+        $mixedResult = $this->_oModule->serviceInitializeCheckout(BX_PAYMENT_TYPE_RECURRING, $iVendorId, $aProvider['name'], array($sCartItem));
+        if(is_string($mixedResult))
+        	return array('code' => 6, 'message' => _t($mixedResult));
+
+		return $mixedResult;
     }
     }
 
 
-    public function updateInfo($mixedPending)
+    protected function _checkData($iClientId, $iVendorId, $iModuleId, $iItemId, $iItemCount)
     {
     {
-    	$aPending = is_array($mixedPending) ? $mixedPending : $this->_oModule->_oDb->getOrderPending(array('type' => 'id', 'id' => (int)$mixedPending));
-    	if(empty($aPending) || !is_array($aPending))
-    		return false;
+		if($iVendorId == BX_PAYMENT_EMPTY_ID || empty($iModuleId) || empty($iItemId) || empty($iItemCount))
+            return array('code' => 1, 'message' => _t($this->_sLangsPrefix . 'err_wrong_data'));
 
 
-		if((int)$aPending['processed'] == 1)
-			return true;
+		$iClientId = $this->_oModule->getProfileId();
+        if(empty($iClientId))
+            return array('code' => 2, 'message' => _t($this->_sLangsPrefix . 'err_required_login'));
 
 
-		$iClientId = (int)$aPending['client_id'];
-		$sOrderId = $this->_oModule->_oConfig->getLicense();
+        if($iClientId == $iVendorId)
+            return array('code' => 3, 'message' => _t($this->_sLangsPrefix . 'err_purchase_from_yourself'));
 
 
-        $sCartItems = $this->_oModule->_oDb->getCartItems($iClientId);
-        $aItems = $this->_oModule->_oConfig->descriptorsM2A($aPending['items']);
+        $aVendor = $this->_oModule->getVendorInfo($iVendorId);
+        if(!$aVendor['active'])
+            return array('code' => 4, 'message' => _t($this->_sLangsPrefix . 'err_inactive_vendor'));
 
 
-        foreach($aItems as $aItem) {
-            $aItemInfo = $this->_oModule->callRegisterCartItem((int)$aItem['module_id'], array($aPending['client_id'], $aPending['seller_id'], $aItem['item_id'], $aItem['item_count'], $sOrderId));
-            if(!is_array($aItemInfo) || empty($aItemInfo))
-                continue;
-
-            $this->_oModule->_oDb->insertOrderProcessed(array(
-                'pending_id' => $aPending['id'],
-                'order_id' => $sOrderId,
-                'client_id' => $aPending['client_id'],
-                'seller_id' => $aPending['seller_id'],
-                'module_id' => $aItem['module_id'],
-                'item_id' => $aItem['item_id'],
-                'item_count' => $aItem['item_count'],
-                'amount' => $aItemInfo['price'] * $aItem['item_count'],
-            ));
-
-            $sCartItems = trim(preg_replace("'" . $this->_oModule->_oConfig->descriptorA2S($aItem) . ":?'", "", $sCartItems), ":");
-        }
+		return true;
+    }
+
+    public function getInfo($sType, $iUserId, $iVendorId = BX_PAYMENT_EMPTY_ID, $aItems = array())
+    {
+        if($iVendorId != BX_PAYMENT_EMPTY_ID && !empty($aItems))
+            return $this->_getInfo($sType, $iUserId, $iVendorId, $this->_oModule->_oConfig->descriptorsM2A($aItems));
+
+        $aContent = $this->_parseByVendor($iUserId);
 
 
-		$this->_oModule->_oDb->setCartItems($iClientId, $sCartItems);
-        return $this->_oModule->_oDb->updateOrderPending($aPending['id'], array('processed' => 1));
+        if($iVendorId != BX_PAYMENT_EMPTY_ID)
+            return isset($aContent[$iVendorId]) ? $this->_getInfo($sType, $iUserId, $iVendorId, $aContent[$iVendorId]) : array();
+
+        $aResult = array();
+        foreach($aContent as $iVendorId => $aVendorItems)
+            $aResult[$iVendorId] = $this->_getInfo($sType, $iUserId, $iVendorId, $aVendorItems);
+
+        return $aResult;
     }
     }
 
 
     /**
     /**
@@ -186,7 +187,7 @@ class BxPaymentCart extends BxBaseModPaymentCart
      * @param  array   $aItems    item descriptors(quaternions) from shopping cart.
      * @param  array   $aItems    item descriptors(quaternions) from shopping cart.
      * @return array   with full info about vendor and items.
      * @return array   with full info about vendor and items.
      */
      */
-    protected function _getInfo($iClientId, $iVendorId, $aItems)
+    protected function _getInfo($sType, $iClientId, $iVendorId, $aItems)
     {
     {
         $iItemsCount = 0;
         $iItemsCount = 0;
         $fItemsPrice = 0;
         $fItemsPrice = 0;
@@ -197,7 +198,7 @@ class BxPaymentCart extends BxBaseModPaymentCart
             $aItemInfo['quantity'] = (int)$aItem['item_count'];
             $aItemInfo['quantity'] = (int)$aItem['item_count'];
 
 
             $iItemsCount += $aItem['item_count'];
             $iItemsCount += $aItem['item_count'];
-            $fItemsPrice += $aItem['item_count'] * $aItemInfo['price'];
+            $fItemsPrice += $aItem['item_count'] * $this->_oModule->_oConfig->getPrice($sType, $aItemInfo);
             $aItemsInfo[] = $aItemInfo;
             $aItemsInfo[] = $aItemInfo;
         }
         }
 
 

+ 32 - 13
modules/boonex/payment/classes/BxPaymentConfig.php

@@ -15,16 +15,18 @@ class BxPaymentConfig extends BxBaseModPaymentConfig
     {
     {
         parent::__construct($aModule);
         parent::__construct($aModule);
 
 
-        $this->_aUrls = array(
-        	'join' => 'page.php?i=payment-join',
-        	'cart' => 'page.php?i=payment-cart',
-        	'history' => 'page.php?i=payment-history',
-        	'orders' => 'page.php?i=payment-orders',
-        	'details' => 'page.php?i=payment-details',
-
-        	'return' => 'page.php?i=payment-cart',
-        	'return_data' => BX_DOL_URL_ROOT . $this->getBaseUri() . 'finalize_checkout/'
-        );
+        $this->CNF = array_merge($this->CNF, array(
+        	'URL_JOIN' => 'page.php?i=payment-join',
+        	'URL_CART' => 'page.php?i=payment-cart',
+        	'URL_HISTORY' => 'page.php?i=payment-history',
+        	'URL_ORDERS' => 'page.php?i=payment-orders',
+        	'URL_DETAILS' => 'page.php?i=payment-details',
+        	'URL_RETURN' => 'page.php?i=payment-cart',
+        	'URL_RETURN_DATA' => BX_DOL_URL_ROOT . $this->getBaseUri() . 'finalize_checkout/',
+
+        	'KEY_ARRAY_PRICE_SINGLE' => 'price_single',
+        	'KEY_ARRAY_PRICE_RECURRING' => 'price_recurring',
+        ));
 
 
         $this->_aHtmlIds = array(
         $this->_aHtmlIds = array(
         	'history' => array(
         	'history' => array(
@@ -86,6 +88,23 @@ class BxPaymentConfig extends BxBaseModPaymentConfig
         return $sResult;
         return $sResult;
     }
     }
 
 
+    public function getPrice($sType, $aItem)
+    {
+    	$fPrice = 0;
+
+		switch($sType) {
+			case BX_PAYMENT_TYPE_SINGLE:
+				$fPrice = $aItem[$this->getKey('KEY_ARRAY_PRICE_SINGLE')];
+				break;
+
+			case BX_PAYMENT_TYPE_RECURRING:
+				$fPrice = $aItem[$this->getKey('KEY_ARRAY_PRICE_RECURRING')];
+				break;
+		}
+
+		return (float)$fPrice;
+    }
+
     public function getModuleId($mixedId)
     public function getModuleId($mixedId)
     {
     {
     	if(is_int($mixedId))
     	if(is_int($mixedId))
@@ -105,12 +124,12 @@ class BxPaymentConfig extends BxBaseModPaymentConfig
 
 
     public function descriptorA2S($a) 
     public function descriptorA2S($a) 
     {
     {
-    	return implode($this->getDivider('descriptor'), $a);
+    	return implode($this->getDivider('DIVIDER_DESCRIPTOR'), $a);
     }
     }
 
 
 	public function descriptorS2A($s) 
 	public function descriptorS2A($s) 
     {
     {
-    	return explode($this->getDivider('descriptor'), $s);
+    	return explode($this->getDivider('DIVIDER_DESCRIPTOR'), $s);
     }
     }
 
 
 	/**
 	/**
@@ -124,7 +143,7 @@ class BxPaymentConfig extends BxBaseModPaymentConfig
         $aResult = array();
         $aResult = array();
 
 
         if(is_string($mixed))
         if(is_string($mixed))
-           $aItems = explode($this->getDivider('descriptors'), $mixed);
+           $aItems = explode($this->getDivider('DIVIDER_DESCRIPTORS'), $mixed);
         else if(is_array($mixed))
         else if(is_array($mixed))
            $aItems = $mixed;
            $aItems = $mixed;
         else
         else

+ 71 - 40
modules/boonex/payment/classes/BxPaymentDb.php

@@ -54,25 +54,40 @@ class BxPaymentDb extends BxBaseModPaymentDb
         return $this->getAllWithKey($sQuery, 'option_id');
         return $this->getAllWithKey($sQuery, 'option_id');
     }
     }
 
 
-	public function getProviders($sName = '')
+	public function getProviders($aParams = array())
     {
     {
-        $sWhereClause = "1";
-        if(!empty($sName))
-            $sWhereClause = $this->prepare("`tp`.`name`=?", $sName);
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
 
 
-        $sQuery = "SELECT
+        $sWhereClause = "";
+        switch($aParams['type']) {
+        	case 'by_name':
+        		$aMethod['name'] = 'getRow';
+        		$sWhereClause = $this->prepare(" AND `tp`.`name`=?", $aParams['name']);
+        		break;
+
+			case 'for_cart':
+				$sWhereClause = " AND `tp`.`for_subscription`='0'";
+        		break;
+
+			case 'for_subscription':
+				$sWhereClause = " AND `tp`.`for_subscription`='1'";
+        		break;
+        }          
+
+        $aMethod['params'][0] = "SELECT
                 `tp`.`id` AS `id`,
                 `tp`.`id` AS `id`,
                 `tp`.`name` AS `name`,
                 `tp`.`name` AS `name`,
                 `tp`.`caption` AS `caption`,
                 `tp`.`caption` AS `caption`,
                 `tp`.`description` AS `description`,
                 `tp`.`description` AS `description`,
                 `tp`.`option_prefix` AS `option_prefix`,
                 `tp`.`option_prefix` AS `option_prefix`,
                 `tp`.`for_visitor` AS `for_visitor`,
                 `tp`.`for_visitor` AS `for_visitor`,
+                `tp`.`for_subscription` AS `for_subscription`,
                 `tp`.`class_name` AS `class_name`,
                 `tp`.`class_name` AS `class_name`,
                 `tp`.`class_file` AS `class_file`
                 `tp`.`class_file` AS `class_file`
             FROM `" . $this->_sPrefix . "providers` AS `tp`
             FROM `" . $this->_sPrefix . "providers` AS `tp`
-            WHERE " . $sWhereClause;
+            WHERE 1" . $sWhereClause;
 
 
-        return !empty($sName) ? $this->getRow($sQuery) : $this->getAll($sQuery);
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
     }
     }
 
 
     public function getOptions($iUserId = BX_PAYMENT_EMPTY_ID, $iProviderId = 0)
     public function getOptions($iUserId = BX_PAYMENT_EMPTY_ID, $iProviderId = 0)
@@ -119,35 +134,45 @@ class BxPaymentDb extends BxBaseModPaymentDb
 
 
         return $this->query($sQuery);
         return $this->query($sQuery);
     }
     }
-    public function getVendorInfoProviders($iId, $sProvider = '')
+
+	public function getVendorInfoProvidersCart($iVendorId)
     {
     {
-        $aResult = array();
+    	return $this->getVendorInfoProviders($iVendorId, array('type' => 'for_cart'));
+    }
 
 
-        //--- Get specified payment provider if it's available ---//
-        if(!empty($sProvider)) {
-            $aProvider = $this->getProviders($sProvider);
-            $aOptions = $this->getOptions($iId, $aProvider['id']);
+	public function getVendorInfoProvidersSubscription($iVendorId)
+    {
+    	return $this->getVendorInfoProviders($iVendorId, array('type' => 'for_subscription'));
+    }
 
 
-            if(isset($aOptions[$aProvider['option_prefix'] . 'active']) && $aOptions[$aProvider['option_prefix'] . 'active']['value'] == 'on') {
-                $aProvider['options'] = $aOptions;
-                $aResult = $aProvider;
-            }
-        }
-        //--- Get all available payment providers ---//
-        else{
-            $aProviders = $this->getProviders();
-            $aOptions = $this->getOptions($iId);
-
-            foreach($aProviders as $aProvider)
-               if(isset($aOptions[$aProvider['option_prefix'] . 'active']) && $aOptions[$aProvider['option_prefix'] . 'active']['value'] == 'on') {
-                   foreach($aOptions as $sName => $aOption)
-                       if(strpos($sName, $aProvider['option_prefix']) !== false)
-                           $aProvider['options'][$sName] = $aOption;
-                   $aResult[] = $aProvider;
-               }
-        }
+    public function getVendorInfoProviders($iVendorId, $aParams = array())
+    {
+		$aProviders = $this->getProviders($aParams);
+		$aOptions = $this->getOptions($iVendorId);
+
+		$aResult = array();
+		foreach($aProviders as $aProvider)
+			if(isset($aOptions[$aProvider['option_prefix'] . 'active']) && $aOptions[$aProvider['option_prefix'] . 'active']['value'] == 'on') {
+				foreach($aOptions as $sName => $aOption)
+					if(strpos($sName, $aProvider['option_prefix']) !== false)
+						$aProvider['options'][$sName] = $aOption;
+				$aResult[] = $aProvider;
+			}
+
+		return $aResult;
+	}
+    public function getVendorInfoProvider($iVendorId, $sProvider)
+    {
+		$aProvider = $this->getProviders(array('type' => 'by_name', 'name' => $sProvider));
+		$aOptions = $this->getOptions($iVendorId, $aProvider['id']);
+
+		$aResult = array();
+		if(isset($aOptions[$aProvider['option_prefix'] . 'active']) && $aOptions[$aProvider['option_prefix'] . 'active']['value'] == 'on') {
+			$aProvider['options'] = $aOptions;
+			$aResult = $aProvider;
+		}
 
 
-        return $aResult;
+		return $aResult;
     }
     }
     public function getFirstAdminId()
     public function getFirstAdminId()
     {
     {
@@ -174,13 +199,18 @@ class BxPaymentDb extends BxBaseModPaymentDb
                 $sWhereClause = $this->prepare(" AND `id`=?", $aParams['id']);
                 $sWhereClause = $this->prepare(" AND `id`=?", $aParams['id']);
                 $sLimitClause = " LIMIT 1";
                 $sLimitClause = " LIMIT 1";
                 break;
                 break;
+
+            case 'order':
+            	$sWhereClause = $this->prepare(" AND `order`=?", $aParams['order']);
+                $sLimitClause = " LIMIT 1";
+                break;
         }
         }
 
 
         $aMethod['params'][0] = "SELECT * FROM `" . $this->_sPrefix . "transactions_pending` WHERE 1 " . $sWhereClause . $sLimitClause;
         $aMethod['params'][0] = "SELECT * FROM `" . $this->_sPrefix . "transactions_pending` WHERE 1 " . $sWhereClause . $sLimitClause;
         return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
         return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
     }
     }
 
 
-    public function insertOrderPending($iClientId, $sProviderName, $aCartInfo)
+    public function insertOrderPending($iClientId, $sType, $sProvider, $aCartInfo)
     {
     {
         $sItems = "";
         $sItems = "";
         foreach($aCartInfo['items'] as $aItem)
         foreach($aCartInfo['items'] as $aItem)
@@ -189,10 +219,11 @@ class BxPaymentDb extends BxBaseModPaymentDb
         $sQuery = $this->prepare("INSERT INTO `" . $this->_sPrefix . "transactions_pending` SET
         $sQuery = $this->prepare("INSERT INTO `" . $this->_sPrefix . "transactions_pending` SET
                     `client_id`=?,
                     `client_id`=?,
                     `seller_id`=?,
                     `seller_id`=?,
+                    `type`=?,
+                    `provider`=?,
                     `items`=?,
                     `items`=?,
                     `amount`=?,
                     `amount`=?,
-                    `provider`=?,
-                    `date`=UNIX_TIMESTAMP()", $iClientId, $aCartInfo['vendor_id'], trim($sItems, ':'), $aCartInfo['items_price'], $sProviderName);
+                    `date`=UNIX_TIMESTAMP()", $iClientId, $aCartInfo['vendor_id'], $sType, $sProvider, trim($sItems, ':'), $aCartInfo['items_price']);
 
 
         return (int)$this->query($sQuery) > 0 ? $this->lastId() : 0;
         return (int)$this->query($sQuery) > 0 ? $this->lastId() : 0;
     }
     }
@@ -203,7 +234,7 @@ class BxPaymentDb extends BxBaseModPaymentDb
         return (int)$this->query($sQuery) > 0;
         return (int)$this->query($sQuery) > 0;
     }
     }
 
 
-    public function cancelOrderPending($mixedId)
+    public function deleteOrderPending($mixedId)
     {
     {
     	if(!is_array($mixedId))
     	if(!is_array($mixedId))
     		$mixedId = array($mixedId);
     		$mixedId = array($mixedId);
@@ -233,9 +264,9 @@ class BxPaymentDb extends BxBaseModPaymentDb
                 $sWhereClause = $this->prepare(" AND `tt`.`pending_id`=?", $aParams['pending_id']);
                 $sWhereClause = $this->prepare(" AND `tt`.`pending_id`=?", $aParams['pending_id']);
                 break;
                 break;
 
 
-            case 'order_id':
+            case 'license':
                 $aMethod['name'] = 'getAll';
                 $aMethod['name'] = 'getAll';
-                $sWhereClause = $this->prepare(" AND `tt`.`order_id`=?", $aParams['order_id']);
+                $sWhereClause = $this->prepare(" AND `tt`.`license`=?", $aParams['license']);
                 break;
                 break;
 
 
             case 'mixed':
             case 'mixed':
@@ -248,7 +279,7 @@ class BxPaymentDb extends BxBaseModPaymentDb
 
 
         $aMethod['params'][0] = "SELECT
         $aMethod['params'][0] = "SELECT
         		`tt`.`id`,
         		`tt`.`id`,
-                `tt`.`order_id`,
+                `tt`.`license`,
                 `tt`.`client_id`,
                 `tt`.`client_id`,
                 `tt`.`seller_id`,
                 `tt`.`seller_id`,
                 `tt`.`module_id`,
                 `tt`.`module_id`,
@@ -277,7 +308,7 @@ class BxPaymentDb extends BxBaseModPaymentDb
         return (int)$this->query($sQuery) > 0;
         return (int)$this->query($sQuery) > 0;
     }
     }
 
 
-    public function cancelOrderProcessed($mixedId)
+    public function deleteOrderProcessed($mixedId)
     {
     {
     	if(!is_array($mixedId))
     	if(!is_array($mixedId))
     		$mixedId = array($mixedId);
     		$mixedId = array($mixedId);

+ 17 - 16
modules/boonex/payment/classes/BxPaymentDetails.php

@@ -85,15 +85,14 @@ class BxPaymentDetails extends BxDol
         );
         );
 
 
         $bCollapsed = $this->_bCollapseFirst;
         $bCollapsed = $this->_bCollapseFirst;
-        $iProviderId = 0;
-        $sProviderName = "";
+        $iProvider = 0;
+        $sProvider = "";
+        $oProvider = null;
         $aUserValues = $this->_oModule->_oDb->getFormData($iUserId);
         $aUserValues = $this->_oModule->_oDb->getFormData($iUserId);
         foreach($aInputs as $aInput) {
         foreach($aInputs as $aInput) {
-            $sReturnDataUrl = $this->_oModule->_oConfig->getUrl('return_data') . $sProviderName . '/' . $iUserId;
-
-            if($iProviderId != $aInput['provider_id']) {
-                if(!empty($iProviderId))
-                    $aForm['inputs']['provider_' . $iProviderId . '_end'] = array(
+            if($iProvider != $aInput['provider_id']) {
+                if(!empty($iProvider))
+                    $aForm['inputs']['provider_' . $iProvider . '_end'] = array(
                         'type' => 'block_end'
                         'type' => 'block_end'
                     );
                     );
 
 
@@ -104,8 +103,9 @@ class BxPaymentDetails extends BxDol
                     'collapsed' => $bCollapsed
                     'collapsed' => $bCollapsed
                 );
                 );
 
 
-                $iProviderId = $aInput['provider_id'];
-                $sProviderName = $aInput['provider_name'];
+                $iProvider = $aInput['provider_id'];
+                $sProvider = $aInput['provider_name'];
+                $oProvider = $this->_oModule->getObjectProvider($sProvider);
                 $bCollapsed = true;
                 $bCollapsed = true;
             }
             }
 
 
@@ -116,7 +116,7 @@ class BxPaymentDetails extends BxDol
                 'value' => isset($aUserValues[$aInput['id']]['value']) ? $aUserValues[$aInput['id']]['value'] : '',
                 'value' => isset($aUserValues[$aInput['id']]['value']) ? $aUserValues[$aInput['id']]['value'] : '',
                 'info' => _t($aInput['description']),
                 'info' => _t($aInput['description']),
             	'attrs' => array(
             	'attrs' => array(
-            		'bx-data-provider' => $iProviderId
+            		'bx-data-provider' => $iProvider
             	),
             	),
                 'checker' => array (
                 'checker' => array (
                     'func' => $aInput['check_type'],
                     'func' => $aInput['check_type'],
@@ -147,7 +147,7 @@ class BxPaymentDetails extends BxDol
 
 
 				 case 'value':
 				 case 'value':
 				 	if(str_replace($aInput['provider_option_prefix'], '', $aInput['name']) == 'return_url')
 				 	if(str_replace($aInput['provider_option_prefix'], '', $aInput['name']) == 'return_url')
-				 		$aForm['inputs'][$aInput['name']]['value'] = $sReturnDataUrl;
+				 		$aForm['inputs'][$aInput['name']]['value'] = $oProvider->getReturnDataUrl($iUserId);
 				 	break;
 				 	break;
             }
             }
 
 
@@ -155,7 +155,7 @@ class BxPaymentDetails extends BxDol
                 $aForm['inputs'][$aInput['name']] = array_merge($aForm['inputs'][$aInput['name']], $aAddon);
                 $aForm['inputs'][$aInput['name']] = array_merge($aForm['inputs'][$aInput['name']], $aAddon);
         }
         }
 
 
-        $aForm['inputs']['provider_' . $iProviderId . '_end'] = array(
+        $aForm['inputs']['provider_' . $iProvider . '_end'] = array(
             'type' => 'block_end'
             'type' => 'block_end'
         );
         );
         $aForm['inputs']['submit'] = array(
         $aForm['inputs']['submit'] = array(
@@ -172,16 +172,17 @@ class BxPaymentDetails extends BxDol
             $aOptions = $this->_oModule->_oDb->getOptions();
             $aOptions = $this->_oModule->_oDb->getOptions();
             foreach($aOptions as $aOption) {
             foreach($aOptions as $aOption) {
             	$sValue = bx_get($aOption['name']) !== false ? bx_get($aOption['name']) : '';
             	$sValue = bx_get($aOption['name']) !== false ? bx_get($aOption['name']) : '';
-                $this->_oModule->_oDb->updateOption($iUserId, $aOption['id'], bx_process_input($sValue, BX_TAGS_STRIP));
+                $this->_oModule->_oDb->updateOption($iUserId, $aOption['id'], bx_process_input($sValue));
             }
             }
 
 
             header('Location: ' . $oForm->aFormAttrs['action']);
             header('Location: ' . $oForm->aFormAttrs['action']);
         }
         }
         else {
         else {
         	foreach($oForm->aInputs as $aInput)
         	foreach($oForm->aInputs as $aInput)
-        		if(!empty($aInput['error'])) {
-        			$iProviderId = (int)$aInput['attrs']['bx-data-provider'];
-        			$oForm->aInputs['provider_' . $iProviderId . '_begin']['collapsed'] = false;
+        		if(!empty($aInput['error']) && !empty($aInput['attrs']['bx-data-provider'])) {
+        			$sProviderBlock = 'provider_' . (int)$aInput['attrs']['bx-data-provider'] . '_begin';
+        			if(!empty($oForm->aInputs[$sProviderBlock]))
+        				$oForm->aInputs[$sProviderBlock]['collapsed'] = false;
         		}
         		}
 
 
 			return $oForm->getCode();
 			return $oForm->getCode();

+ 1 - 1
modules/boonex/payment/classes/BxPaymentGridPending.php

@@ -54,7 +54,7 @@ class BxPaymentGridPending extends BxBaseModPaymentGridOrders
 				'error_msg' => 'Manually processed'
 				'error_msg' => 'Manually processed'
 			));
 			));
 
 
-            if($this->_oModule->getObjectCart()->updateInfo($iId))
+            if($this->_oModule->registerPayment($iId))
                 $aRes = array('grid' => $this->getCode(false), 'blink' => $iId);
                 $aRes = array('grid' => $this->getCode(false), 'blink' => $iId);
             else
             else
                 $aRes = array('msg' => _t($this->_sLangsPrefix . 'err_cannot_perform'));
                 $aRes = array('msg' => _t($this->_sLangsPrefix . 'err_cannot_perform'));

+ 6 - 5
modules/boonex/payment/classes/BxPaymentGridProcessed.php

@@ -75,12 +75,13 @@ class BxPaymentGridProcessed extends BxBaseModPaymentGridOrders
 			}
 			}
 
 
         	$mixedResult = $this->_oModule->getObjectOrders()->addOrder(array(
         	$mixedResult = $this->_oModule->getObjectOrders()->addOrder(array(
-        		'provider' => 'manual',
-        		'error_code' => 0,
-        		'error_msg' => 'Manually processed',
-        		'seller_id' => $oForm->getCleanValue('seller_id'),
         		'client_id' => $oForm->getCleanValue('client_id'),
         		'client_id' => $oForm->getCleanValue('client_id'),
+        		'seller_id' => $oForm->getCleanValue('seller_id'),
+        		'provider' => 'manual',
+        		'type' => BX_PAYMENT_TYPE_SINGLE,
         		'order' => $oForm->getCleanValue('order'),
         		'order' => $oForm->getCleanValue('order'),
+        		'error_code' => 0,
+        		'error_msg' => 'Manually processed',        		
         		'module_id' => $oForm->getCleanValue('module_id'),
         		'module_id' => $oForm->getCleanValue('module_id'),
         		'items' => $aItems
         		'items' => $aItems
         	));
         	));
@@ -88,7 +89,7 @@ class BxPaymentGridProcessed extends BxBaseModPaymentGridOrders
         		return echoJson($mixedResult);
         		return echoJson($mixedResult);
 
 
 			$iPendingId = (int)$mixedResult;
 			$iPendingId = (int)$mixedResult;
-        	if(!$this->_oModule->getObjectCart()->updateInfo($iPendingId))
+        	if(!$this->_oModule->registerPayment($iPendingId))
         		return echoJson(array('msg' => _t($this->_sLangsPrefix . 'err_cannot_perform')));
         		return echoJson(array('msg' => _t($this->_sLangsPrefix . 'err_cannot_perform')));
 
 
 			$aOrders = $this->_oModule->_oDb->getOrderProcessed(array('type' => 'pending_id', 'pending_id' => $iPendingId, 'with_key' => 'id'));
 			$aOrders = $this->_oModule->_oDb->getOrderProcessed(array('type' => 'pending_id', 'pending_id' => $iPendingId, 'with_key' => 'id'));

+ 12 - 12
modules/boonex/payment/classes/BxPaymentJoin.php

@@ -29,8 +29,8 @@ class BxPaymentJoin extends BxBaseModPaymentJoin
      */
      */
 	public function serviceGetBlockJoin()
 	public function serviceGetBlockJoin()
     {
     {
-    	$sSessionKeyPending = $this->_oModule->_oConfig->getKey('session_key_pending');
-    	$sRequestKeyPending = $this->_oModule->_oConfig->getKey('request_key_pending');
+    	$sSessionKeyPending = $this->_oModule->_oConfig->getKey('KEY_SESSION_PENDING');
+    	$sRequestKeyPending = $this->_oModule->_oConfig->getKey('KEY_REQUEST_PENDING');
 
 
     	$oSession = BxDolSession::getInstance();
     	$oSession = BxDolSession::getInstance();
     	$iPendingId = (int)$oSession->getValue($sSessionKeyPending);
     	$iPendingId = (int)$oSession->getValue($sSessionKeyPending);
@@ -63,7 +63,7 @@ class BxPaymentJoin extends BxBaseModPaymentJoin
         	return;
         	return;
 		//--- 'System' -> 'Join after Payment' for Alerts Engine ---//
 		//--- 'System' -> 'Join after Payment' for Alerts Engine ---//
 
 
-    	$sContent = BxDolService::call('system', 'create_account_form', array(array('action' => $this->_oModule->_oConfig->getUrl('join'))), 'TemplServiceAccount');
+    	$sContent = BxDolService::call('system', 'create_account_form', array(array('action' => $this->_oModule->_oConfig->getUrl('URL_JOIN'))), 'TemplServiceAccount');
     	if(!empty($sOverrideError))
     	if(!empty($sOverrideError))
     		$sContent = MsgBox(_t($sOverrideError)) . $sContent;
     		$sContent = MsgBox(_t($sOverrideError)) . $sContent;
 
 
@@ -72,29 +72,29 @@ class BxPaymentJoin extends BxBaseModPaymentJoin
 		);
 		);
     }
     }
 
 
-	public function performJoin($iPendingId, $aPayment = array())
+	public function performJoin($iPendingId, $sClientName = '', $sClientEmail = '')
     {
     {
-		BxDolSession::getInstance()->setValue($this->_oModule->_oConfig->getKey('session_key_pending'), (int)$iPendingId);
+		BxDolSession::getInstance()->setValue($this->_oModule->_oConfig->getKey('KEY_SESSION_PENDING'), (int)$iPendingId);
 
 
-		if(!empty($aPayment['payer_name']) && !empty($aPayment['payer_email'])) {
+		if(!empty($sClientName) && !empty($sClientEmail)) {
 			bx_import('BxDolEmailTemplates');
 			bx_import('BxDolEmailTemplates');
 			$oEmailTemplates = new BxDolEmailTemplates();
 			$oEmailTemplates = new BxDolEmailTemplates();
 
 
 			$aTemplate = $oEmailTemplates->parseTemplate($this->_oModule->_oConfig->getPrefix('general') . 'paid_need_join', array(
 			$aTemplate = $oEmailTemplates->parseTemplate($this->_oModule->_oConfig->getPrefix('general') . 'paid_need_join', array(
-				'RealName' => $aPayment['payer_name'],
-				'JoinLink' => $this->_oModule->_oConfig->getUrl('join', array($this->_oModule->_oConfig->getKey('request_key_pending') => (int)$iPendingId))
+				'RealName' => $sClientName,
+				'JoinLink' => $this->_oModule->_oConfig->getUrl('URL_JOIN', array($this->_oModule->_oConfig->getKey('KEY_REQUEST_PENDING') => (int)$iPendingId))
 			));
 			));
 
 
-			sendMail($aPayment['payer_email'], $aTemplate['Subject'], $aTemplate['Body'], 0, array(), 'html', false, true);
+			sendMail($sClientEmail, $aTemplate['Subject'], $aTemplate['Body'], 0, array(), 'html', false, true);
 		}
 		}
 
 
-		header('Location: ' . $this->_oModule->_oConfig->getUrl('join'));
+		header('Location: ' . $this->_oModule->_oConfig->getUrl('URL_JOIN'));
 		exit;
 		exit;
 	}
 	}
 
 
 	public function onProfileJoin($iProfileId)
 	public function onProfileJoin($iProfileId)
     {
     {
-    	$sSessionKeyPending = $this->_oModule->_oConfig->getKey('session_key_pending');
+    	$sSessionKeyPending = $this->_oModule->_oConfig->getKey('KEY_SESSION_PENDING');
 
 
     	$oSession = BxDolSession::getInstance();
     	$oSession = BxDolSession::getInstance();
 		$iPendingId = (int)$oSession->getValue($sSessionKeyPending);
 		$iPendingId = (int)$oSession->getValue($sSessionKeyPending);
@@ -109,7 +109,7 @@ class BxPaymentJoin extends BxBaseModPaymentJoin
 		if(!$this->_oModule->_oDb->updateOrderPending($iPendingId, array('client_id' => $iProfileId)))
 		if(!$this->_oModule->_oDb->updateOrderPending($iPendingId, array('client_id' => $iProfileId)))
 			return;
 			return;
 
 
-		$this->_oModule->getObjectCart()->updateInfo($iPendingId);
+		$this->_oModule->registerPayment($iPendingId);
 
 
 		$oSession->unsetValue($sSessionKeyPending);
 		$oSession->unsetValue($sSessionKeyPending);
     }
     }

+ 126 - 28
modules/boonex/payment/classes/BxPaymentModule.php

@@ -9,6 +9,9 @@
  * @{
  * @{
  */
  */
 
 
+define('BX_PAYMENT_TYPE_SINGLE', 'single');
+define('BX_PAYMENT_TYPE_RECURRING', 'recurring');
+
 define('BX_PAYMENT_ORDERS_TYPE_PENDING', 'pending');
 define('BX_PAYMENT_ORDERS_TYPE_PENDING', 'pending');
 define('BX_PAYMENT_ORDERS_TYPE_PROCESSED', 'processed');
 define('BX_PAYMENT_ORDERS_TYPE_PROCESSED', 'processed');
 define('BX_PAYMENT_ORDERS_TYPE_SUBSCRIPTION', 'subscription');
 define('BX_PAYMENT_ORDERS_TYPE_SUBSCRIPTION', 'subscription');
@@ -147,7 +150,7 @@ class BxPaymentModule extends BxBaseModPaymentModule
      * Check transaction(s) in database which satisty all conditions.
      * Check transaction(s) in database which satisty all conditions.
      *
      *
      * @param array $aConditions an array of pears('key' => 'value'). Available keys are the following:
      * @param array $aConditions an array of pears('key' => 'value'). Available keys are the following:
-     * a. order_id - internal order ID (string)
+     * a. license - internal license (string)
      * b. client_id - client's ID (integer)
      * b. client_id - client's ID (integer)
      * c. seller_id - seller's ID (integer)
      * c. seller_id - seller's ID (integer)
      * d. module_id - modules's where the purchased product is located. (integer)
      * d. module_id - modules's where the purchased product is located. (integer)
@@ -182,12 +185,12 @@ class BxPaymentModule extends BxBaseModPaymentModule
 			$sProvider = bx_process_input(bx_get('provider'));
 			$sProvider = bx_process_input(bx_get('provider'));
 			$aItems = bx_get('items');
 			$aItems = bx_get('items');
 
 
-			$sError = $this->serviceInitializeCheckout($iVendorId, $sProvider, $aItems);
-			if(!empty($sError))
-	    		return $this->_oTemplate->displayPageCodeError($sError, false);
+			$mixedResult = $this->serviceInitializeCheckout(BX_PAYMENT_TYPE_SINGLE, $iVendorId, $sProvider, $aItems);
+			if($mixedResult !== true)
+	    		return $this->_oTemplate->displayPageCodeError($mixedResult);
 		}
 		}
 
 
-        header('Location: ' . $this->_oConfig->getUrl('cart'));
+        header('Location: ' . $this->_oConfig->getUrl('URL_CART'));
         exit;
         exit;
     }
     }
 
 
@@ -215,34 +218,42 @@ class BxPaymentModule extends BxBaseModPaymentModule
 		echoJson($aResult);
 		echoJson($aResult);
     }
     }
 
 
+    public function actionSubscribe($iVendorId, $iModuleId, $iItemId, $iItemCount = 1)
+    {
+        $aResult = $this->getObjectCart()->serviceSubscribe($iVendorId, $iModuleId, $iItemId, $iItemCount);
+		echoJson($aResult);
+    }
+
 
 
     /**
     /**
      * Payment Processing Methods
      * Payment Processing Methods
      */
      */
-	public function serviceInitializeCheckout($iVendorId, $sProvider, $aItems = array())
+	public function serviceInitializeCheckout($sType, $iVendorId, $sProvider, $aItems = array())
 	{
 	{
 		if(!is_array($aItems))
 		if(!is_array($aItems))
 			$aItems = array($aItems);
 			$aItems = array($aItems);
 
 
 		$iVendorId = (int)$iVendorId;
 		$iVendorId = (int)$iVendorId;
         if($iVendorId == BX_PAYMENT_EMPTY_ID)
         if($iVendorId == BX_PAYMENT_EMPTY_ID)
-            return MsgBox(_t($this->_sLangsPrefix . 'err_unknown_vendor'));
+            return $this->_sLangsPrefix . 'err_unknown_vendor';
 
 
 		$oProvider = $this->getObjectProvider($sProvider, $iVendorId);
 		$oProvider = $this->getObjectProvider($sProvider, $iVendorId);
         if($oProvider === false)
         if($oProvider === false)
-        	return MsgBox(_t($this->_sLangsPrefix . 'err_incorrect_provider'));
+        	return $this->_sLangsPrefix . 'err_incorrect_provider';
 
 
-        $aInfo = $this->getObjectCart()->getInfo($this->_iUserId, $iVendorId, $aItems);
+        $aInfo = $this->getObjectCart()->getInfo($sType, $this->_iUserId, $iVendorId, $aItems);
         if(empty($aInfo) || $aInfo['vendor_id'] == BX_PAYMENT_EMPTY_ID || empty($aInfo['items']))
         if(empty($aInfo) || $aInfo['vendor_id'] == BX_PAYMENT_EMPTY_ID || empty($aInfo['items']))
-            return MsgBox(_t($this->_sLangsPrefix . 'err_empty_order'));
+            return $this->_sLangsPrefix . 'err_empty_order';
 
 
 		/*
 		/*
 		 * Process FREE (price = 0) items for LOGGED IN members
 		 * Process FREE (price = 0) items for LOGGED IN members
 		 * WITHOUT processing via payment provider.
 		 * WITHOUT processing via payment provider.
 		 */
 		 */
 		$bProcessedFree = false;
 		$bProcessedFree = false;
+		$sKeyPriceSingle = $this->_oConfig->getKey('KEY_ARRAY_PRICE_SINGLE');
+		$sKeyPriceRecurring = $this->_oConfig->getKey('KEY_ARRAY_PRICE_RECURRING');
 		foreach($aInfo['items'] as $iIndex => $aItem)
 		foreach($aInfo['items'] as $iIndex => $aItem)
-			if((int)$aInfo['client_id'] != 0 && (float)$aItem['price'] == 0) {
+			if((int)$aInfo['client_id'] != 0 && (float)$aItem[$sKeyPriceSingle] == 0 && (float)$aItem[$sKeyPriceRecurring] == 0) {
 				$aItemInfo = $this->callRegisterCartItem((int)$aItem['module_id'], array($aInfo['client_id'], $aInfo['vendor_id'], $aItem['id'], $aItem['quantity'], $this->_oConfig->getLicense()));
 				$aItemInfo = $this->callRegisterCartItem((int)$aItem['module_id'], array($aInfo['client_id'], $aInfo['vendor_id'], $aItem['id'], $aItem['quantity'], $this->_oConfig->getLicense()));
 	            if(is_array($aItemInfo) && !empty($aItemInfo))
 	            if(is_array($aItemInfo) && !empty($aItemInfo))
 	            	$bProcessedFree = true;
 	            	$bProcessedFree = true;
@@ -256,11 +267,11 @@ class BxPaymentModule extends BxBaseModPaymentModule
 			}
 			}
 
 
 		if(empty($aInfo['items']))
 		if(empty($aInfo['items']))
-            return MsgBox(_t($this->_sLangsPrefix . ($bProcessedFree ? 'msg_successfully_processed_free' : 'err_empty_order')));
+            return $this->_sLangsPrefix . ($bProcessedFree ? 'msg_successfully_processed_free' : 'err_empty_order');
 
 
-        $iPendingId = $this->_oDb->insertOrderPending($this->_iUserId, $sProvider, $aInfo);
+        $iPendingId = $this->_oDb->insertOrderPending($this->_iUserId, $sType, $sProvider, $aInfo);
         if(empty($iPendingId))
         if(empty($iPendingId))
-            return MsgBox(_t($this->_sLangsPrefix . 'err_access_db'));
+            return $this->_sLangsPrefix . 'err_access_db';
 
 
 		/*
 		/*
 		 * Perform Join WITHOUT processing via payment provider
 		 * Perform Join WITHOUT processing via payment provider
@@ -270,7 +281,7 @@ class BxPaymentModule extends BxBaseModPaymentModule
 			reset($aInfo['items']);
 			reset($aInfo['items']);
 			$aItem = current($aInfo['items']);
 			$aItem = current($aInfo['items']);
 
 
-			if(!empty($aItem) && $aItem['price'] == 0) {
+			if(!empty($aItem) && $this->_oConfig->getPrice($sType, $aItem)) {
 				$this->_oDb->updateOrderPending($iPendingId, array(
 				$this->_oDb->updateOrderPending($iPendingId, array(
 		            'order' => $this->_oConfig->getLicense(),
 		            'order' => $this->_oConfig->getLicense(),
 		            'error_code' => '1',
 		            'error_code' => '1',
@@ -281,11 +292,7 @@ class BxPaymentModule extends BxBaseModPaymentModule
 			}
 			}
 		}
 		}
 
 
-		$sError = $oProvider->initializeCheckout($iPendingId, $aInfo);
-		if(!empty($sError))
-			return MsgBox($sError);
-
-        return true;
+		return $oProvider->initializeCheckout($iPendingId, $aInfo);
 	}
 	}
 
 
     public function actionFinalizeCheckout($sProvider, $mixedVendorId = "")
     public function actionFinalizeCheckout($sProvider, $mixedVendorId = "")
@@ -304,31 +311,38 @@ class BxPaymentModule extends BxBaseModPaymentModule
 
 
 		//--- Check "Pay Before Join" situation
 		//--- Check "Pay Before Join" situation
 		if((int)$aPending['client_id'] == 0)
 		if((int)$aPending['client_id'] == 0)
-			$this->getObjectJoin()->performJoin((int)$aPending['id'], $aResult);
+			$this->getObjectJoin()->performJoin((int)$aPending['id'], isset($aResult['client_name']) ? $aResult['client_name'] : '', isset($aResult['client_email']) ? $aResult['client_email'] : '');
 
 
 		//--- Register payment for purchased items in associated modules 
 		//--- Register payment for purchased items in associated modules 
-		$this->getObjectCart()->updateInfo($aPending);
+		if(!empty($aResult['paid']))
+			$this->registerPayment($aPending);
 
 
 		if($oProvider->needRedirect()) {
 		if($oProvider->needRedirect()) {
-			header('Location: ' . $this->_oConfig->getUrl('return'));
+			header('Location: ' . $this->_oConfig->getUrl('URL_RETURN'));
 			exit;
 			exit;
 		}
 		}
 
 
-		return $this->_oTemplate->displayPageCodeResponse($aResult['message']);
+		$this->_oTemplate->displayPageCodeResponse($aResult['message']);
     }
     }
 
 
-    public function actionCheckoutFinished($sProvider, $mixedVendorId = "")
+    public function actionFinalizedCheckout($sProvider, $mixedVendorId = "")
     {
     {
         $oProvider = $this->getObjectProvider($sProvider, $mixedVendorId);
         $oProvider = $this->getObjectProvider($sProvider, $mixedVendorId);
         if($oProvider === false)
         if($oProvider === false)
         	return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_incorrect_provider');
         	return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_incorrect_provider');
 
 
-        $aResult = $oProvider->checkoutFinished();
-
+        $aResult = $oProvider->finalizedCheckout();
         $this->_oTemplate->displayPageCodeResponse($aResult['message']);
         $this->_oTemplate->displayPageCodeResponse($aResult['message']);
-        exit;
     }
     }
 
 
+    public function actionProcessEvent($sProvider, $mixedVendorId = "")
+    {
+    	$oProvider = $this->getObjectProvider($sProvider, $mixedVendorId);
+        if($oProvider === false)
+        	return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_incorrect_provider');
+
+		$oProvider->processEvent();
+    }
 
 
     public function onProfileJoin($iProfileId)
     public function onProfileJoin($iProfileId)
     {
     {
@@ -359,6 +373,90 @@ class BxPaymentModule extends BxBaseModPaymentModule
 
 
         return $aCheckResult[CHECK_ACTION_MESSAGE];
         return $aCheckResult[CHECK_ACTION_MESSAGE];
     }
     }
+
+	public function registerPayment($mixedPending)
+    {
+    	$aPending = is_array($mixedPending) ? $mixedPending : $this->_oDb->getOrderPending(array('type' => 'id', 'id' => (int)$mixedPending));
+    	if(empty($aPending) || !is_array($aPending))
+    		return false;
+
+		if((int)$aPending['processed'] == 1)
+			return true;
+
+		$sType = $aPending['type'];
+		$bTypeSingle = $sType == BX_PAYMENT_TYPE_SINGLE;
+
+		$iClientId = (int)$aPending['client_id'];
+		$sLicense = $this->_oConfig->getLicense();
+
+		$sCartItems = '';
+		if($bTypeSingle)
+			$sCartItems = $this->_oDb->getCartItems($iClientId);
+
+        $aItems = $this->_oConfig->descriptorsM2A($aPending['items']);
+        foreach($aItems as $aItem) {
+        	$sMethod = $bTypeSingle ? 'callRegisterCartItem' : 'callRegisterSubscriptionItem';
+        	$aItemInfo = $this->$sMethod((int)$aItem['module_id'], array($aPending['client_id'], $aPending['seller_id'], $aItem['item_id'], $aItem['item_count'], $aPending['order'], $sLicense));
+            if(empty($aItemInfo) || !is_array($aItemInfo))
+                continue;
+
+            $this->_oDb->insertOrderProcessed(array(
+                'pending_id' => $aPending['id'],
+                'client_id' => $aPending['client_id'],
+                'seller_id' => $aPending['seller_id'],
+                'module_id' => $aItem['module_id'],
+                'item_id' => $aItem['item_id'],
+                'item_count' => $aItem['item_count'],
+                'amount' => $this->_oConfig->getPrice($sType, $aItem) * $aItem['item_count'],
+            	'license' => $sLicense,
+            ));
+
+            if($bTypeSingle)
+            	$sCartItems = trim(preg_replace("'" . $this->_oConfig->descriptorA2S($aItem) . ":?'", "", $sCartItems), ":");
+        }
+
+        if($bTypeSingle)
+			$this->_oDb->setCartItems($iClientId, $sCartItems);
+
+        return $this->_oDb->updateOrderPending($aPending['id'], array('processed' => 1));
+    }
+
+	public function refundPayment($mixedPending)
+	{
+		$aPending = is_array($mixedPending) ? $mixedPending : $this->_oDb->getOrderPending(array('type' => 'id', 'id' => (int)$mixedPending));
+    	if(empty($aPending) || !is_array($aPending))
+    		return false;
+
+		$bTypeSingle = $aPending['type'] == BX_PAYMENT_TYPE_SINGLE;
+
+		$iCanceled = 0;
+		$aOrders = $this->_oDb->getOrderProcessed(array('type' => 'pending_id', 'pending_id' => (int)$aPending['id']));
+		foreach($aOrders as $aOrder) {
+			$sMethod = $bTypeSingle ? 'callUnregisterCartItem' : 'callUnregisterSubscriptionItem';
+			$bResult = $this->$sMethod((int)$aOrder['module_id'], array($aOrder['client_id'], $aOrder['seller_id'], $aOrder['item_id'], $aOrder['item_count'], $aPending['order'], $aOrder['license']));
+			if(!$bResult)
+                continue;
+
+            if($this->_oDb->deleteOrderProcessed($aOrder['id']))
+            	$iCanceled++;
+		}
+
+		if($iCanceled != count($aOrders))
+			return false;
+
+		return $this->_oDb->deleteOrderPending($aPending['id']);
+	}
+
+	public function cancelSubscription($mixedPending)
+	{
+		$aPending = is_array($mixedPending) ? $mixedPending : $this->_oDb->getOrderPending(array('type' => 'id', 'id' => (int)$mixedPending));
+    	if(empty($aPending) || !is_array($aPending) || $aPending['type'] != BX_PAYMENT_TYPE_RECURRING)
+    		return false;
+
+		$aItems = $this->_oConfig->descriptorsM2A($aPending['items']);
+        foreach($aItems as $aItem)
+			$this->callCancelSubscriptionItem((int)$aItem['module_id'], array($aPending['client_id'], $aPending['seller_id'], $aItem['item_id'], $aItem['item_count'], $aPending['order']));
+	}
 }
 }
 
 
 /** @} */
 /** @} */

+ 5 - 5
modules/boonex/payment/classes/BxPaymentOrders.php

@@ -56,7 +56,7 @@ class BxPaymentOrders extends BxBaseModPaymentOrders
         	if(!$this->_oModule->isAllowedSell(array('module_id' => $aData['module_id'], 'item_id' => $aItem['id']), true))
         	if(!$this->_oModule->isAllowedSell(array('module_id' => $aData['module_id'], 'item_id' => $aItem['id']), true))
         		continue;
         		continue;
 
 
-            $aCartInfo['items_price'] += $aItem['price'] * $aItem['quantity'];
+            $aCartInfo['items_price'] += $this->_oModule->_oConfig->getPrice($aData['type'], $aItem) * $aItem['quantity'];
             $aCartInfo['items'][] = array(
             $aCartInfo['items'][] = array(
                 'vendor_id' => $iSellerId,
                 'vendor_id' => $iSellerId,
                 'module_id' => $aData['module_id'],
                 'module_id' => $aData['module_id'],
@@ -65,7 +65,7 @@ class BxPaymentOrders extends BxBaseModPaymentOrders
             );
             );
         }
         }
 
 
-        $iPendingId = $this->_oModule->_oDb->insertOrderPending($aData['client_id'], $aData['provider'], $aCartInfo);
+        $iPendingId = $this->_oModule->_oDb->insertOrderPending($aData['client_id'], $aData['type'], $aData['provider'], $aCartInfo);
         $this->_oModule->_oDb->updateOrderPending($iPendingId, array(
         $this->_oModule->_oDb->updateOrderPending($iPendingId, array(
             'order' => $sOrder,
             'order' => $sOrder,
             'error_code' => $aData['error_code'],
             'error_code' => $aData['error_code'],
@@ -82,15 +82,15 @@ class BxPaymentOrders extends BxBaseModPaymentOrders
 
 
     public function cancel($sType, $iOrderId)
     public function cancel($sType, $iOrderId)
     {
     {
-    	$sMethodName = "getOrder" . bx_gen_method_name($sType);
+    	$sMethodName = 'getOrder' . bx_gen_method_name($sType);
     	$aOrder = $this->_oModule->_oDb->$sMethodName(array('type' => 'id', 'id' => $iOrderId));
     	$aOrder = $this->_oModule->_oDb->$sMethodName(array('type' => 'id', 'id' => $iOrderId));
 		if(empty($aOrder) || !is_array($aOrder))
 		if(empty($aOrder) || !is_array($aOrder))
 	    	return true;
 	    	return true;
 
 
-		if($sType == BX_PAYMENT_ORDERS_TYPE_PROCESSED && !BxDolService::call((int)$aOrder['module_id'], 'unregister_cart_item', array($aOrder['client_id'], $aOrder['seller_id'], $aOrder['item_id'], $aOrder['item_count'], $aOrder['order_id'])))
+		if($sType == BX_PAYMENT_ORDERS_TYPE_PROCESSED && !$this->_oModule->callUnregisterCartItem((int)$aOrder['module_id'], array($aOrder['client_id'], $aOrder['seller_id'], $aOrder['item_id'], $aOrder['item_count'], $aOrder['license'])))
 			return false;
 			return false;
 
 
-		$sMethodName = "cancelOrder" . bx_gen_method_name($sType);
+		$sMethodName = 'deleteOrder' . bx_gen_method_name($sType);
 		if(!$this->_oModule->_oDb->$sMethodName($iOrderId))
 		if(!$this->_oModule->_oDb->$sMethodName($iOrderId))
 			return false;
 			return false;
 
 

+ 6 - 12
modules/boonex/payment/classes/BxPaymentProvider2Checkout.php

@@ -28,10 +28,10 @@ class BxPaymentProvider2Checkout extends BxBaseModPaymentProvider implements iBx
         parent::__construct($aConfig);
         parent::__construct($aConfig);
 
 
         $this->_bRedirectOnResult = true;
         $this->_bRedirectOnResult = true;
-        $this->_sDataReturnUrl = $this->_oModule->_oConfig->getUrl('return_data') . $this->_sName . '/';
+        $this->_sDataReturnUrl = $this->_oModule->_oConfig->getUrl('URL_RETURN_DATA') . $this->_sName . '/';
     }
     }
 
 
-    public function initializeCheckout($iPendingId, $aCartInfo, $bRecurring = false, $iRecurringDays = 0)
+    public function initializeCheckout($iPendingId, $aCartInfo)
     {
     {
     	$bTest = (int)$this->getOption('mode') == TUCO_MODE_TEST;
     	$bTest = (int)$this->getOption('mode') == TUCO_MODE_TEST;
 
 
@@ -67,8 +67,6 @@ class BxPaymentProvider2Checkout extends BxBaseModPaymentProvider implements iBx
         return $this->_registerCheckout($aData);
         return $this->_registerCheckout($aData);
     }
     }
 
 
-	public function checkoutFinished() {}
-
     /**
     /**
      *
      *
      * @param $aData - data from payment provider.
      * @param $aData - data from payment provider.
@@ -85,7 +83,6 @@ class BxPaymentProvider2Checkout extends BxBaseModPaymentProvider implements iBx
             return array('code' => 2, 'message' => _t('_payment_2co_err_no_vendor_given'));
             return array('code' => 2, 'message' => _t('_payment_2co_err_no_vendor_given'));
 
 
         $aResult = $this->_validateCheckout($aData);
         $aResult = $this->_validateCheckout($aData);
-
         if(empty($aResult['pending_id']))
         if(empty($aResult['pending_id']))
             return $aResult;
             return $aResult;
 
 
@@ -117,16 +114,13 @@ class BxPaymentProvider2Checkout extends BxBaseModPaymentProvider implements iBx
         if((float)$sAmount != (float)$aPending['amount'])
         if((float)$sAmount != (float)$aPending['amount'])
             return array('code' => 5, 'message' => _t('_payment_2co_err_wrong_payment'), 'pending_id' => $iPendingId);
             return array('code' => 5, 'message' => _t('_payment_2co_err_wrong_payment'), 'pending_id' => $iPendingId);
 
 
-		$sBuyerFirstName = bx_process_input($aData['first_name'], BX_TAGS_STRIP);
-        $sBuyerLastName = bx_process_input($aData['last_name'], BX_TAGS_STRIP);
-        $sBuyerEmail = bx_process_input($aData['email'], BX_TAGS_STRIP);
-
         return array(
         return array(
-        	'code' => 1, 
+        	'code' => BX_PAYMENT_RESULT_SUCCESS, 
         	'message' => _t('_payment_2co_msg_verified'), 
         	'message' => _t('_payment_2co_msg_verified'), 
         	'pending_id' => $iPendingId,
         	'pending_id' => $iPendingId,
-        	'payer_name' => _t('_payment_txt_buyer_name_mask', $sBuyerFirstName, $sBuyerLastName),
-        	'payer_email' => $sBuyerEmail
+        	'client_name' => _t('_payment_txt_buyer_name_mask', bx_process_input($aData['first_name']), bx_process_input($aData['last_name'])),
+        	'client_email' => bx_process_input($aData['email']),
+        	'paid' => true
         );
         );
     }
     }
 
 

+ 37 - 70
modules/boonex/payment/classes/BxPaymentProviderBitPay.php

@@ -29,11 +29,12 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
         parent::__construct($aConfig);
         parent::__construct($aConfig);
 
 
         $this->_bRedirectOnResult = false;
         $this->_bRedirectOnResult = false;
+        $this->_sLogFile = BX_DIRECTORY_PATH_TMP . 'bx_pp_' . $this->_sName . '.log';
 
 
         $this->_initializeOptions();
         $this->_initializeOptions();
     }
     }
 
 
-    public function initializeCheckout($iPendingId, $aCartInfo, $bRecurring = false, $iRecurringDays = 0)
+    public function initializeCheckout($iPendingId, $aCartInfo)
     {
     {
     	$this->aBpOptions['redirectURL'] .= $aCartInfo['vendor_id'];
     	$this->aBpOptions['redirectURL'] .= $aCartInfo['vendor_id'];
 
 
@@ -105,13 +106,18 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 
 
         //--- Process purchased items in the database if STATUS became CONFIRMED (HIGH and MEDIUM speed), COMPLETE (LOW speed)
         //--- Process purchased items in the database if STATUS became CONFIRMED (HIGH and MEDIUM speed), COMPLETE (LOW speed)
 		$sSpeed = $this->aBpOptions['transactionSpeed'];
 		$sSpeed = $this->aBpOptions['transactionSpeed'];
-		if((in_array($sSpeed, array(BP_SPEED_HIGH, BP_SPEED_MEDIUM)) && $sStatus == BP_STATUS_CONFIRMED) || ($sSpeed == BP_SPEED_LOW && $sStatus == BP_STATUS_COMPLETE))		
-	        return array('code' => 1, 'message' => '', 'pending_id' => $iPendingId);
-
-		return array('code' => 7, 'message' => _t('_payment_bp_err_no_confirmation_given'));
+		if(!((in_array($sSpeed, array(BP_SPEED_HIGH, BP_SPEED_MEDIUM)) && $sStatus == BP_STATUS_CONFIRMED) || ($sSpeed == BP_SPEED_LOW && $sStatus == BP_STATUS_COMPLETE)))
+			return array('code' => 7, 'message' => _t('_payment_bp_err_no_confirmation_given'));		
+
+		return array(
+			'code' => BX_PAYMENT_RESULT_SUCCESS, 
+			'message' => '', 
+			'pending_id' => $iPendingId,
+			'paid' => true
+		);
     }
     }
 
 
-    public function checkoutFinished()
+    public function finalizedCheckout()
     {
     {
     	return array(
     	return array(
     		'message' => _t('_payment_bp_msg_checkout_finished')
     		'message' => _t('_payment_bp_msg_checkout_finished')
@@ -175,10 +181,10 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 			$response = $this->_curl('https://bitpay.com/api/invoice/', $options['apiKey'], $post);
 			$response = $this->_curl('https://bitpay.com/api/invoice/', $options['apiKey'], $post);
 
 
 			if($this->aBpOptions['useLogging']) {
 			if($this->aBpOptions['useLogging']) {
-				$this->_log('Create Invoice: ');
-				$this->_log('-- Data: ' . $post);
-				$this->_log('Response: ');
-				$this->_log($response);
+				$this->log('Create Invoice: ');
+				$this->log('-- Data: ' . $post);
+				$this->log('Response: ');
+				$this->log($response);
 			}
 			}
 
 
 			return $response;
 			return $response;
@@ -186,7 +192,7 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 		}
 		}
 		catch (Exception $e) {
 		catch (Exception $e) {
 			if($this->aBpOptions['useLogging'])
 			if($this->aBpOptions['useLogging'])
-				$this->_log('Error: ' . $e->getMessage());
+				$this->log('Error: ' . $e->getMessage());
 
 
 			return array('error' => $e->getMessage());
 			return array('error' => $e->getMessage());
 		}
 		}
@@ -218,7 +224,7 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 		}
 		}
 		catch (Exception $e) {
 		catch (Exception $e) {
 			if($this->aBpOptions['useLogging'])
 			if($this->aBpOptions['useLogging'])
-				$this->_log('Error: ' . $e->getMessage());
+				$this->log('Error: ' . $e->getMessage());
 
 
 			return 'Error: ' . $e->getMessage();
 			return 'Error: ' . $e->getMessage();
 		}
 		}
@@ -248,7 +254,7 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 		}
 		}
 		catch (Exception $e) {
 		catch (Exception $e) {
 			if($this->aBpOptions['useLogging'])
 			if($this->aBpOptions['useLogging'])
-				$this->_log('Error: ' . $e->getMessage());
+				$this->log('Error: ' . $e->getMessage());
 
 
 			return 'Error: ' . $e->getMessage();
 			return 'Error: ' . $e->getMessage();
 		}
 		}
@@ -281,7 +287,7 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 		}
 		}
 		catch (Exception $e) {
 		catch (Exception $e) {
 			if($this->aBpOptions['useLogging'])
 			if($this->aBpOptions['useLogging'])
-				$this->_log('Error: ' . $e->getMessage());
+				$this->log('Error: ' . $e->getMessage());
 			return 'Error: ' . $e->getMessage();
 			return 'Error: ' . $e->getMessage();
 		}
 		}
 	}
 	}
@@ -300,7 +306,7 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 
 
 		// url where bit-pay server should send update notifications.  See API doc for more details.
 		// url where bit-pay server should send update notifications.  See API doc for more details.
 		// example: $bpNotificationUrl = 'http://www.example.com/callback.php';
 		// example: $bpNotificationUrl = 'http://www.example.com/callback.php';
-		$this->aBpOptions['notificationURL'] = $this->_oModule->_oConfig->getUrl('return_data', array(), true) . $this->_sName . '/';
+		$this->aBpOptions['notificationURL'] = $this->_oModule->_oConfig->getUrl('URL_RETURN_DATA', array(), true) . $this->_sName . '/';
 
 
 		// url where the customer should be directed to after paying for the order
 		// url where the customer should be directed to after paying for the order
 		// example: $bpNotificationUrl = 'http://www.example.com/confirmation.php';
 		// example: $bpNotificationUrl = 'http://www.example.com/confirmation.php';
@@ -323,10 +329,6 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 		// transaction speed: low/medium/high.   See API docs for more details.
 		// transaction speed: low/medium/high.   See API docs for more details.
 		$this->aBpOptions['transactionSpeed'] = $this->getOption('transaction_speed'); 
 		$this->aBpOptions['transactionSpeed'] = $this->getOption('transaction_speed'); 
 
 
-		// Logfile for use by the bpLog function.  Note: ensure the web server process has write access
-		// to this file and/or directory!
-		$this->aBpOptions['logFile'] = $GLOBALS['dir']['tmp'] . 'bx_payment_bp.log';
-
 		// Change to 'true' if you would like automatic logging of invoices and errors.
 		// Change to 'true' if you would like automatic logging of invoices and errors.
 		// Otherwise you will have to call the bpLog function manually to log any information.
 		// Otherwise you will have to call the bpLog function manually to log any information.
 		$this->aBpOptions['useLogging'] = true;
 		$this->aBpOptions['useLogging'] = true;
@@ -343,29 +345,29 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 	 */
 	 */
 	protected function _verifyNotification() {
 	protected function _verifyNotification() {
 		try {
 		try {
-			$this->_log('Notification received: ' . date("m.d.y H:i:s"));
+			$this->log('Notification received: ' . date("m.d.y H:i:s"));
 
 
 			$post = file_get_contents("php://input");
 			$post = file_get_contents("php://input");
 			if(!$post) {
 			if(!$post) {
-				$this->_log('Error: No post data');
+				$this->log('Error: No post data');
 				return false;
 				return false;
 			}
 			}
 
 
 			$json = json_decode($post, true);
 			$json = json_decode($post, true);
-			$this->_log('-- Data: ' . $post);
-			$this->_log($json);
+			$this->log('-- Data: ' . $post);
+			$this->log($json);
 
 
 			if(is_string($json))
 			if(is_string($json))
 				return false;
 				return false;
 
 
 			if(!array_key_exists('posData', $json)) {
 			if(!array_key_exists('posData', $json)) {
-				$this->_log('Error: No posData');
+				$this->log('Error: No posData');
 				return false;
 				return false;
 			}
 			}
 
 
 			$json['posData'] = json_decode($json['posData'], true);
 			$json['posData'] = json_decode($json['posData'], true);
 			if(empty($json['posData']) || !is_array($json['posData'])) {
 			if(empty($json['posData']) || !is_array($json['posData'])) {
-				$this->_log('Error: Empty posData');
+				$this->log('Error: Empty posData');
 				return false;
 				return false;
 			}
 			}
 
 
@@ -373,7 +375,7 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 		}
 		}
 		catch (Exception $e) {
 		catch (Exception $e) {
 			if($this->aBpOptions['useLogging'])
 			if($this->aBpOptions['useLogging'])
-				$this->_log('Error: ' . $e->getMessage());
+				$this->log('Error: ' . $e->getMessage());
 
 
 			return false;
 			return false;
 		}
 		}
@@ -390,7 +392,7 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 	protected function _verifyPosData($aPosData) {
 	protected function _verifyPosData($aPosData) {
 		if(!$this->aBpOptions['verifyPos']) {
 		if(!$this->aBpOptions['verifyPos']) {
 			if(empty($aPosData['d']) || !is_array($aPosData['d'])) {
 			if(empty($aPosData['d']) || !is_array($aPosData['d'])) {
-				$this->_log('Error: Payment data cannot be found.');
+				$this->log('Error: Payment data cannot be found.');
 				return false;
 				return false;
 			}
 			}
 
 
@@ -398,7 +400,7 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 		}
 		}
 
 
 		if($this->_hash(serialize($aPosData['d']), $this->aBpOptions['apiKey']) != $aPosData['h']) {
 		if($this->_hash(serialize($aPosData['d']), $this->aBpOptions['apiKey']) != $aPosData['h']) {
-			$this->_log('Error: Authentication failed (bad posData hash).');
+			$this->log('Error: Authentication failed (bad posData hash).');
 			return false;
 			return false;
 		}
 		}
 
 
@@ -434,7 +436,7 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 		} 
 		} 
 		catch (Exception $e) {
 		catch (Exception $e) {
 			if($this->aBpOptions['useLogging'])
 			if($this->aBpOptions['useLogging'])
-				$this->_log('Error: ' . $e->getMessage());
+				$this->log('Error: ' . $e->getMessage());
 
 
 			return array('error' => $e->getMessage());
 			return array('error' => $e->getMessage());
 		}
 		}
@@ -456,7 +458,7 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 		}
 		}
 		catch (Exception $e) {
 		catch (Exception $e) {
 			if($this->aBpOptions['useLogging'])
 			if($this->aBpOptions['useLogging'])
-				$this->_log('Error: ' . $e->getMessage());
+				$this->log('Error: ' . $e->getMessage());
 
 
 			return 'Error: ' . $e->getMessage();
 			return 'Error: ' . $e->getMessage();
 		}
 		}
@@ -475,7 +477,7 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 		if(!isset($url) || trim($url) == '' || !isset($apiKey) || trim($apiKey) == '') {
 		if(!isset($url) || trim($url) == '' || !isset($apiKey) || trim($apiKey) == '') {
 			// Invalid parameter specified
 			// Invalid parameter specified
 			if($this->aBpOptions['useLogging'])
 			if($this->aBpOptions['useLogging'])
-				$this->_log('Error: You must supply non-empty url and apiKey parameters.');
+				$this->log('Error: You must supply non-empty url and apiKey parameters.');
 
 
 	    	return array('error' => 'You must supply non-empty url and apiKey parameters.');
 	    	return array('error' => 'You must supply non-empty url and apiKey parameters.');
 		}
 		}
@@ -515,14 +517,14 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 				if($responseString == false) {
 				if($responseString == false) {
 					$response = array('error' => curl_error($curl));
 					$response = array('error' => curl_error($curl));
 					if($this->aBpOptions['useLogging'])
 					if($this->aBpOptions['useLogging'])
-						$this->_log('Error: ' . curl_error($curl));
+						$this->log('Error: ' . curl_error($curl));
 				} 
 				} 
 				else {
 				else {
 					$response = json_decode($responseString, true);
 					$response = json_decode($responseString, true);
 					if (!$response) {
 					if (!$response) {
 						$response = array('error' => 'invalid json: '.$responseString);
 						$response = array('error' => 'invalid json: '.$responseString);
 						if($this->aBpOptions['useLogging'])
 						if($this->aBpOptions['useLogging'])
-							$this->_log('Error - Invalid JSON: ' . $responseString);
+							$this->log('Error - Invalid JSON: ' . $responseString);
 					}
 					}
 				}
 				}
 
 
@@ -533,7 +535,7 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 				curl_close($curl);
 				curl_close($curl);
 	
 	
 				if($this->aBpOptions['useLogging'])
 				if($this->aBpOptions['useLogging'])
-					$this->_log('Invalid data found in apiKey value passed to Bitpay::curl method. (Failed: base64_encode(apikey))');
+					$this->log('Invalid data found in apiKey value passed to Bitpay::curl method. (Failed: base64_encode(apikey))');
 
 
 				return array('error' => 'Invalid data found in apiKey value passed to Bitpay::curl method. (Failed: base64_encode(apikey))');
 				return array('error' => 'Invalid data found in apiKey value passed to Bitpay::curl method. (Failed: base64_encode(apikey))');
 			}
 			}
@@ -541,45 +543,10 @@ class BxPaymentProviderBitPay extends BxBaseModPaymentProvider implements iBxBas
 		catch (Exception $e) {
 		catch (Exception $e) {
 			@curl_close($curl);
 			@curl_close($curl);
 			if($this->aBpOptions['useLogging'])
 			if($this->aBpOptions['useLogging'])
-			$this->_log('Error: ' . $e->getMessage());
+			$this->log('Error: ' . $e->getMessage());
 			return array('error' => $e->getMessage());
 			return array('error' => $e->getMessage());
 		}
 		}
 	}
 	}
-
-	/**
-	 *
-	 * Writes $contents to a log file specified in the bp_options file or, if missing,
-	 * defaults to a standard filename of 'bplog.txt'.
-	 *
-	 * @param mixed $contents
-	 * @return
-	 * @throws Exception $e 
-	 *
-	 */
-	protected function _log($contents) {
-		try {
-			if(isset($this->aBpOptions['logFile']) && $this->aBpOptions['logFile'] != '') {
-				$file = $this->aBpOptions['logFile'];
-	    	} 
-	    	else {
-				// Fallback to using a default logfile name in case the variable is
-				// missing or not set.
-				$file = dirname(__FILE__) . '/bplog.txt';
-			}
-
-			file_put_contents($file, date('m-d H:i:s').": ", FILE_APPEND);
-
-			if (is_array($contents))
-				$contents = var_export($contents, true);	
-			else if (is_object($contents))
-				$contents = json_encode($contents);
-
-			file_put_contents($file, $contents."\n", FILE_APPEND);
-	  	}
-	  	catch (Exception $e) {
-			echo 'Error: ' . $e->getMessage();
-	  	}
-	}
 }
 }
 
 
 /** @} */
 /** @} */

+ 279 - 0
modules/boonex/payment/classes/BxPaymentProviderChargebee.php

@@ -0,0 +1,279 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     TridentModules
+ *
+ * @{
+ */
+
+require_once(BX_DIRECTORY_PATH_PLUGINS . 'chargebee/ChargeBee.php');
+
+define('CBEE_MODE_LIVE', 1);
+define('CBEE_MODE_TEST', 2);
+
+class BxPaymentProviderChargebee extends BxBaseModPaymentProvider implements iBxBaseModPaymentProvider
+{
+	protected $_iMode;
+	protected $_bCheckAmount;
+
+    function __construct($aConfig)
+    {
+    	$this->MODULE = 'bx_payment';
+
+        parent::__construct($aConfig);
+
+        $this->_bRedirectOnResult = false;
+        $this->_sLogFile = BX_DIRECTORY_PATH_TMP . 'bx_pp_' . $this->_sName . '.log';        
+
+        $this->_iMode = (int)$this->getOption('mode');
+        $this->_bCheckAmount = false; // Disabled for easier processing of discounted subscriptions.
+    }
+
+    public function initializeCheckout($iPendingId, $aCartInfo)
+    {
+    	$aItem = array_shift($aCartInfo['items']);
+    	if(empty($aItem) || !is_array($aItem))
+    		return $this->_sLangsPrefix . 'err_empty_items';
+
+		$aClient = $this->_oModule->getProfileInfo();
+		$aVendor = $this->_oModule->getProfileInfo($aCartInfo['vendor_id']);
+
+		$oPage = $this->createHostedPage($iPendingId, $aItem, $aClient, $aVendor);
+		if($oPage === false)
+			return $this->_sLangsPrefix . 'err_cannot_perform';
+
+		return array(
+			'code' => 0,
+			'eval' => $this->_oModule->_oConfig->getJsObject('cart') . '.onSubscribeSubmit(oData);',
+			'redirect' => $oPage->url
+		);
+    }
+
+    public function finalizeCheckout(&$aData)
+    {
+    	$sPageId = bx_process_input($aData['id']);
+		$iPendingId = bx_process_input($aData['pending_id'], BX_DATA_INT);
+
+        if(empty($sPageId) || empty($iPendingId))
+        	return array('code' => 1, 'message' => $this->_sLangsPrefix . 'pp_err_no_data_given');
+
+		$oPage = $this->retreiveHostedPage($sPageId);
+		if($oPage === false)
+			return $this->_sLangsPrefix . 'err_cannot_perform';
+		
+		$aPending = $this->_oModule->_oDb->getOrderPending(array('type' => 'id', 'id' => $iPendingId));
+        if(!empty($aPending['order']) || !empty($aPending['error_code']) || !empty($aPending['error_msg']) || (int)$aPending['processed'] != 0)
+            return array('code' => 3, 'message' => $this->_sLangsPrefix . 'pp_err_already_processed');
+
+		$oCustomer = $oPage->content()->customer();
+		$oSubscription = $oPage->content()->subscription();
+
+		$aResult = array(
+			'code' => BX_PAYMENT_RESULT_SUCCESS,
+        	'message' => $this->_sLangsPrefix . 'cbee_msg_subscribed',
+			'pending_id' => $iPendingId,
+			'client_name' => _t($this->_sLangsPrefix . 'txt_buyer_name_mask', $oCustomer->firstName, $oCustomer->lastName),
+			'client_email' => $oCustomer->email,
+			'paid' => false
+		);
+
+        //--- Update pending transaction ---//
+        $this->_oModule->_oDb->updateOrderPending($iPendingId, array(
+            'order' => $oSubscription->id,
+            'error_code' => $aResult['code'],
+            'error_msg' => _t($aResult['message'])
+        ));
+
+        return $aResult;
+    }
+
+    public function processEvent()
+    {
+		$iResult = $this->_processEvent();
+		http_response_code($iResult);
+    }
+
+	public function createHostedPage($iPendingId, $aItem, $aClient, $aVendor) {
+		$oPage = null;
+
+		try {
+			ChargeBee_Environment::configure($this->_getSite(), $this->_getApiKey());
+			$oResult = ChargeBee_HostedPage::checkoutNew(array(
+				'redirectUrl' => bx_append_url_params(parent::getReturnDataUrl($aVendor['id']), array(
+					'pending_id' => $iPendingId
+				)),
+				'subscription' => array(
+					'planId' => $aItem['name']
+				), 
+				'customer' => array(
+					'email' => $aClient['email'],
+					'firstName' => $aClient['name']
+				), 
+			));
+
+			$oPage = $oResult->hostedPage();
+		}
+		catch (Exception $oException) {
+			$iError = $oException->getCode();
+			$sError = $oException->getMessage();
+
+			$this->log('Create Hosted Page Error: ' . $sError . '(' . $iError . ')');
+
+			return false;
+		}
+
+		return $oPage;
+	}
+
+	public function retreiveHostedPage($sPageId) {
+		$oPage = null;
+
+		try {
+			ChargeBee_Environment::configure($this->_getSite(), $this->_getApiKey());
+			$oResult = ChargeBee_HostedPage::retrieve($sPageId);
+
+			$oPage = $oResult->hostedPage();
+		}
+		catch (Exception $oException) {
+			$iError = $oException->getCode();
+			$sError = $oException->getMessage();
+
+			$this->log('Retrieve Hosted Page Error: ' . $sError . '(' . $iError . ')');
+
+			return false;
+		}
+
+		return $oPage;
+	}
+
+	public function retrieveSubscription($sSubscriptionId)
+	{
+		$oSubscription = null;
+
+		try {
+			ChargeBee_Environment::configure($this->_getSite(), $this->_getApiKey());
+			$oResult = ChargeBee_Subscription::retrieve($sSubscriptionId);
+
+			$oSubscription = $oResult->subscription();
+			if($oSubscription->id != $sSubscriptionId)
+				return false;
+		}
+		catch (Exception $oException) {
+			$iError = $oException->getCode();
+			$sError = $oException->getMessage();
+
+			$this->log('Retrieve Subscription Error: ' . $sError . '(' . $iError . ')');
+
+			return false;
+		}
+
+		return $oSubscription;
+	}
+
+	public function deleteSubscription($sSubscriptionId)
+	{
+		try {
+			ChargeBee_Environment::configure($this->_getSite(), $this->_getApiKey());
+			$oResult = ChargeBee_Subscription::cancel($sSubscriptionId);
+
+			$oSubscription = $oResult->subscription();
+			if($oSubscription->status != 'cancelled')
+				return false;
+		}
+		catch (Exception $oException) {
+			$aError = $oException->getJsonBody();
+
+			$this->log('Delete Subscription Error: ' . $aError['error']['message']);
+			$this->log($aError);
+
+			return false;
+		}
+
+		return true;
+	}
+
+	protected function _getSite()
+	{
+		return $this->_iMode == CBEE_MODE_LIVE ? $this->getOption('live_site') : $this->getOption('test_site');
+	}
+
+	protected function _getApiKey()
+	{
+		return $this->_iMode == CBEE_MODE_LIVE ? $this->getOption('live_api_key') : $this->getOption('test_api_key');
+	}
+
+	protected function _processEvent()
+	{
+    	$sInput = @file_get_contents("php://input");
+		$aEvent = json_decode($sInput, true);
+		if(empty($aEvent) || !is_array($aEvent)) 
+			return 404;
+
+		$sType = $aEvent['event_type'];
+		if(!in_array($sType, array('payment_succeeded', ' payment_refunded', 'subscription_cancelled')))
+			return 200;
+
+		$this->log('Webhooks: ' . (!empty($sType) ? $sType : ''));
+		$this->log($aEvent);
+
+		$sMethod = '_processEvent' . bx_gen_method_name($sType, array('.', '_', '-'));
+    	if(!method_exists($this, $sMethod))
+    		return 200;
+
+    	return $this->$sMethod($aEvent) ? 200 : 403;
+    }
+
+	protected function _processEventPaymentSucceeded(&$aEvent)
+	{
+		$mixedResult = $this->_getData($aEvent, true);
+		if($mixedResult === false)
+			return false;
+
+		list($aPending, $aTransaction) = $mixedResult;
+
+		$fTransactionAmount = (float)$aTransaction['amount'] / 100;
+		$sTransactionCurrency = strtoupper($aTransaction['currency_code']);
+		if($this->_bCheckAmount && ((float)$aPending['amount'] != $fTransactionAmount || strcasecmp($this->_oModule->_oConfig->getCurrencyCode(), $sTransactionCurrency) != 0))
+			return false;
+
+		return $this->_oModule->registerPayment($aPending);
+	}
+
+	protected function _processEventPaymentRefunded(&$aEvent)
+	{
+		$mixedResult = $this->_getData($aEvent);
+		if($mixedResult === false)
+			return false;
+
+		list($aPending) = $mixedResult;
+		return $this->_oModule->refundPayment($aPending);
+	}
+
+	protected function _processEventSubscriptionCancelled(&$aEvent)
+	{
+		$mixedResult = $this->_getData($aEvent);
+		if($mixedResult === false)
+			return false;
+
+		list($aPending) = $mixedResult;
+		return $this->_oModule->cancelSubscription($aPending);
+	}
+
+	protected function _getData(&$aEvent, $bWithStatusCheck = false)
+	{
+		$aTransaction = $aEvent['content']['transaction'];
+		if(empty($aTransaction) || ($bWithStatusCheck && $aTransaction['status'] != 'success'))
+			return false;
+
+		$aPending = $this->_oModule->_oDb->getOrderPending(array('type' => 'order', 'order' => $aTransaction['subscription_id']));
+		if(empty($aPending) || !is_array($aPending))
+			return false;
+
+		return array($aPending, $aTransaction);
+	}
+}
+
+/** @} */

+ 7 - 18
modules/boonex/payment/classes/BxPaymentProviderPayPal.php

@@ -16,9 +16,6 @@ define('PP_PRC_TYPE_DIRECT', 1);
 define('PP_PRC_TYPE_PDT', 2);
 define('PP_PRC_TYPE_PDT', 2);
 define('PP_PRC_TYPE_IPN', 3);
 define('PP_PRC_TYPE_IPN', 3);
 
 
-define('PP_CNT_TYPE_SSL', 1);
-define('PP_CNT_TYPE_HTML', 2);
-
 class BxPaymentProviderPayPal extends BxBaseModPaymentProvider implements iBxBaseModPaymentProvider
 class BxPaymentProviderPayPal extends BxBaseModPaymentProvider implements iBxBaseModPaymentProvider
 {
 {
     protected $_sDataReturnUrl;
     protected $_sDataReturnUrl;
@@ -30,7 +27,7 @@ class BxPaymentProviderPayPal extends BxBaseModPaymentProvider implements iBxBas
         parent::__construct($aConfig);
         parent::__construct($aConfig);
 
 
         $this->_bRedirectOnResult = false;
         $this->_bRedirectOnResult = false;
-        $this->_sDataReturnUrl = $this->_oModule->_oConfig->getUrl('return_data') . $this->_sName . '/';
+        $this->_sDataReturnUrl = $this->_oModule->_oConfig->getUrl('URL_RETURN_DATA') . $this->_sName . '/';
     }
     }
 
 
     public function initializeCheckout($iPendingId, $aCartInfo, $bRecurring = false, $iRecurringDays = 0)
     public function initializeCheckout($iPendingId, $aCartInfo, $bRecurring = false, $iRecurringDays = 0)
@@ -78,7 +75,7 @@ class BxPaymentProviderPayPal extends BxBaseModPaymentProvider implements iBxBas
                 break;
                 break;
             case PP_PRC_TYPE_IPN:
             case PP_PRC_TYPE_IPN:
                 $aFormData = array_merge($aFormData, array(
                 $aFormData = array_merge($aFormData, array(
-                    'return' => $this->_oConfig->getUrl('return'),
+                    'return' => $this->_oConfig->getUrl('URL_RETURN'),
                     'notify_url' => $this->_sDataReturnUrl . $aCartInfo['vendor_id'],
                     'notify_url' => $this->_sDataReturnUrl . $aCartInfo['vendor_id'],
                     'rm' => '1'
                     'rm' => '1'
                 ));
                 ));
@@ -97,8 +94,6 @@ class BxPaymentProviderPayPal extends BxBaseModPaymentProvider implements iBxBas
 		return $this->_registerCheckout($aData);
 		return $this->_registerCheckout($aData);
     }
     }
 
 
-	public function checkoutFinished() {}
-
     /**
     /**
      *
      *
      * @param $aData - data from payment provider.
      * @param $aData - data from payment provider.
@@ -136,13 +131,10 @@ class BxPaymentProviderPayPal extends BxBaseModPaymentProvider implements iBxBas
             'error_msg' => _t($aResult['message'])
             'error_msg' => _t($aResult['message'])
         ));
         ));
 
 
-        $sBuyerFirstName = bx_process_input($aData['first_name']);
-        $sBuyerLastName = bx_process_input($aData['last_name']);
-        $sBuyerEmail = bx_process_input($aData['payer_email']);
-
         $aResult['pending_id'] = $iPendingId;
         $aResult['pending_id'] = $iPendingId;
-        $aResult['payer_name'] = _t($this->_sLangsPrefix . 'txt_buyer_name_mask', $sBuyerFirstName, $sBuyerLastName); 
-		$aResult['payer_email'] = $sBuyerEmail;
+        $aResult['client_name'] = _t($this->_sLangsPrefix . 'txt_buyer_name_mask', bx_process_input($aData['first_name']), bx_process_input($aData['last_name'])); 
+		$aResult['client_email'] = bx_process_input($aData['payer_email']);
+		$aResult['paid'] = true;
         return $aResult;
         return $aResult;
     }
     }
 
 
@@ -231,12 +223,9 @@ class BxPaymentProviderPayPal extends BxBaseModPaymentProvider implements iBxBas
 
 
         $iErrCode = 0;
         $iErrCode = 0;
         $sErrMessage = "";
         $sErrMessage = "";
-        if($this->getOption('cnt_type') == PP_CNT_TYPE_SSL)
-            $rSocket = fsockopen("ssl://" . $sConnectionUrl, 443, $iErrCode, $sErrMessage, 60);
-        else
-            $rSocket = fsockopen("tcp://" . $sConnectionUrl, 80, $iErrCode, $sErrMessage, 60);
 
 
-        if(!$rSocket)
+        $rSocket = fsockopen("ssl://" . $sConnectionUrl, 443, $iErrCode, $sErrMessage, 60);
+		if(!$rSocket)
             return array('code' => 6, 'message' => $this->_sLangsPrefix . 'err_cannot_validate');
             return array('code' => 6, 'message' => $this->_sLangsPrefix . 'err_cannot_validate');
 
 
         fputs($rSocket, $sHeader);
         fputs($rSocket, $sHeader);

+ 37 - 7
modules/boonex/payment/classes/BxPaymentTemplate.php

@@ -77,6 +77,34 @@ class BxPaymentTemplate extends BxBaseModPaymentTemplate
         ));
         ));
     }
     }
 
 
+	public function displaySubscribeJs($iVendorId, $iModuleId, $iItemId, $iItemCount = 1, $bWrapped = true)
+    {
+        $sJsCode = $this->displayCartJs($bWrapped);
+        $sJsMethod = $this->parseHtmlByName('subscribe_js.html', array(
+            'js_object' => $this->_oConfig->getJsObject('cart'),
+            'vendor_id' => $iVendorId,
+            'module_id' => $iModuleId,
+            'item_id' => $iItemId,
+            'item_count' => $iItemCount
+        ));
+
+        return array($sJsCode, $sJsMethod);
+    }
+
+    public function displaySubscribeLink($iVendorId, $iModuleId, $iItemId, $iItemCount = 1)
+    {
+        $this->addJsCssCart();
+        return $this->parseHtmlByName('subscribe.html', array(
+        	'js_object' => $this->_oConfig->getJsObject('cart'),
+        	'js_content' => $this->displayJsCode('cart'),
+        	'txt_add_to_cart' => _t($this->_sLangsPrefix . 'txt_subscribe'),
+            'vendor_id' => $iVendorId,
+            'module_id' => $iModuleId,
+            'item_id' => $iItemId,
+            'item_count' => $iItemCount,
+        ));
+    }
+
 	public function displayBlockCart($aCartInfo, $iVendorId = BX_PAYMENT_EMPTY_ID)
 	public function displayBlockCart($aCartInfo, $iVendorId = BX_PAYMENT_EMPTY_ID)
     {
     {
     	if(empty($aCartInfo))
     	if(empty($aCartInfo))
@@ -91,13 +119,15 @@ class BxPaymentTemplate extends BxBaseModPaymentTemplate
         foreach($aCartInfo as $aVendor) {
         foreach($aCartInfo as $aVendor) {
             //--- Get Providers ---//
             //--- Get Providers ---//
             $aProviders = array();
             $aProviders = array();
-            $aVendorProviders = $this->_oDb->getVendorInfoProviders($aVendor['vendor_id']);
-            foreach($aVendorProviders as $aProvider)
-                $aProviders[] = array(
-                    'name' => $aProvider['name'],
-                    'caption' => _t($this->_sLangsPrefix . 'txt_cart_' . $aProvider['name']),
-                    'checked' => empty($aProviders) ? 'checked="checked"' : ''
-                );
+            $aVendorProviders = $this->_oDb->getVendorInfoProvidersCart($aVendor['vendor_id']);
+
+            if(!empty($aVendorProviders) && is_array($aVendorProviders))
+	            foreach($aVendorProviders as $aProvider)
+	                $aProviders[] = array(
+	                    'name' => $aProvider['name'],
+	                    'caption' => _t($this->_sLangsPrefix . 'txt_cart_' . $aProvider['name']),
+	                    'checked' => empty($aProviders) ? 'checked="checked"' : ''
+	                );
 
 
             //--- Get Items ---//
             //--- Get Items ---//
             $aItems = array();
             $aItems = array();

+ 25 - 4
modules/boonex/payment/install/langs/en.xml

@@ -171,6 +171,8 @@
 
 
 
 
 	<!-- Other -->
 	<!-- Other -->
+	<string name="_bx_payment_txt_add_to_cart"><![CDATA[Add to Cart]]></string>
+	<string name="_bx_payment_txt_subscribe"><![CDATA[Subscribe]]></string>
 	<string name="_bx_payment_txt_shopping_cart"><![CDATA[{0}'s cart]]></string>
 	<string name="_bx_payment_txt_shopping_cart"><![CDATA[{0}'s cart]]></string>
 	<string name="_bx_payment_txt_payment_to"><![CDATA[Payment to {0} for:]]></string>
 	<string name="_bx_payment_txt_payment_to"><![CDATA[Payment to {0} for:]]></string>
 	<string name="_bx_payment_txt_client"><![CDATA[Client]]></string>
 	<string name="_bx_payment_txt_client"><![CDATA[Client]]></string>
@@ -213,10 +215,6 @@
 	<string name="_bx_payment_pp_prc_type_direct"><![CDATA[direct]]></string>
 	<string name="_bx_payment_pp_prc_type_direct"><![CDATA[direct]]></string>
 	<string name="_bx_payment_pp_prc_type_pdt"><![CDATA[PDT]]></string>
 	<string name="_bx_payment_pp_prc_type_pdt"><![CDATA[PDT]]></string>
 	<string name="_bx_payment_pp_prc_type_ipn"><![CDATA[IPN]]></string>
 	<string name="_bx_payment_pp_prc_type_ipn"><![CDATA[IPN]]></string>
-	<string name="_bx_payment_pp_cnt_type_cpt"><![CDATA[Connection type]]></string>
-	<string name="_bx_payment_pp_cnt_type_dsc"><![CDATA[The type of connection to be used to transfer data]]></string>
-	<string name="_bx_payment_pp_cnt_type_ssl"><![CDATA[SSL]]></string>
-	<string name="_bx_payment_pp_cnt_type_http"><![CDATA[HTTP]]></string>
 	<string name="_bx_payment_pp_token_cpt"><![CDATA[Identity token]]></string>
 	<string name="_bx_payment_pp_token_cpt"><![CDATA[Identity token]]></string>
 	<string name="_bx_payment_pp_token_dsc"><![CDATA[Identity token]]></string>
 	<string name="_bx_payment_pp_token_dsc"><![CDATA[Identity token]]></string>
 	<string name="_bx_payment_pp_sandbox_cpt"><![CDATA[Sandbox]]></string>
 	<string name="_bx_payment_pp_sandbox_cpt"><![CDATA[Sandbox]]></string>
@@ -286,4 +284,27 @@
 	<string name="_bx_payment_bp_err_no_confirmation_given"><![CDATA[Payment is waiting for full confirmation from the Bitcoin network.]]></string>
 	<string name="_bx_payment_bp_err_no_confirmation_given"><![CDATA[Payment is waiting for full confirmation from the Bitcoin network.]]></string>
 	<string name="_bx_payment_bp_msg_checkout_finished"><![CDATA[A payment has been confirmed. Once the transaction is fully confirmed on the Bitcoin network, the payment will be processed automatically here. Then the purchased product(s) will be displayed in shopping cart history.<br /><b>Note.</b> If it doesn't happen for some reason, you need to contact with product\'s vendor and provide him with your payment's details. He'll be able to process payment manually if the payment was received.]]></string>
 	<string name="_bx_payment_bp_msg_checkout_finished"><![CDATA[A payment has been confirmed. Once the transaction is fully confirmed on the Bitcoin network, the payment will be processed automatically here. Then the purchased product(s) will be displayed in shopping cart history.<br /><b>Note.</b> If it doesn't happen for some reason, you need to contact with product\'s vendor and provide him with your payment's details. He'll be able to process payment manually if the payment was received.]]></string>
 	<string name="_bx_payment_txt_cart_bitpay"><![CDATA[BitPay]]></string>
 	<string name="_bx_payment_txt_cart_bitpay"><![CDATA[BitPay]]></string>
+
+	<!-- Chargebee payment provider -->
+	<string name="_bx_payment_cbee_cpt"><![CDATA[Chargebee]]></string>
+	<string name="_bx_payment_cbee_dsc"><![CDATA[Chargebee payment provider]]></string>
+	<string name="_bx_payment_cbee_active_cpt"><![CDATA[Active]]></string>
+	<string name="_bx_payment_cbee_active_dsc"><![CDATA[Activate(Deactivate) provider]]></string>
+	<string name="_bx_payment_cbee_active_err"><![CDATA[You should have SSL certificate (HTTPS connection) to activate and use Chargebee on your site.]]></string>
+	<string name="_bx_payment_cbee_mode_cpt"><![CDATA[Mode]]></string>
+	<string name="_bx_payment_cbee_mode_dsc"><![CDATA[Mode to process payments]]></string>
+	<string name="_bx_payment_cbee_mode_live"><![CDATA[live]]></string>
+	<string name="_bx_payment_cbee_mode_test"><![CDATA[test]]></string>
+	<string name="_bx_payment_cbee_live_site_cpt"><![CDATA[Site (live)]]></string>
+	<string name="_bx_payment_cbee_live_site_dsc"><![CDATA[Your site name registered in Chargebee for 'live' mode]]></string>
+	<string name="_bx_payment_cbee_live_api_key_cpt"><![CDATA[API Key (live)]]></string>
+	<string name="_bx_payment_cbee_live_api_key_dsc"><![CDATA[Your Chargebee API Access key for 'live' mode]]></string>
+	<string name="_bx_payment_cbee_test_site_cpt"><![CDATA[Site (test)]]></string>
+	<string name="_bx_payment_cbee_test_site_dsc"><![CDATA[Your site name registered in Chargebee for 'test' mode]]></string>
+	<string name="_bx_payment_cbee_test_api_key_cpt"><![CDATA[API Key (test)]]></string>
+	<string name="_bx_payment_cbee_test_api_key_dsc"><![CDATA[Your Chargebee API Access key for 'test' mode]]></string>
+	<string name="_bx_payment_cbee_return_url_cpt"><![CDATA[Data return URL]]></string>
+	<string name="_bx_payment_cbee_msg_subscribed"><![CDATA[Subscription was successfully created.]]></string>
+	<string name="_bx_payment_txt_cart_chargebee"><![CDATA[Chargebee]]></string>
+
 </resources>
 </resources>

+ 29 - 14
modules/boonex/payment/install/sql/install.sql

@@ -9,6 +9,7 @@ CREATE TABLE IF NOT EXISTS `bx_payment_providers` (
   `description` text NOT NULL default '',
   `description` text NOT NULL default '',
   `option_prefix` varchar(32) NOT NULL default '',
   `option_prefix` varchar(32) NOT NULL default '',
   `for_visitor` tinyint(4) NOT NULL default '0',
   `for_visitor` tinyint(4) NOT NULL default '0',
+  `for_subscription` tinyint(4) NOT NULL default '0',
   `class_name` varchar(128) NOT NULL default '',
   `class_name` varchar(128) NOT NULL default '',
   `class_file` varchar(255) NOT NULL  default '',
   `class_file` varchar(255) NOT NULL  default '',
   PRIMARY KEY(`id`)
   PRIMARY KEY(`id`)
@@ -46,13 +47,13 @@ CREATE TABLE IF NOT EXISTS `bx_payment_cart` (
 CREATE TABLE IF NOT EXISTS `bx_payment_transactions` (
 CREATE TABLE IF NOT EXISTS `bx_payment_transactions` (
   `id` int(11) NOT NULL auto_increment,
   `id` int(11) NOT NULL auto_increment,
   `pending_id` int(11) NOT NULL default '0',
   `pending_id` int(11) NOT NULL default '0',
-  `order_id` varchar(16) NOT NULL default '',
   `client_id` int(11) NOT NULL default '0',
   `client_id` int(11) NOT NULL default '0',
   `seller_id` int(11) NOT NULL default '0',
   `seller_id` int(11) NOT NULL default '0',
   `module_id` int(11) NOT NULL default '0',  
   `module_id` int(11) NOT NULL default '0',  
   `item_id` int(11) NOT NULL default '0',
   `item_id` int(11) NOT NULL default '0',
   `item_count` int(11) NOT NULL default '0',
   `item_count` int(11) NOT NULL default '0',
   `amount` float NOT NULL default '0',
   `amount` float NOT NULL default '0',
+  `license` varchar(16) NOT NULL default '',
   `date` int(11) NOT NULL default '0',
   `date` int(11) NOT NULL default '0',
   PRIMARY KEY(`id`)
   PRIMARY KEY(`id`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
@@ -61,12 +62,13 @@ CREATE TABLE IF NOT EXISTS `bx_payment_transactions_pending` (
   `id` int(10) unsigned NOT NULL auto_increment,
   `id` int(10) unsigned NOT NULL auto_increment,
   `client_id` int(11) NOT NULL default '0',
   `client_id` int(11) NOT NULL default '0',
   `seller_id` int(11) NOT NULL default '0',
   `seller_id` int(11) NOT NULL default '0',
+  `type` varchar(16) NOT NULL default 'single',
+  `provider` varchar(32) NOT NULL default '',
   `items` text NOT NULL default '',
   `items` text NOT NULL default '',
   `amount` float NOT NULL default '0',
   `amount` float NOT NULL default '0',
   `order` varchar(32) NOT NULL default '',
   `order` varchar(32) NOT NULL default '',
   `error_code` varchar(16) NOT NULL default '',
   `error_code` varchar(16) NOT NULL default '',
   `error_msg` varchar(255) NOT NULL default '',
   `error_msg` varchar(255) NOT NULL default '',
-  `provider` varchar(32) NOT NULL default '',
   `date` int(11) NOT NULL default '0',
   `date` int(11) NOT NULL default '0',
   `processed` tinyint(4) NOT NULL default '0',
   `processed` tinyint(4) NOT NULL default '0',
   PRIMARY KEY(`id`)
   PRIMARY KEY(`id`)
@@ -81,8 +83,8 @@ CREATE TABLE IF NOT EXISTS `bx_payment_modules` (
 
 
 
 
 -- PayPal payment provider
 -- PayPal payment provider
-INSERT INTO `bx_payment_providers`(`name`, `caption`, `description`, `option_prefix`, `for_visitor`, `class_name`) VALUES
-('paypal', '_bx_payment_pp_cpt', '_bx_payment_pp_dsc', 'pp_', 1, 'BxPaymentProviderPayPal');
+INSERT INTO `bx_payment_providers`(`name`, `caption`, `description`, `option_prefix`, `for_visitor`,`for_subscription`, `class_name`) VALUES
+('paypal', '_bx_payment_pp_cpt', '_bx_payment_pp_dsc', 'pp_', 1, 0, 'BxPaymentProviderPayPal');
 SET @iProviderId = LAST_INSERT_ID();
 SET @iProviderId = LAST_INSERT_ID();
 
 
 INSERT INTO `bx_payment_providers_options`(`provider_id`, `name`, `type`, `caption`, `description`, `extra`, `check_type`, `check_params`, `check_error`, `order`) VALUES
 INSERT INTO `bx_payment_providers_options`(`provider_id`, `name`, `type`, `caption`, `description`, `extra`, `check_type`, `check_params`, `check_error`, `order`) VALUES
@@ -90,15 +92,14 @@ INSERT INTO `bx_payment_providers_options`(`provider_id`, `name`, `type`, `capti
 (@iProviderId, 'pp_mode', 'select', '_bx_payment_pp_mode_cpt', '_bx_payment_pp_mode_dsc', '1|_bx_payment_pp_mode_live,2|_bx_payment_pp_mode_test', '', '', '', 2),
 (@iProviderId, 'pp_mode', 'select', '_bx_payment_pp_mode_cpt', '_bx_payment_pp_mode_dsc', '1|_bx_payment_pp_mode_live,2|_bx_payment_pp_mode_test', '', '', '', 2),
 (@iProviderId, 'pp_business', 'text', '_bx_payment_pp_business_cpt', '_bx_payment_pp_business_dsc', '', '', '', '', 3),
 (@iProviderId, 'pp_business', 'text', '_bx_payment_pp_business_cpt', '_bx_payment_pp_business_dsc', '', '', '', '', 3),
 (@iProviderId, 'pp_prc_type', 'select', '_bx_payment_pp_prc_type_cpt', '_bx_payment_pp_prc_type_dsc', '1|_bx_payment_pp_prc_type_direct,2|_bx_payment_pp_prc_type_pdt,3|_bx_payment_pp_prc_type_ipn', '', '', '', 4),
 (@iProviderId, 'pp_prc_type', 'select', '_bx_payment_pp_prc_type_cpt', '_bx_payment_pp_prc_type_dsc', '1|_bx_payment_pp_prc_type_direct,2|_bx_payment_pp_prc_type_pdt,3|_bx_payment_pp_prc_type_ipn', '', '', '', 4),
-(@iProviderId, 'pp_cnt_type', 'select', '_bx_payment_pp_cnt_type_cpt', '_bx_payment_pp_cnt_type_dsc', '1|_bx_payment_pp_cnt_type_ssl,2|_bx_payment_pp_cnt_type_http', '', '', '', 5),
-(@iProviderId, 'pp_token', 'text', '_bx_payment_pp_token_cpt', '_bx_payment_pp_token_dsc', '', '', '', '', 6),
-(@iProviderId, 'pp_sandbox', 'text', '_bx_payment_pp_sandbox_cpt', '_bx_payment_pp_sandbox_dsc', '', '', '', '', 7),
-(@iProviderId, 'pp_return_url', 'value', '_bx_payment_pp_return_url_cpt', '', '', '', '', '', 8);
+(@iProviderId, 'pp_token', 'text', '_bx_payment_pp_token_cpt', '_bx_payment_pp_token_dsc', '', '', '', '', 5),
+(@iProviderId, 'pp_sandbox', 'text', '_bx_payment_pp_sandbox_cpt', '_bx_payment_pp_sandbox_dsc', '', '', '', '', 6),
+(@iProviderId, 'pp_return_url', 'value', '_bx_payment_pp_return_url_cpt', '', '', '', '', '', 7);
 
 
 
 
 -- 2Checkout payment provider
 -- 2Checkout payment provider
-INSERT INTO `bx_payment_providers`(`name`, `caption`, `description`, `option_prefix`, `for_visitor`, `class_name`) VALUES
-('2checkout', '_bx_payment_2co_cpt', '_bx_payment_2co_dsc', '2co_', 1, 'BxPaymentProvider2Checkout');
+INSERT INTO `bx_payment_providers`(`name`, `caption`, `description`, `option_prefix`, `for_visitor`, `for_subscription`, `class_name`) VALUES
+('2checkout', '_bx_payment_2co_cpt', '_bx_payment_2co_dsc', '2co_', 1, 0, 'BxPaymentProvider2Checkout');
 SET @iProviderId = LAST_INSERT_ID();
 SET @iProviderId = LAST_INSERT_ID();
 
 
 INSERT INTO `bx_payment_providers_options`(`provider_id`, `name`, `type`, `caption`, `description`, `extra`, `check_type`, `check_params`, `check_error`, `order`) VALUES
 INSERT INTO `bx_payment_providers_options`(`provider_id`, `name`, `type`, `caption`, `description`, `extra`, `check_type`, `check_params`, `check_error`, `order`) VALUES
@@ -111,8 +112,8 @@ INSERT INTO `bx_payment_providers_options`(`provider_id`, `name`, `type`, `capti
 
 
 
 
 -- BitPay payment provider
 -- BitPay payment provider
-INSERT INTO `bx_payment_providers`(`name`, `caption`, `description`, `option_prefix`, `for_visitor`, `class_name`) VALUES
-('bitpay', '_bx_payment_bp_cpt', '_bx_payment_bp_dsc', 'bp_', 0, 'BxPaymentProviderBitPay');
+INSERT INTO `bx_payment_providers`(`name`, `caption`, `description`, `option_prefix`, `for_visitor`, `for_subscription`, `class_name`) VALUES
+('bitpay', '_bx_payment_bp_cpt', '_bx_payment_bp_dsc', 'bp_', 0, 0, 'BxPaymentProviderBitPay');
 SET @iProviderId = LAST_INSERT_ID();
 SET @iProviderId = LAST_INSERT_ID();
 
 
 INSERT INTO `bx_payment_providers_options`(`provider_id`, `name`, `type`, `caption`, `description`, `extra`, `check_type`, `check_params`, `check_error`, `order`) VALUES
 INSERT INTO `bx_payment_providers_options`(`provider_id`, `name`, `type`, `caption`, `description`, `extra`, `check_type`, `check_params`, `check_error`, `order`) VALUES
@@ -123,10 +124,24 @@ INSERT INTO `bx_payment_providers_options`(`provider_id`, `name`, `type`, `capti
 (@iProviderId, 'bp_notification_email', 'text', '_bx_payment_bp_notification_email_cpt', '_bx_payment_bp_notification_email_dsc', '', '', '', '', 5);
 (@iProviderId, 'bp_notification_email', 'text', '_bx_payment_bp_notification_email_cpt', '_bx_payment_bp_notification_email_dsc', '', '', '', '', 5);
 
 
 
 
+-- Chargebee payment provider
+INSERT INTO `bx_payment_providers`(`name`, `caption`, `description`, `option_prefix`, `for_visitor`, `for_subscription`, `class_name`) VALUES
+('chargebee', '_bx_payment_cbee_cpt', '_bx_payment_cbee_dsc', 'cbee_', 1, 1, 'BxPaymentProviderChargebee');
+SET @iProviderId = LAST_INSERT_ID();
+
+INSERT INTO `bx_payment_providers_options`(`provider_id`, `name`, `type`, `caption`, `description`, `extra`, `check_type`, `check_params`, `check_error`, `order`) VALUES
+(@iProviderId, 'cbee_active', 'checkbox', '_bx_payment_cbee_active_cpt', '_bx_payment_cbee_active_dsc', '', 'https', '', '_bx_payment_cbee_active_err', 1);
+(@iProviderId, 'cbee_mode', 'select', '_bx_payment_cbee_mode_cpt', '_bx_payment_cbee_mode_dsc', '1|_bx_payment_cbee_mode_live,2|_bx_payment_cbee_mode_test', '', '', '', 2),
+(@iProviderId, 'cbee_live_site', 'text', '_bx_payment_cbee_live_site_cpt', '_bx_payment_cbee_live_site_dsc', '', '', '', '', 3),
+(@iProviderId, 'cbee_live_api_key', 'text', '_bx_payment_cbee_live_api_key_cpt', '_bx_payment_cbee_live_api_key_dsc', '', '', '', '', 4),
+(@iProviderId, 'cbee_test_site', 'text', '_bx_payment_cbee_test_site_cpt', '_bx_payment_cbee_test_site_dsc', '', '', '', '', 5),
+(@iProviderId, 'cbee_test_api_key', 'text', '_bx_payment_cbee_test_api_key_cpt', '_bx_payment_cbee_test_api_key_dsc', '', '', '', '', 6),
+(@iProviderId, 'cbee_return_url', 'value', '_bx_payment_cbee_return_url_cpt', '', '', '', '', '', 7);
+
 -- GRIDS
 -- GRIDS
 INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `override_class_name`, `override_class_file`) VALUES
 INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `override_class_name`, `override_class_file`) VALUES
-('bx_payment_grid_orders_history', 'Sql', 'SELECT `tt`.`id` AS `id`, `tt`.`seller_id` AS `seller_id`, `ttp`.`order` AS `transaction`, `tt`.`order_id` AS `license`, `tt`.`amount` AS `amount`, `tt`.`date` AS `date` FROM `bx_payment_transactions` AS `tt` LEFT JOIN `bx_payment_transactions_pending` AS `ttp` ON `tt`.`pending_id`=`ttp`.`id` WHERE 1 ', 'bx_payment_transactions', 'id', 'date', '', '', 100, NULL, 'start', '', 'ttp`.`order,tt`.`order_id,tt`.`amount,tt`.`date', '', 'auto', '', '', 'BxPaymentGridHistory', 'modules/boonex/payment/classes/BxPaymentGridHistory.php'),
-('bx_payment_grid_orders_processed', 'Sql', 'SELECT `tt`.`id` AS `id`, `tt`.`client_id` AS `client_id`, `tt`.`seller_id` AS `seller_id`, `tt`.`module_id` AS `module_id`, `tt`.`item_id` AS `item_id`, `tt`.`item_count` AS `item_count`, `ttp`.`order` AS `transaction`, `ttp`.`error_msg` AS `error_msg`, `ttp`.`provider` AS `provider`, `tt`.`order_id` AS `license`, `tt`.`amount` AS `amount`, `tt`.`date` AS `date` FROM `bx_payment_transactions` AS `tt` LEFT JOIN `bx_payment_transactions_pending` AS `ttp` ON `tt`.`pending_id`=`ttp`.`id` WHERE 1 ', 'bx_payment_transactions', 'id', 'date', '', '', 100, NULL, 'start', '', 'ttp`.`order,tt`.`order_id,tt`.`amount,tt`.`date', '', 'auto', '', '', 'BxPaymentGridProcessed', 'modules/boonex/payment/classes/BxPaymentGridProcessed.php'),
+('bx_payment_grid_orders_history', 'Sql', 'SELECT `tt`.`id` AS `id`, `tt`.`seller_id` AS `seller_id`, `ttp`.`order` AS `transaction`, `tt`.`license` AS `license`, `tt`.`amount` AS `amount`, `tt`.`date` AS `date` FROM `bx_payment_transactions` AS `tt` LEFT JOIN `bx_payment_transactions_pending` AS `ttp` ON `tt`.`pending_id`=`ttp`.`id` WHERE 1 ', 'bx_payment_transactions', 'id', 'date', '', '', 100, NULL, 'start', '', 'ttp`.`order,tt`.`license,tt`.`amount,tt`.`date', '', 'auto', '', '', 'BxPaymentGridHistory', 'modules/boonex/payment/classes/BxPaymentGridHistory.php'),
+('bx_payment_grid_orders_processed', 'Sql', 'SELECT `tt`.`id` AS `id`, `tt`.`client_id` AS `client_id`, `tt`.`seller_id` AS `seller_id`, `tt`.`module_id` AS `module_id`, `tt`.`item_id` AS `item_id`, `tt`.`item_count` AS `item_count`, `ttp`.`order` AS `transaction`, `ttp`.`error_msg` AS `error_msg`, `ttp`.`provider` AS `provider`, `tt`.`license` AS `license`, `tt`.`amount` AS `amount`, `tt`.`date` AS `date` FROM `bx_payment_transactions` AS `tt` LEFT JOIN `bx_payment_transactions_pending` AS `ttp` ON `tt`.`pending_id`=`ttp`.`id` WHERE 1 ', 'bx_payment_transactions', 'id', 'date', '', '', 100, NULL, 'start', '', 'ttp`.`order,tt`.`license,tt`.`amount,tt`.`date', '', 'auto', '', '', 'BxPaymentGridProcessed', 'modules/boonex/payment/classes/BxPaymentGridProcessed.php'),
 ('bx_payment_grid_orders_pending', 'Sql', 'SELECT `tt`.`id` AS `id`, `tt`.`client_id` AS `client_id`, `tt`.`seller_id` AS `seller_id`, `tt`.`items` AS `items`, `tt`.`amount` AS `amount`, `tt`.`order` AS `transaction`, `tt`.`error_msg` AS `error_msg`, `tt`.`provider` AS `provider`, `tt`.`date` AS `date` FROM `bx_payment_transactions_pending` AS `tt` WHERE 1 AND (ISNULL(`tt`.`order`) OR (NOT ISNULL(`tt`.`order`) AND `tt`.`error_code`<>''0'')) ', 'bx_payment_transactions_pending', 'id', 'date', '', '', 100, NULL, 'start', '', 'tt`.`order,tt`.`amount,tt`.`date', '', 'auto', '', '', 'BxPaymentGridPending', 'modules/boonex/payment/classes/BxPaymentGridPending.php');
 ('bx_payment_grid_orders_pending', 'Sql', 'SELECT `tt`.`id` AS `id`, `tt`.`client_id` AS `client_id`, `tt`.`seller_id` AS `seller_id`, `tt`.`items` AS `items`, `tt`.`amount` AS `amount`, `tt`.`order` AS `transaction`, `tt`.`error_msg` AS `error_msg`, `tt`.`provider` AS `provider`, `tt`.`date` AS `date` FROM `bx_payment_transactions_pending` AS `tt` WHERE 1 AND (ISNULL(`tt`.`order`) OR (NOT ISNULL(`tt`.`order`) AND `tt`.`error_code`<>''0'')) ', 'bx_payment_transactions_pending', 'id', 'date', '', '', 100, NULL, 'start', '', 'tt`.`order,tt`.`amount,tt`.`date', '', 'auto', '', '', 'BxPaymentGridPending', 'modules/boonex/payment/classes/BxPaymentGridPending.php');
 
 
 INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
 INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES

+ 56 - 9
modules/boonex/payment/js/cart.js

@@ -15,10 +15,11 @@ BxPaymentCart.prototype.init = function(oOptions) {
 };
 };
 
 
 BxPaymentCart.prototype.addToCart = function(iVendorId, iModuleId, iItemId, iItemCount, iNeedRedirect) {
 BxPaymentCart.prototype.addToCart = function(iVendorId, iModuleId, iItemId, iItemCount, iNeedRedirect) {
+	var $this = this;
     var oDate = new Date();
     var oDate = new Date();
-    var $this = this;
 
 
-    if(!(iNeedRedirect = parseInt(iNeedRedirect)))
+    iNeedRedirect = parseInt(iNeedRedirect);
+    if(!iNeedRedirect)
     	iNeedRedirect = 0;
     	iNeedRedirect = 0;
 
 
     $.post(
     $.post(
@@ -27,7 +28,7 @@ BxPaymentCart.prototype.addToCart = function(iVendorId, iModuleId, iItemId, iIte
             _t:oDate.getTime()
             _t:oDate.getTime()
         },
         },
         function(oData){
         function(oData){
-        	alert(oData.message);
+        	$this.processResult(oData);
 
 
             if(oData.code == 0) {
             if(oData.code == 0) {
             	/*
             	/*
@@ -98,15 +99,61 @@ BxPaymentCart.prototype.emptyCart = function(iVendorId) {
     );
     );
 };
 };
 
 
-BxPaymentCart.prototype.toggle = function(oElement) {
-	$(oElement).find('.sys-icon').toggleClass('caret-down').toggleClass('caret-right');
-    $(oElement).parents('.bx-payment-box:first').find('.bx-payment-box-cnt').bx_anim('toggle', 'slide', this._iAnimationSpeed);
-};
-
-BxPaymentCart.prototype.onSubmit = function(oForm) {
+BxPaymentCart.prototype.onCartSubmit = function(oForm) {
     if($(oForm).find(":checkbox[name='items[]']:checked").length > 0)
     if($(oForm).find(":checkbox[name='items[]']:checked").length > 0)
     	return true;
     	return true;
 
 
     alert(_t(this._sErrNothingSelected));
     alert(_t(this._sErrNothingSelected));
 	return false;
 	return false;
 };
 };
+
+BxPaymentCart.prototype.toggleCartVendor = function(oElement) {
+	$(oElement).find('.sys-icon').toggleClass('caret-down').toggleClass('caret-right');
+    $(oElement).parents('.bx-payment-box:first').find('.bx-payment-box-cnt').bx_anim('toggle', 'slide', this._iAnimationSpeed);
+};
+
+BxPaymentCart.prototype.subscribe = function(iVendorId, iModuleId, iItemId, iItemCount) {
+    var $this = this;
+    var oDate = new Date();
+
+    $.post(
+        this._sActionsUrl + 'subscribe/' + iVendorId + '/' + iModuleId + '/' + iItemId + (iItemCount != undefined ? '/' + iItemCount + '/' : ''),
+        {
+            _t:oDate.getTime()
+        },
+        function(oData){
+        	$this.processResult(oData);
+        },
+        'json'
+    );
+};
+
+BxPaymentCart.prototype.onSubscribeSubmit = function(oData) {
+	document.location = oData.redirect;
+};
+
+BxPaymentCart.prototype.processResult = function(oData) {
+	var $this = this;
+
+	if(oData && oData.message != undefined && oData.message.length != 0)
+    	alert(oData.message);
+
+    if(oData && oData.reload != undefined && parseInt(oData.reload) == 1)
+    	document.location = document.location;
+
+    if(oData && oData.popup != undefined) {
+    	var oPopup = $(oData.popup).hide(); 
+
+    	$('#' + oPopup.attr('id')).remove();
+        oPopup.prependTo('body').dolPopup({
+            fog: {
+				color: '#fff',
+				opacity: .7
+            },
+            closeOnOuterClick: false
+        });
+    }
+
+    if (oData && oData.eval != undefined)
+        eval(oData.eval);
+};

+ 2 - 2
modules/boonex/payment/template/cart.html

@@ -3,7 +3,7 @@
         <div class="bx-payment-box bx-def-border bx-def-margin-top-auto">
         <div class="bx-payment-box bx-def-border bx-def-margin-top-auto">
             <div class="bx-payment-box-cpt bx-def-padding-sec-left">
             <div class="bx-payment-box-cpt bx-def-padding-sec-left">
                 <div class="bx-payment-box-collapse">
                 <div class="bx-payment-box-collapse">
-                	<a href="javascript:void(0)" onclick="javascript:__js_object__.toggle(this)">
+                	<a href="javascript:void(0)" onclick="javascript:__js_object__.toggleCartVendor(this)">
                 		<i class="sys-icon caret-down"></i>
                 		<i class="sys-icon caret-down"></i>
                 	</a>
                 	</a>
                 </div>
                 </div>
@@ -13,7 +13,7 @@
                 <bx_if:show_text>__txt_shopping_cart__ (__items_count__) - __items_price__ __vendor_currency_code__</bx_if:show_text>
                 <bx_if:show_text>__txt_shopping_cart__ (__items_count__) - __items_price__ __vendor_currency_code__</bx_if:show_text>
             </div>
             </div>
             <div class="bx-payment-box-cnt bx-def-border-top">
             <div class="bx-payment-box-cnt bx-def-border-top">
-                <form id="items_from___vendor_id__" name="items_from___vendor_id__" method="POST" action="__process_url__" onsubmit="javascript:return __js_object__.onSubmit(this)">
+                <form id="items_from___vendor_id__" name="items_from___vendor_id__" method="POST" action="__process_url__" onsubmit="javascript:return __js_object__.onCartSubmit(this)">
                     <input type="hidden" name="vendor_id" value="__vendor_id__" />
                     <input type="hidden" name="vendor_id" value="__vendor_id__" />
                     <div class="bx-payment-vendor-icon">
                     <div class="bx-payment-vendor-icon">
                     	<img src="__vendor_icon__" />
                     	<img src="__vendor_icon__" />

+ 4 - 0
modules/boonex/payment/template/subscribe.html

@@ -0,0 +1,4 @@
+<button class="bx-btn bx-btn-img bx-payment-subscribe bx-def-margin-sec-left-auto" onclick="javascript:__js_object__.subscribe(__vendor_id__, __module_id__, __item_id__, __item_count__)">
+    <i class="sys-icon rss"></i>__txt_subscribe__
+</button>
+__js_content__

+ 1 - 0
modules/boonex/payment/template/subscribe_js.html

@@ -0,0 +1 @@
+__js_object__.subscribe(__vendor_id__, __module_id__, __item_id__, __item_count__)

+ 17 - 5
modules/boonex/russian/data/langs/bx_market/ru.xml

@@ -4,6 +4,7 @@
 	<string name="_bx_market"><![CDATA[Рынок]]></string>
 	<string name="_bx_market"><![CDATA[Рынок]]></string>
 	<string name="_bx_market_cmts"><![CDATA[Рынок - Обзоры]]></string>
 	<string name="_bx_market_cmts"><![CDATA[Рынок - Обзоры]]></string>
 
 
+	<string name="_bx_market_option_enable_recurring"><![CDATA[Разрешить продажу подписок]]></string>
 	<string name="_bx_market_option_summary_chars"><![CDATA[Количество символов в автогенерируемой сводке к продуктам]]></string>
 	<string name="_bx_market_option_summary_chars"><![CDATA[Количество символов в автогенерируемой сводке к продуктам]]></string>
 	<string name="_bx_market_option_plain_summary_chars"><![CDATA[Количество символов в описании продукта при отсутствующей картинке продукта]]></string>
 	<string name="_bx_market_option_plain_summary_chars"><![CDATA[Количество символов в описании продукта при отсутствующей картинке продукта]]></string>
 	<string name="_bx_market_option_per_page_browse"><![CDATA[Количество элементов на странице]]></string>
 	<string name="_bx_market_option_per_page_browse"><![CDATA[Количество элементов на странице]]></string>
@@ -21,12 +22,18 @@
 	<string name="_bx_market_form_entry_input_sys_title"><![CDATA[Заголовок]]></string>
 	<string name="_bx_market_form_entry_input_sys_title"><![CDATA[Заголовок]]></string>
 	<string name="_bx_market_form_entry_input_title"><![CDATA[Заголовок]]></string>
 	<string name="_bx_market_form_entry_input_title"><![CDATA[Заголовок]]></string>
 	<string name="_bx_market_form_entry_input_title_err"><![CDATA[Заголовок обязателен. Пожалуйста, заполните это поле]]></string>
 	<string name="_bx_market_form_entry_input_title_err"><![CDATA[Заголовок обязателен. Пожалуйста, заполните это поле]]></string>
+	<string name="_bx_market_form_entry_input_sys_name"><![CDATA[Имя]]></string>
+	<string name="_bx_market_form_entry_input_name"><![CDATA[Имя]]></string>
+	<string name="_bx_market_form_entry_input_name_err"><![CDATA[Имя должно быть уникально и будет использоваться для внутренних целей. Пожалуйста, заполните это поле]]></string>
 	<string name="_bx_market_form_entry_input_sys_cat"><![CDATA[Категория]]></string>
 	<string name="_bx_market_form_entry_input_sys_cat"><![CDATA[Категория]]></string>
 	<string name="_bx_market_form_entry_input_cat"><![CDATA[Категория]]></string>
 	<string name="_bx_market_form_entry_input_cat"><![CDATA[Категория]]></string>
 	<string name="_bx_market_form_entry_input_cat_err"><![CDATA[Нужно обязательно выбрать категорию]]></string>
 	<string name="_bx_market_form_entry_input_cat_err"><![CDATA[Нужно обязательно выбрать категорию]]></string>
-	<string name="_bx_market_form_entry_input_sys_price"><![CDATA[Оплата за месяц]]></string>
-	<string name="_bx_market_form_entry_input_price"><![CDATA[Оплата за месяц]]></string>
-    <string name="_bx_market_form_entry_input_price_err"><![CDATA[Нужно обязательно выбрать цену.]]></string>
+	<string name="_bx_market_form_entry_input_sys_price_single"><![CDATA[Цена]]></string>
+	<string name="_bx_market_form_entry_input_price_single"><![CDATA[Цена]]></string>
+    <string name="_bx_market_form_entry_input_price_single_inf"><![CDATA[Оставьте пустым, чтобы сделать продукт бесплатным.]]></string>
+	<string name="_bx_market_form_entry_input_sys_price_recurring"><![CDATA[Оплата за месяц]]></string>
+	<string name="_bx_market_form_entry_input_price_recurring"><![CDATA[Оплата за месяц]]></string>
+    <string name="_bx_market_form_entry_input_price_recurring_inf"><![CDATA[Оставьте пустым, чтобы сделать продукт бесплатным.]]></string>
 	<string name="_bx_market_form_entry_input_sys_text"><![CDATA[Текст]]></string>
 	<string name="_bx_market_form_entry_input_sys_text"><![CDATA[Текст]]></string>
 	<string name="_bx_market_form_entry_input_text"><![CDATA[Текст]]></string>
 	<string name="_bx_market_form_entry_input_text"><![CDATA[Текст]]></string>
 	<string name="_bx_market_form_entry_input_text_err"><![CDATA[Поле для Текста не может быть пустым]]></string>
 	<string name="_bx_market_form_entry_input_text_err"><![CDATA[Поле для Текста не может быть пустым]]></string>
@@ -225,6 +232,7 @@
     <string name="_bx_market_cat_video"><![CDATA[Видео]]></string>
     <string name="_bx_market_cat_video"><![CDATA[Видео]]></string>
 
 
     <string name="_bx_market_pre_lists_prices"><![CDATA[Product prices]]></string>
     <string name="_bx_market_pre_lists_prices"><![CDATA[Product prices]]></string>
+    <string name="_bx_market_cat_price_0"><![CDATA[Нет]]></string>
     <string name="_bx_market_cat_price_1"><![CDATA[1]]></string>
     <string name="_bx_market_cat_price_1"><![CDATA[1]]></string>
     <string name="_bx_market_cat_price_2"><![CDATA[2]]></string>
     <string name="_bx_market_cat_price_2"><![CDATA[2]]></string>
     <string name="_bx_market_cat_price_3"><![CDATA[3]]></string>
     <string name="_bx_market_cat_price_3"><![CDATA[3]]></string>
@@ -246,6 +254,10 @@
     <string name="_bx_market_txt_updated"><![CDATA[Дата обновления:]]></string>
     <string name="_bx_market_txt_updated"><![CDATA[Дата обновления:]]></string>
     <string name="_bx_market_txt_joined"><![CDATA[Зарегистрирован:]]></string>
     <string name="_bx_market_txt_joined"><![CDATA[Зарегистрирован:]]></string>
     <string name="_bx_market_txt_last_active"><![CDATA[Последняя активность:]]></string>
     <string name="_bx_market_txt_last_active"><![CDATA[Последняя активность:]]></string>
-    <string name="_bx_market_txt_get_for_fixed"><![CDATA[Приобрести за {0}{1}]]></string>
-    <string name="_bx_market_txt_get_for_per_month"><![CDATA[Приобрести за {0}{1} в месяц]]></string>
+    <string name="_bx_market_txt_get_for_single"><![CDATA[Приобрести за {0}{1}]]></string>
+    <string name="_bx_market_txt_price_single"><![CDATA[{0}{1}]]></string>
+    <string name="_bx_market_txt_get_for_recurring"><![CDATA[Приобрести за {0}{1} в месяц]]></string>
+    <string name="_bx_market_txt_price_recurring"><![CDATA[{0}{1}/мес]]></string>
+    <string name="_bx_market_txt_or"><![CDATA[или]]></string>
+    <string name="_bx_market_txt_get_for_free"><![CDATA[Бесплатно]]></string>
 </resources>
 </resources>