AntonLV 9 年之前
父節點
當前提交
147eda3a49

+ 10 - 10
inc/classes/BxDolPayments.php

@@ -204,36 +204,36 @@ class BxDolPayments extends BxDolFactory implements iBxDolSingleton
     /**
      * Adds an item to cart in background mode.
      */
-	public function addToCart($iVendorId, $mixedModuleId, $iItemId, $iItemCount)
+	public function addToCart($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $aCustom = array())
     {
     	if(!BxDolRequest::serviceExists($this->_sActive, 'add_to_cart', 'Cart'))
 			return array();
 
-		$aSrvParams = array($iVendorId, $mixedModuleId, $iItemId, $iItemCount);
+		$aSrvParams = array($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $aCustom);
 		return BxDolService::call($this->_sActive, 'add_to_cart', $aSrvParams, 'Cart');
     }
 
     /**
      * Returns "Add To Cart" JavaScript code to use in onclick attribute.
      */
-    public function getAddToCartJs($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $bNeedRedirect = false)
+    public function getAddToCartJs($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $bNeedRedirect = false, $aCustom = array())
     {
     	if(!BxDolRequest::serviceExists($this->_sActive, 'get_add_to_cart_js', 'Cart'))
 			return array();
 
-		$aSrvParams = array($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $bNeedRedirect);
+		$aSrvParams = array($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $bNeedRedirect, $aCustom);
 		return BxDolService::call($this->_sActive, 'get_add_to_cart_js', $aSrvParams, 'Cart');
     }
 
     /**
      * Returns the whole "Add To Cart" link including HTML tag BUTTON and cart JavaScript code.
      */
-    public function getAddToCartLink($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $bNeedRedirect = false)
+    public function getAddToCartLink($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $bNeedRedirect = false, $aCustom = array())
     {
 		if(!BxDolRequest::serviceExists($this->_sActive, 'get_add_to_cart_link', 'Cart'))
 			return '';
 
-		$aSrvParams = array($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $bNeedRedirect);
+		$aSrvParams = array($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $bNeedRedirect, $aCustom);
 		return BxDolService::call($this->_sActive, 'get_add_to_cart_link', $aSrvParams, 'Cart');
     }
 
@@ -256,24 +256,24 @@ class BxDolPayments extends BxDolFactory implements iBxDolSingleton
 	/**
      * Returns "Subscribe" JavaScript code to use in onclick attribute.
      */
-    public function getSubscribeJs($iVendorId, $sVendorProvider, $mixedModuleId, $iItemId, $iItemCount = 1, $sRedirect = '')
+    public function getSubscribeJs($iVendorId, $sVendorProvider, $mixedModuleId, $iItemId, $iItemCount = 1, $sRedirect = '', $aCustom = array())
     {
     	if(!BxDolRequest::serviceExists($this->_sActive, 'get_subscribe_js', 'Subscriptions'))
 			return array();
 
-		$aSrvParams = array($iVendorId, $sVendorProvider, $mixedModuleId, $iItemId, $iItemCount, $sRedirect);
+		$aSrvParams = array($iVendorId, $sVendorProvider, $mixedModuleId, $iItemId, $iItemCount, $sRedirect, $aCustom);
 		return BxDolService::call($this->_sActive, 'get_subscribe_js', $aSrvParams, 'Subscriptions');
     }
 
     /**
      * Returns the whole "Subscribe" link including HTML tag BUTTON and cart JavaScript code.
      */
-    public function getSubscribeLink($iVendorId, $sVendorProvider, $mixedModuleId, $iItemId, $iItemCount = 1, $sRedirect = '')
+    public function getSubscribeLink($iVendorId, $sVendorProvider, $mixedModuleId, $iItemId, $iItemCount = 1, $sRedirect = '', $aCustom = array())
     {
 		if(!BxDolRequest::serviceExists($this->_sActive, 'get_subscribe_link', 'Subscriptions'))
 			return '';
 
-		$aSrvParams = array($iVendorId, $sVendorProvider, $mixedModuleId, $iItemId, $iItemCount, $sRedirect);
+		$aSrvParams = array($iVendorId, $sVendorProvider, $mixedModuleId, $iItemId, $iItemCount, $sRedirect, $aCustom);
 		return BxDolService::call($this->_sActive, 'get_subscribe_link', $aSrvParams, 'Subscriptions');
     }
 

+ 6 - 4
modules/base/payment/classes/BxBaseModPaymentCart.php

@@ -88,6 +88,7 @@ class BxBaseModPaymentCart extends BxDol
      * @param $iItemId $iItemId integer value with item ID. 
      * @param $iItemCount integer value with a number of items for purchasing. 
      * @param $bNeedRedirect (optional) boolean value determining whether redirect is needed after add action or not.
+     * @param $aCustom (optional) array with custom data to attach to an item added into a cart.
      * @return string with JavaScript code to use in OnClick attributes of HTML elements.
      * 
      * @see BxBaseModPaymentCart::serviceGetAddToCartJs
@@ -95,13 +96,13 @@ class BxBaseModPaymentCart extends BxDol
     /** 
      * @ref bx_base_payment-get_add_to_cart_js "get_add_to_cart_js"
      */
-    public function serviceGetAddToCartJs($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $bNeedRedirect = false)
+    public function serviceGetAddToCartJs($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $bNeedRedirect = false, $aCustom = array())
     {
 		$iModuleId = $this->_oModule->_oConfig->getModuleId($mixedModuleId);
         if(empty($iModuleId))
             return '';
 
-        return $this->_oModule->_oTemplate->displayAddToCartJs($iVendorId, $iModuleId, $iItemId, $iItemCount, $bNeedRedirect);
+        return $this->_oModule->_oTemplate->displayAddToCartJs($iVendorId, $iModuleId, $iItemId, $iItemCount, $bNeedRedirect, $aCustom);
     }
 
     /**
@@ -119,6 +120,7 @@ class BxBaseModPaymentCart extends BxDol
      * @param $iItemId $iItemId integer value with item ID. 
      * @param $iItemCount integer value with a number of items for purchasing. 
      * @param $bNeedRedirect (optional) boolean value determining whether redirect is needed after add action or not.
+     * @param $aCustom (optional) array with custom data to attach to an item added into a cart.
      * @return HTML string with link to display on the site.
      * 
      * @see BxBaseModPaymentCart::serviceGetAddToCartLink
@@ -126,13 +128,13 @@ class BxBaseModPaymentCart extends BxDol
     /** 
      * @ref bx_base_payment-get_add_to_cart_link "get_add_to_cart_link"
      */
-	public function serviceGetAddToCartLink($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $bNeedRedirect = false)
+	public function serviceGetAddToCartLink($iVendorId, $mixedModuleId, $iItemId, $iItemCount, $bNeedRedirect = false, $aCustom = array())
     {
         $iModuleId = $this->_oModule->_oConfig->getModuleId($mixedModuleId);
         if(empty($iModuleId))
             return '';
 
-		return $this->_oModule->_oTemplate->displayAddToCartLink($iVendorId, $iModuleId, $iItemId, $iItemCount, $bNeedRedirect);
+		return $this->_oModule->_oTemplate->displayAddToCartLink($iVendorId, $iModuleId, $iItemId, $iItemCount, $bNeedRedirect, $aCustom);
     }
 
     /**

+ 4 - 4
modules/base/payment/classes/BxBaseModPaymentSubscriptions.php

@@ -109,13 +109,13 @@ class BxBaseModPaymentSubscriptions extends BxDol
     /** 
      * @ref bx_base_payment-get_subscribe_js "get_subscribe_js"
      */
-    public function serviceGetSubscribeJs($iVendorId, $sVendorProvider, $mixedModuleId, $iItemId, $iItemCount = 1, $sRedirect = '')
+    public function serviceGetSubscribeJs($iVendorId, $sVendorProvider, $mixedModuleId, $iItemId, $iItemCount = 1, $sRedirect = '', $aCustom = array())
     {
 		$iModuleId = $this->_oModule->_oConfig->getModuleId($mixedModuleId);
         if(empty($iModuleId))
             return '';
 
-        return $this->_oModule->_oTemplate->displaySubscribeJs($iVendorId, $sVendorProvider, $iModuleId, $iItemId, $iItemCount, $sRedirect);
+        return $this->_oModule->_oTemplate->displaySubscribeJs($iVendorId, $sVendorProvider, $iModuleId, $iItemId, $iItemCount, $sRedirect, $aCustom);
     }
 
     /**
@@ -141,13 +141,13 @@ class BxBaseModPaymentSubscriptions extends BxDol
     /** 
      * @ref bx_base_payment-get_subscribe_link "get_subscribe_link"
      */
-    public function serviceGetSubscribeLink($iVendorId, $sVendorProvider, $mixedModuleId, $iItemId, $iItemCount = 1, $sRedirect = '')
+    public function serviceGetSubscribeLink($iVendorId, $sVendorProvider, $mixedModuleId, $iItemId, $iItemCount = 1, $sRedirect = '', $aCustom = array())
     {
         $iModuleId = $this->_oModule->_oConfig->getModuleId($mixedModuleId);
         if(empty($iModuleId))
             return '';
 
-		return $this->_oModule->_oTemplate->displaySubscribeLink($iVendorId, $sVendorProvider, $iModuleId, $iItemId, $iItemCount, $sRedirect);
+		return $this->_oModule->_oTemplate->displaySubscribeLink($iVendorId, $sVendorProvider, $iModuleId, $iItemId, $iItemCount, $sRedirect, $aCustom);
     }
 }
 

+ 38 - 13
modules/boonex/payment/classes/BxPaymentCart.php

@@ -147,6 +147,7 @@ class BxPaymentCart extends BxBaseModPaymentCart
      * @param $mixedModuleId mixed value (ID, Name or URI) determining a module from which the action was initiated.
      * @param $iItemId integer value with item ID.
      * @param $iItemCount integer value with a number of items for purchasing.
+     * @param $aCustom array with custom data.
      * @return an array with special format which describes the result of operation.
      * 
      * @see BxPaymentCart::serviceAddToCart
@@ -154,7 +155,7 @@ class BxPaymentCart extends BxBaseModPaymentCart
     /** 
      * @ref bx_payment-add_to_cart "add_to_cart"
      */
-    public function serviceAddToCart($iSellerId, $mixedModuleId, $iItemId, $iItemCount)
+    public function serviceAddToCart($iSellerId, $mixedModuleId, $iItemId, $iItemCount, $aCustom = array())
     {
     	$CNF = &$this->_oModule->_oConfig->CNF;
 
@@ -169,19 +170,29 @@ class BxPaymentCart extends BxBaseModPaymentCart
         if(empty($aSellerProviders))
             return array('code' => 5, 'message' => _t($CNF['T']['ERR_NOT_ACCEPT_PAYMENTS']));
 
-        $sCartItem = $this->_oModule->_oConfig->descriptorA2S(array($iSellerId, $iModuleId, $iItemId, $iItemCount));
-        $sCartItems = $this->_oModule->_oDb->getCartItems($iClientId);
+        $aCart = $this->_oModule->_oDb->getCartContent($iClientId);
+        $sCartItems = !empty($aCart['items']) ? $aCart['items'] : '';
 
-        if(strpos($sCartItems, $this->_oModule->_oConfig->descriptorA2S(array($iSellerId, $iModuleId, $iItemId))) !== false)
+        $sCiDsc = $this->_oModule->_oConfig->descriptorA2S(array($iSellerId, $iModuleId, $iItemId));
+        if(strpos($sCartItems, $sCiDsc) !== false)
             $sCartItems = preg_replace_callback(
             	"/" . $this->_oModule->_oConfig->descriptorA2S(array($iSellerId, $iModuleId, $iItemId, '([0-9])+')) . "/", 
             	create_function('$aMatches', 'return ' . $this->_oModule->_oConfig->descriptorA2S(array("'" . $iSellerId, $iModuleId, $iItemId, "' . (\$aMatches[1] + " . $iItemCount . ")")) . ';'),
             	$sCartItems
 			);
-        else
+        else {
+            $sCartItem = $this->_oModule->_oConfig->descriptorA2S(array($iSellerId, $iModuleId, $iItemId, $iItemCount));
             $sCartItems = empty($sCartItems) ? $sCartItem : $sCartItems . $this->_oModule->_oConfig->getDivider('DIVIDER_DESCRIPTORS') . $sCartItem;
+        }
+
+        $aCartCustom = array();
+        if(!empty($aCart['customs']))
+            $aCartCustom = unserialize($aCart['customs']);
 
-        $this->_oModule->_oDb->setCartItems($iClientId, $sCartItems);
+        if(!empty($aCustom) && is_array($aCustom))
+            $aCartCustom[$sCiDsc] = !empty($aCartCustom[$sCiDsc]) && is_array($aCartCustom[$sCiDsc]) ? array_merge($aCartCustom[$sCiDsc], $aCustom) : $aCustom;
+
+        $this->_oModule->_oDb->setCartItems($iClientId, $sCartItems, $aCartCustom);
 
         $aInfo = $this->getInfo(BX_PAYMENT_TYPE_SINGLE, $iClientId);
         $iTotalQuantity = 0;
@@ -228,14 +239,28 @@ class BxPaymentCart extends BxBaseModPaymentCart
         if(empty($iClientId))
             return array('code' => 2, 'message' => _t($CNF['T']['ERR_REQUIRED_LOGIN']));
 
-        if(!empty($iModuleId) && !empty($iItemId))
-            $sPattern = "'" . $iSellerId . "_" . $iModuleId . "_" . $iItemId . "_[0-9]+:?'";
-        else
-            $sPattern = "'" . $iSellerId . "_[0-9]+_[0-9]+_[0-9]+:?'";
+        $aCart = $this->_oModule->_oDb->getCartContent($iClientId);
+
+        $aCartCustom = array();
+        if(!empty($aCart['customs']))
+            $aCartCustom = unserialize($aCart['customs']);
+
+        if(!empty($iModuleId) && !empty($iItemId)) {
+            $sCiDsc = $this->_oModule->_oConfig->descriptorA2S(array($iSellerId, $iModuleId, $iItemId));
+            if(!empty($aCartCustom[$sCiDsc]))
+                unset($aCartCustom[$sCiDsc]);
+        }
+        else {
+            $aCiDscs = array_keys($aCartCustom);
+            foreach($aCiDscs as $sCiDsc)
+                if(strpos($sCiDsc, $iSellerId . '_') === 0)
+                    unset($aCartCustom[$sCiDsc]);
+
+            $iModuleId = $iItemId = '[0-9]+';
+        }
 
-        $sCartItems = $this->_oModule->_oDb->getCartItems($iClientId);
-        $sCartItems = trim(preg_replace($sPattern, "", $sCartItems), ":");
-        $this->_oModule->_oDb->setCartItems($iClientId, $sCartItems);
+        $aCart['items'] = trim(preg_replace("'" . $this->_oModule->_oConfig->descriptorA2S(array($iSellerId, $iModuleId, $iItemId, '[0-9]+:?')) . "'", "", $aCart['items']), ":");
+        $this->_oModule->_oDb->setCartItems($iClientId, $aCart['items'], $aCartCustom);
 
         return array('code' => 0, 'message' => _t($CNF['T']['MSG_ITEM_DELETED']));
     }

+ 36 - 0
modules/boonex/payment/classes/BxPaymentConfig.php

@@ -225,6 +225,42 @@ class BxPaymentConfig extends BxBaseModPaymentConfig
         return $aResult;
     }
 
+    public function putCustom($mDsc, $aCustom, &$aCustoms)
+    {
+        if(empty($aCustom) || !is_array($aCustom))
+            return;
+
+        if(is_array($mDsc))
+            $mDsc = $this->descriptorA2S(array_slice($mDsc, 0, 3));
+
+        $aCustoms[$mDsc] = !empty($aCustoms[$mDsc]) && is_array($aCustoms[$mDsc]) ? array_merge($aCustoms[$mDsc], $aCustom) : $aCustom;
+    }
+
+    public function getCustom($mDsc, &$aCustoms)
+    {
+        if(is_array($mDsc))
+            $mDsc = $this->descriptorA2S(array_slice($mDsc, 0, 3));
+
+        if(empty($aCustoms) || !is_array($aCustoms) || empty($aCustoms[$mDsc]))
+            return array();
+
+        return $aCustoms[$mDsc];
+    }
+
+    public function pullCustom($mDsc, &$aCustoms)
+    {
+        if(is_array($mDsc))
+            $mDsc = $this->descriptorA2S(array_slice($mDsc, 0, 3));
+
+        if(empty($aCustoms) || !is_array($aCustoms) || empty($aCustoms[$mDsc]))
+            return array();
+
+        $aResult = $aCustoms[$mDsc];
+        unset($aCustoms[$mDsc]);           
+
+        return $aResult;
+    }
+
 	public function http2https($s)
     {
     	if(strncmp($s, 'https://', 8) === 0)

+ 30 - 19
modules/boonex/payment/classes/BxPaymentDb.php

@@ -137,15 +137,27 @@ class BxPaymentDb extends BxBaseModPaymentDb
     	$sQuery = $this->prepare("SELECT `items` FROM `" . $this->_sPrefix . "cart` WHERE `client_id`=? LIMIT 1", $iId);
         return $this->getOne($sQuery);
     }
-    public function setCartItems($iId, $sItems)
+
+    public function getCartContent($iId)
+    {
+    	return $this->getRow("SELECT * FROM `" . $this->_sPrefix . "cart` WHERE `client_id`=:client_id LIMIT 1", array(
+    		'client_id' => $iId
+    	));
+    }
+
+    public function setCartItems($iId, $sItems, $aCustoms = array())
     {
         $sItems = trim($sItems, ":");
         if(empty($sItems))
-            $sQuery = $this->prepare("DELETE FROM `" . $this->_sPrefix . "cart` WHERE `client_id`=? LIMIT 1", $iId);
-        else
-            $sQuery = $this->prepare("REPLACE INTO `" . $this->_sPrefix . "cart` SET `client_id`=?, `items`=?", $iId, $sItems);
-
-        return $this->query($sQuery);
+            return $this->query("DELETE FROM `" . $this->_sPrefix . "cart` WHERE `client_id`=:client_id LIMIT 1", array(
+                'client_id' => $iId
+            ));
+
+        return $this->query("REPLACE INTO `" . $this->_sPrefix . "cart` SET `client_id`=:client_id, `items`=:items, `customs`=:customs", array(
+            'client_id' => $iId,
+            'items' => $sItems,
+            'customs' => !empty($aCustoms) && is_array($aCustoms) ? serialize($aCustoms) : ''
+        ));
     }
 
 	public function getVendorInfoProvidersSingle($iVendorId)
@@ -236,22 +248,21 @@ class BxPaymentDb extends BxBaseModPaymentDb
         return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
     }
 
-    public function insertOrderPending($iClientId, $sType, $sProvider, $aCartInfo)
+    public function insertOrderPending($iClientId, $sType, $sProvider, $aCartInfo, $aCustom = array())
     {
         $sItems = "";
         foreach($aCartInfo['items'] as $aItem)
-            $sItems .= $aCartInfo['vendor_id'] . '_' . $aItem['module_id'] . '_' . $aItem['id'] . '_' . $aItem['quantity'] . ':';
-
-        $sQuery = $this->prepare("INSERT INTO `" . $this->_sPrefix . "transactions_pending` SET
-                    `client_id`=?,
-                    `seller_id`=?,
-                    `type`=?,
-                    `provider`=?,
-                    `items`=?,
-                    `amount`=?,
-                    `date`=UNIX_TIMESTAMP()", $iClientId, $aCartInfo['vendor_id'], $sType, $sProvider, trim($sItems, ':'), $aCartInfo['items_price']);
-
-        return (int)$this->query($sQuery) > 0 ? $this->lastId() : 0;
+            $sItems .= $this->_oConfig->descriptorA2S(array($aCartInfo['vendor_id'], $aItem['module_id'], $aItem['id'], $aItem['quantity'])) . ':';
+
+        return (int)$this->query("INSERT INTO `" . $this->_sPrefix . "transactions_pending` SET `client_id`=:client_id, `seller_id`=:seller_id, `type`=:type, `provider`=:provider, `items`=:items, `customs`=:customs, `amount`=:amount, `date`=UNIX_TIMESTAMP()", array(
+            'client_id' => $iClientId,
+            'seller_id' => $aCartInfo['vendor_id'],
+            'type' => $sType, 
+            'provider' => $sProvider,
+            'items' => trim($sItems, ':'),
+            'customs' => !empty($aCustom) && is_array($aCustom) ? serialize($aCustom) : '',
+            'amount' => $aCartInfo['items_price']
+        )) > 0 ? $this->lastId() : 0;
     }
 
     public function updateOrderPending($iId, $aValues)

+ 96 - 24
modules/boonex/payment/classes/BxPaymentModule.php

@@ -298,9 +298,19 @@ class BxPaymentModule extends BxBaseModPaymentModule
     /**
      * Cart Processing Methods
      */
-    public function actionAddToCart($iSellerId, $iModuleId, $iItemId, $iItemCount)
+    public function actionAddToCart($iSellerId, $iModuleId, $iItemId, $iItemCount, $sCustom = '')
     {
-        $aResult = $this->getObjectCart()->serviceAddToCart($iSellerId, $iModuleId, $iItemId, $iItemCount);
+        if(empty($sCustom) && bx_get('custom') !== false)
+            $sCustom = bx_process_input(bx_get('custom'));
+
+        $aCustom = array();
+        if(!empty($sCustom)) {
+            $aCustom = unserialize(base64_decode($sCustom));
+            if(empty($aCustom) || !is_array($aCustom))
+                $aCustom = array();
+        }
+
+        $aResult = $this->getObjectCart()->serviceAddToCart($iSellerId, $iModuleId, $iItemId, $iItemCount, $aCustom);
 		echoJson($aResult);
     }
 
@@ -332,7 +342,17 @@ class BxPaymentModule extends BxBaseModPaymentModule
     	if(empty($iItemCount))
     		$iItemCount = 1;
 
-        $aResult = $this->getObjectSubscriptions()->serviceSubscribe($iSellerId, $sSellerProvider, $iModuleId, $iItemId, $iItemCount);
+        $sRedirect = bx_process_input(bx_get('redirect'));
+        $sCustom = bx_process_input(bx_get('custom'));
+
+        $aCustom = array();
+        if(!empty($sCustom)) {
+            $aCustom = unserialize(base64_decode($sCustom));
+            if(empty($aCustom) || !is_array($aCustom))
+                $aCustom = array();
+        }
+
+        $aResult = $this->getObjectSubscriptions()->serviceSubscribe($iSellerId, $sSellerProvider, $iModuleId, $iItemId, $iItemCount, $sRedirect, $aCustom);
         $bRedirect = !empty($aResult['redirect']);
 
         if(!empty($aResult['popup'])) {
@@ -361,12 +381,22 @@ class BxPaymentModule extends BxBaseModPaymentModule
     	$sSellerProvider = bx_process_input(bx_get('seller_provider'));
     	$iModuleId = bx_process_input(bx_get('module_id'), BX_DATA_INT);
     	$iItemId = bx_process_input(bx_get('item_id'), BX_DATA_INT);
+
     	$iItemCount = bx_process_input(bx_get('item_count'), BX_DATA_INT);
     	if(empty($iItemCount))
     		$iItemCount = 1;
+
         $sRedirect = bx_process_input(bx_get('redirect'));
+        $sCustom = bx_process_input(bx_get('custom'));
+
+        $aCustom = array();
+        if(!empty($sCustom)) {
+            $aCustom = unserialize(base64_decode($sCustom));
+            if(empty($aCustom) || !is_array($aCustom))
+                $aCustom = array();
+        }
 
-        $aResult = $this->getObjectSubscriptions()->serviceSubscribe($iSellerId, $sSellerProvider, $iModuleId, $iItemId, $iItemCount, $sRedirect);
+        $aResult = $this->getObjectSubscriptions()->serviceSubscribe($iSellerId, $sSellerProvider, $iModuleId, $iItemId, $iItemCount, $sRedirect, $aCustom);
 		echoJson($aResult);
     }
 
@@ -468,6 +498,7 @@ class BxPaymentModule extends BxBaseModPaymentModule
      * @param $sProvider string value with payment provider name. 
      * @param $aItems (optional) an array with items to be purchased. 
      * @param $sRedirect (optional) string value with redirect URL if it's needed.
+     * @param $aCustom (optional) array with custom data to attach to a payment.
      * @return the result depends on the payment provider which is used for processing or represented as string value with error message if something is wrong.
      * 
      * @see BxPaymentModule::serviceInitializeCheckout
@@ -475,8 +506,11 @@ class BxPaymentModule extends BxBaseModPaymentModule
     /** 
      * @ref bx_payment-initialize_checkout "initialize_checkout"
      */
-	public function serviceInitializeCheckout($sType, $iSellerId, $sProvider, $aItems = array(), $sRedirect = '')
+	public function serviceInitializeCheckout($sType, $iSellerId, $sProvider, $aItems = array(), $sRedirect = '', $aCustoms = array())
 	{
+	    $bTypeSingle = $sType == BX_PAYMENT_TYPE_SINGLE;
+	    $bTypeRecurring = $sType == BX_PAYMENT_TYPE_RECURRING;
+
 		if(!is_array($aItems))
 			$aItems = array($aItems);
 
@@ -491,38 +525,67 @@ class BxPaymentModule extends BxBaseModPaymentModule
         $aInfo = $this->getObjectCart()->getInfo($sType, $this->_iUserId, $iSellerId, $aItems);
         if(empty($aInfo) || $aInfo['vendor_id'] == BX_PAYMENT_EMPTY_ID || empty($aInfo['items']))
             return $this->_sLangsPrefix . 'err_empty_order';
-
+            
 		/*
 		 * Process FREE (price = 0) items for LOGGED IN members
 		 * WITHOUT processing via payment provider.
+		 * Note. This section isn't used for now!
 		 */
 		$bProcessedFree = false;
 		$sKeyPriceSingle = $this->_oConfig->getKey('KEY_ARRAY_PRICE_SINGLE');
 		$sKeyPriceRecurring = $this->_oConfig->getKey('KEY_ARRAY_PRICE_RECURRING');
-		foreach($aInfo['items'] as $iIndex => $aItem)
-			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()));
+		foreach($aInfo['items'] as $iIndex => $aItem) {
+		    if((int)$aInfo['client_id'] == 0)
+		        continue;
+
+            //--- For Single time payments.
+			if($bTypeSingle && (float)$aItem[$sKeyPriceSingle] == 0) {
+			    $aCart = $this->_oDb->getCartContent($aInfo['client_id']);
+			    $aCartCustoms = !empty($aCart['customs']) ? unserialize($aCart['customs']) : array();
+
+			    $aCartItem = array($aInfo['vendor_id'], $aItem['module_id'], $aItem['id'], $aItem['quantity']);
+			    $aCartItemCustom = $this->_oConfig->pullCustom($aCartItem, $aCartCustoms);
+
+				$aItemInfo = $this->callRegisterCartItem((int)$aItem['module_id'], array($aInfo['client_id'], $aInfo['vendor_id'], $aItem['id'], $aItem['quantity'], $this->_oConfig->getLicense(), $aCartItemCustom));
 	            if(is_array($aItemInfo) && !empty($aItemInfo))
 	            	$bProcessedFree = true;
 
 	            $aInfo['items_count'] -= 1;
 	            unset($aInfo['items'][$iIndex]);
 
-	            $sCartItems = $this->_oDb->getCartItems($aInfo['client_id']);
-	            $sCartItems = trim(preg_replace("'" . $this->_oConfig->descriptorA2S(array($aInfo['vendor_id'], $aItem['module_id'], $aItem['id'], $aItem['quantity'])) . ":?'", "", $sCartItems), ":");
-	            $this->_oDb->setCartItems($aInfo['client_id'], $sCartItems);
+	            $aCart['items'] = trim(preg_replace("'" . $this->_oConfig->descriptorA2S($aCartItem) . ":?'", "", $aCart['items']), ":");
+	            $this->_oDb->setCartItems($aInfo['client_id'], $aCart['items'], $aCartCustoms);
 			}
 
+			//--- For Recurring payments.
+			if($bTypeRecurring && (float)$aItem[$sKeyPriceRecurring] == 0) {
+			    //TODO: Process FREE subscription here, if such situation will be possible.
+			}
+		}
+
 		if(empty($aInfo['items']))
             return $this->_sLangsPrefix . ($bProcessedFree ? 'msg_successfully_processed_free' : 'err_empty_order');
 
-        $iPendingId = $this->_oDb->insertOrderPending($this->_iUserId, $sType, $sProvider, $aInfo);
+        if($bTypeSingle && (empty($aCustoms) || !is_array($aCustoms))) {
+            $aCart = $this->_oDb->getCartContent($aInfo['client_id']);
+            $aCartCustoms = !empty($aCart['customs']) ? unserialize($aCart['customs']) : array();
+
+            $aCustoms = array();
+            foreach($aInfo['items'] as $aItem) {
+                $sCartItem = $this->_oConfig->descriptorA2S(array($aInfo['vendor_id'], $aItem['module_id'], $aItem['id']));
+                $aCartItemCustom = $this->_oConfig->getCustom($sCartItem, $aCartCustoms);
+                $this->_oConfig->putCustom($sCartItem, $aCartItemCustom, $aCustoms);
+            }
+        }
+
+        $iPendingId = $this->_oDb->insertOrderPending($this->_iUserId, $sType, $sProvider, $aInfo, $aCustoms);
         if(empty($iPendingId))
             return $this->_sLangsPrefix . 'err_access_db';
 
 		/*
 		 * Perform Join WITHOUT processing via payment provider
 		 * if a client ISN'T logged in and has only ONE FREE item in the card.
+		 * Note. This section isn't used for now because only a member can purchase!
 		 */
 		if((int)$aInfo['client_id'] == 0 && (int)$aInfo['items_count'] == 1) {
 			reset($aInfo['items']);
@@ -704,16 +767,22 @@ class BxPaymentModule extends BxBaseModPaymentModule
 
 		$iClientId = (int)$aPending['client_id'];
 		$sLicense = $this->_oConfig->getLicense();
+		$aCustoms = !empty($aPending['customs']) ? unserialize($aPending['customs']) : array();
 
-		$sCartItems = '';
-		if($bTypeSingle)
-			$sCartItems = $this->_oDb->getCartItems($iClientId);
+		$aCart = array();
+		if($bTypeSingle) {
+			$aCart = $this->_oDb->getCartContent($iClientId);
+			$aCart['customs'] = !empty($aCart['customs']) ? unserialize($aCart['customs']) : array();
+		}
 
 		$bResult = false;
         $aItems = $this->_oConfig->descriptorsM2A($aPending['items']);
         foreach($aItems as $aItem) {
+            $sItem = $this->_oConfig->descriptorA2S(array($aItem['vendor_id'], $aItem['module_id'], $aItem['item_id']));
+		    $aItemCustom = $this->_oConfig->getCustom($sItem, $aCustoms);
+
         	$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));
+        	$aItemInfo = $this->$sMethod((int)$aItem['module_id'], array($aPending['client_id'], $aPending['seller_id'], $aItem['item_id'], $aItem['item_count'], $aPending['order'], $sLicense, $aItemCustom));
             if(empty($aItemInfo) || !is_array($aItemInfo))
                 continue;
 
@@ -721,21 +790,24 @@ class BxPaymentModule extends BxBaseModPaymentModule
                 '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' => $aItem['item_count'] * $this->_oConfig->getPrice($sType, $aItemInfo),
+                'module_id' => (int)$aItem['module_id'],
+                'item_id' => (int)$aItem['item_id'],
+                'item_count' => (int)$aItem['item_count'],
+                'amount' => (int)$aItem['item_count'] * $this->_oConfig->getPrice($sType, $aItemInfo),
             	'license' => $sLicense,
             ));
 
-            if($bTypeSingle)
-            	$sCartItems = trim(preg_replace("'" . $this->_oConfig->descriptorA2S($aItem) . ":?'", "", $sCartItems), ":");
+            if($bTypeSingle) {
+                $this->_oConfig->pullCustom($sItem, $aCart['customs']);
+
+            	$aCart['items'] = trim(preg_replace("'" . $this->_oConfig->descriptorA2S($aItem) . ":?'", "", $aCart['items']), ":");
+            }
 
 			$bResult = true;
         }
 
         if($bTypeSingle)
-			$this->_oDb->setCartItems($iClientId, $sCartItems);
+			$this->_oDb->setCartItems($iClientId, $aCart['items'], $aCart['customs']);
 
         if($bResult) {
         	$this->_oDb->updateOrderPending($aPending['id'], array('processed' => 1));

+ 6 - 4
modules/boonex/payment/classes/BxPaymentSubscriptions.php

@@ -111,7 +111,7 @@ class BxPaymentSubscriptions extends BxBaseModPaymentSubscriptions
     /** 
      * @ref bx_payment-subscribe "subscribe"
      */
-	public function serviceSubscribe($iSellerId, $sSellerProvider, $iModuleId, $iItemId, $iItemCount, $sRedirect = '')
+	public function serviceSubscribe($iSellerId, $sSellerProvider, $iModuleId, $iItemId, $iItemCount, $sRedirect = '', $aCustom = array())
     {
     	$CNF = &$this->_oModule->_oConfig->CNF;
 
@@ -132,13 +132,15 @@ class BxPaymentSubscriptions extends BxBaseModPaymentSubscriptions
 			$sId = $this->_oModule->_oConfig->getHtmlIds('cart', 'providers_select') . BX_PAYMENT_TYPE_RECURRING;
 			$sTitle = _t($CNF['T']['POPUP_PROVIDERS_SELECT']);
 			return array('popup' => array(
-				'html' => BxTemplStudioFunctions::getInstance()->popupBox($sId, $sTitle, $this->_oModule->_oTemplate->displayProvidersSelector($aCartItem, $aSellerProviders, $sRedirect)), 
+				'html' => BxTemplStudioFunctions::getInstance()->popupBox($sId, $sTitle, $this->_oModule->_oTemplate->displayProvidersSelector($aCartItem, $aSellerProviders, $sRedirect, $aCustom)), 
 				'options' => array('closeOnOuterClick' => true)
 			));
 		}
 
-		$aProvider = $aSellerProviders[$sSellerProvider];
-        $mixedResult = $this->_oModule->serviceInitializeCheckout(BX_PAYMENT_TYPE_RECURRING, $iSellerId, $aProvider['name'], array($sCartItem), $sRedirect);
+		$aCustoms = array();
+		$this->_oModule->_oConfig->putCustom($aCartItem, $aCustom, $aCustoms);
+
+        $mixedResult = $this->_oModule->serviceInitializeCheckout(BX_PAYMENT_TYPE_RECURRING, $iSellerId, $aSellerProviders[$sSellerProvider]['name'], array($sCartItem), $sRedirect, $aCustoms);
         if(is_string($mixedResult))
         	return array('code' => 6, 'message' => _t($mixedResult));
 

+ 16 - 21
modules/boonex/payment/classes/BxPaymentTemplate.php

@@ -62,7 +62,7 @@ class BxPaymentTemplate extends BxBaseModPaymentTemplate
         return $this->displayJsCode('cart');
     }
 
-    public function displayAddToCartJs($iVendorId, $iModuleId, $iItemId, $iItemCount, $bNeedRedirect = false)
+    public function displayAddToCartJs($iVendorId, $iModuleId, $iItemId, $iItemCount, $bNeedRedirect = false, $aCustom = array())
     {
         $sJsCode = $this->displayCartJs(BX_PAYMENT_TYPE_SINGLE, $iVendorId);
         $sJsMethod = $this->parseHtmlByName('add_to_cart_js.html', array(
@@ -71,13 +71,14 @@ class BxPaymentTemplate extends BxBaseModPaymentTemplate
             'module_id' => $iModuleId,
             'item_id' => $iItemId,
             'item_count' => $iItemCount,
-            'need_redirect' => (int)$bNeedRedirect
+            'need_redirect' => (int)$bNeedRedirect,
+            'custom' => !empty($aCustom) && is_array($aCustom) ? base64_encode(serialize($aCustom)) : ''
         ));
 
         return array($sJsCode, $sJsMethod);
     }
 
-    public function displayAddToCartLink($iVendorId, $iModuleId, $iItemId, $iItemCount, $bNeedRedirect = false)
+    public function displayAddToCartLink($iVendorId, $iModuleId, $iItemId, $iItemCount, $bNeedRedirect = false, $aCustom = array())
     {
         $this->addJsCssCart(BX_PAYMENT_TYPE_SINGLE, $iVendorId);
         return $this->parseHtmlByName('add_to_cart.html', array(
@@ -88,11 +89,12 @@ class BxPaymentTemplate extends BxBaseModPaymentTemplate
             'module_id' => $iModuleId,
             'item_id' => $iItemId,
             'item_count' => $iItemCount,
-            'need_redirect' => (int)$bNeedRedirect
+            'need_redirect' => (int)$bNeedRedirect,
+        	'custom' => !empty($aCustom) && is_array($aCustom) ? base64_encode(serialize($aCustom)) : ''
         ));
     }
 
-	public function displaySubscribeJs($iVendorId, $sVendorProvider, $iModuleId, $iItemId, $iItemCount = 1, $sRedirect = '')
+	public function displaySubscribeJs($iVendorId, $sVendorProvider, $iModuleId, $iItemId, $iItemCount = 1, $sRedirect = '', $aCustom = array())
     {
         $sJsCode = $this->displayCartJs(BX_PAYMENT_TYPE_RECURRING, $iVendorId);
         $sJsMethod = $this->parseHtmlByName('subscribe_js.html', array(
@@ -102,18 +104,14 @@ class BxPaymentTemplate extends BxBaseModPaymentTemplate
             'module_id' => $iModuleId,
             'item_id' => $iItemId,
             'item_count' => $iItemCount,
-            'bx_if:show_redirect' => array(
-                'condition' => !empty($sRedirect),
-                'content' => array(
-                    'redirect' => $sRedirect
-                )
-            )
+            'redirect' => !empty($sRedirect) ? $sRedirect : '',
+            'custom' => !empty($aCustom) && is_array($aCustom) ? base64_encode(serialize($aCustom)) : ''
         ));
 
         return array($sJsCode, $sJsMethod);
     }
 
-    public function displaySubscribeLink($iVendorId, $sVendorProvider, $iModuleId, $iItemId, $iItemCount = 1, $sRedirect = '')
+    public function displaySubscribeLink($iVendorId, $sVendorProvider, $iModuleId, $iItemId, $iItemCount = 1, $sRedirect = '', $aCustom = array())
     {
         $this->addJsCssCart(BX_PAYMENT_TYPE_RECURRING, $iVendorId);
         return $this->parseHtmlByName('subscribe.html', array(
@@ -125,12 +123,8 @@ class BxPaymentTemplate extends BxBaseModPaymentTemplate
             'module_id' => $iModuleId,
             'item_id' => $iItemId,
             'item_count' => $iItemCount,
-            'bx_if:show_redirect' => array(
-                'condition' => !empty($sRedirect),
-                'content' => array(
-                    'redirect' => $sRedirect
-                )
-            )
+            'redirect' => !empty($sRedirect) ? $sRedirect : '',
+            'custom' => !empty($aCustom) && is_array($aCustom) ? base64_encode(serialize($aCustom)) : ''
         ));
     }
 
@@ -336,7 +330,7 @@ class BxPaymentTemplate extends BxBaseModPaymentTemplate
         ));
     }
 
-    public function displayProvidersSelector($aCartItem, $aProviders, $sRedirect = '')
+    public function displayProvidersSelector($aCartItem, $aProviders, $sRedirect = '', $aCustom = array())
     {
     	$oModule = $this->getModule();
     	$iClientId = $oModule->getProfileId();
@@ -355,7 +349,8 @@ class BxPaymentTemplate extends BxBaseModPaymentTemplate
 					'iModuleId' => $iModuleId,
 					'iItemId' => $iItemId,
 					'iItemCount' => $iItemCount,
-				    'sRedirect' => $sRedirect
+				    'sRedirect' => $sRedirect,
+			        'sCustom' => base64_encode(serialize($aCustom))
 				);
 
 			    $aCartInfo = $oCart->getInfo(BX_PAYMENT_TYPE_RECURRING, $iClientId, $iSellerId, $this->_oConfig->descriptorA2S($aCartItem));
@@ -373,7 +368,7 @@ class BxPaymentTemplate extends BxBaseModPaymentTemplate
 				$sButton = $oProvider->getButtonRecurring($iClientId, $iSellerId, $aParams);
 			}
 			else {
-				list($sJsCode, $sJsOnclick) = $oSubscriptions->serviceGetSubscribeJs($iSellerId, $aProvider['name'], $iModuleId, $iItemId, $iItemCount, $sRedirect);
+				list($sJsCode, $sJsOnclick) = $oSubscriptions->serviceGetSubscribeJs($iSellerId, $aProvider['name'], $iModuleId, $iItemId, $iItemCount, $sRedirect, $aCustom);
 
 				$sButton = $this->parsePageByName('providers_select_button.html', array(
 					'onclick' => $sJsOnclick,

+ 2 - 0
modules/boonex/payment/install/sql/install.sql

@@ -42,6 +42,7 @@ CREATE TABLE IF NOT EXISTS `bx_payment_user_values` (
 CREATE TABLE IF NOT EXISTS `bx_payment_cart` (
   `client_id` int(11) NOT NULL default '0',
   `items` text NOT NULL default '',
+  `customs` text NOT NULL default '',
   PRIMARY KEY(`client_id`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 
@@ -91,6 +92,7 @@ CREATE TABLE IF NOT EXISTS `bx_payment_transactions_pending` (
   `type` varchar(16) NOT NULL default 'single',
   `provider` varchar(32) NOT NULL default '',
   `items` text NOT NULL default '',
+  `customs` text NOT NULL default '',
   `amount` float NOT NULL default '0',
   `order` varchar(32) NOT NULL default '',
   `error_code` varchar(16) NOT NULL default '',

+ 12 - 8
modules/boonex/payment/js/cart.js

@@ -24,20 +24,23 @@ BxPaymentCart.prototype.init = function(oOptions) {
     this._iAnimationSpeed = oOptions.iAnimationSpeed == undefined ? 'slow' : oOptions.iAnimationSpeed;
 };
 
-BxPaymentCart.prototype.addToCart = function(iSellerId, iModuleId, iItemId, iItemCount, iRedirect, sRedirect) {
+BxPaymentCart.prototype.addToCart = function(iSellerId, iModuleId, iItemId, iItemCount, iRedirect, sCustom) {
 	var $this = this;
     var oDate = new Date();
 
-    iRedirect = parseInt(iRedirect);
-    if(!iRedirect)
-    	iRedirect = 0;
+    var sRedirect = '';
+    if(typeof iRedirect == 'number' && parseInt(iRedirect) > 0)
+    	sRedirect = sUrlRoot + 'cart.php?seller_id=' + iSellerId;
+	else if(typeof iRedirect == 'string' && iRedirect.length > 0)
+		sRedirect = iRedirect;
 
     $.post(
         this._sActionsUrl + 'add_to_cart/' + iSellerId + '/' + iModuleId + '/' + iItemId + '/' + iItemCount + '/',
         {
+        	custom: sCustom ? sCustom : '',
             _t:oDate.getTime()
         },
-        function(oData){
+        function(oData) {
         	$this.processResult(oData);
 
             if(oData.code == 0) {
@@ -48,8 +51,8 @@ BxPaymentCart.prototype.addToCart = function(iSellerId, iModuleId, iItemId, iIte
                 $('#bx-payment-tbar-content').replaceWith(oData.content);
                 */
 
-            	if(iRedirect == 1)
-            		window.location.href = sRedirect && sRedirect.length > 0 ? sRedirect : sUrlRoot + 'cart.php?seller_id=' + iSellerId;
+            	if(sRedirect)
+            		window.location.href = sRedirect;
             }
         },
         'json'
@@ -70,7 +73,7 @@ BxPaymentCart.prototype.onCartCheckout = function(oData) {
 	location.href = oData.link;
 };
 
-BxPaymentCart.prototype.subscribe = function(iSellerId, sSellerProvider, iModuleId, iItemId, iItemCount, sRedirect) {
+BxPaymentCart.prototype.subscribe = function(iSellerId, sSellerProvider, iModuleId, iItemId, iItemCount, sRedirect, sCustom) {
     var $this = this;
     var oDate = new Date();
 
@@ -81,6 +84,7 @@ BxPaymentCart.prototype.subscribe = function(iSellerId, sSellerProvider, iModule
     	item_id: iItemId,
     	item_count: 1,
     	redirect: sRedirect ? sRedirect : '',
+    	custom: sCustom ? sCustom : '',
     	_t: oDate.getTime()
     };
 

+ 2 - 0
modules/boonex/payment/js/stripe.js

@@ -42,6 +42,7 @@ BxPaymentProviderStripe.prototype.init = function(oOptions) {
     this._iItemId  = oOptions.iItemId;
     this._iItemCount  = oOptions.iItemCount;
     this._sRedirect  = oOptions.sRedirect;
+    this._sCustom  = oOptions.sCustom;
 };
 
 BxPaymentProviderStripe.prototype.checkout = function(oLink) {
@@ -85,6 +86,7 @@ BxPaymentProviderStripe.prototype.subscribe = function(oLink) {
 		    	item_id: $this._iItemId,
 		    	item_count: $this._iItemCount,
 		    	redirect: $this._sRedirect,
+		    	custom: $this._sCustom,
 		    	token: token.id,
 		    	_t: oDate.getTime()
 		    };

+ 1 - 1
modules/boonex/payment/template/add_to_cart.html

@@ -1,4 +1,4 @@
-<button class="bx-btn bx-btn-img bx-payment-add-to-cart bx-def-margin-sec-left-auto" onclick="javascript:__js_object__.addToCart(__vendor_id__, __module_id__, __item_id__, __item_count__, __need_redirect__)">
+<button class="bx-btn bx-btn-img bx-payment-add-to-cart bx-def-margin-sec-left-auto" onclick="javascript:__js_object__.addToCart(__vendor_id__, __module_id__, __item_id__, __item_count__, __need_redirect__, '__custom__')">
     <i class="sys-icon shopping-cart"></i>__txt_add_to_cart__
 </button>
 __js_content__

+ 1 - 1
modules/boonex/payment/template/add_to_cart_js.html

@@ -1 +1 @@
-__js_object__.addToCart(__vendor_id__, __module_id__, __item_id__, __item_count__, __need_redirect__)
+__js_object__.addToCart(__vendor_id__, __module_id__, __item_id__, __item_count__, __need_redirect__, '__custom__')

+ 1 - 1
modules/boonex/payment/template/subscribe.html

@@ -1,4 +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__, '__vendor_provider__', __module_id__, __item_id__, __item_count__<bx_if:show_redirect>, '__redirect__'</bx_if:show_redirect>)">
+<button class="bx-btn bx-btn-img bx-payment-subscribe bx-def-margin-sec-left-auto" onclick="javascript:__js_object__.subscribe(__vendor_id__, '__vendor_provider__', __module_id__, __item_id__, __item_count__, '__redirect__', '__custom__')">
     <i class="sys-icon credit-card"></i>__txt_subscribe__
 </button>
 __js_content__

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

@@ -1 +1 @@
-__js_object__.subscribe(__vendor_id__, '__vendor_provider__', __module_id__, __item_id__, __item_count__<bx_if:show_redirect>, '__redirect__'</bx_if:show_redirect>)
+__js_object__.subscribe(__vendor_id__, '__vendor_provider__', __module_id__, __item_id__, __item_count__, '__redirect__', '__custom__')