# Suscripciones con checkout personalizado

Recoge los datos de pago directamente en tu sitio usando [MONEI Components](https://docs.monei.com/es/es/monei-js/overview/.md) para activar suscripciones. Esto te da control total sobre la experiencia de checkout.

## Antes de empezar[​](#antes-de-empezar "Enlace directo al Antes de empezar")

* Necesitas una cuenta de MONEI, tu [clave de API](https://dashboard.monei.com/settings/api) y tu **Account ID** (disponible en los [ajustes del MONEI Dashboard](https://dashboard.monei.com/settings/api)).
* Usa tus [claves de modo de prueba](https://docs.monei.com/es/es/testing/.md) durante el desarrollo.
* Asegúrate de que al menos un [método de pago esté habilitado](https://dashboard.monei.com/settings/payment-methods) en los ajustes de tu cuenta.

## Elige tu flujo[​](#elige-tu-flujo "Enlace directo al Elige tu flujo")

Hay dos formas de activar una suscripción con MONEI Components:

|                         | Token primero                                             | Activar primero                                               |
| ----------------------- | --------------------------------------------------------- | ------------------------------------------------------------- |
| **Cómo funciona**       | Recoger datos de pago → generar token → activar con token | Activar → obtener ID de pago → recoger datos → confirmar pago |
| **Cuándo usarlo**       | Flujo más sencillo, menos peticiones al servidor          | Cuando necesitas el objeto de pago antes de recoger los datos |
| **Init del componente** | `accountId` + `sessionId`                                 | `paymentId`                                                   |

## Token primero (recomendado)[​](#token-primero-recomendado "Enlace directo al Token primero (recomendado)")

Genera un token de pago en el cliente y luego activa la suscripción en el servidor con ese token.

<!-- -->

<!-- -->

### 1. Crear una suscripción (lado del servidor)[​](#1-crear-una-suscripción-lado-del-servidor "Enlace directo al 1. Crear una suscripción (lado del servidor)")

Crea una [Suscripción](https://docs.monei.com/es/es/apis/rest/subscriptions-create/.md) en tu servidor. Este paso es idéntico al flujo de la [página de pago prediseñada](https://docs.monei.com/es/es/subscriptions/use-prebuilt-payment-page/.md#1-create-a-subscription-server-side).

* cURL
* Node.js
* PHP
* Python

POST https\://api.monei.com/v1/subscriptions

```
curl --request POST 'https://api.monei.com/v1/subscriptions' \

--header 'Authorization: YOUR_API_KEY' \

--header 'Content-Type: application/json' \

--data-raw '{

  "amount": 1500,

  "currency": "EUR",

  "interval": "month",

  "intervalCount": 1,

  "description": "Pro Plan Monthly",

  "customer": {

    "name": "John Doe",

    "email": "john.doe@example.com"

  },

  "callbackUrl": "https://example.com/subscriptions/callback",

  "paymentCallbackUrl": "https://example.com/payments/callback"

}'
```

server.js

```
import {Monei} from '@monei-js/node-sdk';



const monei = new Monei('YOUR_API_KEY');



const subscription = await monei.subscriptions.create({

  amount: 1500,

  currency: 'EUR',

  interval: 'month',

  intervalCount: 1,

  description: 'Pro Plan Monthly',

  customer: {

    name: 'John Doe',

    email: 'john.doe@example.com'

  },

  callbackUrl: 'https://example.com/subscriptions/callback',

  paymentCallbackUrl: 'https://example.com/payments/callback'

});



const subscriptionId = subscription.id;
```

server.php

```
<?php

require_once 'vendor/autoload.php';



use Monei\MoneiClient;

use Monei\Model\CreateSubscriptionRequest;

use Monei\Model\PaymentCustomer;



$monei = new MoneiClient('YOUR_API_KEY');



$subscription = $monei->subscriptions->create(

  new CreateSubscriptionRequest([

    'amount' => 1500,

    'currency' => 'EUR',

    'interval' => 'month',

    'interval_count' => 1,

    'description' => 'Pro Plan Monthly',

    'customer' => new PaymentCustomer([

      'name' => 'John Doe',

      'email' => 'john.doe@example.com'

    ]),

    'callback_url' => 'https://example.com/subscriptions/callback',

    'payment_callback_url' => 'https://example.com/payments/callback'

  ])

);



$subscriptionId = $subscription->getId();

?>
```

server.py

```
import Monei

from Monei import CreateSubscriptionRequest, PaymentCustomer



monei = Monei.MoneiClient(api_key="YOUR_API_KEY")



subscription = monei.subscriptions.create(

    CreateSubscriptionRequest(

        amount=1500,

        currency="EUR",

        interval="month",

        interval_count=1,

        description="Pro Plan Monthly",

        customer=PaymentCustomer(

            name="John Doe",

            email="john.doe@example.com"

        ),

        callback_url="https://example.com/subscriptions/callback",

        payment_callback_url="https://example.com/payments/callback"

    )

)



subscription_id = subscription.id
```

### 2. Añadir el componente a tu página (lado del cliente)[​](#2-añadir-el-componente-a-tu-página-lado-del-cliente "Enlace directo al 2. Añadir el componente a tu página (lado del cliente)")

Incluye `monei.js` en tu página de checkout y monta el componente CardInput usando tu `accountId` y un `sessionId` único.

checkout.html

```
<head>

  <title>Checkout</title>

  <script src="https://js.monei.com/v3/monei.js"></script>

</head>

<body>

  <div id="card-element">

    <!-- MONEI Card Input Component will be inserted here -->

  </div>

  <button id="subscribe-button">Subscribe</button>

  <script src="client.js"></script>

</body>
```

client.js

```
// Initialize CardInput with your accountId and a unique sessionId

const cardElement = monei.CardInput({

  accountId: 'YOUR_ACCOUNT_ID',

  sessionId: 'unique_session_id' // Unique per customer session

});



// Render the Component into the container

cardElement.render('#card-element');
```

important

Usa un `sessionId` diferente para cada sesión de cliente. Esto garantiza que el cliente que genera el token coincide con el cliente que paga. Debes pasar el **mismo `sessionId`** al activar la suscripción en el paso 4.

### 3. Obtener el token de pago (lado del cliente)[​](#3-obtener-el-token-de-pago-lado-del-cliente "Enlace directo al 3. Obtener el token de pago (lado del cliente)")

Cuando el cliente hace clic en el botón de suscripción, envía el input de tarjeta para generar un `paymentToken` de un solo uso.

client.js

```
document.getElementById('subscribe-button').addEventListener('click', async () => {

  // Generate a payment token from the card input

  const {token, error} = await cardElement.submit();



  if (error) {

    // Show the error to the customer

    console.error('Error:', error);

    return;

  }



  // Send the token and sessionId to your server

  const response = await fetch('/activate-subscription', {

    method: 'POST',

    headers: {'Content-Type': 'application/json'},

    body: JSON.stringify({

      subscriptionId: '{{subscription_id}}',

      paymentToken: token,

      sessionId: 'unique_session_id'

    })

  });



  const result = await response.json();

  // Handle the result (e.g., show success message)

});
```

### 4. Activar con token (lado del servidor)[​](#4-activar-con-token-lado-del-servidor "Enlace directo al 4. Activar con token (lado del servidor)")

Activa la suscripción con el `paymentToken` y el `sessionId` recibidos del cliente.

* cURL
* Node.js
* PHP
* Python

POST https\://api.monei.com/v1/subscriptions/{id}/activate

```
curl --request POST 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID/activate' \

--header 'Authorization: YOUR_API_KEY' \

--header 'Content-Type: application/json' \

--data-raw '{

  "paymentToken": "token_from_client",

  "sessionId": "unique_session_id"

}'
```

server.js

```
// In your /activate-subscription route handler

app.post('/activate-subscription', async (req, res) => {

  const {subscriptionId, paymentToken, sessionId} = req.body;



  const activation = await monei.subscriptions.activate(subscriptionId, {

    paymentToken,

    sessionId

  });



  res.json({status: activation.status});

});
```

server.php

```
<?php

use Monei\Model\ActivateSubscriptionRequest;



$body = json_decode(file_get_contents('php://input'), true);



$activation = $monei->subscriptions->activate(

  $body['subscriptionId'],

  new ActivateSubscriptionRequest([

    'payment_token' => $body['paymentToken'],

    'session_id' => $body['sessionId']

  ])

);



echo json_encode(['status' => $activation->getStatus()]);

?>
```

server.py

```
from Monei import ActivateSubscriptionRequest



# In your /activate-subscription route handler

activation = monei.subscriptions.activate(

    body["subscriptionId"],

    ActivateSubscriptionRequest(

        payment_token=body["paymentToken"],

        session_id=body["sessionId"]

    )

)
```

### 5. Gestionar webhooks (lado del servidor)[​](#5-gestionar-webhooks-lado-del-servidor "Enlace directo al 5. Gestionar webhooks (lado del servidor)")

La gestión de webhooks es la misma que en el flujo de la [página de pago prediseñada](https://docs.monei.com/es/es/subscriptions/use-prebuilt-payment-page/.md#5-handle-webhooks-server-side). MONEI envía callbacks de pago a `paymentCallbackUrl` y los cambios de estado de la suscripción a `callbackUrl`. Siempre [verifica la firma](https://docs.monei.com/es/es/guides/verify-signature/.md) y devuelve un código de estado `200`.

***

## Activar primero (alternativa)[​](#activar-primero-alternativa "Enlace directo al Activar primero (alternativa)")

Activa la suscripción primero para obtener un ID de pago, luego recoge los datos de pago y confirma desde el cliente.

<!-- -->

### 1. Crear una suscripción[​](#1-crear-una-suscripción "Enlace directo al 1. Crear una suscripción")

Igual que el paso 1 anterior.

### 2. Activar la suscripción (lado del servidor)[​](#2-activar-la-suscripción-lado-del-servidor "Enlace directo al 2. Activar la suscripción (lado del servidor)")

Activa sin `paymentToken` — la respuesta es un [objeto Payment](https://docs.monei.com/es/es/apis/rest/schemas/payment/.md) con un `payment.id`.

* cURL
* Node.js
* PHP
* Python

POST https\://api.monei.com/v1/subscriptions/{id}/activate

```
curl --request POST 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID/activate' \

--header 'Authorization: YOUR_API_KEY' \

--header 'Content-Type: application/json' \

--data-raw '{

  "completeUrl": "https://example.com/checkout/complete"

}'
```

server.js

```
const activation = await monei.subscriptions.activate('YOUR_SUBSCRIPTION_ID', {

  completeUrl: 'https://example.com/checkout/complete'

});



// Pass the payment ID to your client-side

const paymentId = activation.id;
```

server.php

```
<?php

use Monei\Model\ActivateSubscriptionRequest;



$activation = $monei->subscriptions->activate(

  'YOUR_SUBSCRIPTION_ID',

  new ActivateSubscriptionRequest([

    'complete_url' => 'https://example.com/checkout/complete'

  ])

);



// Pass the payment ID to your client-side

$paymentId = $activation->getId();

?>
```

server.py

```
from Monei import ActivateSubscriptionRequest



activation = monei.subscriptions.activate(

    "YOUR_SUBSCRIPTION_ID",

    ActivateSubscriptionRequest(

        complete_url="https://example.com/checkout/complete"

    )

)



# Pass the payment ID to your client-side

payment_id = activation.id
```

important

Usa el `payment.id` de la respuesta para inicializar el componente CardInput — **no** redirijas al cliente a `nextAction.redirectUrl`. Esa URL es para el flujo de la [página de pago prediseñada](https://docs.monei.com/es/es/subscriptions/use-prebuilt-payment-page/.md).

### 3. Montar el componente y confirmar el pago (lado del cliente)[​](#3-montar-el-componente-y-confirmar-el-pago-lado-del-cliente "Enlace directo al 3. Montar el componente y confirmar el pago (lado del cliente)")

Inicializa el CardInput con el `paymentId` de la respuesta de activación y luego confirma el pago.

checkout.html

```
<head>

  <title>Checkout</title>

  <script src="https://js.monei.com/v3/monei.js"></script>

</head>

<body>

  <div id="card-element"></div>

  <button id="subscribe-button">Subscribe</button>

  <script src="client.js"></script>

</body>
```

client.js

```
// Initialize CardInput with the paymentId from the activation response

const paymentId = '{{payment_id}}'; // Passed from your server

const cardElement = monei.CardInput({paymentId: paymentId});

cardElement.render('#card-element');



document.getElementById('subscribe-button').addEventListener('click', async () => {

  const {token, error} = await cardElement.submit();



  if (error) {

    console.error('Error:', error);

    return;

  }



  // Confirm the payment with the generated token

  const result = await monei.confirmPayment({

    paymentId: paymentId,

    paymentToken: token

  });



  // Show the result to the customer

  // Always rely on webhooks for the definitive payment status

  console.log('Payment status:', result.status);

});
```

### 4. Gestionar webhooks[​](#4-gestionar-webhooks "Enlace directo al 4. Gestionar webhooks")

Igual que en el [flujo token primero](#5-handle-webhooks-server-side) — MONEI envía webhooks tanto para los pagos como para los cambios de estado de la suscripción.

## Antes de pasar a producción[​](#antes-de-pasar-a-producción "Enlace directo al Antes de pasar a producción")

* Cambia a la clave de API y al Account ID en [modo producción](https://dashboard.monei.com/settings/api).
* Asegúrate de que tus [métodos de pago estén habilitados](https://dashboard.monei.com/settings/payment-methods) en modo producción.
* Comprueba que tus endpoints de webhook gestionan correctamente tanto los callbacks de pago como los de suscripción.

Límites del modo de prueba

En modo de prueba, las suscripciones tienen los siguientes límites:

* Máximo **3 suscripciones activas** por cuenta
* Las suscripciones se **cancelan automáticamente tras 12 pagos**
* Los intervalos de facturación por **minuto y hora** están disponibles para pruebas más rápidas
