Antes que te vayas
Inscr铆bete en nuestro curso gratuito de Laravel
La mayor铆a de personas en la actualidad nos encontramos suscritos a alg煤n servicio.
El ejemplo m谩s pr谩ctico es Netflix.
Suscribirte a Netflix significa que te inscribes a uno de sus planes, y mes tras mes se realiza un cobro sobre tu tarjeta.
A esto se le conoce tambi茅n como Software as a Service, o de manera abreviada, SaaS.
Significa que tienes acceso a un servicio, a una aplicaci贸n, a un software, a cambio de un pago recurrente.
驴Te gustar铆a tener tu propio sistema de suscripciones?
Hoy aprender谩s a implementar uno, usando la API de PayPal.
Ya hemos visto anteriormente c贸mo implementar pagos con PayPal.
Sin embargo, en ese caso se trata de pagos 煤nicos.
Un usuario realiza un pago, se confirma la validez de la transacci贸n, y el usuario recibe aquello por lo que pag贸.
Ahora en cambio, no se trata de una operaci贸n 煤nica, sino m谩s bien de pagos recurrentes.
Para ello, lo primero es entender la diferencia entre:
Para la API de PayPal, un Producto es lo que ofreces, un Plan es c贸mo lo ofreces, y una Suscripci贸n es un contrato entre t煤 y cada uno de tus clientes.
Antes de empezar a ver c贸digo, es importante que tengas una cuenta de PayPal configurada.
Debes registrar con la API de PayPal al menos un Producto y al menos un Plan.
Recuerda que los usuarios se suscriben a Planes. Ellos deciden qu茅 Plan les interesa m谩s.
Para comunicarnos con la API de PayPal, b谩sicamente necesitamos hacer peticiones HTTP.
脡stas peticiones se pueden hacer de muchas formas:
Tus Productos y Planes los puedes definir con cualquier de estas alternativas.
Sin embargo, la comunicaci贸n con la API desde nuestro backend, de igual forma debe llevarse a cabo, ya que ser谩 necesaria para los pasos siguientes.
Entonces, a continuaci贸n te comparto una clase PayPalClient
que he definido.
Se trata de una clase PHP que podr谩s usar en tu proyecto para realizar peticiones a la API de PayPal.
use GuzzleHttp\Client as GuzzleClient;
class PayPalClient
{
private $client;
private $accessToken;
public function __construct()
{
if (config('paypal.settings.mode') === 'live') {
$clientId = config('paypal.live_client_id');
$secret = config('paypal.live_secret');
$baseUri = 'https://api-m.paypal.com';
} else {
$clientId = config('paypal.sandbox_client_id');
$secret = config('paypal.sandbox_secret');
$baseUri = 'https://api-m.sandbox.paypal.com';
}
$this->client = new GuzzleClient(['base_uri' => $baseUri]);
$this->accessToken = $this->getAccessToken($clientId, $secret);
// dd($this->accessToken);
}
private function getAccessToken($clientId, $secret)
{
$response = $this->client->request('POST', '/v1/oauth2/token', [
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/x-www-form-urlencoded',
],
'body' => 'grant_type=client_credentials',
'auth' => [
$clientId, $secret, 'basic'
]
]
);
$data = json_decode($response->getBody(), true);
return $data['access_token'];
}
private function getHeaders()
{
return [
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $this->accessToken,
'Content-Type' => 'application/json'
];
}
public function getPlans()
{
$response = $this->client->request('GET', '/v1/billing/plans', [
'headers' => $this->getHeaders()
]
);
return json_decode($response->getBody(), true);
}
// ...
}
Aqu铆 tienes una explicaci贸n m谩s detallada de c贸mo conectarte a la API de PayPal para registrar productos y planes:
Lo primero es agregar el JS SDK de PayPal.
Este es un script que puedes ubicar justo antes del cierre de tu etiqueta body
:
<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&vault=true&intent=subscription"></script>
En donde dice YOUR_CLIENT_ID
debes agregar tu Client ID, proporcionado por PayPal.
Lo segundo es tener un div
donde vamos a renderizar nuestros botones:
<div id="paypal-button-container"></div>
Este elemento lo puedes ubicar en cualquier parte de tu HTML, seg煤n creas conveniente.
Por 煤ltimo, renderizamos los botones ejecutando el siguiente script:
paypal.Buttons({
createSubscription: function(data, actions) {
return actions.subscription.create({
'plan_id': 'YOUR_PLAN_ID'
});
},
onApprove: function(data, actions) {
console.log('You have successfully created subscription ' + data.subscriptionID);
}
}).render('#paypal-button-container');
De esta manera los usuarios de nuestro sitio podr谩n suscribirse a nuestros planes.
N贸tese que debemos reemplazar el valor para plan_id
en el c贸digo anterior.
A continuaci贸n puedes ver una explicaci贸n m谩s detallada sobre:
驴Quieres permitir que tus usuarios se suscriban a un plan Mensual, pero tambi茅n a uno Anual?
Luego de definir m煤ltiples planes con PayPal, puedes mostrar los botones de pago para uno u otro.
S贸lo necesitas cambiar el "plan id" al momento de renderizar los botones de pago.
Aqu铆 tienes un ejemplo de c贸mo lograr ello en tu proyecto Laravel:
La funci贸n onApprove
nos da el ID de la suscripci贸n creada v铆a PayPal.
Lo que debemos hacer entonces es pasar este ID a nuestro backend y verificar all铆 que el pago realmente se haya completado.
De ser as铆, procederemos a registrar la suscripci贸n en nuestra base de datos.
En el siguiente video podemos ver qu茅 datos debemos considerar, la ruta a definir, y la forma de validaci贸n:
Una vez que registramos en nuestra base de datos qu茅 usuarios son premium y cu谩les no, lo siguiente es adaptar nuestras vistas, para que los usuarios suscritos a planes vean un contenido distinto a aquellos que no tienen membres铆a.
Para esto podemos modificar nuestro modelo User y definir nuevos accessors, que nos permitan consultar qu茅 usuarios son premium y cu谩les son los datos de la suscripci贸n activa que cada uno tiene.
En el siguiente video vemos c贸mo declarar una relaci贸n entre User
y Suscription
, y c贸mo adaptar nuestras vistas en funci贸n a los accessors isPremium
y lastSubscription
.
Como parte del flujo b谩sico de suscripciones, debemos permitir a nuestros usuarios cancelar su suscripci贸n.
Esto significa que un usuario contar谩 con los beneficios premium hasta que termine el periodo por el cu谩l ha pagado. Pero ya no se realizar谩n m谩s pagos por la suscripci贸n.
Para esto podemos definir un m茅todo cancel
en nuestro controlador.
public function cancel(PayPalClient $payPalClient)
{
$subscription = auth()->user()->lastSubscription;
if (!$subscription) {
return back();
}
$body = [
'reason' => 'User cancelled from the platform Settings.'
];
$statusCode = $payPalClient->cancelSubscription($subscription->paypal_subscription_id, $body);
if ($statusCode >= 200 && $statusCode < 300) {
$subscription->cancel();
$notification = 'Tu suscripci贸n se ha cancelado correctamente.';
} else {
$notification = 'Ocurri贸 un error inesperado. Por favor escribe un mensaje a [email protected] si necesitas ayuda.';
}
return back()->with(compact('notification'));
}
脡ste m茅todo debe ir asociado a una nueva ruta, y ejecutarse cuando un usuario haga clic sobre el bot贸n "Cancelar" en su panel.
Puedes ver el siguiente cap铆tulo, donde implementamos esto paso a paso:
Si un usuario cancela su suscripci贸n desde nuestro sitio:
Sin embargo, si un usuario cancela su suscripci贸n desde PayPal, o a trav茅s de su banco, 驴c贸mo nos enteramos de ello?
En ese caso, PayPal nos debe notificar de dicho cambio de estado, para que nosotros podamos actualizar nuestra base de datos y dejar de renovar la membres铆a premium para el usuario.
Esto es posible a trav茅s de Webhooks.
El siguiente video explica c贸mo escuchar PayPal Webhook Events y c贸mo hacer uso de PayPal Sandbox para verificar el funcionamiento de nuestra aplicaci贸n:
Cada vez que hacemos cambios a nuestra estructura de base de datos, l贸gica de negocio y dependencias, tenemos que seguir un orden para publicar nuestros cambios.
Es importante:
En el siguiente video puedes ver c贸mo hacer ello, adem谩s de otras buenas pr谩cticas y recomendaciones:
Hasta el momento, nuestra tabla de suscripciones crea un registro nuevo por cada nuevo usuario que se suscribe a nuestra plataforma.
En el momento en que identificamos el inicio de una suscripci贸n, creamos el nuevo registro en nuestra base de datos.
驴Pero qu茅 ocurre al finalizar el primer mes o el primer a帽o del usuario suscrito?
PayPal se encargar谩 de cobrar de manera recurrente a los usuarios suscritos.
Sin embargo, nuestra base de datos no se actualizar谩 si nosotros no implementamos ello.
Esto 煤ltimo podemos lograrlo escuchando a eventos PayPal adicionales.
En la 煤ltima lecci贸n vemos c贸mo mejorar nuestro controlador (el que atiende PayPal Webhook Events), y c贸mo probar nuestro flujo completo de suscripci贸n:
Te recomiendo continuar viendo la serie completa en YouTube, sobre c贸mo implementar un Sistema de Suscripciones con PayPal.
Si tienes alguna duda, s贸lo deja un comentario en el video correspondiente, y estar茅 encantando de ayudarte ?.
Comparte este post si te fue de ayuda 馃檪.
Cualquier duda y/o sugerencia es bienvenida.
Reg铆strate
Inicia sesi贸n para acceder a nuestros cursos y llevar un control de tu progreso.
Cursos recomendados
Curso intensivo. Incluye el desarrollo de una API, su consumo, y autenticaci贸n v铆a JWT. Tambi茅n vemos Kotlin desde 0.
Ingresar al cursoDomina JS con este curso pr谩ctico y completo! Fundamentos, ejemplos reales, ES6+, POO, Ajax, Webpack, NPM y m谩s.
Ingresar al cursoAprende por qu茅 es importante y c贸mo funciona Docker, con este nuevo curso pr谩ctico!
Ingresar al cursoInscr铆bete en nuestro curso gratuito de Laravel