() translation by (you can also view the original English article)
Es probable que, en algún momento, desees implementar pagos recurrentes o de suscripción para un SaaS u otro servicio. Afortunadamente, PayPal ofrece las herramientas que necesitamos para implementar una solución de pago de suscripción totalmente integrada.
Lo que construiremos
Nota: Estoy usando Laravel en este tutorial, pero puedes aplicar estos conceptos a otros lenguajes y frameworks.
Configuraremos PayPal para aceptar pagos de suscripción y configuraremos nuestro oyente de notificación de pago instantáneo (IPN). Una vez que completemos el componente de registro, veremos el proceso de cancelación a través de la API de PayPal. Estoy comenzando con una aplicación básica de Laravel con registro e inicio de sesión simples, y agregaremos los componentes que necesitamos para introducir los pagos de suscripción a medida que avanzamos en el tutorial.
Paso 1: Configuración de los botones de suscripción
PayPal proporciona un campo personalizado que podemos utilizar para pasar la identificación del usuario.
Antes de comenzar, asegúrate de tener una cuenta comercial de PayPal. Es gratis, pero debes tener una cuenta comercial para implementar los pagos de suscripción en tu sitio.
PayPal ofrece varios tipos de botones que podemos usar, incluidos: Comprar ahora, Suscribirse y Facturación automática. Hoy, veremos el botón de suscripción. Los botones de suscripción te permiten establecer el monto de facturación, así como el período de tiempo de pago recurrente. También puedes configurar un período de prueba y dejar que PayPal cree la cuenta de usuario cuando hagan ping a tu servidor.
Primero, inicia sesión en tu cuenta de PayPal y navega hasta Perfil -> Mis preferencias de venta. Luego busca la sección Botones de PayPal y selecciona Suscripciones en la lista desplegable. Asegúrate de completar el resto de la información.
Recomiendo dejar sin marcar la casilla "Hacer que PayPal cree nombres de usuario y contraseñas para los clientes" y seleccionar la opción "Usar mi ID de cuenta de comerciante segura".
Vamos a permitir que los usuarios se registren para obtener una cuenta gratuita y luego se actualicen más adelante.
Crea tu botón y copia el código generado; lo usarás en tu aplicación.
Transmitir información adicional
Mientras vinculamos las suscripciones a las cuentas, necesitaremos saber quién realiza el pago. La forma más sencilla de hacerlo es hacer coincidir la dirección de correo electrónico de la transacción de PayPal con la cuenta de correo electrónico utilizada para iniciar sesión en nuestra aplicación. Sin embargo, esto no es infalible porque muchas personas usan diferentes direcciones de correo electrónico. Por lo tanto, debemos pasar la identificación del usuario de nuestra aplicación a PayPal.
Afortunadamente, PayPal proporciona un campo personalizado que podemos usar para pasar la identificación del usuario. Tiene un límite de 256 caracteres. Así que voy a usar una estructura JSON, lo que nos permitirá pasar información adicional si es necesario.
1 |
<input type="hidden" name="custom" value="{{json_encode(array('user_id' => Auth::user()->id))}}"> |
2 |
Asegúrate de consultar la lista completa de variables HTML aceptadas.
Paso 2: Preparando tu aplicación
Primero necesitamos configurar nuestra tabla de pagos, donde almacenaremos nuestras transacciones. Vamos a crearlo con las siguientes columnas:
-
id
: Un entero de incremento automático y nuestra clave principal. -
txn_id
: Nuestro ID de transacción que nos dará PayPal. Establece esto como varchar. -
user_id
: Usaremos esto para configurar nuestra relación con la tabla de usuarios, un número entero servirá. -
paypal_id
: El ID de perfil de PayPal que necesitaremos para manejar cancelaciones más adelante. Establece esto como varchar. -
created_at
: Lo usaremos para ver cuándo se completa la transacción e iniciar la suscripción.
Además, agrega una columna subscription
a tu tabla user
. Voy a establecer esto como un número entero para permitir múltiples niveles: uno, dos y tres para desbloquear funciones adicionales. También me adelanté y creé el modelo que nos permitirá interactuar con la tabla de pagos.
Paso 3: Escribiendo tu oyente
PayPal proporciona una solución sencilla para notificarnos cuando se ha procesado un pago; lo llaman Notificaciones de pago instantáneo (IPN). Para aprovechar IPN, necesitamos crear un oyente de IPN para nuestra aplicación. El oyente valida los datos, los inserta en nuestra tabla de pagos y establece el nivel de suscripción del usuario.
Afortunadamente, no tenemos que reinventar la rueda gracias a esta práctica clase. Usaremos la clase IpnListener
para verificar rápidamente los datos, y luego podemos procesarlos para insertarlos en nuestra base de datos. Con Laravel, podemos colocar la clase en nuestra carpeta de bibliotecas, haciéndola autocargar para nosotros.
Crea un nuevo controlador o ruta y agrega el siguiente código:
1 |
$listener = new IpnListener(); try { $verified = $listener->processIpn(); } catch (Exception $e) { exit(0); } if ($verified) { // IPN response was "VERIFIED" } else { // IPN response was "INVALID" } |
2 |
Llamé a mi archivo ipn.php
y lo asignaré a /ipn
. No olvides que PayPal PUBLICARÁ en esta URL; así que si estás usando verbos HTTP/REST, configúralo en consecuencia. Desde aquí podemos procesar nuestros datos:
1 |
$listener = new IpnListener(); try { $verified = $listener->processIpn(); } catch (Exception $e) { return Log::error($e->getMessage()); } if ($verified) { $data = $_POST; $user_id = json_decode($data['custom'])->user_id; $subscription = ($data['mc_gross_1'] == '10') ? 2 : 1; $txn = array( 'txn_id' => $data['txn_id'], 'user_id' => $user_id, 'paypal_id' => $data['subscr_id'], 'subscription' => $subscription, 'expires' => date('Y-m-d H:i:s', strtotime('+1 Month')), ); Payment::create($txn); } else { Log::error('Transaction not verified'); } |
2 |
En este código, primero decodificamos el JSON pasado a nuestro campo personalizado, lo que nos da fácil acceso al ID de usuario. Luego, establecemos el nivel de suscripción en función del monto de la transacción y lo almacenamos en la base de datos. También registramos cualquier error usando la clase Log de Laravel. También puede ser bueno enviar un recibo al usuario, pero eso te lo dejo a ti.
Paso 4: Habilitando el IPN
A continuación, debemos habilitar IPN y configurar PayPal para hacer ping a nuestro oyente. Debido a que el panel de administración de PayPal puede ser complicado de navegar, he incluido las siguientes capturas de pantalla para guiarte. Ve a Perfil > Preferencias de venta:



Luego busca Notificaciones de pago instantáneas:



A continuación, haz clic en Elegir configuración de IPN:



Y luego ingresa la URL a tu oyente:



Paso 5: Obtener tu nombre de usuario, contraseña y firma de la API
Mientras estamos en el tablero, vale la pena obtener nuestras credenciales de API antes de resolver nuestro proceso de cancelación. Ve a Perfil > Preferencias de venta:



Busca el acceso a la API:



Selecciona la opción 2:



Solicita una firma de la API:



Y toma nota de tus credenciales:



Paso 6: Manejo de cancelaciones
Debes tener una cuenta comercial para implementar los pagos de suscripción.
Nota: Necesitarás un certificado SSL para manejar cancelaciones, o PayPal arrojará un error.
Para brindar la mejor experiencia de usuario, es probable que desees manejar las cancelaciones dentro de tu aplicación o servicio. PayPal proporciona algunas API que nos permiten hacer esto: NVP o SOAP. Recomiendo ir con NVP.
La documentación de PayPal parece complicar demasiado las cosas, pero NVP (Name-Value-Pair - Nombre de clave valor) es esencialmente solo una cadena codificada en la URL que podemos pasar mediante cURL.
El método que nos interesa es ManageRecurringPaymentsProfileStatus. Podemos cambiar el estado de la suscripción eligiendo una de las siguientes tres acciones:
- Cancelar: Solo se pueden cancelar las suscripciones activas o suspendidas. La elección de esta acción evita que el usuario se reactive más adelante.
- Suspender: Solo se pueden suspender las suscripciones activas. Esta acción permite a los usuarios reactivar su suscripción más tarde.
- Reactivar: Solo las suscripciones suspendidas se pueden reactivar, restableciendo la suscripción.
Usaremos la acción de cancelación, ya que nuestros botones de suscripción crean una suscripción completamente nueva en caso de que el usuario desee reactivarla más adelante. Entonces, nuestra solicitud se vería así:
1 |
$input = Input::all(); $req = array( 'USER' => 'YOUR_API_USER', 'PASSWORD' => 'YOUR_API_PASSWORD', 'SIGNATURE' => 'YOUR_API_SIGNATURE', 'VERSION' => '76.0', 'METHOD' => 'ManageRecurringPaymentsProfileStatus', 'PROFILEID' => urlencode($input['paypal_id']), 'ACTION' => 'Cancel', 'NOTE' => 'User cancelled on website', ); $ch = curl_init(); // Swap these if you're testing with the sandbox // curl_setopt($ch, CURLOPT_URL, 'https://api-3t.sandbox.paypal.com/nvp'); curl_setopt($ch, CURLOPT_URL, 'https://api-3t.paypal.com/nvp'); curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($req)); curl_exec($ch); curl_close($ch); return Redirect::to('settings')->with('cancelled', true); |
2 |
Ahora podemos cancelar fácilmente la suscripción, pero por alguna razón PayPal optó por no enviar una solicitud de IPN. Sin embargo, esto no es un problema, ya que configuramos nuestra aplicación para incluir una columna de vencimientos llamada expires
. Entonces podemos verificar ese campo para determinar si el usuario está suscrito.
Paso 7: Jugar en la zona de pruebas
PayPal proporciona un entorno de pruebas llamado sandbox para que podamos probar nuestra implementación. Si no lo has utilizado antes, deberás crear una cuenta gratuita. A partir de ahí, podrás probar con múltiples usuarios y transacciones para asegurarte de que tu código funcione como lo esperas.
Vamos a probar nuestro oyente, asegurándonos de que funcione correctamente sin tener que realizar transacciones reales. Antes de hacer algo en sandbox, necesitamos configurar nuestro oyente de IPN para hacer ping en sandbox en lugar del servidor en vivo.
1 |
$listener->use_sandbox = true; |
2 |
Ahora ve a PayPal Sandbox, inicia sesión, haz clic en Herramientas de prueba a la izquierda y abre el simulador de IPN.



Ingresa la URL de tu oyente y selecciona Pago rápido en el menú desplegable. Puedes usar la mayoría de los detalles predeterminados, pero no olvides poner tu JSON en el campo personalizado hacia la parte inferior de la página.
Paso 8: Verificando la suscripción
Ya configuramos nuestra suscripción y permitimos a los usuarios cancelar el servicio. Ahora bien, ¿cómo verificamos esto? Laravel lo hace fácil y su método se traduce en muchos lenguajes y frameworks. Voy a agregar un método a mi modelo User
que nos da acceso a la suscripción usando la clase Auth de Laravel:
1 |
public function subscription(){ return Payment::where('user_id', '=', Auth::user()->id) ->where('expires', '>', date('Y-m-d H:i:s', time())) ->first(array('subscription', 'expires', 'paypal_id', 'txn_id')); } |
2 |
Ahora podemos acceder a esto y verificar dentro de nuestros controladores y vistas muy fácilmente. Por ejemplo:
1 |
<?php $sub = Auth::user()->subscription(); if($sub && $sub->subscription == 1){ echo 'You\'re on the standard plan'; } elseif($sub && $sub->subscription == 2){ echo 'You\'re on the premium plan'; } else { echo 'You\'re not subscribed'; } ?> |
2 |
En conclusión
Esperamos que este tutorial te haya dado una idea de lo fácil que es configurar pagos recurrentes o de suscripción en tus aplicaciones. PayPal no es de ninguna manera el único procesador de pagos, pero es uno de los más reconocidos y utilizados.
Desde aquí, puedes agregar recibos, recordatorios de pago y notificaciones de cancelación para crear una solución totalmente integrada.