dg.run

طرح‌ها و اشتراک‌ها

بدون نوشتن کد پرداخت از برنامه‌ی خود درآمد کسب کنید. شما طرح‌ها را تعریف می‌کنید، برنامه‌ی شما از SDK می‌پرسد چه کسی دسترسی دارد، و dg.run پرداخت را انجام می‌دهد: از کیف پول کاربر یا با کارت از طریق Stripe. قیمت هر طرح به دلار آمریکا یا ریال ایران است.

نوع طرح‌ها

نوع کاربر چه چیزی می‌گیرد قیمت
آزمایش رایگان دسترسی برای N روز (۱ تا ۹۰). برای هر کاربر در هر برنامه فقط یک‌بار. رایگان
اشتراک دسترسی برای یک دوره (هر N هفته، ماه یا سال). تا وقتی کاربر متوقفش نکند، خودکار از کیف پول تمدید می‌شود. ۱ تا ۱٬۰۰۰ دلار، یا ۱۰۰٬۰۰۰ تا ۵٬۰۰۰٬۰۰۰٬۰۰۰ ریال
خرید یک‌باره دسترسی برای N روز یا همیشگی (۰ روز). هرگز تمدید نمی‌شود. ۱ تا ۱٬۰۰۰ دلار، یا ۱۰۰٬۰۰۰ تا ۵٬۰۰۰٬۰۰۰٬۰۰۰ ریال

طرح‌ها را در برنامه‌های من ← طرح‌ها بسازید. هر طرح یک کلید دارد (مثلاً monthly) که برنامه‌ی شما با آن به طرح اشاره می‌کند، یک نام، یک توضیح کوتاه و فهرست امکانات. هر برنامه تا ۱۰ طرح می‌تواند داشته باشد.

نوع، قیمت و مدت یک طرح پس از ساخته شدن قابل تغییر نیست، چون مشترکان آن را پذیرفته‌اند. برای تغییر قیمت، طرح جدیدی بسازید و طرح قدیمی را بایگانی کنید: برای خریداران جدید نمایش داده نمی‌شود و مشترکان فعلی همان چیزی را که خریده‌اند نگه می‌دارند. فقط طرحی را می‌توان حذف کرد که هیچ‌کس هرگز آن را نگرفته باشد.

استفاده در برنامه‌ی شما

import { createDg } from '@dgrun/sdk'
const dg = createDg()

const plans = await dg.billing.plans()   // آنچه ارائه می‌دهید (بدون نیاز به ورود)
const sub = await dg.billing.status()    // null یا اشتراک کاربر واردشده
if (sub?.active) { /* امکانات پولی را باز کنید */ }

await dg.billing.subscribe('monthly')    // کاربر را برای پرداخت به dg.run می‌برد و برمی‌گرداند
await dg.billing.cancel()                // تمدید خودکار را متوقف می‌کند (دسترسی تا پایان دوره می‌ماند)

status() مقدار { active, plan, startedAt, currentPeriodEnd, autoRenew, trial, renewalError } را برمی‌گرداند. برای دسترسی همیشگی currentPeriodEnd برابر null است. آزمایش یا اشتراکِ تمام‌شده هم با active: false برگردانده می‌شود.

پس از بازگشت از پرداخت، SDK نشانی را پاک می‌کند و dg.billing.checkout را با { result: 'ok' | 'cancel', plan } (یا در بارگذاری‌های دیگر null) برمی‌گرداند. این مقدار نمی‌گوید کاربر پرداخت کرده یا نه: status() را صدا بزنید.

نمونه‌ی Pro Notes در مخزن (examples/pro-notes) یک برنامه‌ی کامل است.

پرداخت چگونه انجام می‌شود

۱. برنامه‌ی شما subscribe('monthly') را صدا می‌زند. مرورگر به dg.run/subscribe می‌رود که برنامه‌ی شما، طرح، قیمت و موجودی کیف پول را نشان می‌دهد. ۲. کاربر در dg.run و با نشست خودش تأیید می‌کند و انتخاب می‌کند از کیف پول بپردازد یا با کارت (Stripe). آزمایش رایگان فقط یک کلیک است. ۳. مرورگر به برنامه‌ی شما برمی‌گردد و برنامه status() را صدا می‌زند.

صفحه‌ی شما هرگز کارت نمی‌بیند و پولی جابه‌جا نمی‌کند. یک برنامه فقط می‌تواند طرح‌ها و وضعیت را بخواند، تمدید خودکار را متوقف کند و از کاربر بخواهد برای پرداخت برود؛ نمی‌تواند از کسی پولی کسر کند.

کیف پول و تمدید

هر کاربر در نمایه‌اش یک کیف پول دارد: با کارت پول اضافه می‌کند و این پول صرف طرح‌های همه‌ی برنامه‌ها و تمدیدها می‌شود. هر پرداخت در تاریخچه‌ی تراکنش‌ها دیده می‌شود.

  • اشتراک در پایان دوره خودکار از کیف پول تمدید می‌شود. اگر موجودی کم باشد تمدید ناموفق است و اشتراک منقضی می‌شود (renewalError برابر insufficient_funds است).
  • پرداخت اشتراک با کارت یک دوره می‌خرد؛ تمدیدهای بعدی از کیف پول انجام می‌شود.
  • رفتن به طرح دیگر، طرح فعلی را فوراً جایگزین می‌کند و زمان باقی‌مانده بازپرداخت نمی‌شود.
  • سرور تصمیم می‌گیرد: تمدید و انقضا هر بار که کسی اشتراکی را می‌خواند اعمال می‌شود و یک کار روزانه بقیه را جارو می‌کند.

در برنامه‌های من ← داده‌ها و کاربران ← کاربران می‌توانید طرح هر کاربر، زمان باقی‌مانده (یا همیشگی) و تمدید خودکار بودن آن را ببینید.

پول و آزمایش

  • مشتریان به dg.run پرداخت می‌کنند. صفحه‌ی طرح‌ها نشان می‌دهد مشتریان چقدر پرداخته‌اند؛ و آنچه پس از مالیات، کارمزد و سهم پلتفرم به شما می‌رسد را نشان می‌دهد؛ پلتفرم پول را دستی به شما واریز می‌کند (بخش بالا را ببینید).
  • در پیش‌نمایش مدیر فقط آزمایش‌های رایگان قابل امتحان است.
  • بدون کلید Stripe، پرداخت با کارت در حالت توسعه شبیه‌سازی می‌شود.

بررسی دسترسی آفلاین (اثبات امضاشده)

status() همیشه از سرور می‌پرسد. برای برنامه‌ای که باید آفلاین هم کار کند، از entitlement() استفاده کنید:

const e = await dg.billing.entitlement()   // null یا { plan, trial, periodEnd, validUntil, source }
if (e) { /* باز کنید */ }

تا وقتی اشتراک فعال است، سرور یک اثبات امضاشده (Ed25519) به SDK می‌دهد. SDK آن را در IndexedDB ذخیره و روی دستگاه با کلید عمومی dg.run بررسی می‌کند؛ پس تا ۱۵ روز آفلاین کار می‌کند (هرگز فراتر از پایان اشتراک) و تغییر داده‌های ذخیره‌شده امضا را می‌شکند. اثبات به برنامه شما و همان کاربر گره خورده است. آنلاین، SDK اثبات قدیمی‌تر از یک روز را جایگزین می‌کند (با createDg({ proofRefreshAfterMs }) تغییرش دهید) و به‌محض از بین رفتن اشتراک، خروج کاربر یا قطع اتصال برنامه، آن را حذف می‌کند. برای اعتماد فقط به کلیدی که خودتان دارید، آن را از https://<dg.run>/api/jwks کپی کنید و createDg({ publicKeys }) را بدهید. مرورگرهایی که Ed25519 را در WebCrypto ندارند، آفلاین null می‌گیرند (به‌صورت بسته شکست می‌خورند).

ارزها

قیمت هر طرح به یک ارز است، USD یا IRR (ریال ایران، بدون اعشار)، که هنگام ساخت طرح انتخاب می‌کنید. پس از اینکه کسی از طرح استفاده کرد، دیگر قابل تغییر نیست. هیچ‌چیز تبدیل نمی‌شود: طرح ریالی از موجودی ریالی مشتری و طرح دلاری از موجودی دلاری او پرداخت می‌شود. هر دو در یک کیف پول هستند. کارت (Stripe) فقط برای دلار کار می‌کند؛ موجودی ریالی را پلتفرم اضافه می‌کند. یک برنامه می‌تواند طرح‌هایی به هر دو ارز داشته باشد.

درآمد شما و نحوه‌ی دریافت پول

مشتریان قیمت کامل طرح را می‌پردازند. درآمد شما آنچه می‌ماند پس از مالیات فروشِ موجود در قیمت، هزینه‌ی پرداخت با کارت و سهم پلتفرم. نرخ‌ها در صفحه‌ی طرح‌های شما نمایش داده می‌شود، همراه با نمودار درآمد و برای هر طرح نحوه‌ی تقسیم هر فروش. هنگام تعیین قیمت تقریباً می‌بینید از هر فروش چقدر به شما می‌رسد. نرخ‌ها ممکن است تغییر کنند، اما هر فروش همیشه همان تقسیمی را که هنگام خرید داشته نگه می‌دارد.

برای دریافت پول، در صفحه پرداخت‌ها (بخش توسعه‌دهنده) برای هر ارزی که با آن می‌فروشید یک روش پرداخت اضافه کنید: برای دلار پی‌پال، انتقال Interac، انتقال بانکی یا روش دیگر؛ برای ریال شمارهٔ شبا، نام صاحب حساب و نام بانک. پلتفرم تعیین می‌کند برای هر ارز چه گزینه‌هایی در دسترس باشد. وقتی موجودی شما به حداقل برسد، پلتفرم پول را می‌فرستد و پرداخت را ثبت می‌کند و شما آن را در همان صفحه می‌بینید.

نکته‌ها

  • مقدار status().active هر بار توسط سرور محاسبه می‌شود. اما کاری که صفحه‌ی شما با آن می‌کند فقط به اندازه‌ی استحکام صفحه‌ی شماست: از آن برای تصمیم درباره‌ی نمایش استفاده کنید و آنچه باید محافظت شود را در سمت سرور حفاظت کنید.
  • خطاها: plan_not_found، not_recurring، unauthorized.
  • حذف برنامه، طرح‌ها و اشتراک‌هایش را حذف می‌کند؛ تاریخچه‌ی پرداخت‌ها می‌ماند.