Codemaster
Tutoriales

JavaScript pagos con PayPal

Jesús Quintana
#Laravel#Backup#restore

Cómo Integrar PayPal en tu Sitio Web Usando JavaScript

paypal}

Índice:

  1. Requisitos Previos
  2. Paso 1: Registrar una Aplicación en PayPal Developer
  3. Paso 2: Incluir el SDK de PayPal en tu Página Web
  4. Paso 3: Crear un Archivo JavaScript para la Integración
  5. Paso 4: Configurar el Botón de PayPal
  6. Paso 5: Probar la Integración en el Entorno Sandbox
  7. Paso 6: Pasar a Producción
  8. Conclusión

Requisitos Previos

Paso 1: Registrar una Aplicación en PayPal Developer y un Usuario

Antes de comenzar, necesitas crear una aplicación en PayPal Developer para obtener un Client ID y un Secret que usarás en la integración.

  1. Accede a PayPal Developer.

  2. Inicia sesión con tu cuenta de PayPal.

  3. En el Dashboard, ve a Apps & Credentials. paypal

  4. Selecciona Sandbox (para pruebas) o Live (para producción). En nuestro caso seleccionaremos Sambox pues solo queremos realizar pruebas y evitar que Paypal nos facture por estas. paypal

  5. Haz clic en Create Acount y proporciona y crea una cuenta cuenta para nuestras pruebas. paypal

  6. Configura la cuenta. Escoja Personal y su pais en pais/región. paypal

  7. Clicka sobre la cuenta recien creada paypal

  8. Copie el e-mail y el password que le proporciona Paypal para usuario de pruebas. paypal

  9. A continuación vuelva a la opción de menú App & Credentials. paypal

  10. Ya dentro de la opción de menu, pulse Create App y rellana los campos del formulario. En typo escoja la primera opción. paypal

  11. A continuación se muestra la aplicación recién creada. Debe copiar el Client ID que nos servira para configurar nuestro botón de Paypal. paypal

Paso 2: Incluir el SDK de PayPal en tu Página Web

En tu archivo HTML, debes incluir el SDK de PayPal para poder utilizar sus funciones. Este script permite cargar el botón de PayPal en tu sitio web. Para este ejemplo utilizaremos un carrito de compras desarrollado previamente. Sustituya CLIENT_ID, por el CLIENT_ID copiado anteriormente. También debes incluir un elemento html donde quieres que aparezca el botón de Paypal, como se muestra en el ejemplo:

 <div class="container-md mx-auto" id="paypal-button-container"></div>

Código completo

<!DOCTYPE html>
<html lang="es">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Carrito de Compras</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
    <!-- Pagos con Paypal-->
    <script
        src="https://www.paypal.com/sdk/js?client-id=<CLIENT_ID>&currency=USD"></script>
    <style>
        .product,
        .cart-item {
            border: 1px solid #dee2e6;
            border-radius: 5px;
            padding: 10px;
            margin: 10px 0;
        }

        .product img,
        .cart-item img {
            max-width: 100%;
            height: auto;
        }

        .img-150 {
            width: 150px;
            align-items: center;
        }

        #paypal-button-container {
            width: 450px;
            /* Ajusta el ancho del contenedor */
            height: 50px;
            /* Ajusta la altura del contenedor */
            /* Añadir cualquier otro estilo necesario */
        }
        #tarjeta {
            width: 400px;
            /* Ajusta el ancho del contenedor */
                
        }

    </style>
</head>

<body>
    <div class="container">
        <h1 class="my-4">Lista de Productos</h1>
        <div id="product-list" class="row"></div>
        <h2 class="my-4">Carrito de Compras</h2>
        <div id="cart"></div>
        <h3>Total: <span id="total">0.00</span>€</h3>
        <br>
        <div class="mx-auto mb-4 p-4 border" id="tarjeta">
            <h6>Tarjeta : 4032034262504429</h6>
            <h6>Caducidad : 09/2029</h6>
            <h6>CVC: 048</h6>
        </div>

    </div>

    <!-- Contenedor para el botón de pagos con Paypal -->
    <div class="container-md mx-auto" id="paypal-button-container"></div>

    <!-- Incluir el archivo JavaScript externo -->
    <script src="script.js"></script>
    <!-- Código para manejar los pagos con Paypal -->
    <script src="paypal-integration.js"></script>

</body>

</html>
Advertencia: El presente manual esta creado solo con fines didácticos, en una aplicación real debería plantearse si es conveniente introducir el CLIENT_ID con este método. Sería recomendable utilizar librerías o framenworks como React o Next para este tipo de aplicaciones. Para información consulte la documentación oficial de Paypal.

Información adicional

Si desea seguir el ejemplo situado al principio de este tutoríal, deberá crearse el siguiente Script que crea un carrito de compras de ejemplo para poder tener algo sobre lo que facturar. Este paso es opcional.

Script.js

// Lista de productos disponibles
const products = [
    {
      id: 1,
      nombre: "CAMPO BURGO RESERVA 2018",
      descripcion: "Tradición y calidad son las señas de identidad de Bodegas Isidro Milagro. Disfruta de su Campo Burgo Reserva 2018, un rioja de perfil clásico, con un tanino noble, maduro y redondo, aterciopelado, con volumen en boca y un perfecto equilibrio entre la fruta madura y la barrica.",
      precio: 10.5,
      graduacion: 13.5,
      imagen: "https://res.cloudinary.com/dkrew530b/image/upload/v1719863077/fo7xxbtviptvh1x7uwme.webp",
    },
    {
      id: 2,
      nombre: "CUNE GRAN RESERVA 2017",
      descripcion: "Cune Gran Reserva 2017 es un tinto que reúne toda la complejidad que ha dado fama mundial a Rioja y ofrece un estilo actual de entender los grandes reservas. CVNE, una marca centenaria que es también una de las más conocidas de Rioja, te ofrece ahora su 'top' de la gama. Un Gran Reserva con el que la firma demuestra que las grandes bodegas logran elaborar grandes vinos en añadas difíciles.",
      precio: 12.0,
      graduacion: 14.0,
      imagen: "https://res.cloudinary.com/dkrew530b/image/upload/v1719863376/kaznug3n7aihmi6oozu2.webp",
    },
    {
      id: 3,
      nombre: "CUNE SEMIDULCE",
      descripcion: "Un blanco suave y fresco producto de la sobremaduración. Cune Semidulce conserva toda la frescura de los blancos jóvenes secos, y la elegancia y suavidad de los tradicionales vinos dulces de Rioja.",
      precio: 5.2,
      graduacion: 12.28,
      imagen: "https://res.cloudinary.com/dkrew530b/image/upload/v1719863787/av09rgd6gkjspixdkemy.webp",
    },
    {
      id: 4,
      nombre: "CARRAMONTE CRIANZA 2021",
      descripcion: "Bodegas Viyuela se consolida como una apuesta importante y un referente en la Ribera del Duero. Como prueba, en 2019 fue reconocida por Mundus Vini como la mejor bodega de esta denominación. Ahora nos presenta Carramonte Crianza 2021. Un tinto exclusivo para Vinoselección que ya presentamos con la añada 2020. La calidad de esta cosecha 2021, calificada como Excelente en la D.O., ha hecho que no esperemos más para repetir experiencia. Disfruta ahora de este magnífico tempranillo diseñado en el término burgalés de Boada de Roa, en el corazón de la denominación. Es intenso, carnoso, de suaves taninos, tacto sedoso y final fresco.",
      precio: 15.0,
      graduacion: 14.5,
      imagen: "https://res.cloudinary.com/dkrew530b/image/upload/v1719864181/nixctxnj25jmfoubofld.webp",
    },
  ];
  
  // Carrito inicial vacío
  let cart = [];
  
  // Referencias a elementos del DOM
  const productList = document.getElementById("product-list");
  const cartList = document.getElementById("cart");
  const totalElement = document.getElementById("total");
  
  // Cargar el carrito desde LocalStorage al iniciar
  loadCart();
  displayCart();
  
  // Función para guardar el carrito en LocalStorage
  function saveCart() {
    localStorage.setItem('cart', JSON.stringify(cart));
  }
  
  // Función para cargar el carrito desde LocalStorage
  function loadCart() {
    const savedCart = localStorage.getItem('cart');
    if (savedCart) {
      try {
        cart = JSON.parse(savedCart);
      } catch (error) {
        console.error('Error al parsear el carrito desde LocalStorage:', error);
        cart = []; // Inicializa el carrito como vacío en caso de error
      }
    }
  }
  
  // Función para mostrar los productos en la página
  function displayProducts() {
    products.forEach((product) => {
      const productElement = document.createElement("div");
      productElement.classList.add("col-md-3", "mb-4");
      productElement.innerHTML = `
        <div class="card h-100">
          <img src="${product.imagen}" class="card-img-top" alt="${product.nombre}" style="width: 200px;">
          <div class="card-body">
            <h5 class="card-title">${product.nombre}</h5>
            <p class="card-text">Precio: ${product.precio.toFixed(2)}€</p>
            <button class="btn btn-primary" onclick="addToCart(${product.id})">Agregar al carrito</button>
          </div>
        </div>
      `;
      productList.appendChild(productElement);
    });
  }
  
  // Función para añadir un producto al carrito
  function addToCart(productId) {
    const product = products.find((p) => p.id === productId);
    if (!product) {
      console.error("Producto no encontrado");
      return;
    }
  
    // Verifica si el producto ya está en el carrito
    const existingProduct = cart.find((p) => p.id === productId);
    if (existingProduct) {
      // Si el producto ya está en el carrito, incrementa la cantidad
      existingProduct.cantidad++;
    } else {
      // Si el producto no está en el carrito, añádelo
      cart.push({
        id: product.id,
        imagen: product.imagen,
        nombre: product.nombre,
        precio: product.precio,
       
  
   cantidad: 1,
      });
    }
    saveCart();
    displayCart();
  }
  
  // Función para eliminar o reducir la cantidad de un producto en el carrito
  function removeFromCart(index) {
    if (index >= 0 && index < cart.length) {
      if (cart[index].cantidad > 1) {
        // Si la cantidad es mayor que 1, reduce la cantidad
        cart[index].cantidad--;
      } else {
        // Si la cantidad es 1, elimina el producto del carrito
        cart.splice(index, 1);
      }
      displayCart();
    } else {
      console.error("Índice fuera de rango");
    }
    saveCart();
  }
  
  // Función para mostrar el carrito en la página
  function displayCart() {
    cartList.innerHTML = "";
    cart.forEach((item, index) => {
      const cartItem = document.createElement("div");
      cartItem.classList.add("d-flex", "align-items-center", "mb-3", "p-2", "border", "rounded");
      cartItem.innerHTML = `
        <img src="${item.imagen}" class="img-150" alt="${item.nombre}" style="width: 100px; height: auto; margin-right: 15px;">
        <div class="flex-grow-1">
          <h5 class="mb-1">${item.nombre}</h5>
          <p class="mb-1">Precio: ${item.precio.toFixed(2)}€</p>
          <p class="mb-1">Cantidad: ${item.cantidad}</p>
          <p class="mb-1">Total: ${(item.precio * item.cantidad).toFixed(2)}€</p>
        </div>
        <div>
          <button class="btn btn-success btn-sm me-2" onclick="increaseQuantity(${index})">Añadir</button>
          <button class="btn btn-danger btn-sm" onclick="removeFromCart(${index})">Eliminar</button>
        </div>
      `;
      cartList.appendChild(cartItem);
    });
    calculateTotal(); // Calcula el total después de actualizar el carrito
  }
  
  // Función para incrementar la cantidad de un producto en el carrito
  function increaseQuantity(index) {
    if (index >= 0 && index < cart.length) {
      cart[index].cantidad++;
      displayCart(); // Actualiza la vista del carrito después de incrementar la cantidad
    } else {
      console.error("Índice fuera de rango");
    }
  }
  
  // Función para calcular y mostrar el total del carrito
  function calculateTotal() {
    const total = cart.reduce((sum, item) => sum + item.precio * item.cantidad, 0);
    totalElement.textContent = total.toFixed(2) + '€';
  }
  
  // Mostrar productos al cargar la página
  displayProducts();

Paso 3: Crear un Archivo JavaScript para la Integración

Para mantener tu código organizado, coloca el código de integración de PayPal en un archivo JavaScript separado.

  1. Crea un archivo llamado paypal-integration.js en el mismo directorio que tu archivo HTML.

  2. Escribe el siguiente código en paypal-integration.js:

// Obtener el total de la venta y lo formateamos con dos decimales
let totalNode = document.querySelector('#total');
let total1 = parseFloat(totalNode.innerText.trim()); // Convierte el texto a número decimal
total1 = total1.toFixed(2); // Formatea el número a dos decimales

paypal.Buttons({
    // Configura la creación del pedido
    createOrder: function(data, actions) {
        return actions.order.create({
            purchase_units: [{
                description: 'Descripción del artículo o servicio',
                amount: {
                    currency_code: 'USD', // Moneda de la transacción
                    value: total1 // Usa el valor formateado con dos decimales como importe de la transacción
                }
            }]
        });
    },
    // Maneja la aprobación del pago
    onApprove: function(data, actions) {
        return actions.order.capture().then(function(details) {
            alert('Pago realizado con éxito por ' + details.payer.name.given_name + ' ' + details.payer.name.surname);
            // Aquí puedes redirigir al usuario o realizar otras acciones necesarias
            // Por ejmplo llamar a una API
        });
    },
    // Maneja la cancelación del pago
    onCancel: function(data) {
        alert('Pago cancelado.');
    },
    // Maneja los errores durante la transacción
    onError: function(err) {
        console.error('Ocurrió un error durante la transacción:', err);
    }
}).render('#paypal-button-container'); // Renderiza el botón en el contenedor especificado

Paso 4: Configurar el Botón de PayPal con Carrito de Compras

En el archivo paypal-integration.js, hemos configurado el botón de PayPal para que:

Paso 5: Probar la Integración en el Entorno Sandbox

Antes de lanzar tu integración en producción, es fundamental probarla en un entorno seguro utilizando las cuentas Sandbox de PayPal:

  1. Crea cuentas de prueba en el entorno Sandbox en PayPal Developer.
  2. Accede a tu página de pruebas e intenta realizar un pago con una cuenta Sandbox.
  3. Verifica que el flujo de pago funcione correctamente, incluyendo la creación del pedido, la aprobación del pago, y el manejo de errores o cancelaciones.

Paso 6: Pasar a Producción

Una vez que hayas completado las pruebas en el entorno Sandbox y todo funcione correctamente, puedes pasar a producción:

  1. Cambia el client-id en tu archivo HTML al Client ID de producción.
  2. Asegúrate de que las configuraciones sean correctas y realiza pruebas adicionales en producción para verificar que todo funcione como se espera.

Conclusión

Siguiendo este tutorial, habrás integrado PayPal en tu sitio web utilizando JavaScript de manera segura y eficiente. Mantener el código de PayPal en un archivo JavaScript separado ayuda a mantener tu proyecto organizado y facilita el mantenimiento y la escalabilidad en el futuro.

← Volver al Blog