Integrar la pasarela de pago de PayPal en Laravel
Índice de contenido
- ¿Por qué usar PayPal como pasarela de pago en Laravel?
- Ventajas de integrar PayPal en tus proyectos web
- Claves de acceso y usuarios de prueba
- ⚙️ Configurar las credenciales en Laravel (.env y config/app.php)
- Implementar el botón de pago de PayPal con JavaScript SDK
- Crear el botón con paypal.Buttons()
- ️ Procesar la orden PayPal desde Laravel (backend)
- Validación de la respuesta en el servidor
- Errores comunes y cómo solucionarlos
- Consejos finales basados en mi experiencia
PayPal es la billetera electrónica por excelencia y es muy utilizada para las compras en líneas, es decir, por Internet y la podemos emplear muy fácilmente en cualquier proyecto web y en Laravel no es la excepción y podemos configurarla fácilmente como una pasalera de pago.
En este apartado vamos a conocer los pasos para configurar PayPal como método de pago en base a algún producto que queramos vender.
Aunque no tenemos un paquete de PayPal exclusivo para Laravel, si tenemos una solución en JavaScript, la cual, no requiere de emplear algún paquete exclusivo para PHP como veremos más adelante:
https://www.npmjs.com/package/@paypal/paypal-js
Lo primero que debemos de hacer es instalar el paquete mediante el siguiente comando, solo si quieres emplear la opción de Node:
$ npm install @paypal/paypal-jsUsaremos la opción de la CDN.
¿Por qué usar PayPal como pasarela de pago en Laravel?
PayPal ofrece una forma rápida y global de recibir pagos sin preocuparte por la gestión de tarjetas.
Además, al integrarlo en Laravel puedes aprovechar la estructura del framework y mantener tu aplicación segura, modular y escalable.
Ventajas de integrar PayPal en tus proyectos web
- Confianza del usuario (marca reconocida mundialmente).
- Compatibilidad con Laravel y JavaScript SDK.
- Entorno de pruebas (sandbox) ideal para desarrolladores.
- Sin necesidad de manejar datos sensibles del cliente.
Requisitos previos y entorno de desarrollo
- Laravel 10 o superior.
- Cuenta de PayPal Developer.
- Node.js (si usas npm) o solo acceso a la CDN oficial de PayPal.
- Axios (ya incluido por defecto en Laravel).
En mi caso, prefiero usar la CDN del SDK de PayPal porque evita configuraciones adicionales y simplifica la carga del script.
Claves de acceso y usuarios de prueba
Para poder integrar PayPal en nuestra aplicación, debemos de tener una cuenta en PayPal, una vez conseguido, si vamos al sitio de desarrollo de PayPal:
https://developer.paypal.com/home
Damos click sobre la opción que dice "API Credentials" y crear una aplicación, para ello, presionamos el botón de "Create App" y aparecerá un diálogo como el siguiente:
Puedes dejar la opción de "Merchant" y "Create App".
Creada las credenciales para poder emplear la API de PayPal, aparecerán listadas en la parte de abajo:
Tenemos una clave secreta que la usaremos en el servidor y una pública que la usaremos en el cliente, por lo tanto, quedará expuesta para cualquier persona que vea el código fuente de la página desde su navegador, a su vez, tenemos acceso a unas claves de prueba, con las cuales podemos ir realizando las peticiones a una cuenta de prueba o sandbox.
Aparte de las claves, se generan usuarios de prueba que emplearemos para realizar la conexiones a la API de pruebas de PayPal disponibles en "Sandbox accounts":
⚙️ Configurar las credenciales en Laravel (.env y config/app.php)
En el servidor debemos de configurar las claves de acceso, como recomendación, define las de pruebas como variables de entorno:
.env
PAYPAL_CLIENT_ID="<YOUR_DEV_PAYPAL_CLIENT_ID>"
PAYPAL_SECRET="<YOUR_DEV_PAYPAL_SECRET>"Y en las configuraciones las as de producción:
config\app.php
return [
***
'paypal_id' => env('PAYPAL_CLIENT_ID', "<YOUR_PRO_PAYPAL_CLIENT_ID>"),
'paypal_secrect' => env('PAYPAL_SECRET',"<YOUR_PRO_PAYPAL_SECRET>"
),Implementar el botón de pago de PayPal con JavaScript SDK
Al emplear este paquete, tenemos que hacer desarrollos en ambos lados, en el cliente y en el servidor., comencemos por el cliente que es en donde hacemos la mayor configuración.
Puedes usar npm:
$ npm install @paypal/paypal-jsO la CDN oficial:
<script src="https://www.paypal.com/sdk/js?client-id={{config('app')['paypalCrear el botón con paypal.Buttons()
En el cliente, comencemos creando un DIV que servirá como elemento contenedor para el widget de PayPal, puedes colocar cualquier identificador que luego colocaremos para referenciar el elemento HTML:
<div id="paypalCard"></div>La siguiente función permite crear el widget de PayPal, primero, obtenemos una referencia al API de PayPal que usaremos para crear el widget mediante:
paypal = await loadScriptEsto lo tenemos que hacer si trabajamos con el paquete en Node y algunas opciones de la CDN.
El siguiente paso es crear la orden, existen muchos parámetros de configuración pero, en este ejemplo solamente usamos el monto:
{
amount: {
value: this.price,
},
},Siguiendo con la implementación, tenemos el callback de onApprove() que se ejecutoria cuando el usuario da clicks sobre el widget y autoriza el pago, en el mismo, tenemos referencia a la orden ya creada que consta de la información del pago al igual que la información del cliente que luego utilizaremos en el servidor, por lo tanto, el siguiente paso es pasar esta data al servidor para autorizarla (y es el el servidor donde se emplea la clave privada), por ejemplo, usando una petición por axios:
onApprove: function (data, actions) {
// TODO send data.orderID to server
}La implementación con la CDN de PayPal, tenemos dos formatos:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
src="https://unpkg.com/@paypal/paypal-js@8.0.0/dist/iife/paypal-js.min.js"></script>
</head>
<body>
<div id="paypalButtons"></div>
<script>
window.paypalLoadScript({
clientId: "{{config('app')['paypal_id']}}"
}).then((paypal) => {
paypal.Buttons().render("#paypalButtons");
});
</script>
</body>
</html>O la siguiente que es la que vamos a usar:
resources\views\paypal.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script src="https://www.paypal.com/sdk/js?client-id={{config('app')['paypal_id']}}"></script>
</head>
<body>
<div id="paypalButtons"></div>
<script>
paypal.Buttons({
createOrder: function(data, actions){
return actions.order.create({
purchase_units:[
{
amount: {
value:50
}
}
]
})
},
onApprove: function(data, actions){
// TODO send order to server
console.log(data.orderID)
axios.post('paypal-process-order/'+data.orderID)
}
}).render("#paypalButtons");
</script>
</body>
</html>En el código anterior, enviamos el identificador de la orden mediante axios, para eso, empleamos vite (recordemos que axios viene instalado por defecto en Laravel en el archivo resources\js\bootstrap.js).
Creamos el controlador y la ruta:
routes\web.php
Route::get('/paypal', [PaymentPaypalController::class, 'paypal']);
Route::post('/paypal-process-order/{order}', [PaymentPaypalController::class, 'paypalProcessOrder']);app\Http\Controllers\PaymentPaypalController.php
<?php
namespace App\Http\Controllers;
class PaymentPaypalController extends Controller
{
public function paypal() {
return view('paypal');
}
function paypalProcessOrder(string $order) {
dd($order);
}
}En el controlador puedes ver que hacemos un sencillo condicional para siempre emplear las claves de acceso en producción de PayPal cuando estamos en producción o las de desarrollo cuando estamos en desarrollo.
En caso de que quieras emplear Node, el código, queda como:
function setPaypal() {
let paypal;
try {
paypal = await loadScript({
"client-id":{{ config('app')['paypal_id'] }},
});
} catch (error) {
console.error("failed to load the PayPal JS SDK script", error);
}
if (paypal) {
try {
await paypal
.Buttons({
createOrder: function (data, actions) {
// This function sets up the details of the transaction, including the amount and line item details.
return actions.order.create({
purchase_units: [
{
amount: {
value: this.price,
},
},
],
});
}.bind(this),
onApprove: function (data, actions) {
// TODO send data.orderID to server
}.bind(this),
})
.render("#paypalCard");
} catch (error) {
console.error("failed to render the PayPal Buttons", error);
}
}
},
}Es importante que notes que cuando estás en un ambiente de pruebas, la URL de PayPal indica que está en modo sandbox:
https://www.sandbox.paypal.com/checkoutnow?***
Y en producción luce de la siguiente manera:
https://www.paypal.com/checkoutnow?***
Con createOrder() creamos la orden, que se crea en base a los datos suministrados (el precio en este ejemplo de 50$) y la autenticación del usuario, que indica que va a pagar la orden, con la función de onApprove() se ejecuta cuando la orden ha sido aprobada y se pasa al servidor para su posterior completación.
Con esto, se genera el plugin de PayPal en el cliente, faltando el procesamiento de la orden del lado del servidor.
️ Procesar la orden PayPal desde Laravel (backend)
Rutas y controlador para procesar el pago
Define tus rutas:
Route::get('/paypal', [PaymentPaypalController::class, 'paypal']);
Route::post('/paypal-process-order/{order}', [PaymentPaypalController::class, 'paypalProcessOrder']);Y el controlador:
class PaymentPaypalController extends Controller {
public function paypal() {
return view('paypal');
}
public function paypalProcessOrder(string $order) {
dd($order); // Aquí procesarás la orden con tu lógica de negocio
}
}Validación de la respuesta en el servidor
El orderID recibido debe validarse usando la API oficial de PayPal y las claves privadas.
Esto garantiza que el pago fue realmente aprobado y no manipulado.
Pruebas con entorno Sandbox
Durante tus pruebas verás URLs como:
https://www.sandbox.paypal.com/checkoutnow?token=...
Y en producción:
https://www.paypal.com/checkoutnow?token=...
Siempre confirmo visualmente que la URL indique “sandbox” antes de probar, así evito cargos reales.
Errores comunes y cómo solucionarlos
- El botón de PayPal no se muestra
- Verifica el client-id.
- Comprueba que el div #paypalButtons exista y no esté oculto.
- Error con credenciales o entorno de pruebas
- Usa siempre las credenciales correctas (sandbox o producción).
- Revisa si el SDK fue cargado con el client-id correcto.
- Problemas con Axios o rutas en Laravel
- Asegúrate de incluir @csrf en tus formularios o configurar correctamente el token CSRF.
- Comprueba que la ruta POST existe y devuelve una respuesta JSON válida.
Consejos finales basados en mi experiencia
En mis pruebas, usar la CDN oficial me dio menos errores que el paquete npm.
- Implementar una lógica de validación del pago en backend me permitió detectar transacciones falsas.
- Siempre registro el orderID en la base de datos para trazabilidad.
- ⚡ Tip extra: Prueba los tiempos de respuesta del SDK, ya que una carga lenta puede impedir que se renderice el botón correctamente.
❓ Preguntas frecuentes sobre Laravel y PayPal
- ¿Cómo integrar PayPal paso a paso en Laravel?
→ Crea las credenciales, configura el .env, agrega el script del SDK y procesa la orden en el backend. - ¿Cómo probar pagos con PayPal Sandbox?
→ Usa las credenciales de sandbox en el .env y revisa que la URL incluya “sandbox.paypal.com”. - ¿Qué hacer si el botón no aparece?
→ Verifica la carga del SDK, el client-id y el contenedor del botón. - ¿Puedo usar el SDK JS junto con un paquete PHP?
→ Sí, pero no es necesario. El SDK JS es suficiente para la mayoría de integraciones básicas.
Acepto recibir anuncios de interes sobre este Blog.
PayPal es la billetera electrónica por excelencia y es muy utilizada para las compras en líneas, es decir, por Internet y la podemos emplear muy fácilmente en cualquier proyecto web y en Laravel no es la excepción y podemos configurarla fácilmente como una pasalera de pago.