From 0b64d8086cbd6a5c6121ea2fb0de5c6c6eafcd72 Mon Sep 17 00:00:00 2001 From: Vlad Chikalkin Date: Tue, 7 Oct 2025 19:13:41 +0300 Subject: [PATCH] Feature/documents pages (#118) * apps/web: add generic privacy & offer pages * Update environment variables and enhance offer and privacy pages - Added `OFFER_URL` and `SUPPORT_TELEGRAM_URL` to environment variable configuration for better flexibility. - Updated the offer page to dynamically link to the offer URL and improved contact information presentation with a direct link to the support Telegram. - Revised the privacy policy page to reflect the service name and updated contact details, ensuring clarity and consistency in communication. * move offer & privacy -> (documents) sub directory * Update offer and privacy pages to include user consent for third-party data sharing - Added a clause in the offer page requiring users to ensure consent from third parties when adding their contact information. - Updated the privacy policy to clarify that users can share third-party data, emphasizing the need for consent for data processing within the service. * Add privacy agreement and update environment variables - Introduced `PRIVACY_URL` to the environment configuration for dynamic linking. - Updated localization files to include a user consent agreement for sharing phone numbers, linking to the offer and privacy URLs. - Enhanced welcome and contact addition messages to incorporate the new consent clause, improving user clarity on data handling. * Refactor phone agreement localization and enhance user consent messaging - Updated the Russian localization file to streamline the phone sharing agreement, improving clarity on user consent for data processing. - Modified the contact addition and welcome messages to incorporate the new agreement format, ensuring users are informed about their consent to share personal data. * Enhance Russian localization and update message formatting - Added a new payment agreement clause in the Russian localization file, clarifying user consent for payments. - Updated message formatting in the contact addition and subscription processes to support HTML parsing, improving message presentation and user experience. - Incorporated the new payment agreement into the subscription flow, ensuring users are informed about their consent to the terms. * Refactor Russian localization for contact agreements and enhance user consent messaging - Updated the Russian localization file to separate and clarify the phone sharing and contact sharing agreements, improving user understanding of consent requirements. - Modified the contact addition and welcome messages to utilize the new agreement format, ensuring users are informed about their consent to share personal data in a more structured manner. * Enhance Russian localization and add document handling features - Updated the Russian localization file to include new entries for privacy policy and public offer documents, improving user access to important information. - Added 'documents' command to the bot's command list, allowing users to easily access document-related features. - Integrated document handling in the main menu and handlers, enhancing user experience and navigation within the bot. --- apps/bot/locales/ru.ftl | 27 +- apps/bot/src/bot/conversations/add-contact.ts | 25 +- .../bot/src/bot/conversations/subscription.ts | 15 +- apps/bot/src/bot/features/documents.ts | 12 + apps/bot/src/bot/features/index.ts | 1 + apps/bot/src/bot/features/welcome.ts | 16 +- apps/bot/src/bot/handlers/documents.ts | 18 ++ apps/bot/src/bot/handlers/index.ts | 1 + apps/bot/src/bot/settings/commands.ts | 10 +- apps/bot/src/config/env.ts | 2 + apps/bot/src/config/keyboards.ts | 10 +- apps/web/app/(documents)/offer/page.tsx | 242 ++++++++++++++++ apps/web/app/(documents)/privacy/page.tsx | 266 ++++++++++++++++++ apps/web/config/env.ts | 2 + apps/web/middleware.ts | 4 +- turbo.json | 5 +- 16 files changed, 643 insertions(+), 13 deletions(-) create mode 100644 apps/bot/src/bot/features/documents.ts create mode 100644 apps/bot/src/bot/handlers/documents.ts create mode 100644 apps/web/app/(documents)/offer/page.tsx create mode 100644 apps/web/app/(documents)/privacy/page.tsx diff --git a/apps/bot/locales/ru.ftl b/apps/bot/locales/ru.ftl index d6e90ab..1c93b98 100644 --- a/apps/bot/locales/ru.ftl +++ b/apps/bot/locales/ru.ftl @@ -45,6 +45,8 @@ commands-list = Откройте приложение кнопкой "Открыть", чтобы отредактировать свой профиль или создать запись support = { -support-contact } +documents = + .description = Документы # Кнопки btn-add-contact = 👤 Добавить контакт @@ -53,9 +55,26 @@ btn-pro = 👑 Pro доступ btn-subscribe = 👑 Приобрести Pro btn-pro-info = ℹ️ Мой Pro доступ btn-open-app = 📱 Открыть приложение +btn-documents = 📋 Документы btn-back = ◀️ Назад +# Согласие +share-phone-agreement = + Нажимая кнопку «Отправить номер телефона», + вы: + - соглашаетесь с Публичной офертой + - подтверждаете согласие на обработку персональных данных согласно Политике конфиденциальности +share-contact-agreement = + Отправляя контакт, имя и номер телефона, вы подтверждаете, что имеете согласие этого человека на передачу его контактных данных и на их обработку в рамках нашего сервиса. + (Пункт 4.5 Политики конфиденциальности) +payment-agreement = + Совершая оплату, вы соглашаетесь с Публичной офертой +agreement-links = + Публичная оферта + Политика конфиденциальности + + # Приветственные сообщения msg-welcome = 👋 Добро пожаловать! @@ -64,14 +83,14 @@ msg-welcome-back = 👋 С возвращением, { $name }! # Сообщения о телефоне -msg-need-phone = 📱 Чтобы добавить контакт, сначала поделитесь своим номером телефона +msg-need-phone = 📱 Чтобы добавить контакт, сначала поделитесь своим номером телефона. msg-phone-saved = ✅ Спасибо! Мы сохранили ваш номер телефона Теперь вы можете открыть приложение или воспользоваться командами бота msg-already-registered = ✅ Вы уже зарегистрированы в системе - Для смены номера телефона обратитесь в поддержку (Контакты в профиле бота) + Для смены номера телефона обратитесь в поддержку (Контакты в профиле бота) msg-invalid-phone = ❌ Некорректный номер телефона. Пример: +79999999999 # Сообщения о контактах @@ -85,7 +104,7 @@ msg-contact-added = ✅ Добавили { $fullname } в список ваших контактов Пригласите пользователя в приложение, чтобы вы могли добавлять с ним записи -msg-contact-forward = Перешлите пользователю следующее сообщение, чтобы он мог начать пользоваться ботом ⬇️ +msg-contact-forward = Перешлите пользователю следующее сообщение, чтобы он мог начать пользоваться ботом ⬇️ # Сообщения для шаринга msg-share-bot = @@ -96,7 +115,7 @@ msg-share-bot = # Системные сообщения msg-cancel = ❌ Операция отменена msg-unhandled = ❓ Неизвестная команда. Попробуйте /start -msg-cancel-operation = Для отмены операции используйте команду /cancel +msg-cancel-operation = Для отмены операции используйте команду /cancel # Ошибки err-generic = ⚠️ Что-то пошло не так. Попробуйте еще раз через несколько секунд diff --git a/apps/bot/src/bot/conversations/add-contact.ts b/apps/bot/src/bot/conversations/add-contact.ts index 90eb8f8..3007d63 100644 --- a/apps/bot/src/bot/conversations/add-contact.ts +++ b/apps/bot/src/bot/conversations/add-contact.ts @@ -1,6 +1,7 @@ /* eslint-disable sonarjs/cognitive-complexity */ /* eslint-disable id-length */ import { type Context } from '@/bot/context'; +import { env } from '@/config/env'; import { KEYBOARD_SHARE_BOT, KEYBOARD_SHARE_PHONE } from '@/config/keyboards'; import { parseContact } from '@/utils/contact'; import { combine } from '@/utils/messages'; @@ -21,16 +22,34 @@ export async function addContact(conversation: Conversation, c if (!customer) { return ctx.reply( - await conversation.external(({ t }) => t('msg-need-phone')), - KEYBOARD_SHARE_PHONE, + await conversation.external(({ t }) => + combine( + t('msg-need-phone'), + t('share-phone-agreement', { + offerUrl: env.OFFER_URL, + privacyUrl: env.PRIVACY_URL, + }), + ), + ), + { ...KEYBOARD_SHARE_PHONE, parse_mode: 'HTML' }, ); } // Просим отправить контакт или номер телефона await ctx.reply( await conversation.external(({ t }) => - combine(t('msg-send-client-contact-or-phone'), t('msg-cancel-operation')), + combine( + t('msg-send-client-contact-or-phone'), + t('msg-cancel-operation'), + t('share-contact-agreement', { + offerUrl: env.OFFER_URL, + privacyUrl: env.PRIVACY_URL, + }), + ), ), + { + parse_mode: 'HTML', + }, ); // Ждём первое сообщение: контакт или текст с номером diff --git a/apps/bot/src/bot/conversations/subscription.ts b/apps/bot/src/bot/conversations/subscription.ts index 71fc0df..6b7e8c3 100644 --- a/apps/bot/src/bot/conversations/subscription.ts +++ b/apps/bot/src/bot/conversations/subscription.ts @@ -66,7 +66,7 @@ export async function subscription(conversation: Conversation, return combine(statusLine, fmt`${i}${t('msg-cancel-operation')}${i}`.text); }), ), - { reply_markup: keyboard }, + { parse_mode: 'HTML', reply_markup: keyboard }, ); // ждём выбора @@ -95,6 +95,18 @@ export async function subscription(conversation: Conversation, month: '2-digit', year: 'numeric', }); + + const agreementText = await conversation.external(({ t }) => { + return t('payment-agreement', { + offerUrl: env.OFFER_URL, + privacyUrl: env.PRIVACY_URL, + }); + }); + + await ctx.reply(agreementText, { + parse_mode: 'HTML', + }); + return ctx.replyWithInvoice( 'Оплата Pro доступа', combine( @@ -110,6 +122,7 @@ export async function subscription(conversation: Conversation, }, ], { + protect_content: true, provider_token: env.BOT_PROVIDER_TOKEN, start_parameter: 'get_access', }, diff --git a/apps/bot/src/bot/features/documents.ts b/apps/bot/src/bot/features/documents.ts new file mode 100644 index 0000000..e660ca5 --- /dev/null +++ b/apps/bot/src/bot/features/documents.ts @@ -0,0 +1,12 @@ +import { handleDocuments } from '../handlers/documents'; +import { type Context } from '@/bot/context'; +import { logHandle } from '@/bot/helpers/logging'; +import { Composer } from 'grammy'; + +const composer = new Composer(); + +const feature = composer.chatType('private'); + +feature.command('documents', logHandle('command-documents'), handleDocuments); + +export { composer as documents }; diff --git a/apps/bot/src/bot/features/index.ts b/apps/bot/src/bot/features/index.ts index 8d8908e..b909d3c 100644 --- a/apps/bot/src/bot/features/index.ts +++ b/apps/bot/src/bot/features/index.ts @@ -1,4 +1,5 @@ export * from './add-contact'; +export * from './documents'; export * from './help'; export * from './pro'; export * from './registration'; diff --git a/apps/bot/src/bot/features/welcome.ts b/apps/bot/src/bot/features/welcome.ts index 7bce81f..1da9b4b 100644 --- a/apps/bot/src/bot/features/welcome.ts +++ b/apps/bot/src/bot/features/welcome.ts @@ -1,6 +1,8 @@ import { type Context } from '@/bot/context'; import { logHandle } from '@/bot/helpers/logging'; +import { env } from '@/config/env'; import { KEYBOARD_SHARE_PHONE, mainMenu } from '@/config/keyboards'; +import { combine } from '@/utils/messages'; import { RegistrationService } from '@repo/graphql/api/registration'; import { Composer } from 'grammy'; @@ -22,7 +24,19 @@ feature.command('start', logHandle('command-start'), async (ctx) => { } // Новый пользователь — просим поделиться номером - return ctx.reply(ctx.t('msg-welcome'), { ...KEYBOARD_SHARE_PHONE, parse_mode: 'HTML' }); + return ctx.reply( + combine( + ctx.t('msg-welcome'), + ctx.t('share-phone-agreement', { + offerUrl: env.OFFER_URL, + privacyUrl: env.PRIVACY_URL, + }), + ), + { + ...KEYBOARD_SHARE_PHONE, + parse_mode: 'HTML', + }, + ); }); export { composer as welcome }; diff --git a/apps/bot/src/bot/handlers/documents.ts b/apps/bot/src/bot/handlers/documents.ts new file mode 100644 index 0000000..df3f756 --- /dev/null +++ b/apps/bot/src/bot/handlers/documents.ts @@ -0,0 +1,18 @@ +import { type Context } from '@/bot/context'; +import { env } from '@/config/env'; +import { KEYBOARD_REMOVE } from '@/config/keyboards'; + +async function handler(ctx: Context) { + await ctx.reply( + ctx.t('agreement-links', { + offerUrl: env.OFFER_URL, + privacyUrl: env.PRIVACY_URL, + }), + { + ...KEYBOARD_REMOVE, + parse_mode: 'HTML', + }, + ); +} + +export { handler as handleDocuments }; diff --git a/apps/bot/src/bot/handlers/index.ts b/apps/bot/src/bot/handlers/index.ts index 64abb56..ca3db4b 100644 --- a/apps/bot/src/bot/handlers/index.ts +++ b/apps/bot/src/bot/handlers/index.ts @@ -1,4 +1,5 @@ export * from './add-contact'; +export * from './documents'; export * from './pro'; export * from './share-bot'; export * from './subscription'; diff --git a/apps/bot/src/bot/settings/commands.ts b/apps/bot/src/bot/settings/commands.ts index 08a8473..8fd1638 100644 --- a/apps/bot/src/bot/settings/commands.ts +++ b/apps/bot/src/bot/settings/commands.ts @@ -5,7 +5,15 @@ import { type LanguageCode } from '@grammyjs/types'; import { type Api, type Bot, type RawApi } from 'grammy'; export async function setCommands({ api }: Bot>) { - const commands = createCommands(['start', 'addcontact', 'sharebot', 'help', 'subscribe', 'pro']); + const commands = createCommands([ + 'start', + 'addcontact', + 'sharebot', + 'help', + 'subscribe', + 'pro', + 'documents', + ]); for (const command of commands) { addLocalizations(command); diff --git a/apps/bot/src/config/env.ts b/apps/bot/src/config/env.ts index 8ccd57e..de8a2da 100644 --- a/apps/bot/src/config/env.ts +++ b/apps/bot/src/config/env.ts @@ -4,6 +4,8 @@ export const envSchema = z.object({ BOT_PROVIDER_TOKEN: z.string(), BOT_TOKEN: z.string(), BOT_URL: z.string(), + OFFER_URL: z.string(), + PRIVACY_URL: z.string(), RATE_LIMIT: z .string() .transform((value) => Number.parseInt(value, 10)) diff --git a/apps/bot/src/config/keyboards.ts b/apps/bot/src/config/keyboards.ts index 18bca4d..a1277c7 100644 --- a/apps/bot/src/config/keyboards.ts +++ b/apps/bot/src/config/keyboards.ts @@ -1,6 +1,12 @@ import { env } from './env'; import { type Context } from '@/bot/context'; -import { handleAddContact, handlePro, handleShareBot, handleSubscribe } from '@/bot/handlers'; +import { + handleAddContact, + handleDocuments, + handlePro, + handleShareBot, + handleSubscribe, +} from '@/bot/handlers'; import { Menu } from '@grammyjs/menu'; import { type InlineKeyboardMarkup, @@ -50,6 +56,8 @@ export const mainMenu = new Menu('main-menu', { autoAnswer: true }) .row() .text((ctx) => ctx.t('btn-share-bot'), handleShareBot) .row() + .text((ctx) => ctx.t('btn-documents'), handleDocuments) + .row() .url( (ctx) => ctx.t('btn-open-app'), () => { diff --git a/apps/web/app/(documents)/offer/page.tsx b/apps/web/app/(documents)/offer/page.tsx new file mode 100644 index 0000000..138c692 --- /dev/null +++ b/apps/web/app/(documents)/offer/page.tsx @@ -0,0 +1,242 @@ +import { Container } from '@/components/layout'; +import { PageHeader } from '@/components/navigation'; +import { env } from '@/config/env'; + +export default function OfferPage() { + return ( + <> + + +
+

+ Договор-оферта на использование сервиса «Запишись.онлайн» (@zapishis_online_bot) +

+

+ Настоящий документ является публичной офертой в соответствии с пунктом 2 статьи 437 + Гражданского кодекса Российской Федерации и представляет собой предложение + индивидуального предпринимателя (самозанятого) — далее именуемого «Администрация», + заключить Договор на использование Сервиса (далее – «Договор», «Оферта») с любым + физическим лицом, принявшим условия настоящей Оферты (далее – «Пользователь»). +

+ +
+ +

1. Термины и определения

+
+

+ 1.1. Оферта — настоящий документ, постоянно размещенный в сети + Интернет по адресу {env.OFFER_URL}. +

+

+ 1.2. Акцепт — полное и безоговорочное принятие условий Оферты + Пользователем путем оплаты доступа через встроенный платежный бот ЮKassa в Telegram. +

+

+ 1.3. Сервис — Telegram-бот и мини-приложение, позволяющее + пользователям создавать и принимать заказы, управлять расписанием и взаимодействовать + друг с другом без необходимости регистрации. +

+

+ 1.4. Администрация — самозанятое лицо, являющееся разработчиком и + правообладателем Сервиса. +

+

+ 1.5. Пользователь — любое физическое лицо, использующее Сервис в + личных или профессиональных целях. +

+

+ 1.6. Доступ — право использования функционала Сервиса на определённый + оплаченный период (например, неделя, месяц, год). +

+

+ 1.7. Оплата — денежные средства, перечисленные Пользователем через + платёжный бот ЮKassa в Telegram. +

+
+ +
+ +

2. Акцепт оферты и заключение договора

+
+

+ 2.1. Акцептом настоящей Оферты считается оплата Пользователем доступа + к Сервису любым доступным способом. +

+

+ 2.2. С момента совершения оплаты Пользователь считается заключившим + Договор с Администрацией на условиях, изложенных в настоящей Оферте. +

+

+ 2.3. Пользователь подтверждает, что ему понятны все условия настоящей + Оферты и он принимает их без ограничений. +

+
+ +
+ +

3. Предмет договора

+
+

+ 3.1. Администрация предоставляет Пользователю неисключительное право + (доступ) на использование функционала Сервиса в пределах оплаченного периода времени. +

+

+ 3.2. Сервис предоставляется в онлайн-формате через Telegram-бота без + установки дополнительного программного обеспечения. +

+

+ 3.3. Пользователь получает право использовать функционал Сервиса в + личных целях, в том числе для организации и планирования заказов, встреч и тренировок. +

+
+ +
+ +

4. Порядок оплаты и использование

+
+

+ 4.1. Оплата производится через встроенные инструменты Telegram-бота с + использованием платёжной системы ЮKassa. +

+

+ 4.2. Комиссия платёжной системы включена в итоговую стоимость. + Администрация не взимает дополнительных платежей. +

+

+ 4.3. Доступ активируется автоматически после успешного подтверждения + оплаты. +

+

+ 4.4. Пользователь может продлить доступ путём повторной оплаты. + Автоматическое продление не применяется. +

+

+ 4.5. Возврат денежных средств возможен только в случае технических + ошибок, по письменному обращению на адрес поддержки. +

+
+ +
+ +

5. Права и обязанности сторон

+
+

+ 5.1. Пользователь обязуется: +

+
    +
  • не использовать Сервис в противоправных целях;
  • +
  • + не вмешиваться в работу Сервиса и не предпринимать действий, направленных на + нарушение его функционирования; +
  • +
  • предоставлять достоверную информацию при оплате и использовании Сервиса.
  • +
  • + при добавлении контактов других лиц (например, клиентов, мастеров) гарантировать, + что у него есть согласие этих лиц на передачу и обработку их персональных данных в + рамках Сервиса. +
  • +
+

+ 5.2. Администрация обязуется: +

+
    +
  • + обеспечивать бесперебойную работу Сервиса, за исключением периодов технического + обслуживания; +
  • +
  • + обрабатывать персональные данные Пользователей в соответствии с{' '} + Политикой конфиденциальности; +
  • +
  • принимать обращения и запросы Пользователей по вопросам работы Сервиса.
  • +
+
+ +
+ +

6. Ответственность сторон

+
+

+ 6.1. Сервис предоставляется «как есть». Администрация не несёт + ответственности за временные сбои, потерю данных или недоступность Сервиса, возникшие + по причинам, не зависящим от неё. +

+

+ 6.2. Пользователь несёт полную ответственность за корректность + совершаемых платежей и действий, совершаемых через свой Telegram-аккаунт. +

+
+ +
+ +

7. Обработка персональных данных

+
+

+ 7.1. Администрация обрабатывает персональные данные Пользователя в + соответствии с Федеральным законом №152-ФЗ «О персональных данных» и{' '} + Политикой конфиденциальности. +

+

+ 7.2. Использование Сервиса означает согласие Пользователя на + обработку его персональных данных. +

+
+ +
+ +

8. Срок действия и расторжение договора

+
+

+ 8.1. Договор вступает в силу с момента оплаты доступа и действует в + течение оплаченного периода. +

+

+ 8.2. Пользователь может прекратить использование Сервиса в любое + время без возврата оплаченных средств. +

+

+ 8.3. Администрация вправе приостановить доступ в случае нарушения + Пользователем условий настоящей Оферты. +

+
+ +
+ +

9. Заключительные положения

+
+

+ 9.1. Настоящий Договор регулируется законодательством Российской + Федерации. +

+

+ 9.2. Все споры и разногласия решаются путём переговоров, а при + недостижении соглашения — в судебном порядке по месту нахождения Администрации. +

+

+ 9.3. Администрация оставляет за собой право изменять условия Оферты с + размещением новой редакции на сайте. +

+
+ +
+ +

10. Контакты

+

+ Если у Вас есть вопросы по настоящему договору публичной оферты персональных данных, + пожалуйста, свяжитесь с Разработчиком: +

+ + +
+
+
+ + ); +} diff --git a/apps/web/app/(documents)/privacy/page.tsx b/apps/web/app/(documents)/privacy/page.tsx new file mode 100644 index 0000000..f2445ee --- /dev/null +++ b/apps/web/app/(documents)/privacy/page.tsx @@ -0,0 +1,266 @@ +import { Container } from '@/components/layout'; +import { PageHeader } from '@/components/navigation'; +import { env } from '@/config/env'; + +export default function PrivacyPolicyPage() { + return ( + <> + + +

+ Политика конфиденциальности бота / мини-приложения «Запишись.онлайн» + (@zapishis_online_bot) +

+ +

1. Термины и определения

+
    +
  1. + Telegram – Telegram Messenger Inc. (платформа, на которой работает бот + и мини-приложение). +
  2. +
  3. + Платформа – экосистема ботов и мини-приложений Telegram. +
  4. +
  5. + Разработчик – физическое лицо, самозанятый, владелец и оператор сервиса + «Запишись.онлайн» (@zapishis_online_bot) (далее — «Разработчик»). +
  6. +
  7. + Сторонний сервис – бот/мини-приложение Разработчика, предоставляемое в + Платформе. +
  8. +
  9. + Пользователь – лицо, использующее Сторонний сервис через свою учетную + запись Telegram (далее — «Вы»). +
  10. +
  11. + Политика – настоящий документ, регулирующий отношения между + Разработчиком и Пользователем в части сбора и обработки персональных данных. +
  12. +
+ +

2. Общие положения

+

+ 2.1. Настоящая Политика регулирует исключительно отношения между Разработчиком и + Пользователем. Она не заменяет и не изменяет Политику конфиденциальности Telegram:{' '} + https://telegram.org/privacy. +

+

+ 2.2. Разработчик соблюдает применимые требования платформы Telegram к конфиденциальности и + защите данных. +

+

+ 2.3. Использование Сервиса Пользователем и/или активация платного доступа означает + согласие Пользователя с условиями настоящей Политики. +

+

2.4. Если Вы не согласны с условиями Политики — прекратите использование Сервиса.

+ +

3. Отказ от ответственности

+

+ 3.1. Сторонний сервис является независимым приложением и не поддерживается, не одобряется + и не аффилирован с Telegram (за исключением использования API и инфраструктуры Telegram). +

+

+ 3.2. Разработчик вправе изменять настоящую Политику — изменения вступают в силу с момента + их публикации. Вы обязаны самостоятельно отслеживать обновления. +

+

+ 3.3. Используя Сервис, Вы подтверждаете, что ознакомлены и согласны с условиями + использования Telegram для ботов и мини-приложений:{' '} + https://telegram.org/tos/bots,{' '} + https://telegram.org/tos/mini-apps. +

+

+ 3.4. Вы гарантируете, что используете Сервис в соответствии с действующим + законодательством и обладаете правом взаимодействовать с ним (например, достигли возраста, + необходимого для использования услуг). +

+

+ 3.5. Вы обязуетесь предоставлять точную и актуальную информацию, если Сервис запрашивает + её. +

+

+ 3.6. Любая информация, которую Вы делаете общедоступной самостоятельно (через профиль + Telegram, публичные сообщения и т.п.), может стать доступна другим пользователям и не + подпадает под защиту настоящей Политики в части конфиденциальности этой общедоступной + информации. +

+ +

4. Сбор персональных данных

+

+ 4.1. Telegram по умолчанию предоставляет сторонним сервисам ограниченный набор данных о + Пользователе — подробнее:{' '} + + https://telegram.org/privacy#6-bot-messages + + . +

+

+ 4.2. Сторонний сервис может дополнительно получать данные, которые Вы передаёте в чате + бота или в мини-приложении (например, контакт, телефон), если Вы явно их отправляете. +

+

+ 4.3. В случае мини-приложения дополнительно могут передаваться данные в соответствии с + правилами мини-приложений Telegram:{' '} + + https://telegram.org/tos/mini-apps#4-privacy + + . +

+

+ 4.4. Сторонний сервис может собирать также анонимную статистику использования + (диагностика, события взаимодействия), не связываемую напрямую с персоной. +

+

+ 4.5. Пользователь может передавать данные третьих лиц (например, контактные данные + клиентов или мастеров) для использования в Сервисе. При этом пользователь гарантирует, что + эти лица дали согласие на обработку их персональных данных в рамках Сервиса. +

+ +

5. Какие данные мы собираем и как используем

+

+ 5.1. Разработчик запрашивает, собирает и обрабатывает только те данные, которые необходимы + для корректной работы функций Сервиса, в частности: +

+
    +
  • Telegram ID и (опционально) отображаемое имя пользователя;
  • +
  • телефон, только если Вы предоставили его добровольно (например, при регистрации);
  • +
  • данные о заказах: дата/время, описание заказа, статус;
  • +
  • + информация о факте покупки Pro-доступа: период доступа, тип покупки (детали платёжной + транзакции обрабатывает платёжный оператор — ЮKassa). +
  • +
+

5.2. Цели обработки:

+
    +
  • + предоставление и поддержка работы Сервиса (создание заказов, напоминания, управление + доступом); +
  • +
  • + подтверждение и учет оплат (взаимодействие с платёжным оператором для актуализации + статуса доступа); +
  • +
  • + реализация реферальной программы (хранение связей «кто пригласил/кого пригласили»); +
  • +
  • анализ использования и улучшение сервиса;
  • +
  • выполнение юридических обязательств (хранение информации о транзакциях и др.).
  • +
+

+ Важно: детальные платёжные данные (реквизиты карт и т.д.) не хранятся у Разработчика — их + обрабатывает платёжный оператор (ЮKassa) и Telegram-платежный бот. +

+ +

6. Передача данных третьим лицам

+

+ 6.1. Разработчик не передаёт персональные данные третьим лицам, за исключением следующих + случаев: +

+
    +
  • платёжному оператору (ЮKassa) и связанным службам для обработки платежей;
  • +
  • Telegram как платформе для функционирования бота и мини-приложения;
  • +
  • + в случае необходимости — исполнителям, оказывающим техническую поддержку, при условии + подписания ими обязательств о конфиденциальности; +
  • +
  • если передача требуется по закону (запросы уполномоченных органов и т.п.).
  • +
+

+ 6.2. Разработчик не продаёт и не передаёт персональные данные для рекламных целей третьим + лицам без Вашего отдельного согласия. +

+ +

7. Защита и хранение данных

+

+ 7.1. Разработчик применяет разумные технические и организационные меры для защиты + персональных данных (использование надежного VPS, ограничения доступа, резервное + копирование и т.п.). +

+

+ 7.2. Доступ к персональным данным имеет только Разработчик (и/или доверенные исполнители + технической поддержки при необходимости). +

+

+ 7.3. Данные хранятся на серверах, указанных Разработчиком. Если используются внешние + сервисы/облачные хранилища — это будет указано в соответствующих местах Политики или + сообщения при сборе данных. +

+ +

8. Права и обязанности сторон

+

8.1. Права Разработчика:

+
    +
  • вносить изменения в Политику с публикацией новой версии;
  • +
  • ограничивать доступ к API/сервису при подозрении в злоупотреблениях;
  • +
  • + запросить подтверждение личности при необходимости обработки привилегированных запросов. +
  • +
+

8.2. Обязанности Разработчика:

+
    +
  • обеспечивать доступность Политики и исполнять её условия;
  • +
  • + обрабатывать законные запросы пользователей о доступе, изменении или удалении данных в + разумные сроки (не позднее 30 дней, если иное не установлено законом); +
  • +
  • соблюдать применимое законодательство о защите персональных данных.
  • +
+

8.3. Права Пользователя:

+
    +
  • запросить копию своих персональных данных, хранящихся у Разработчика;
  • +
  • потребовать исправления неточных данных;
  • +
  • + потребовать удаления персональных данных в пределах, допустимых законом (с сохранением + данных, необходимых для выполнения юридических обязательств, например, по учёту + платежей); +
  • +
  • + отозвать согласие на обработку персональных данных, если такое согласие предоставлялось + добровольно; +
  • +
  • + подать жалобу в уполномоченные органы по защите персональных данных, если считает, что + его права нарушены. +
  • +
+

8.4. Обязанности Пользователя:

+
    +
  • предоставлять точную и актуальную информацию;
  • +
  • не использовать Сервис в нарушении законодательства и условий Telegram.
  • +
+ +

9. Реклама и использование данных для аналитики

+

+ 9.1. На текущем этапе Разработчик не использует персональные данные для демонстрации + таргетированной рекламы третьих лиц без явного согласия Пользователя. +

+

+ 9.2. Разработчик может собирать агрегированную (анонимную) статистику использования + Сервиса для улучшения функционала. +

+ +

10. Изменения Политики

+

+ 10.1. Разработчик вправе вносить изменения в настоящую Политику. Все изменения публикуются + на этой странице и вступают в силу с момента публикации. +

+ +

11. Контакты

+

+ Если у Вас есть вопросы по Политике конфиденциальности или запросы в отношении + персональных данных, пожалуйста, свяжитесь с Разработчиком: +

+ + +
+ + + ); +} diff --git a/apps/web/config/env.ts b/apps/web/config/env.ts index d9cf351..f9c8b87 100644 --- a/apps/web/config/env.ts +++ b/apps/web/config/env.ts @@ -4,6 +4,8 @@ import { z } from 'zod'; export const envSchema = z.object({ __DEV_TELEGRAM_ID: z.string().default(''), BOT_URL: z.string(), + OFFER_URL: z.string(), + SUPPORT_TELEGRAM_URL: z.string(), }); export const env = envSchema.parse(process.env); diff --git a/apps/web/middleware.ts b/apps/web/middleware.ts index a7f5f1d..59de87e 100644 --- a/apps/web/middleware.ts +++ b/apps/web/middleware.ts @@ -11,5 +11,7 @@ export default withAuth({ }); export const config = { - matcher: ['/((?!auth|browser|telegram|unregistered|api|_next/static|_next/image|favicon.ico).*)'], + matcher: [ + '/((?!auth|browser|telegram|unregistered|privacy|public-offer|api|_next/static|_next/image|favicon.ico).*)', + ], }; diff --git a/turbo.json b/turbo.json index d430a15..8fa4a4f 100644 --- a/turbo.json +++ b/turbo.json @@ -13,10 +13,13 @@ "BOT_TOKEN", "NEXTAUTH_SECRET", "BOT_URL", + "SUPPORT_TELEGRAM_URL", "BOT_PROVIDER_TOKEN", "REDIS_HOST", "REDIS_PORT", - "REDIS_PASSWORD" + "REDIS_PASSWORD", + "OFFER_URL", + "PRIVACY_URL" ] }, "lint": {