Muchas aplicaciones y web nos permiten hacer compras de artículos, suscripciones y servicios a partir de una pasarela de pago. Puede parecer complicado añadir esta funcionalidad a una aplicación, pero es bastante sencillo y en este artículo aprenderemos hacerlo en pocos minutos con la plataforma de pago Paypal y Laravel.

¿Por qué elegir PayPal? PayPal es una opción popular de pago en línea que ofrece seguridad y facilidad de uso, mejorando la experiencia del cliente y ayudándote a aumentar tus reservas.

Pasos para la Integración:

  1. Instalar el SDK de PayPal para PHP Para interactuar con la API de PayPal, necesitas instalar el SDK de PayPal para PHP. Añade la siguiente línea a tu archivo composer.json:
"paypal/rest-api-sdk-php": "^1.14"

Luego, ejecuta composer install para instalar el paquete.

  1. Registrar una app en paypal Crea una nueva aplicación en el sitio web de desarrolladores de PayPal para obtener las credenciales de la API. Sigue las instrucciones proporcionadas para crear tu aplicación y obtener el Client ID y Secret.

  2. Configurar las credenciales de PayPal en Laravel Añade las credenciales de la API de PayPal a tu archivo .env de Laravel de la siguiente manera:

PAYPAL_CLIENT_ID=tu_client_id
PAYPAL_SECRET=tu_secret
PAYPAL_MODE=sandbox

El valor de PAYPAL_MODE puede ser sandbox para pruebas o live para producción.

Crear un formulario de pago

Define una ruta en tu aplicación Laravel para mostrar un formulario donde los usuarios puedan ingresar los detalles de su pago:

// Mostrar el formulario de pago
Route::get('/pagar-con-paypal', function () {
    return view('paypal-form');
});

// Procesar el pago
Route::post('/pagar-con-paypal', function (Request $request) {
    $apiContext = new \PayPal\Rest\ApiContext(
        new \PayPal\Auth\OAuthTokenCredential(
            config('services.paypal.client_id'),
            config('services.paypal.secret')
        )
    );

    $payer = new \PayPal\Api\Payer();
    $payer->setPaymentMethod('paypal');

    $amount = new \PayPal\Api\Amount();
    $amount->setTotal($request->input('amount'));
    $amount->setCurrency('USD');

    $transaction = new \PayPal\Api\Transaction();
    $transaction->setAmount($amount);

    $redirectUrls = new \PayPal\Api\RedirectUrls();
    $redirectUrls->setReturnUrl(url('/pago-exitoso'))
                 ->setCancelUrl(url('/pago-cancelado'));

    $payment = new \PayPal\Api\Payment();
    $payment->setIntent('sale')
            ->setPayer($payer)
            ->setTransactions([$transaction])
            ->setRedirectUrls($redirectUrls);

    try {
        $payment->create($apiContext);
        return redirect($payment->getApprovalLink());
    } catch (\PayPal\Exception\PayPalConnectionException $e) {
        return redirect('/error-de-pago');
    }
});

Este código crea una nueva instancia de ApiContext utilizando las credenciales de PayPal almacenadas en el archivo .env de Laravel. Luego, configura un nuevo pago con la API de PayPal y redirige al usuario al sitio web de PayPal para completar el pago.

  1. Rutas para los pagos Define rutas para controlar las respuestas de PayPal cuando un pago se ha efectuado o, por el contrario, ha habido un error:
// Controlar el pago efectuado
Route::get('/success-payament-paypal', function () {
    return view('payment-success');
});

// Controlar un pago que no se terminó de efectuar
Route::get('/cancelled-payment-cacelled', function () {
    return view('payment-cancelled');
});

En estas rutas puedes informar al usuario que todo ha ido bien o mal, etc.

  1. Implementar la notificación instantánea de pago (IPN) de PayPal Para verificar los pagos y actualizar tu aplicación, implementa la IPN de PayPal, que notifica a tu aplicación sobre los cambios en los pagos:
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;

Route::post('/paypal-ipn', function (Request $request) {
    $ipnListener = new \PayPal\IPN\Listener();
    $ipnListener->useSandbox();
    $ipnListener->setSecret(config('services.paypal.secret'));

    try {
        $isVerified = $ipnListener->processIpn($request->getContent());
    } catch (\Exception $exception) {
        Log::error('PayPal IPN verification failed: ' . $exception->getMessage());
        return response()->json(['error' => 'IPN verification failed'], 400);
    }

    if ($isVerified) {
        $transactionId = $request->input('txn_id');
        
        // Actualizar el registro de la reserva en la base de datos con el ID de la transacción
        // Se asume que hay una función updateReservationWithTransactionId()
        updateReservationWithTransactionId($transactionId);

        // Enviar un correo de confirmación al cliente
        // Se asume que hay una función sendConfirmationEmail()
        sendConfirmationEmail($transactionId);

        return response()->json(['status' => 'ok'], 200);
    } else {
        Log::warning('Invalid PayPal IPN received');
        return response()->json(['error' => 'Invalid IPN'], 400);
    }
});

function updateReservationWithTransactionId($transactionId) {
    // Lógica para actualizar el registro de la reserva en la base de datos
    // Ejemplo:
    // $reservation = Reservation::where('transaction_id', $transactionId)->first();
    // $reservation->update(['status' => 'paid']);
}

function sendConfirmationEmail($transactionId) {
    // Lógica para enviar un correo de confirmación
    // Ejemplo:
    // $reservation = Reservation::where('transaction_id', $transactionId)->first();
    // Mail::to($reservation->email)->send(new ReservationConfirmed($reservation));
}

Esta ruta maneja las solicitudes IPN enviadas por PayPal, verifica la autenticidad del mensaje y actualiza el registro de la reserva en la base de datos con el ID de la transacción.

Una vez seguido los pasos, solo queda probar para comprobar que todo funciona correctamente., recuerda el valor de PAYPAL_MODE debe ser sandbox para pruebas y live para producción.