انتقل إلى المحتوى الرئيسي

الاشتراك في المحتوى

يتحكم في الوصول إلى المحتوى عبر الاشتراك: يتحقق مما إذا كان لدى المستخدم اشتراك نشط، فإما يمنحه الوصول إلى المحتوى المميز أو يطلب منه الاشتراك.

ما يفعله هذا المثال:

  • يعرض المحتوى المميّز فقط للمستخدمين ذوي الاشتراك النشط
  • يعتمد التحقق على Orders وUsers.
  • يحصل المستخدمون المسجّلون دخولهم دون اشتراك نشط على طلب وجلسة دفع للاشتراك.

المتطلبات المسبقة:

  • قيمتا PROJECT_URL وAPP_TOKEN صالحتان لـ OneEntry API.
  • نموذج طلب (من النوع "Order form") بالعلامة subscription والسمتين expired_date (date) وsubscription_time (list مع خيار قيمته 1)
  • تخزين طلبات بالعلامة subscriptions مرتبط بذلك النموذج، مع حساب الدفع cash
  • منتج يُباع كاشتراك (يستخدم المثال productId: 15؛ استبدله بمعرّف منتجك)
  • صفحة بعنوان URL premium_page
  • مستخدم مسجل

ملاحظات:

  • تعالج الأمثلة الأخطاء بالحد الأدنى: فهي ترمي استثناءً عندما يُرجع الاستدعاء كائن خطأ.
  • افتراضيًا (isShell: true) يُعيد SDK كائن خطأ بدلًا من رمي استثناء، لذا تحقق من النتيجة، مثل 'statusCode' in result. مع isShell: false يرمي استثناءً، وتعالج الأخطاء باستخدام try/catch. راجع الأخطاء.
  • لا يُفتح الوصول إلا بعد اكتمال جلسة الدفع (isCompleted: true). مع حساب الدفع cash لا يحدث ذلك إلا عند تأكيد الدفع من جانب المنصة.
  • يجري التحقق من الاشتراك في تطبيقك، لذا فهو يتحكم فقط فيما تعرضه واجهتك. أما الصفحة نفسها فتبقى متاحة عبر Content API لأي شخص تملك مجموعة مستخدميه صلاحية قراءتها. لتقييدها فعليًا، اسمح بالوصول إلى الصفحة فقط لمجموعة مستخدمين ينتمي إليها المشتركون (صلاحيات مجموعات المستخدمين في لوحة الإدارة)، واستدعِ API نيابةً عن المستخدم المسجّل دخوله.

وثائق المنصة:

مرجع SDK:

جربها مباشرة​

شغّل هذا المثال في بيئة JS SDK التجريبية. اربط Project URL وApp Token عند الزيارة الأولى، ثم افتح:

السيناريو​

1. استورد defineOneEntry وعرّف PROJECT_URL وAPP_TOKEN​

import { defineOneEntry } from 'oneentry';

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

2. أنشئ عميل API باستخدام defineOneEntry()​

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

3. احصل على نموذج الاشتراك باستخدام Forms.getFormByMarker()​

const form = await Forms.getFormByMarker('subscription');
console.log(form);
// expired_date - Date
// subscription_time - list
النتيجة:
{
"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. جهّز البيانات للمصادقة على المستخدم​

const authData = [
{ marker: 'email_reg', value: 'your-email' },
{ marker: 'password_reg', value: 'your-password' },
];
النتيجة:
[
{
"marker": "email_reg",
"value": "john@example.com"
},
{
"marker": "password_reg",
"value": "123456"
}
]

5. سجّل الدخول باستخدام AuthProvider.auth() واحصل على المستخدم باستخدام 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():

النتيجة:
{
"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. احصل على طلبات المستخدم باستخدام Orders.getAllOrdersByMarker()​

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

if ('statusCode' in orders) {
throw new Error(orders.message);
}
النتيجة:
{
"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. تحقق من وجود اشتراك نشط​

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. إذا كان الاشتراك نشطًا، امنح الوصول؛ وإلا فأنشئ طلبًا ودفعة​

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);
}

المثال النهائي​

// 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);
}