Jump to content

[ RESOLU] Choix du type de paiement


Recommended Posts

Bonjour

 

Je travaille avec Prestashop 1.4.4.0 et je me demande s'il y a la possibilité en native d'imposer, ou supprimer un type de paiement pour une commande.

Je m'explique:

Dans ma boutique, j'ai tous types de prix pour une multitude d'article. L'article le moins cher avoisine 0.50€. Or le client qui achète ce produit (en 1 seul exemplaire) à le choix total des modes de paiements (PayPal, chèque national, virement..) Si ce client opte pour le paiement PayPal, non seulement je ne fais pas de bénéfice, mais je perd de l'argent car la commission en plus élevée que le prix du produit.

Pour éviter ce problème, j'ai imposé un montant minimum de 3.5€ par commande, mais les paniers remplis ne se transforment jamais en commande ferme.

Je souhaiterais donc supprimer ce minimum commande et authoriser PayPal à compter d'une certaine somme. De cette façon, le client qui n'a un panier que de 0.50€ pourait le payer soit par chèque, soit par virement. Il pourrait même y avoir un message d'avertissement qui indique la somme qui reste à ajouter au panier pour pouvoir utiliser Paypal

 

Si cette action n'est pas possible en native, existe-t-il un module, de préférence gratuit, qui puisse exécuter mon souhait?

 

Merci d'avance pour vos réponses.

 

Numismeuros

Edited by numismeuros (see edit history)
Link to comment
Share on other sites

  • 5 months later...

ok alors on y va...

Commencez par effectuer une sauvegarde des fichiers classes/Module.php et  controllers/OrderOpcController.php

 

Dans la table ps_module récupérez l'id_module du module Paypal.

 

Dans OrderOpcController.php, vers la ligne 384 vous devez trouver:

$return = Module::hookExecPayment();

remplacez-le par:

$no_paypal = self::$cart->getOrderTotal() <= 1 ? true : false;
$return = Module::hookExecPayment($no_paypal);

On vient de dire ceci: si le prix du panier est inférieur à 1 (vous pouvez changer ce chiffre) on passe le paramètre $no_paypal à vrai.

 

Maintenant dans Module.php recherchez vers la ligne 551:

	public static function hookExecPayment()
	{
		global $cart, $cookie;
		$hookArgs = array('cookie' => $cookie, 'cart' => $cart);
		$id_customer = (int)($cookie->id_customer);
		$billing = new Address((int)($cart->id_address_invoice));
		$output = '';

		$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
		SELECT DISTINCT h.`id_hook`, m.`name`, hm.`position`
		FROM `'._DB_PREFIX_.'module_country` mc
		LEFT JOIN `'._DB_PREFIX_.'module` m ON m.`id_module` = mc.`id_module`
		INNER JOIN `'._DB_PREFIX_.'module_group` mg ON (m.`id_module` = mg.`id_module`)
		INNER JOIN `'._DB_PREFIX_.'customer_group` cg on (cg.`id_group` = mg.`id_group` AND cg.`id_customer` = '.(int)($id_customer).')
		LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module`
		LEFT JOIN `'._DB_PREFIX_.'hook` h ON hm.`id_hook` = h.`id_hook`
		WHERE h.`name` = \'payment\'
		AND mc.id_country = '.(int)($billing->id_country).'
		AND m.`active` = 1
		ORDER BY hm.`position`, m.`name` DESC');
		if ($result)
			foreach ($result AS $k => $module)
				if (($moduleInstance = Module::getInstanceByName($module['name'])) AND is_callable(array($moduleInstance, 'hookpayment')))
					if (!$moduleInstance->currencies OR ($moduleInstance->currencies AND sizeof(Currency::checkPaymentCurrencies($moduleInstance->id))))
						$output .= call_user_func(array($moduleInstance, 'hookpayment'), $hookArgs);
		return $output;
	}

à remplacer par:

	public static function hookExecPayment($no_paypal = false)
	{
		global $cart, $cookie;
                $paypal_id = id_de_Paypal;
		$restricted = $no_paypal ? 'AND m.`id_module` != '.(int)$paypal_id.' : '';
		$hookArgs = array('cookie' => $cookie, 'cart' => $cart);
		$id_customer = (int)($cookie->id_customer);
		$billing = new Address((int)($cart->id_address_invoice));
		$output = '';

		$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
		SELECT DISTINCT h.`id_hook`, m.`name`, hm.`position`
		FROM `'._DB_PREFIX_.'module_country` mc
		LEFT JOIN `'._DB_PREFIX_.'module` m ON m.`id_module` = mc.`id_module`
		INNER JOIN `'._DB_PREFIX_.'module_group` mg ON (m.`id_module` = mg.`id_module`)
		INNER JOIN `'._DB_PREFIX_.'customer_group` cg on (cg.`id_group` = mg.`id_group` AND cg.`id_customer` = '.(int)($id_customer).')
		LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module`
		LEFT JOIN `'._DB_PREFIX_.'hook` h ON hm.`id_hook` = h.`id_hook`
		WHERE h.`name` = \'payment\'
		AND mc.id_country = '.(int)($billing->id_country).'
		AND m.`active` = 1
		'.$restricted.'
		ORDER BY hm.`position`, m.`name` DESC');
		if ($result)
			foreach ($result AS $k => $module)
				if (($moduleInstance = Module::getInstanceByName($module['name'])) AND is_callable(array($moduleInstance, 'hookpayment')))
					if (!$moduleInstance->currencies OR ($moduleInstance->currencies AND sizeof(Currency::checkPaymentCurrencies($moduleInstance->id))))
						$output .= call_user_func(array($moduleInstance, 'hookpayment'), $hookArgs);
		return $output;
	}

Fonction dans laquelle vous remplacez évidemment id_de_Paypal par l'id récupéré au début (n'enlevez pas le ; en fin de ligne)

Cette fonction (qui appelle les modules de paiement au moment de la validation du panier) vérifie si le paramètre $no_paypal est à true ou false. S'il est vrai (true) on rajoute une condition dans la requête qui exclu le module Paypal comme moyen de paiement. Sinon, on fait comme d'habitude.

 

Voili, voilou :)

Link to comment
Share on other sites

Bonsoir Eolia

 

Waouaaaa, super, tout bien expliqué. Merci

 

Quand vous marquez "Dans la table ps_module récupérez l'id_module du module Paypal.", c'est dans la base de donnée qu'il me faut chercher ? ça doit se presenter comment ?

 

Si oui, je ferais ça après une bonne nuit de repos afin de ne pas faire d'erreur a cause de la fatique.

 

Merci d'avance pour cette aide

 

Numismeuros

Link to comment
Share on other sites

l'option de crédit oui (entre 150 et 4000) mais pas l'option de paiement...

 

En 1.6 la fonction est à présent:

$return = Hook::exec('displayPayment');

Donc appelle tous les modules accrochés à ce hook 'displayPayment'.

Je ne vois pas (à moins de faire un override) comment modifier cette méthode autrement...

 

On pourrait éventuellement effectuer le test du montant directement dans le module Paypal mais si le client a choisi Paypal il se prendra un refus. Cela peut faire partir le consommateur.

 

Là, on ne modifie réellement que 3 lignes et c'est transparent. Si upgrade on refera une modif, de toute façon l'override ne suivrait pas non plus, la fonction hookExecPayment() étant dépréciée.

Edited by Eolia (see edit history)
Link to comment
Share on other sites

ok alors on y va...

Commencez par effectuer une sauvegarde des fichiers classes/Module.php et  controllers/OrderOpcController.php

 

Dans la table ps_module récupérez l'id_module du module Paypal.

 

Dans OrderOpcController.php, vers la ligne 384 vous devez trouver:

$return = Module::hookExecPayment();

remplacez-le par:

$no_paypal = self::$cart->getOrderTotal() <= 1 ? true : false;
$return = Module::hookExecPayment($no_paypal);

On vient de dire ceci: si le prix du panier est inférieur à 1 (vous pouvez changer ce chiffre) on passe le paramètre $no_paypal à vrai.

 

Jusque là, ça va. J'ai mis 4 à la place de 1 pour 4€

 

Maintenant dans Module.php recherchez vers la ligne 551:

	public static function hookExecPayment()
	{
		global $cart, $cookie;
		$hookArgs = array('cookie' => $cookie, 'cart' => $cart);
		$id_customer = (int)($cookie->id_customer);
		$billing = new Address((int)($cart->id_address_invoice));
		$output = '';

		$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
		SELECT DISTINCT h.`id_hook`, m.`name`, hm.`position`
		FROM `'._DB_PREFIX_.'module_country` mc
		LEFT JOIN `'._DB_PREFIX_.'module` m ON m.`id_module` = mc.`id_module`
		INNER JOIN `'._DB_PREFIX_.'module_group` mg ON (m.`id_module` = mg.`id_module`)
		INNER JOIN `'._DB_PREFIX_.'customer_group` cg on (cg.`id_group` = mg.`id_group` AND cg.`id_customer` = '.(int)($id_customer).')
		LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module`
		LEFT JOIN `'._DB_PREFIX_.'hook` h ON hm.`id_hook` = h.`id_hook`
		WHERE h.`name` = \'payment\'
		AND mc.id_country = '.(int)($billing->id_country).'
		AND m.`active` = 1
		ORDER BY hm.`position`, m.`name` DESC');
		if ($result)
			foreach ($result AS $k => $module)
				if (($moduleInstance = Module::getInstanceByName($module['name'])) AND is_callable(array($moduleInstance, 'hookpayment')))
					if (!$moduleInstance->currencies OR ($moduleInstance->currencies AND sizeof(Currency::checkPaymentCurrencies($moduleInstance->id))))
						$output .= call_user_func(array($moduleInstance, 'hookpayment'), $hookArgs);
		return $output;
	}

Là, il y a un problème, voilà ce que j'ai à la ligne 739 (ouvert avec Notepad++)

public static function hookExecPayment()
	{
		global $cart, $cookie;
		$hookArgs = array('cookie' => $cookie, 'cart' => $cart);
		$output = '';

		$result = self::getPaymentModules();

		if ($result)
			foreach ($result AS $module)
				if (($moduleInstance = Module::getInstanceByName($module['name'])) AND is_callable(array($moduleInstance, 'hookpayment')))
					if (!$moduleInstance->currencies OR ($moduleInstance->currencies AND sizeof(Currency::checkPaymentCurrencies($moduleInstance->id))))
						$output .= call_user_func(array($moduleInstance, 'hookpayment'), $hookArgs);
		return $output;
	}

à remplacer par:

	public static function hookExecPayment($no_paypal = false)
	{
		global $cart, $cookie;
                $paypal_id = id_de_Paypal;
		$restricted = $no_paypal ? 'AND m.`id_module` != '.(int)$paypal_id.' : '';
		$hookArgs = array('cookie' => $cookie, 'cart' => $cart);
		$id_customer = (int)($cookie->id_customer);
		$billing = new Address((int)($cart->id_address_invoice));
		$output = '';

		$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
		SELECT DISTINCT h.`id_hook`, m.`name`, hm.`position`
		FROM `'._DB_PREFIX_.'module_country` mc
		LEFT JOIN `'._DB_PREFIX_.'module` m ON m.`id_module` = mc.`id_module`
		INNER JOIN `'._DB_PREFIX_.'module_group` mg ON (m.`id_module` = mg.`id_module`)
		INNER JOIN `'._DB_PREFIX_.'customer_group` cg on (cg.`id_group` = mg.`id_group` AND cg.`id_customer` = '.(int)($id_customer).')
		LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module`
		LEFT JOIN `'._DB_PREFIX_.'hook` h ON hm.`id_hook` = h.`id_hook`
		WHERE h.`name` = \'payment\'
		AND mc.id_country = '.(int)($billing->id_country).'
		AND m.`active` = 1
		'.$restricted.'
		ORDER BY hm.`position`, m.`name` DESC');
		if ($result)
			foreach ($result AS $k => $module)
				if (($moduleInstance = Module::getInstanceByName($module['name'])) AND is_callable(array($moduleInstance, 'hookpayment')))
					if (!$moduleInstance->currencies OR ($moduleInstance->currencies AND sizeof(Currency::checkPaymentCurrencies($moduleInstance->id))))
						$output .= call_user_func(array($moduleInstance, 'hookpayment'), $hookArgs);
		return $output;
	}

Fonction dans laquelle vous remplacez évidemment id_de_Paypal par l'id récupéré au début (n'enlevez pas le ; en fin de ligne)

Cette fonction (qui appelle les modules de paiement au moment de la validation du panier) vérifie si le paramètre $no_paypal est à true ou false. S'il est vrai (true) on rajoute une condition dans la requête qui exclu le module Paypal comme moyen de paiement. Sinon, on fait comme d'habitude.

 

Voili, voilou :)

Link to comment
Share on other sites

ok on va s'adapter.

Donc dans module.php remplacez la fonction hookExecPayment() par:

	public static function hookExecPayment($no_paypal = false)
	{
		global $cart, $cookie;
		$hookArgs = array('cookie' => $cookie, 'cart' => $cart);
		$output = '';

		$result = self::getPaymentModules($no_paypal);

		if ($result)
			foreach ($result AS $module)
				if (($moduleInstance = Module::getInstanceByName($module['name'])) AND is_callable(array($moduleInstance, 'hookpayment')))
					if (!$moduleInstance->currencies OR ($moduleInstance->currencies AND sizeof(Currency::checkPaymentCurrencies($moduleInstance->id))))
						$output .= call_user_func(array($moduleInstance, 'hookpayment'), $hookArgs);
		return $output;
	}

et dans la fonction getPaymentModules() un peu plus bas, vous la remplacez par:

	public static function getPaymentModules($no_paypal = false)
	{
		global $cart, $cookie;
                $paypal_id = id_de_Paypal;
		$id_customer = (int)($cookie->id_customer);
		$restricted = $no_paypal ? 'AND m.`id_module` != '.$paypal_id.' : '';
		$billing = new Address((int)($cart->id_address_invoice));

		$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
		SELECT DISTINCT h.`id_hook`, m.`name`, hm.`position`
		FROM `'._DB_PREFIX_.'module_country` mc
		LEFT JOIN `'._DB_PREFIX_.'module` m ON m.`id_module` = mc.`id_module`
		INNER JOIN `'._DB_PREFIX_.'module_group` mg ON (m.`id_module` = mg.`id_module`)
		INNER JOIN `'._DB_PREFIX_.'customer_group` cg on (cg.`id_group` = mg.`id_group` AND cg.`id_customer` = '.(int)($id_customer).')
		LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module`
		LEFT JOIN `'._DB_PREFIX_.'hook` h ON hm.`id_hook` = h.`id_hook`
		WHERE h.`name` = \'payment\'
		AND mc.id_country = '.(int)($billing->id_country).'
		AND m.`active` = 1
		'.$restricted.'
		ORDER BY hm.`position`, m.`name` DESC');

		return $result;
	}
Edited by Eolia (see edit history)
Link to comment
Share on other sites

avec cette nouvelle méthode, il n'y a plus à faire ça ?

Fonction dans laquelle vous remplacez évidemment id_de_Paypal par l'id récupéré au début (n'enlevez pas le ; en fin de ligne)

 

Si, bien vu ;) je l'ai rajouté dans la fonction getPaymentModules()

Link to comment
Share on other sites

:(  ça fonctionne pas. maintenant il n'y a plus accès à la boutique,ni au BO, c'est une page blanche qui s'affiche

Ca, c'est une erreur 500, donc soit vous avez accès aux logs et vous regardez l'erreur soit vous controlez bien le copier collé.

 

A mon avis il manque un ; ou une } quelquepart...

 

Vous avez bien mis:  $paypal_id = 108;

Edited by Eolia (see edit history)
Link to comment
Share on other sites

J'ai remis les originaux sauvegardés (et ça refonctionne) et je vérifie ça.

Comment on a accès aux logs?

Trouvé (c'est ma faute), il manque un '

remplacez cette ligne par:

$restricted = $no_paypal ? 'AND m.`id_module` != '.$paypal_id.'' : '';
Link to comment
Share on other sites

Je ne vois pas où il manque quelque chose. voilà mon code:

public static function hookExecPayment($no_paypal = false)
	{
		global $cart, $cookie;
		$hookArgs = array('cookie' => $cookie, 'cart' => $cart);
		$output = '';

		$result = self::getPaymentModules($no_paypal);

		if ($result)
			foreach ($result AS $module)
				if (($moduleInstance = Module::getInstanceByName($module['name'])) AND is_callable(array($moduleInstance, 'hookpayment')))
					if (!$moduleInstance->currencies OR ($moduleInstance->currencies AND sizeof(Currency::checkPaymentCurrencies($moduleInstance->id))))
						$output .= call_user_func(array($moduleInstance, 'hookpayment'), $hookArgs);
		return $output;
	}
	
	public static function getPaymentModules($no_paypal = false)
	{
		global $cart, $cookie;
                $paypal_id = 108;
		$id_customer = (int)($cookie->id_customer);
		$restricted = $no_paypal ? 'AND m.`id_module` != '.$paypal_id.' : '';
		$billing = new Address((int)($cart->id_address_invoice));

		$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
		SELECT DISTINCT h.`id_hook`, m.`name`, hm.`position`
		FROM `'._DB_PREFIX_.'module_country` mc
		LEFT JOIN `'._DB_PREFIX_.'module` m ON m.`id_module` = mc.`id_module`
		INNER JOIN `'._DB_PREFIX_.'module_group` mg ON (m.`id_module` = mg.`id_module`)
		INNER JOIN `'._DB_PREFIX_.'customer_group` cg on (cg.`id_group` = mg.`id_group` AND cg.`id_customer` = '.(int)($id_customer).')
		LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module`
		LEFT JOIN `'._DB_PREFIX_.'hook` h ON hm.`id_hook` = h.`id_hook`
		WHERE h.`name` = \'payment\'
		AND mc.id_country = '.(int)($billing->id_country).'
		AND m.`active` = 1
		'.$restricted.'
		ORDER BY hm.`position`, m.`name` DESC');

		return $result;
	}


ET

$no_paypal = self::$cart->getOrderTotal() <= 4 ? true : false;
		$return = Module::hookExecPayment($no_paypal);
Edited by numismeuros (see edit history)
Link to comment
Share on other sites

il manque un second apostrophe après id dans: $restricted = $no_paypal ? 'AND m.`id_module` != '.$paypal_id.'' : '';

 

Vous devez modifier également la fonction comme suit dans controllers/ParentOrderController.php, ligne 405 env.

	protected function _assignPayment()
	{
		
		$no_paypal = self::$cart->getOrderTotal() <= 4 ? true : false;
		self::$smarty->assign(array(
		   'HOOK_TOP_PAYMENT' => Module::hookExec('paymentTop'),
			'HOOK_PAYMENT' => Module::hookExecPayment($no_paypal)
		));
	}

Cette modif permet de fonctionner si achat en 5 étapes ou onepage.

Je viens de tester l'ensemble sur une boutique 1.4.4 et tout fonctionne

Edited by Eolia (see edit history)
  • Like 1
Link to comment
Share on other sites

:wacko: :wacko:  Heu, non, aijourd'hui ça marche plus :wacko: :wacko: :wacko:

 

J'explique. Pour les paniers qui étaient en attente de validation, les produits ont tous disparus, ne restent que les frais de port.

J'ai d'abord cru que les clients avec supprimé leur panier (mais pourquoi les frais de port seraient restés ?)

J'ai donc refait un test en mettant un article dans mon panier. avec les frais de port, ça dépassait la limite des 4€ dans le module PayPal aurait du s'afficher, mais comme il n'y a pas d'article (bien que j'en ai mis un) dans mon panier, uniquement les frais de port s'affichent (inférieur à 4€) Il faut que je fasse grimper les frais de port jusqu'à obtenir les 4€ pour que PayPal s'affiche.

 

Donc ma boutique est en panne parceque les clients ne peuvent pas remplir leur panier. 

 

EOLIA au secours s'il te plait

Link to comment
Share on other sites

Ca n'est pas possible.

Activez l'affichage des erreurs et retentez un ajout au panier, il y a forcément qqchose qui cloche ->fichier /config/config.inc.php passez l'affichage à true:

/* Debug only */
@ini_set('display_errors', 'true');
Link to comment
Share on other sites

oui je vois ça dans la console, l'erreur complète est:

Invalid argument supplied for foreach() in <b>/home/numismeu/www/override/classes/Cart.php</b> on line <b>101</b>

 Pourriez-vous me copier le contenu de ce fichier svp ?

(la requête ajax est bonne, donc ca coince sur la requete sql)

 

Requete ajax:

add:1
ajax:true
qty:1
id_product:8034
token:b2a297b5bf6a7ee7eeb522b50fec767d
je persiste dans l'idée qu'autre chose a été modifié... Edited by Eolia (see edit history)
Link to comment
Share on other sites

oui je vois ça dans la console, l'erreur complète est:

 Pourriez-vous me copier le contenu de ce fichier svp ? <----- Je ne comprends pas ce que vous voulez

(la requête ajax est bonne, donc ca coince sur la requete sql)

 

Requete ajax:

add:1
ajax:true
qty:1
id_product:8034
token:b2a297b5bf6a7ee7eeb522b50fec767d
je persiste dans l'idée qu'autre chose a été modifié...

 

Link to comment
Share on other sites

<?php
/*
* 2007-2011 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
*  @author PrestaShop SA <[email protected]>
*  @copyright  2007-2011 PrestaShop SA
*  @version  Release: $Revision: 7713 $
*  @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
*  International Registered Trademark & Property of PrestaShop SA
*/
  /**
  * Customization by XPG @Stiff [email protected]
  * 090702: Added id_carriercateg field for StiffCarriercateg module
  * 100213: v1.3.0.1 upgrade
  * 100401: v1.3.0.3 upgrade
  * 100614: v1.3.1 upgrade
  * 110512: v1.6.0 upgrade for PSP 1.4
  * 110604: v1.6.2 upgrade for PSP 1.4.2,5
  * Search tag: XPG
  */


class Cart extends CartCore
{
	/**
	 * Return cart products
	 *
	 * @result array Products
	 */
	public function getProducts($refresh = false, $id_product = false)
	{
		if (!$this->id)
			return array();
		// Product cache must be strictly compared to NULL, or else an empty cart will add dozens of queries
		if ($this->_products !== NULL AND !$refresh)
			return $this->_products;
// XPG 090702 modify: add p.id_carriercateg, cc.order, cc.id_carrier_default fields and ps_carriercateg cc table
		$sql = '
		SELECT cp.`id_product_attribute`, cp.`id_product`, cu.`id_customization`, cp.`quantity` AS cart_quantity, cu.`quantity` AS customization_quantity, pl.`name`,
		pl.`description_short`, pl.`available_now`, pl.`available_later`, p.`id_product`, p.`id_category_default`, p.`id_supplier`, p.`id_manufacturer`, p.`on_sale`, p.`ecotax`, p.`additional_shipping_cost`, p.`available_for_order`,
		p.`quantity`, p.`price`, p.`weight`, p.`width`, p.`height`, p.`depth`, p.`out_of_stock`, p.`active`, p.`date_add`, p.`date_upd`, IFNULL(pa.`minimal_quantity`, p.`minimal_quantity`) as minimal_quantity,
		t.`id_tax`, tl.`name` AS tax, t.`rate`, pa.`price` AS price_attribute, pa.`quantity` AS quantity_attribute,
        pa.`ecotax` AS ecotax_attr, pl.`link_rewrite`, cl.`link_rewrite` AS category, CONCAT(cp.`id_product`, cp.`id_product_attribute`) AS unique_id,
        p.`id_carriercateg`, cc.`order`, cc.`id_carrier_default`,
        IF (IFNULL(pa.`reference`, \'\') = \'\', p.`reference`, pa.`reference`) AS reference,
        IF (IFNULL(pa.`supplier_reference`, \'\') = \'\', p.`supplier_reference`, pa.`supplier_reference`) AS supplier_reference,
        (p.`weight`+ pa.`weight`) weight_attribute,
        IF (IFNULL(pa.`ean13`, \'\') = \'\', p.`ean13`, pa.`ean13`) AS ean13, IF (IFNULL(pa.`upc`, \'\') = \'\', p.`upc`, pa.`upc`) AS upc,
		pai.`id_image` as pai_id_image
		FROM `'._DB_PREFIX_.'cart_product` cp
		LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = cp.`id_product`
		LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$this->id_lang.')
		LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON (pa.`id_product_attribute` = cp.`id_product_attribute`)
		LEFT JOIN `'._DB_PREFIX_.'tax_rule` tr ON (p.`id_tax_rules_group` = tr.`id_tax_rules_group`
			AND tr.`id_country` = '.(int)Country::getDefaultCountryId().'
			AND tr.`id_state` = 0)
	    LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = tr.`id_tax`)
		LEFT JOIN `'._DB_PREFIX_.'tax_lang` tl ON (t.`id_tax` = tl.`id_tax` AND tl.`id_lang` = '.(int)$this->id_lang.')
		LEFT JOIN `'._DB_PREFIX_.'customization` cu ON (p.`id_product` = cu.`id_product`)
		LEFT JOIN `'._DB_PREFIX_.'product_attribute_image` pai ON (pai.`id_product_attribute` = pa.`id_product_attribute`)
		LEFT JOIN `'._DB_PREFIX_.'image` i ON (IF(pai.`id_image`,
				i.`id_image` =
				(SELECT i2.`id_image`
				FROM `'._DB_PREFIX_.'image` i2
				INNER JOIN `'._DB_PREFIX_.'product_attribute_image` pai2 ON (pai2.`id_image` = i2.`id_image`)
				WHERE i2.`id_product` = p.`id_product` AND pai2.`id_product_attribute` = pa.`id_product_attribute`
				ORDER BY i2.`position`
				LIMIT 1),
				i.`id_product` = p.`id_product` AND i.`cover` = 1)
		)
		LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$this->id_lang.')
		LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (p.`id_category_default` = cl.`id_category` AND cl.`id_lang` = '.(int)$this->id_lang.')
		LEFT JOIN `'._DB_PREFIX_.'carriercateg` cc ON (p.`id_carriercateg` = cc.`id_carriercateg`)
		WHERE cp.`id_cart` = '.(int)$this->id.'
		'.($id_product ? ' AND cp.`id_product` = '.(int)$id_product : '').'
		AND p.`id_product` IS NOT NULL
		GROUP BY unique_id
		ORDER BY cp.date_add ASC';
// end XPG modify
		$result = Db::getInstance()->ExecuteS($sql);


		$productsIds = array();
		$paIds = array();
		foreach ($result as $row)
		{
			$productsIds[] = $row['id_product'];
			$paIds[] = $row['id_product_attribute'];
		}
		// Thus you can avoid one query per product, because there will be only one query for all the products of the cart
		Product::cacheProductsFeatures($productsIds);
		self::cacheSomeAttributesLists($paIds, $this->id_lang);

		$this->_products = array();
		if (empty($result))
			return array();
		foreach ($result AS $row)
		{
			if (isset($row['ecotax_attr']) AND $row['ecotax_attr'] > 0)
				$row['ecotax'] = (float)($row['ecotax_attr']);
			$row['stock_quantity'] = (int)($row['quantity']);
			// for compatibility with 1.2 themes
			$row['quantity'] = (int)($row['cart_quantity']);
			if (isset($row['id_product_attribute']) AND (int)$row['id_product_attribute'])
			{
				$row['weight'] = $row['weight_attribute'];
				$row['stock_quantity'] = $row['quantity_attribute'];
			}
			if ($this->_taxCalculationMethod == PS_TAX_EXC)
			{
				$row['price'] = Product::getPriceStatic((int)$row['id_product'], false, isset($row['id_product_attribute']) ? (int)($row['id_product_attribute']) : NULL, 2, NULL, false, true, (int)($row['cart_quantity']), false, ((int)($this->id_customer) ? (int)($this->id_customer) : NULL), (int)($this->id), ((int)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) ? (int)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) : NULL), $specificPriceOutput); // Here taxes are computed only once the quantity has been applied to the product price
				$row['price_wt'] = Product::getPriceStatic((int)$row['id_product'], true, isset($row['id_product_attribute']) ? (int)($row['id_product_attribute']) : NULL, 2, NULL, false, true, (int)($row['cart_quantity']), false, ((int)($this->id_customer) ? (int)($this->id_customer) : NULL), (int)($this->id), ((int)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) ? (int)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) : NULL));
                $tax_rate = Tax::getProductTaxRate((int)$row['id_product'], (int)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}));

				$row['total_wt'] = Tools::ps_round($row['price'] * (float)$row['cart_quantity'] * (1 + (float)($tax_rate) / 100), 2);
				$row['total'] = $row['price'] * (int)($row['cart_quantity']);
			}
			else
			{
				$row['price'] = Product::getPriceStatic((int)$row['id_product'], false, (int)$row['id_product_attribute'], 6, NULL, false, true, $row['cart_quantity'], false, ((int)($this->id_customer) ? (int)($this->id_customer) : NULL), (int)($this->id), ((int)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) ? (int)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) : NULL), $specificPriceOutput);
				$row['price_wt'] = Product::getPriceStatic((int)$row['id_product'], true, (int)$row['id_product_attribute'], 2, NULL, false, true, $row['cart_quantity'], false, ((int)($this->id_customer) ? (int)($this->id_customer) : NULL), (int)($this->id), ((int)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) ? (int)($this->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) : NULL));

				/* In case when you use QuantityDiscount, getPriceStatic() can be return more of 2 decimals */
				$row['price_wt'] = Tools::ps_round($row['price_wt'], 2);
				$row['total_wt'] = $row['price_wt'] * (int)($row['cart_quantity']);
				$row['total'] = Tools::ps_round($row['price'] * (int)($row['cart_quantity']), 2);
			}
	
			$row2 = Db::getInstance()->getRow('
			SELECT i.`id_image`, il.`legend`
			FROM `'._DB_PREFIX_.'image` i
			LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$this->id_lang.')
			WHERE '.((isset($row['`pai_id_image`']) AND $row['`pai_id_image`'])
				? 'i.`id_image` = (
				SELECT i2.`id_image`
					FROM `'._DB_PREFIX_.'image` i2
					INNER JOIN `'._DB_PREFIX_.'product_attribute_image` pai2 ON (pai2.`id_image` = i2.`id_image`)
					WHERE i2.`id_product` = p.`id_product` AND pai2.`id_product_attribute` = pa.`id_product_attribute`
					ORDER BY i2.`position`
					LIMIT 1
				)'
				: 'i.`id_product` = '.(int)$row['id_product'].' AND i.`cover` = 1').'
			');
			if (!$row2)
				$row2 = array('id_image' => false, 'legend' => false);
			$row = array_merge($row, $row2);
	
			$row['reduction_applies'] = ($specificPriceOutput AND (float)$specificPriceOutput['reduction']);
			$row['id_image'] = Product::defineProductImage($row,$this->id_lang);
			$row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']);
			$row['features'] = Product::getFeaturesStatic((int)$row['id_product']);
			if (array_key_exists($row['id_product_attribute'].'-'.$this->id_lang, self::$_attributesLists))
				$row = array_merge($row, self::$_attributesLists[$row['id_product_attribute'].'-'.$this->id_lang]);

			$this->_products[] = $row;
		}
		return $this->_products;
	}

	/**
	* Return shipping total
	*
	* @param integer $id_carrier Carrier ID (default : current carrier)
	* @return float Shipping total
	*/
    function getOrderShippingCost($id_carrier = NULL, $useTax = true)
    {
		global $defaultCountry;

		if ($this->isVirtualCart())
			return 0;

		// Checking discounts in cart
		$products = $this->getProducts();
		$discounts = $this->getDiscounts(true);
		if ($discounts)
			foreach ($discounts AS $id_discount)
				if ($id_discount['id_discount_type'] == 3)
				{
					if ($id_discount['minimal'] > 0)
					{
						$total_cart = 0;

						$categories = Discount::getCategories((int)($id_discount['id_discount']));
						if (sizeof($categories))
							foreach($products AS $product)
								if (Product::idIsOnCategoryId((int)($product['id_product']), $categories))
									$total_cart += $product['total_wt'];

						if ($total_cart >= $id_discount['minimal'])
							return 0;
					}
					else
						return 0;
				}

		// Order total without fees
		$order_total = $this->getOrderTotal(true, Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING);

		// Start with shipping cost at 0
        $shipping_cost = 0;

		// If no product added, return 0
		if ($order_total <= 0 AND !(int)(self::getNbProducts($this->id)))
			return $shipping_cost;

		// Get id zone
		if (isset($this->id_address_delivery)
      AND $this->id_address_delivery
			AND Customer::customerHasAddress($this->id_customer, $this->id_address_delivery))
			$id_zone = Address::getZoneById((int)($this->id_address_delivery));
		else
		{

			if (!Validate::isLoadedObject($defaultCountry))
				$defaultCountry = new Country(Configuration::get('PS_COUNTRY_DEFAULT'), Configuration::get('PS_LANG_DEFAULT'));
			$id_zone = (int)$defaultCountry->id_zone;
		}
		// If no carrier, select default one
// XPG 090702 Add find default carrier using products carrier categories
		if (!$id_carrier)
			if (!$this->id_carrier) {
 				$id_carrier = $this->MinCarriercategOrder('id_carrier_default');
 			}
			else {
				$id_carrier = $this->MinCarriercategOrder('id_carrier_default', $this->id_carrier);
			}
		if (!$id_carrier)
			$id_carrier = $this->id_carrier;
		if (empty($id_carrier))
		{
			$carrier = new Carrier((int)(Configuration::get('PS_CARRIER_DEFAULT')), Configuration::get('PS_LANG_DEFAULT'));

		if ($id_carrier && !$this->isCarrierInRange($id_carrier, $id_zone))
			$id_carrier = '';

		if (empty($id_carrier) && $this->isCarrierInRange(Configuration::get('PS_CARRIER_DEFAULT'), $id_zone))
				$id_carrier = (int)(Configuration::get('PS_CARRIER_DEFAULT'));

			unset($carrier);
		}

		if (empty($id_carrier))
		{
			if ((int)($this->id_customer))
			{
				$customer = new Customer((int)($this->id_customer));
				$result = Carrier::getCarriers((int)(Configuration::get('PS_LANG_DEFAULT')), true, false, (int)($id_zone), $customer->getGroups());
				unset($customer);
			}
			else
				$result = Carrier::getCarriers((int)(Configuration::get('PS_LANG_DEFAULT')), true, false, (int)($id_zone));

			foreach ($result AS $k => $row)
			{
				if ($row['id_carrier'] == Configuration::get('PS_CARRIER_DEFAULT'))
					continue;

				if (!isset(self::$_carriers[$row['id_carrier']]))
					self::$_carriers[$row['id_carrier']] = new Carrier((int)($row['id_carrier']));

				$carrier = self::$_carriers[$row['id_carrier']];
				// Get only carriers that are compliant with shipping method
				// Get only carriers that are compliant with shipping method
				if (($carrier->getShippingMethod() == Carrier::SHIPPING_METHOD_WEIGHT AND $carrier->getMaxDeliveryPriceByWeight($id_zone) === false)
				OR ($carrier->getShippingMethod() == Carrier::SHIPPING_METHOD_PRICE AND $carrier->getMaxDeliveryPriceByPrice($id_zone) === false))
				{
					unset($result[$k]);
					continue ;
				}

				// If out-of-range behavior carrier is set on "Desactivate carrier"
				if ($row['range_behavior'])
				{
					// Get only carriers that have a range compatible with cart
					if (($carrier->getShippingMethod() == Carrier::SHIPPING_METHOD_WEIGHT AND (!Carrier::checkDeliveryPriceByWeight($row['id_carrier'], $this->getTotalWeight(), $id_zone)))
					OR ($carrier->getShippingMethod() == Carrier::SHIPPING_METHOD_PRICE AND (!Carrier::checkDeliveryPriceByPrice($row['id_carrier'], $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING), $id_zone, (int)($this->id_currency)))))
					{
						unset($result[$k]);
						continue ;
					}
				}

				if ($carrier->getShippingMethod() == Carrier::SHIPPING_METHOD_WEIGHT)
				{
					$shipping = $carrier->getDeliveryPriceByWeight($this->getTotalWeight(), $id_zone);

					if (!isset($tmp))
						$tmp = $shipping;

					if ($shipping <= $tmp)
						$id_carrier = (int)($row['id_carrier']);
				}
				else // by price
				{
					$shipping = $carrier->getDeliveryPriceByPrice($order_total, $id_zone, (int)($this->id_currency));

					if (!isset($tmp))
						$tmp = $shipping;

					if ($shipping <= $tmp)
						$id_carrier = (int)($row['id_carrier']);
				}
			}
		}

		if (empty($id_carrier))
			$id_carrier = Configuration::get('PS_CARRIER_DEFAULT');

		if (!isset(self::$_carriers[$id_carrier]))
			self::$_carriers[$id_carrier] = new Carrier((int)($id_carrier), Configuration::get('PS_LANG_DEFAULT'));
		$carrier = self::$_carriers[$id_carrier];
		if (!Validate::isLoadedObject($carrier))
			die(Tools::displayError('Fatal error: "no default carrier"'));
        if (!$carrier->active)
			return $shipping_cost;

		// Free fees if free carrier
		if ($carrier->is_free == 1)
			return 0;

		// Select carrier tax
		if ($useTax AND !Tax::excludeTaxeOption())
			 $carrierTax = Tax::getCarrierTaxRate((int)$carrier->id, (int)$this->{Configuration::get('PS_TAX_ADDRESS_TYPE')});

		$configuration = Configuration::getMultiple(array('PS_SHIPPING_FREE_PRICE', 'PS_SHIPPING_HANDLING', 'PS_SHIPPING_METHOD', 'PS_SHIPPING_FREE_WEIGHT'));
		// Free fees
		$free_fees_price = 0;
		if (isset($configuration['PS_SHIPPING_FREE_PRICE']))
			$free_fees_price = Tools::convertPrice((float)($configuration['PS_SHIPPING_FREE_PRICE']), Currency::getCurrencyInstance((int)($this->id_currency)));
		$orderTotalwithDiscounts = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING);
		if ($orderTotalwithDiscounts >= (float)($free_fees_price) AND (float)($free_fees_price) > 0)
			return $shipping_cost;
		if (isset($configuration['PS_SHIPPING_FREE_WEIGHT']) AND $this->getTotalWeight() >= (float)($configuration['PS_SHIPPING_FREE_WEIGHT']) AND (float)($configuration['PS_SHIPPING_FREE_WEIGHT']) > 0)
			return $shipping_cost;

			// Get shipping cost using correct method
			if ($carrier->range_behavior)
			{
				// Get id zone
		        if (
              isset($this->id_address_delivery)
              AND $this->id_address_delivery
              AND Customer::customerHasAddress($this->id_customer, $this->id_address_delivery)
            )
					$id_zone = Address::getZoneById((int)($this->id_address_delivery));
				else
					$id_zone = (int)$defaultCountry->id_zone;
				if (($carrier->getShippingMethod() == Carrier::SHIPPING_METHOD_WEIGHT AND (!Carrier::checkDeliveryPriceByWeight($carrier->id, $this->getTotalWeight(), $id_zone)))
						OR ($carrier->getShippingMethod() == Carrier::SHIPPING_METHOD_PRICE AND (!Carrier::checkDeliveryPriceByPrice($carrier->id, $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING), $id_zone, (int)($this->id_currency)))))
						$shipping_cost += 0;
					else {
							if ($carrier->getShippingMethod() == Carrier::SHIPPING_METHOD_WEIGHT)
								$shipping_cost += $carrier->getDeliveryPriceByWeight($this->getTotalWeight(), $id_zone);
							else // by price
								$shipping_cost += $carrier->getDeliveryPriceByPrice($order_total, $id_zone, (int)($this->id_currency));
						 }
			}
			else
			{
				if ($carrier->getShippingMethod() == Carrier::SHIPPING_METHOD_WEIGHT)
					$shipping_cost += $carrier->getDeliveryPriceByWeight($this->getTotalWeight(), $id_zone);
				else
					$shipping_cost += $carrier->getDeliveryPriceByPrice($order_total, $id_zone, (int)($this->id_currency));

			}
		// Adding handling charges
		if (isset($configuration['PS_SHIPPING_HANDLING']) AND $carrier->shipping_handling)
			$shipping_cost += (float)($configuration['PS_SHIPPING_HANDLING']);

		$shipping_cost = Tools::convertPrice($shipping_cost, Currency::getCurrencyInstance((int)($this->id_currency)));

		// Additional Shipping Cost per product
		foreach($products AS $product)
			$shipping_cost += $product['additional_shipping_cost'] * $product['cart_quantity'];

		//get external shipping cost from module
		if ($carrier->shipping_external)
		{
			$moduleName = $carrier->external_module_name;
			$module = Module::getInstanceByName($moduleName);
	
			if (Validate::isLoadedObject($module))
			{
				if (array_key_exists('id_carrier', $module))
				$module->id_carrier = $carrier->id;
			if($carrier->need_range)
				$shipping_cost = $module->getOrderShippingCost($this, $shipping_cost);
			else
				$shipping_cost = $module->getOrderShippingCostExternal($this);

			// Check if carrier is available
			if ($shipping_cost === false)
					return false;
			}
			else
				return false;
		}

		// Apply tax
		if (isset($carrierTax))
			$shipping_cost *= 1 + ($carrierTax / 100);

		return (float)(Tools::ps_round((float)($shipping_cost), 2));
    }

/**
*  XPG 090702 added: function MinCarriercategOrder:
* @param string $returntype: set return value type
* 			returntype = 'maxorder' : Return the carrier corresponding to the min order of products carrier category
* 			returntype = 'id_carrier_default' : Check if id_carrier_init is compatible with categories and replace if not
*    					with default carrier for the category of the cart
* @param integer $id_carrier_init: optional carrier id to test
* @return id_carrier_default or Maxorder
**/
	public function MinCarriercategOrder($returntype, $id_carrier_init = false)
	{
// XPG 100401 Add $cookie global
		global $cookie;

		$products = $this->getProducts();
		$maxorder = Carriercateg::_CARRIERCATEG_MAXORDER_+1;
		$id_carriercateg_max = 0;
		$id_carrier_default = null;

// XPG 100401 add customer groups filter for PSP 1,3,0,3
		if (isset($cookie->id_customer))
		{
			$customer = new Customer((int) $cookie->id_customer);
			$ids_group = $customer->getGroups();
		}
		else
			$ids_group = null;
		foreach ($products AS $product)
			if(!is_null($product['order']))
				if( $product['order'] < $maxorder)
				{
					$maxorder = $product['order'];
					$id_carrier_default = $product['id_carrier_default'];
					$id_carriercateg_max = $product['id_carriercateg'];
				}
		if (is_null($id_carrier_default))
			$id_carrier_default = (int) Configuration::get('PS_CARRIER_DEFAULT');
		if ($returntype == 'id_carrier_default')
		{
			
// XPG 100401 Test if default carrier belongs to customer groups. If not, use first carrier linked to groups
			if ($id_carrier_init AND Carriercateg::CheckCarriercateg($id_carrier_init, $maxorder,  $ids_group) >0)
				$result =$id_carrier_init;
			elseif (Carriercateg::CheckCarriercateg($id_carrier_default, $maxorder,  $ids_group))
				$result = $id_carrier_default;
			else
			{
				$carriers = Carrier::getCarriers((int) $cookie->id_lang, true, false, (isset($id_zone) ? (int) $id_zone : false), $ids_group, $id_carriercateg_max);
				if (is_array($carriers) AND count($carriers))
					$result = $carriers[0]['id_carrier'];
				else
					$result = $id_carrier_default;
			}
		}
		elseif ($returntype == 'maxorder')
			$result = $id_carriercateg_max; // $maxorder;
		else
			$result = false;
		return $result;
	}
// end XPG added

}
?>

c'est le contenu de  Cart.php

Link to comment
Share on other sites

et je viens de recevoir ce mail

Bonjour,
 
Rapport d'erreur à partir de votre module PayPalAPI
 
Un client a rencontré un problème avec le module PayPalAPI:
 
PayPal response:
TIMESTAMP -> 2014-11-19T20:48:10Z
L_ERRORCODE0 -> 10413
L_SHORTMESSAGE0 -> Transaction refused because of an invalid argument. See additional error messages for details.
L_LONGMESSAGE0 -> The totals of the cart item amounts do not match order amounts.
L_SEVERITYCODE0 -> Error
PayPal a retourné une erreur
Edited by numismeuros (see edit history)
Link to comment
Share on other sites

Ok, apparemment l'id_cart n'est pas transmis/trouvé par Prestashop

 

Il faudrait investiguer plus profondément (ce que je ne vais pas faire cette nuit)

 

Pouvez-vous m'envoyer par MP un accès à votre BO et FTP ?

Je regarderai cela demain.

et je viens de recevoir ce mail

Bonjour,
 
Rapport d'erreur à partir de votre module PayPalAPI
 
Un client a rencontré un problème avec le module PayPalAPI:
 
PayPal response:
TIMESTAMP -> 2014-11-19T20:48:10Z
L_ERRORCODE0 -> 10413
L_SHORTMESSAGE0 -> Transaction refused because of an invalid argument. See additional error messages for details.
L_LONGMESSAGE0 -> The totals of the cart item amounts do not match order amounts.
L_SEVERITYCODE0 -> Error
PayPal a retourné une erreur

 

C'est normal je viens de faire un test :)

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...