Saltar al contenido principal

Suscribirse al contenido

Controla el acceso al contenido por suscripción: comprueba si el usuario tiene una suscripción activa y le da acceso al contenido premium o le invita a suscribirse.

Qué hace este ejemplo:

  • Muestra el contenido premium solo a los usuarios con una suscripción activa
  • La comprobación se basa en Orders y Users.
  • Los usuarios con sesión iniciada sin una suscripción activa reciben un pedido y una sesión de pago para suscribirse.

Requisitos previos:

  • Un PROJECT_URL y un APP_TOKEN válidos para la API de OneEntry.
  • Un formulario de pedido (tipo "Order form") con el marcador subscription y los atributos expired_date (fecha) y subscription_time (lista con una opción cuyo valor es 1)
  • Un almacén de pedidos con el marcador subscriptions vinculado a ese formulario, con la cuenta de pago cash
  • Un producto que se venda como suscripción (el ejemplo usa productId: 15; sustitúyelo por el id de tu producto)
  • Una página con la URL premium_page
  • Un usuario registrado

Notas:

  • Los ejemplos manejan los errores de forma mínima: lanzan una excepción cuando una llamada devuelve un objeto de error.
  • Por defecto (isShell: true), el SDK devuelve un objeto de error en lugar de lanzar una excepción, así que comprueba el resultado, p. ej., 'statusCode' in result. Con isShell: false lanza la excepción y los errores se manejan con try/catch. Consulta Errors.
  • El acceso se abre solo después de que se complete la sesión de pago (isCompleted: true). Con la cuenta de pago cash, esto ocurre solo cuando el pago se confirma en la plataforma.
  • La comprobación de la suscripción se ejecuta en tu aplicación, así que solo controla lo que muestra tu interfaz. La página en sí sigue disponible a través de la Content API para cualquiera cuyo grupo de usuarios pueda leerla. Para restringirla de verdad, permite el acceso a la página solo a un grupo de usuarios al que pertenezcan los suscriptores (permisos de grupos de usuarios en el panel de administración) y llama a la API en nombre del usuario con sesión iniciada.

Documentación de la plataforma:

Referencia del SDK:

Pruébalo en vivo​

Ejecuta este ejemplo en el sandbox del SDK de JS. Conecta tu Project URL y App Token en la primera visita y luego abre:

Escenario​

1. Importar defineOneEntry y definir PROJECT_URL y APP_TOKEN​

import { defineOneEntry } from 'oneentry';

const PROJECT_URL = 'https://your-project.oneentry.cloud';
const APP_TOKEN = 'your-app-token';

2. Crear un cliente de API con defineOneEntry()​

const { Users, Orders, Pages, Payments, AuthProvider, Forms } = defineOneEntry(
PROJECT_URL,
{
token: APP_TOKEN,
},
);

3. Obtener el formulario de suscripción con Forms.getFormByMarker()​

const form = await Forms.getFormByMarker('subscription');
console.log(form);
// expired_date - Date
// subscription_time - list
Resultado:
{
"id": 6,
"attributeSetId": 8,
"type": "order",
"localizeInfos": {
"title": "Subscription",
"titleForSite": "Subscription",
"successMessage": "Message about successful data processing",
"unsuccessMessage": "Message about unsuccessful data processing",
"urlAddress": "",
"database": "0",
"script": "0"
},
"version": 21,
"position": 1,
"identifier": "subscription",
"processingType": "script",
"templateId": null,
"attributes": [
{
"type": "date",
"marker": "expired_date",
"position": 2,
"settings": {},
"isVisible": true,
"listTitles": [],
"validators": {},
"initialValue": null,
"localizeInfos": {
"title": "Expired date"
},
"additionalFields": {}
},
{
"type": "list",
"marker": "subscription_time",
"position": 5,
"settings": {},
"isVisible": true,
"listTitles": [
{
"title": "1 month",
"value": "1",
"extended": {
"type": "real",
"value": "100"
},
"position": 1
},
{
"title": "6 months",
"value": "6",
"extended": {
"type": "real",
"value": "500"
},
"position": 2
},
{
"title": "1 year",
"value": "12",
"extended": {
"type": "real",
"value": "999"
},
"position": 3
}
],
"validators": {},
"initialValue": null,
"localizeInfos": {
"title": "Subscription time"
},
"additionalFields": {}
}
],
"total": "1",
"moduleFormConfigs": []
}

4. Prepara los datos para autenticar al usuario​

const authData = [
{ marker: 'email_reg', value: 'your-email' },
{ marker: 'password_reg', value: 'your-password' },
];
Resultado:
[
{
"marker": "email_reg",
"value": "john@example.com"
},
{
"marker": "password_reg",
"value": "123456"
}
]

5. Iniciar sesión con AuthProvider.auth() y obtener el usuario con Users.getUser()​

const authResponse = await AuthProvider.auth('email', { authData });

if ('statusCode' in authResponse) {
throw new Error(authResponse.message);
}

console.log(authResponse);

const user = await Users.getUser();
console.log(user);

Users.getUser() devuelve:

Resultado:
{
"id": 39,
"total": "1",
"identifier": "john@example.com",
"authProviderIdentifier": "email",
"formData": [
{
"marker": "name_reg",
"type": "string",
"value": "John"
},
{
"marker": "phone_reg",
"type": "string",
"value": "+12025550147"
},
{
"marker": "email_notification_reg",
"type": "string",
"value": "john@example.com"
}
],
"formIdentifier": "reg",
"groups": [
1
],
"state": {},
"rating": {},
"moduleFormConfigs": []
}

6. Obtener los pedidos del usuario con Orders.getAllOrdersByMarker()​

const orders = await Orders.getAllOrdersByMarker('subscriptions');

if ('statusCode' in orders) {
throw new Error(orders.message);
}
Resultado:
{
"items": [
{
"id": 119,
"storageId": 2,
"createdDate": "2026-06-06T11:50:12.995Z",
"statusIdentifier": "active",
"statusLocalizeInfos": {
"title": "Active"
},
"formIdentifier": "subscription",
"formData": [
{
"type": "date",
"marker": "expired_date",
"value": {
"fullDate": "2026-05-07T00:00:00.000Z",
"formattedValue": "07-05-2026 00:00",
"formatString": "DD-MM-YYYY HH:mm"
}
},
{
"type": "list",
"marker": "subscription_time",
"value": [
"1"
]
}
],
"attributeSetIdentifier": "subscriptions",
"paymentStrategy": "once",
"totalSum": "400",
"totalSumRaw": "400",
"currency": "USD",
"paymentAccountIdentifier": "cash",
"paymentAccountLocalizeInfos": {
"title": "Cash"
},
"products": [
{
"id": 15,
"title": "Orange ball",
"sku": null,
"previewImage": "[]",
"price": 400,
"quantity": 1,
"isGift": false
}
],
"paymentUrl": null,
"discountConfig": {
"orderDiscounts": [],
"productDiscounts": [],
"coupon": null,
"settings": {
"allowStacking": false,
"maxDiscountValue": null,
"allowGiftStacking": false,
"maxBonusPaymentPercent": null,
"minBonusAmount": null,
"minOrderAmountForBonus": null,
"giftRefundPolicy": "KEEP_GIFT"
},
"additionalDiscountsMarkers": [],
"totalRaw": 400,
"totalSumWithDiscount": 400,
"excludedGiftProductIds": [],
"bonus": {
"availableBalance": 0,
"maxBonusDiscount": 0,
"minBonusAmount": null,
"minOrderAmountForBonus": null,
"bonusApplied": 0
},
"bonusApplied": 0,
"totalDue": 400
},
"isPartial": false,
"isCompleted": false
}
],
"total": 1
}

7. Comprobar si hay una suscripción activa​

const now = new Date();
const hasActiveSubscription = (orders.items ?? []).some((order) => {
// isCompleted: true = payment completed; null = no payment session
if (!order.isCompleted) return false;
const expiry = order.formData.find((d) => d.marker === 'expired_date')
?.value as { fullDate?: string } | undefined;
return !!expiry?.fullDate && new Date(expiry.fullDate) > now;
});

8. Si la suscripción está activa, dar acceso; en caso contrario, crear un pedido y un pago​

let content = null;
if (hasActiveSubscription) {
// Active subscription: show the content
content = await Pages.getPageByUrl('premium_page');
console.log('Access granted:', content);
} else {
// No active subscription: create an order and a payment session
const months = 1;
const expires = new Date();
expires.setMonth(expires.getMonth() + months);
const pad = (n: number) => String(n).padStart(2, '0');
const formatted = `${pad(expires.getDate())}-${pad(expires.getMonth() + 1)}-${expires.getFullYear()} ${pad(expires.getHours())}:${pad(expires.getMinutes())}`;
const body = {
formIdentifier: 'subscription',
paymentAccountIdentifier: 'cash',
formData: [
{
type: 'date',
marker: 'expired_date',
value: {
fullDate: expires.toISOString(),
formattedValue: formatted,
formatString: 'DD-MM-YYYY HH:mm',
},
},
{
// A `list` field takes an array of the selected option values
// (plain strings), not option objects. '1' = the "1 month" option.
type: 'list',
marker: 'subscription_time',
value: [String(months)],
},
],
products: [
{
productId: 15,
quantity: 1,
},
],
};
const order = await Orders.createOrder('subscriptions', body);

if ('statusCode' in order) {
throw new Error(order.message);
}

const payment = await Payments.createSession(order.id, 'session', false);

if ('statusCode' in payment) {
throw new Error(payment.message);
}

console.log('Payment session:', payment);
}

Ejemplo final​

// 1. Import defineOneEntry and define PROJECT_URL and APP_TOKEN
import { defineOneEntry } from 'oneentry';

const PROJECT_URL = 'https://your-project.oneentry.cloud';
const APP_TOKEN = 'your-app-token';

// 2. Create an API client
const { Users, Orders, Pages, Payments, AuthProvider, Forms } = defineOneEntry(
PROJECT_URL,
{
token: APP_TOKEN,
},
);

// 3. Get the subscription form
const form = await Forms.getFormByMarker('subscription');
console.log(form);
// expired_date - Date
// subscription_time - list

// 4. Prepare the data to authenticate the user
const authData = [
{ marker: 'email_reg', value: 'your-email' },
{ marker: 'password_reg', value: 'your-password' },
];

// 5. Sign in and get the user
const authResponse = await AuthProvider.auth('email', { authData });

if ('statusCode' in authResponse) {
throw new Error(authResponse.message);
}

console.log(authResponse);

const user = await Users.getUser();
console.log(user);

// 6. Get the user's orders
const orders = await Orders.getAllOrdersByMarker('subscriptions');

if ('statusCode' in orders) {
throw new Error(orders.message);
}

// 7. Check for an active subscription
const now = new Date();
const hasActiveSubscription = (orders.items ?? []).some((order) => {
// isCompleted: true = payment completed; null = no payment session
if (!order.isCompleted) return false;
const expiry = order.formData.find((d) => d.marker === 'expired_date')
?.value as { fullDate?: string } | undefined;
return !!expiry?.fullDate && new Date(expiry.fullDate) > now;
});

// 8. If the subscription is active, grant access; otherwise create an order and a payment
let content = null;
if (hasActiveSubscription) {
// Active subscription: show the content
content = await Pages.getPageByUrl('premium_page');
console.log('Access granted:', content);
} else {
// No active subscription: create an order and a payment session
const months = 1;
const expires = new Date();
expires.setMonth(expires.getMonth() + months);
const pad = (n: number) => String(n).padStart(2, '0');
const formatted = `${pad(expires.getDate())}-${pad(expires.getMonth() + 1)}-${expires.getFullYear()} ${pad(expires.getHours())}:${pad(expires.getMinutes())}`;
const body = {
formIdentifier: 'subscription',
paymentAccountIdentifier: 'cash',
formData: [
{
type: 'date',
marker: 'expired_date',
value: {
fullDate: expires.toISOString(),
formattedValue: formatted,
formatString: 'DD-MM-YYYY HH:mm',
},
},
{
// A `list` field takes an array of the selected option values
// (plain strings), not option objects. '1' = the "1 month" option.
type: 'list',
marker: 'subscription_time',
value: [String(months)],
},
],
products: [
{
productId: 15,
quantity: 1,
},
],
};
const order = await Orders.createOrder('subscriptions', body);

if ('statusCode' in order) {
throw new Error(order.message);
}

const payment = await Payments.createSession(order.id, 'session', false);

if ('statusCode' in payment) {
throw new Error(payment.message);
}

console.log('Payment session:', payment);
}