Assinatura de conteúdo
Controla o acesso ao conteúdo por assinatura: verifica se o usuário tem uma assinatura ativa e, conforme o caso, libera o acesso ao conteúdo premium ou o convida a assinar.
O que este exemplo faz:
- Exibe conteúdo premium apenas para usuários com uma assinatura ativa
- A verificação é baseada em Orders e Users.
- Usuários logados sem uma assinatura ativa recebem um pedido e uma sessão de pagamento para assinar.
Pré-requisitos:
- Um PROJECT_URL e um APP_TOKEN válidos para a API do OneEntry.
- Um formulário de pedido (tipo "Order form") com o marcador
subscriptione os atributosexpired_date(date) esubscription_time(list com uma opção cujo valor é1) - Um armazenamento de pedidos com o marcador
subscriptionsvinculado a esse formulário, com a conta de pagamentocash - Um produto a ser vendido como assinatura (o exemplo usa
productId: 15; substitua pelo id do seu produto) - Uma página com a URL
premium_page - Um usuário cadastrado
Observações:
- Os exemplos tratam erros de forma mínima: lançam uma exceção quando uma chamada retorna um objeto de erro.
- Por padrão (
isShell: true), o SDK retorna um objeto de erro em vez de lançar uma exceção, então verifique o resultado, por exemplo'statusCode' in result. ComisShell: false, ele lança a exceção, e você trata os erros com try/catch. Veja Erros. - O acesso é liberado somente depois que a sessão de pagamento é concluída (
isCompleted: true). Com a conta de pagamentocash, isso só acontece quando o pagamento é confirmado no lado da plataforma. - A verificação da assinatura é feita no seu app, portanto ela controla apenas o que a sua UI exibe. A página em si continua disponível pela Content API para qualquer pessoa cujo grupo de usuários possa lê-la. Para restringi-la de fato, permita o acesso à página apenas para um grupo de usuários ao qual os assinantes pertençam (permissões de grupos de usuários no painel de administração) e chame a API em nome do usuário logado.
Documentação da plataforma:
Referência do SDK:
Experimente ao vivo
Execute este exemplo no sandbox do JS SDK. Conecte a URL do seu projeto e o App Token na primeira visita e, em seguida, abra:
Cenário
1. Importar defineOneEntry e definir PROJECT_URL e APP_TOKEN
import { defineOneEntry } from 'oneentry';
const PROJECT_URL = 'https://your-project.oneentry.cloud';
const APP_TOKEN = 'your-app-token';
2. Criar um cliente da API com defineOneEntry()
const { Users, Orders, Pages, Payments, AuthProvider, Forms } = defineOneEntry(
PROJECT_URL,
{
token: APP_TOKEN,
},
);
3. Obter o formulário de assinatura com 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. Preparar os dados para autenticar o usuário
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. Fazer login com AuthProvider.auth() e obter o usuário com 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() retorna:
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. Obter os pedidos do usuário com 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. Verificar se há uma assinatura ativa
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. Se a assinatura estiver ativa, liberar o acesso; caso contrário, criar um pedido e um pagamento
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);
}
Exemplo 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);
}