Tictac Soluciones Informáticas > Comercio electrónico > Recargo al cliente al pagar con paypal en una tienda Prestashop 1.5

Recargo al cliente al pagar con paypal en una tienda Prestashop 1.5

Paypal es un método de pago bastante habitual en Internet, y por extendido, normalmente querremos añadirlo a nuestra tienda. Es bastante sencillo, tiene su módulo oficial, rellenamos 3 datos de nuestra cuenta paypal y listo.
El problema son las comisiones, entre fijas y por baremos, seguramente paypal se lleve casi un 4% de nuestra venta. Por eso hay tiendas que optan por cargar ese porcentaje al cliente como recargo. Esta opción de cargar un extra según la opción de pago no está preparado en prestashop, pero vamos a ver cómo modificar el código del módulo de paypal para llevarlo a cabo.
Es una primera aproximación, y lo describimos según donde va el código original, aunque para no tener problemas con las actualizaciones sería mejor poner overrides.
Al instalar el módulo de paypal por el administrador de prestashop, quedará a nombre del usuario del servidor web (www-root, apache o similar), por lo que no
podremos modificar el código del módulo a través de ftp. Si nos sucede esto hay dos maneras de proceder:
Hacer un zip de paypal cada vez que hagamos un cambio e intentar volver a instalarlo. Si hubiera cualquier problema en el código, es posible que nos carguemos toda la página y no se pueda acceder a la tienda ni al panel de administrador. Así que no podríamos corregirlo por ftp ni por panel. Mala pinta. La solución si pasa esto es la segunda opción. (Añadiendo el borrar la fila de paypal en la tabla de módulos de la BBDD si la cosa se pone fea).
Hacer un script en php para borrar los archivos del módulo de paypal (en los comentarios de la documentación de rmdir hay una función para borrar recursivo) y subir nuestros propios ficheros por ftp. Así el módulo sigue instalado, pero los ficheros van a nombre del usuario ftp y ya podemos irlos modificando por ftp para hacer pruebas más rápidas.

1. Añadir en la lista de métodos de pagos el recargo que conlleva paypal

1a. Añadir mensaje en la plantilla
Express_checkout_payment.tpl
en: (views/templates/hook)
Añadir un texto con una variable en la línea que dice:
{$PayPal_content.payment_choice}
Podría quedar algo como:
{$PayPal_content.payment_choice}
(Se aplicará un recargo de {$PayPal_content.recargo}
€)
La variable recargo nos la hemos inventado, habrá que darle valor en el código php. Si tenemos activo Ajax en el carrito podríamos quitar productos del carrito sin que recargue la página, ni se recalcule el recargo. En estos casos es más sencillo poner “Recargo del 3%” que la cifra ya calculada.
1b. Añadir la variable recargo y calcularla.
Paypal.php
Al principio, en la lista de variables, añadimos 2 varibales, una $porcentajeRecargo, donde especificaremos ese porcentaje a aplicar y la segunda $recargo, donde quedará el recargo que calculemos, ya en euros.
En el método hookPayment, en la parte del elseif (línea 462 aprox.) añadimos el siguiente código:
$cart
= $this->context->cart;
$cart_details
= $cart->getSummaryDetails(null, true);
$p=new
Product(1);
$iva=1+($p->getTaxesRate()/100);
$rec=number_format(($cart_details[‘total_price’]*$this->porcentajeRecargo)/100,2,’.’,”);
$rec=number_format($rec/$iva,2,’.’,”);
$this->recargo=number_format($rec*$iva,2,’.’,”);
Cargamos el carrito para saber el total de la compra hasta ahora, y el producto 1, será nuestro producto Recargo paypal que crearemos previamente y dejaremos desactivado para que no aparezca en la tienda. Este producto tiene el % de iva a aplicar (21% ahora mismo).
El recargo que se calcula es el total que queremos aplicar, pero ese recargo lleva su iva, por lo que cuando lo grabemos en el producto lo tenemos que hacer sin iva, a veces esta operación de calcular el precio sin iva y que después se calcule con iva otra vez, hace que por redondeo el precio del recargo cambie 1 céntimo. El céntimo como tal no es un valor importante, sin embargo podemos tener problemas de rechazos de pagos en prestashop por ese céntimo, y aunque no los tuviéramos, es raro una factura de 1 céntimo más de lo cobrado, lo suyo es que siempre coincida hasta el céntimo. Por eso cada vez que calcule el recargo, le quito el iva y se lo vuelvo a poner para que quede exacto.
En la línea 734 (o alrededores dependiendo cómo separemos todo el código anterior), antes de:
$content
+= $default;
Añadimos la variable recargo al array, con el valor calculado.
$default[‘recargo’]=$this->recargo;
Para que se pueda usar desde la plantilla para mostratr al usuario.
 

2. Mandar a paypal el recargo como un producto

Una vez que el cliente selecciona paypal, la tienda redirige a paypal, y claro allí tiene que aparecer ese recargo para poder cobrárselo.
process.php (en
express_checkout)
Añadimos el siguiente código dentro de _setPaymentDetails debajo de la línea:
$this->setProductsList($fields,
$index, $total, $taxes);
El siguiente código:
$cart
= $this->context->cart;
$cart_details
= $cart->getSummaryDetails(null, true);
$p=new
Product(1);
$iva=1+($p->getTaxesRate()/100);
$rec=number_format(($cart_details[‘total_price’]*$this->porcentajeRecargo)/100,2,’.’,”);
$rec=number_format($rec/$iva,2,’.’,”);
$this->recargo=number_format($rec*$iva,2,’.’,”);
$fields[‘L_PAYMENTREQUEST_0_NAME’.++$index] = “Recargo uso paypal”;
$fields[‘L_PAYMENTREQUEST_0_AMT’.$index] = $this->recargo;
$total
= $total + $fields[‘L_PAYMENTREQUEST_0_AMT’.$index];
Recalculo el recargo porque el objeto suele ser distinto, y por si han cambiado el carrito por ajax. Esa parte es análoga a la del primer paso.
Después se rellenan las variables del nuevo producto, que será el último. Tiene más campos per solo relleno nombre y cantidad, hay que recalcular el total de la compra con el nuevo recargo.
3. Registrar el recargo en el encargo final al volver de paypal
3a. Añadir el recargo al carrito
Hay que añadir el recargo al carrito para que la compra coincida con la de paypal y no de error la tienda.
Creo el siguiente método en process.php (en express_checkout) para añadir el producto a la lista de productos del objeto de proceso de pago, como no es un objeto producto de verdad, sino un array, lo creo al vuelo:
public
function addRecargoPaypal(){
  $cart
= $this->context->cart;
  $cart_details
= $cart->getSummaryDetails(null, true);
  $p=new
Product(1);
  $iva=1+($p->getTaxesRate()/100);   $rec=number_format(($cart_details[‘total_price’]*$this->porcentajeRecargo)/100,2,’.’,”);
  $rec=number_format($rec/$iva,2,’.’,”);
  $this->recargo=number_format($rec*$iva,2,’.’,”);
  $producto_recargo_paypal=array();
  $producto_recargo_paypal[‘id_product_atribute’]=0;
  $producto_recargo_paypal[‘id_product’]=1;
  $producto_recargo_paypal[‘cart_quantity’]=1;
  $producto_recargo_paypal[‘quantity’]=1;
  $producto_recargo_paypal[‘id_shop’]=1;
  $producto_recargo_paypal[‘name’]=
“Recargo uso paypal”;
  $producto_recargo_paypal[‘id_supplier’]=0;
  $producto_recargo_paypal[‘id_manufacturer’]=0;
  $producto_recargo_paypal[‘total’]=$this->recargo;
  $producto_recargo_paypal[‘price_wt’]=$this->recargo;
  $producto_recargo_paypal[‘total_wt’]=$this->recargo;
  $this->product_list[]=$producto_recargo_paypal;
}
Aquí solo se pone el precio completo, con IVA, porque es para que coincidan cantidades, no se usa este nuevo producto para mucho.
3b. Función para que la llave del proceso no de error
El objeto proceso de pago tiene una llave de seguridad, una suma md5, para comprobar que no se ha añadido ni quitado nada del carrito que teníamos antes de pagar. Pero nosotros añadimos el recargo, por lo que hay que recalcular esa llave para que no de error. Añado la siguiente función a process.php (en express_checkout).
public
function updateSecureKey(){
  $this->secure_key
= $this->getSecureKey();
  $this->_storeCookieInfo();
}
3c. Añadir el recargo al carrito y a la orden
En el archivo payment.php (en express_checkout) hacemos todo lo referente a añadir el recargo a los diferentes sitios, usando las funciones anteriores entre otras. Después de la instrucción
$ppec->doExpressCheckout();
más o menos en la línea 287, añadimos:
$ppec->addRecargoPaypal();
$rp=$ppec->product_list[count($ppec->product_list)-1];
$p=new
Product(1);
$iva=1+($p->getTaxesRate()/100);
$p->price=number_format($rp[‘total’]/$iva,2,’.’,”);
$p->updateWs();
$cart->updateQty(1,1);
$ppec->updateSecureKey();
$cart->getPackageList(true);
Primero añadimos el recargo de paypal como producto al proceso. Después cargamos ese producto, para usar aquí su precio en $rp, hay que tener en cuenta que ese producto es un array, no un objeto producto. Después cargamos el producto 1, el que hemos creado para el recargo.
Le ponemos el precio del recargo sin IVA. Después actualizamos el producto para que se guarde el precio, y en el carrito añadimos 1 unidad del producto. Al haber modificado el carrito hay que actualizar la llave del proceso, y por último actualizar la lista de paquetes, el true como argumento es importante, ya que indica que hay que desechar la cache y volver a generar la lista de paquetes con el nuevo producto. Si no hacemos esto, aunque tengamos el producto en el
carrito, no llegará al detalle de la orden, ya que pasa a orden los paquetes, no la lista de productos del carrito.
Hay que tener en cuenta que con esta forma de hacerlo, en casos de mucho tráfico podrían darse casos de carreras. Si dos personas hacen el pago por paypal a la vez, que la primera modifique el precio del recargo y lo guarde en la base de datos y la segunda lo haga también antes de que la primera llegue a completar el paso a orden. En este tipo de casos extremos una posible solución sería crear productos al vuelo, uno por pedido, para cada recargo e irlos borrando al acabar.
Con esto, y si no se me ha olvidado ningún paso, se consigue tener un recargo funcional al pagar por paypal en prestashop. Si bien es una primera aproximación y se podría mejorar ciertos aspectos para hacer un funcionamiento más fino.
2018-07-02T17:31:34+00:0020/09/2013|Comercio electrónico, Prestashop|

31 Comments

  1. Unknown 02/12/2013 en 18:39 - Responder

    Hola.

    Acabo de hacer todas estas modificaciones y realiza correctamente los cálculos, pero cuando voy a finalizar la compra, se me queda la pantalla en blanco y no regresa a mi tienda. Sí que me llega un e-mail como que un usuario ha hecho una compra con el resumen, pero en el backoffice no figura nada, aunque en mi cuenta de paypal sí que figura el ingreso…

    Sabés de que puede ser…?
    Muchas gracias!

  2. Agus 03/12/2013 en 20:32 - Responder

    A mi tambien me pasa lo mismo, ¿que puede pasar?

    El resto va a la perfección!

    Un saludo

  3. Agus 03/12/2013 en 20:37 - Responder

    Por lo que he podido ver, al llamar al archivo payment.php le pasa dos argumento (token y PayerID)
    token=EC-88J661364W2940619&PayerID=PEUPDUDR2CJD2
    Pero da un error 500

  4. Unknown 04/12/2013 en 18:22 - Responder

    Creo que tiene algo que ver con que se están duplicando entradas en la base de datos…
    He probado a comentar, para que no se tenga en cuenta la última parte que dice que añadamos más o menos en la línea 287 y funciona todo pero da un error. Ya no se queda en blanco, pero al redirigir a la tienda, aparece un error de pago que dice lo siguiente:

    An error occurred while processing payment.

    No se qué más probar…

  5. Agus 04/12/2013 en 18:35 - Responder

    Yo he hecho algo parecido, pero en mi caso solo he comentado estas lineas (de la última parte):

    $p->updateWs();
    $cart->updateQty(1,1);
    $ppec->updateSecureKey();

    Comentando eso, no da el error, ademas realiza el pago y todo, pero hay un pequeño-gran problema, y es que la factura no incluye ese recargo…y por tanto supongo que no sería valido…por lo que creo que el fallo podría estar dentro de la actualización del carrito, pero por más vueltas que le doy no lo consigo… 🙁 a ver si nos puede ayudar alguien

    Un saludo!

  6. ¿En qué versión de Prestashop estáis?

    ¿Dónde se os queda en blanco? ¿al volver de paypal?

    • Agus 10/12/2013 en 21:37 - Responder

      Yo estoy en la 1.5.6 y si..se queda blanco tras volver de paypal

  7. silvina otero 26/05/2014 en 10:20 - Responder

    A ver gente ya lo solucione.

    En la linea 145 de el archivo payment.php

    /* Set details for a payment */
    $ppec->setExpressCheckout(($login_user ? $login_user->access_token : true));

    Ven que esta en true. Pues eso es porque lo cambie yo, estaba en false. Comprobado funciona a la perfeccion.

    Saludos y buena suerte =)

  8. Naiara 29/05/2014 en 14:29 - Responder

    Buenasss!!

    Yo tengo Prestashop 1.6.0 y estoy trabajando con el módulo que venía por defecto en Prestashop 1.5 (ya que el de la versión 1.6.0 no funciona).

    Probé a hacer todos los pasos que se indican y tengo un problemilla, y es que en la tienda, el pedido me lo almacena de manera incorrecta, me duplica los productos del pedido 🙁

    ¿A alguien le pasó lo mismo?

    • Kruger nada 02/06/2014 en 09:05 - Responder

      A ver yo hice la prueba en localhost y funciona correctamente con la version 1.6.0. La version del paypal que estoy usando actualmente en prestashop 1.5.6 es la 3.7.0 y la prueba en localhost de prestashop 1.6.0 con la 3.7.0 o la 3.7.1 funciona bien.

      El unico error que habia era el que puse anteriormente y solucionaba todo.

      "/* Set details for a payment */
      $ppec->setExpressCheckout(($login_user ? $login_user->access_token : true));"

      Suerte!!

    • Pedro Gallego 25/11/2015 en 11:34 - Responder

      podrias compartirlo el de la 1.06 a mi me da el error en ñ y acentos

  9. Hola, busco hacer un recargo de 0.35€ fijos + 3.5% de comisión, donde he de ponerlo?

    Muchas gracias por el aporte,

    Saludos

  10. Buenas, he seguido los pasos que indican para la versión 1.6 de PrestaShop, me hace la compra y suma la comisión, todo bien, pero lo guarda en Prestashop con 10€ más iva incluido para el producto recargo, ¿Alguien tiene el mismo problema?

    saludos y gracias

  11. Juan Pablo 12/02/2015 en 15:47 - Responder

    He probado esto con la ultima version del modulo de paypal (han cambiado la seguridad creo, ya no funciona con SSL), en prestashop 1.6 y el recargo que suma siempre es 0. Se podria actualizar el tutorial??

  12. Ramon Perez 21/04/2015 en 17:04 - Responder

    Versión de PrestaShop 1.6.0.14
    Version del modulo paypal 3.8.2
    El paso 3. Registrar el recargo en el encargo final al volver de paypal
    Ambas funciones publicas addRecargoPaypal() y updateSecureKey() me dan este error unexpected T_PUBLIC

  13. Manuel Lopez 02/08/2015 en 11:11 - Responder

    Os comento mi solución del pantallazo en blanco para el módulo de PayPal versión 3.8.1, con Prestashop versión 1.5.3.1, que imagino que funcionará con cualquier prestashop versión 1.5.x.x y con el módulo PayPal versión 3.x.x

    Yo también obtenía un error 500 y la correspondiente pantalla en blanco, para ver el error activé el modo desarrollador con la siguiente línea en /config/defines.inc.php

    define('_PS_MODE_DEV_', true);

    Al ver que obtenía el siguiente error:

    Fatal error: Uncaught exception 'PrestaShopException' with message 'Property Product->link_rewrite is empty' in…

    Añadí en la función addRecargoPayPal de /modules/paypal/express_checkout/payment.php las siguientes línea tras $p=new Product(1);

    $p->link_rewrite = 'recargo-paypal';
    $p->quantity=1;
    $p->name= "Recargo PayPal";
    $p->id_supplier=0;
    $p->id_manufacturer=0;

    Y listo, todo funcionando al 100%, por cierto, no olvidéis crear a través del gestor de Prestashop el artículo "Recargo PayPal", a mí se me olvidó y me tuvo dandole vueltas a otro error hasta que caí en la cuenta de que no había creado el artículo del recargo.

    Si el error que os aparece tras activar el modo desarrollador es distinto buscad un poco por Internet a ver que encontráis o preguntad por aquí por si algún alma caritativa se presta a echar una mano.

    Suerte!!

    • Manuel Lopez 02/08/2015 en 11:16 - Responder

      Por cierto, sería recomendable tras crear el artículo "Recargo PayPal" que o bien le cambiéis el valor id_product a 1 en las tablas product y product_shop (este es mi caso), o bien en las líneas

      $p=new Product(X);
      $cart->updateQty(1,X);

      En todo el código sustituyáis la X por el número del artículo "Recargo PayPal" que hayáis obtenido tras crear dicho artículo.

  14. Fer 24/11/2015 en 09:56 - Responder

    A mi me da este error en Prestashop 1.6.1.2 con la versión del modulo 3.10.2

    Fatal error: Uncaught Duplicate entry '0-1' for key 1

    <>INSERT INTO `pre9673_product_shop` (`id_category_default`, `id_tax_rules_group`, `on_sale`, `online_only`, `ecotax`, `minimal_quantity`, `price`, `wholesale_price`, `unity`, `unit_price_ratio`, `additional_shipping_cost`, `customizable`, `text_fields`, `uploadable_files`, `active`, `redirect_type`, `id_product_redirected`, `available_for_order`, `available_date`, `condition`, `show_price`, `indexed`, `visibility`, `cache_default_attribute`, `advanced_stock_management`, `date_add`, `date_upd`, `pack_stock_type`, `id_product`, `id_shop`) VALUES ('0', '1', '0', '0', '0', '1', '0.45', '0', '', '0', '0', '0', '0', '0', '1', '', '0', '1', '0000-00-00', 'new', '1', '0', 'both', '0', '0', '2015-11-24 10:48:22', '2015-11-24 10:48:22', '3', '0', '1') thrown in D:AppServwwwtiendaclassesdbDb.php on line 791

    Es una prueba en local y con el SandBox activado.

    • Pedro Gallego 24/11/2015 en 12:28 - Responder

      fer lo conseguiste yo lo quiero adaptar a la version 1.6.1.2

    • Pedro Gallego 24/11/2015 en 13:53 - Responder

      https://www.dropbox.com/s/uawkyns0klnd89h/paypal_con_recargo.zip?dl=0

      este funciona pero me da error con pedidos con ñ y acentos alguien puede ayudarme

    • Fer 26/11/2015 en 12:31 - Responder

      Ya lo conseguí siguiendo el manual y los añadidos del comentario de Manuel Lopez, importante crear el articulo "Recargo PayPal", sino no funciona.

    • Manuel Lopez 26/11/2015 en 12:40 - Responder

      Celebro haber ayudado con mi aportación, estaba siguiendo vuestros comentarios pero estoy hasta arriba de trabajo, por lo que no podía profundizar mucho para intentar ayudaros.

      Tan sólo comentar que tengo otro Prestashop versión 1.6.0.8 con el módulo de PayPal 3.9.0 con el recargo añadido funcionando correctamente, todo esto siguiendo el manual + mis añadidos. Por lo que todo esto debería funcionar para cualquier versión 1.5.x.x y 1.6.x.x de prestashop, junto con versiones 3.x.x de PayPal.

      Suerte!!

    • Fer 26/11/2015 en 14:55 - Responder

      Lo suyo sería ahora poder añadir el recargo a la factura… pero ya lo dejo por imposible jajaja

    • Manuel Lopez 26/11/2015 en 15:00 - Responder

      Al constar este recargo como un artículo más dentro del pedido, éste aparece en la factura.

    • Fer 26/11/2015 en 15:09 - Responder

      Manuel, a mi no me aparece, he hecho varias pruebas y nada

    • Fer 26/11/2015 en 15:22 - Responder

      Vale acabo de ver porque, he colocado algo diferente a como lo explicas tu, pero si lo pongo ahi me da el fallo de link_rewrite is empty'

      Coloco

      $p->link_rewrite = "recargo-paypal";
      $p->quantity=1;
      $p->name= "Recargo PayPal";
      $p->id_supplier=0;
      $p->id_manufacturer=0;

      despues de $p->updateWs();

    • Fer 27/11/2015 en 15:20 - Responder

      Nada no lo consigo, si tengo la linea $p->updateWs(); sin comentar me da el error de link_rewrite is empty lo ponga donde lo ponga… no hay manera

      Pero sino lo pongo el recargo se queda con el del anterior carrito en la factura y en el pedido… ya no sé que hacer :'(

  15. Fer 30/11/2015 en 12:09 - Responder

    Me he fijado una cosa curiosa, si no comento el $p->updateWs(); me da el fallo de link_rewrite empty, como estoy haciendo las pruebas en local, con el error abierto en el navegador, comento esa linea, recargo y funciona… algún alma caritativa sabría decirme donde colocar entonces el updateWs para que no dé el error de Link_rewrite, porque es obvio que hace falta…

    • Fer 30/11/2015 en 12:26 - Responder

      Me respondo a mi mismo, ya lo conseguí… Fue eliminando estas líneas

      $p->link_rewrite = "recargo-paypal";
      $p->quantity=1;
      $p->name= "Recargo PayPal";
      $p->id_supplier=0;
      $p->id_manufacturer=0;

      Además lo configure para que me cobre un % y un fijo en el recargo, tal y como hace PayPal con las compras

      Gracias a todos por vuestra ayuda!!

  16. Alberto Moreno 18/10/2017 en 17:20 - Responder

    El único post que me ha servido (Tengo versión 1.6.0.9 de Prestashop y versión 3.11.4 de Paypal).
    Lo único es que he tardado un buen rato en darme cuenta de cómo y donde se añadían las variables $porcentajeRecargo y $recargo, por eso no me funcionaba (no tengo mucha idea del tema).
    Por si le viene bien a alguien, se añaden dentro del "class PayPal extends PaymentModule" (en paypal.php). Yo lo he puesto debajo del "public $module_key …", y se añaden poniéndolos de la siguiente manera:

    public $porcentajeRecargo=4;
    public $recargo;

    Otra cosa. Puesto que Paypal cobra actualmente un 3.5% + 0.35€, lo que he hecho es calcularlo de la siguiente manera:
    $rec=number_format((($cart_details['total_price']*$this->porcentajeRecargo)/100)+0.35,2,'.','');

    Por lo demás todo bien, tal cual se explica en el post.

    ¡¡Ah, Tened cuidado porque el módulo de Paypal deja de funcionar cuando llevas un tiempo sin actualizar!! Me avisó un cliente porque le fallaba al intentar pagar. Así que cada cierto tiempo hay que actualizar el módulo y volver a modificar los archivos con los archivos nuevos.

    ¡Muchas gracias por la ayuda! Un saludo

Deje su comentario