> ## Documentation Index
> Fetch the complete documentation index at: https://veriqa.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Номер телефона

> Как Veriqa получает номер телефона пользователя в каждом канале: механизм, доказана ли принадлежность номера, что ограничивает платформа и какая часть работы — Veriqa, а какая — ваша.

Номер телефона Veriqa берёт **только из канала**: его передаёт мессенджер, пользователь его не
вводит. Поля телефона на странице входа нет, а номер, набранный в чате сообщением, не принимается.
Ваше приложение получает его стандартным claim `phone_number` в формате E.164, рядом с
`phone_number_verified`.

## Когда Veriqa запрашивает номер

Veriqa спрашивает, только если номер нужен вашему приложению, а канал его ещё не дал. Нужность —
это уровень требования claim `phone_number`:

| Уровень | Откуда берётся |
| - | - |
| `Required` | `RequirePhone` или `Level: Required` в [`Veriqa:ScopesClaims`](/docs/ru/reference/configuration#veriqascopesclaims), `RequirePhone` или `ClaimLevels` [записи клиента](/docs/ru/reference/configuration#clients) либо `essential: true` у `phone_number` в параметре `claims` запроса |
| `Optional` | `Level: Optional` либо `phone_number` в параметре `claims` запроса без `essential` |
| `IfAvailable` (по умолчанию) | ничего не спрашивается: номер выдаётся, только если канал дал его сам |

Требование действует, только если вход запрашивает scope `phone`. При `Required` окно входа
предлагает только каналы, способные дать номер; если таких не осталось, `/connect/authorize`
отвечает `400 no_channel_for_required_phone` ([разбор проблем](/docs/ru/guides/troubleshooting)).

Запрос приходит, когда пользователь подтвердил вход — в чате или кнопкой «Да» на странице
подтверждения в браузере. Бот отправляет его в тот чат, из которого пользователь входил: короткий
текст, кнопку, которая делится номером, и вторую кнопку, смысл которой зависит от уровня. Тексты
показываются на языке пользователя.

| Уровень | Вторая кнопка | Нет ответа |
| - | - | - |
| `Optional` | **Пропустить** — вход продолжается без номера | шаг пропускается, когда истекает окно `ClaimCompletion.PhoneOptionalWindow` |
| `Required` | **Отменить вход** — вход не состоялся, ваше приложение получает `error=access_denied` | транзакция ждёт до истечения: ни одна платформа не сообщает боту, что пользователь отказался делиться |

Окно по умолчанию — 60 секунд. Меняется ключом `Veriqa:ClaimCompletion:PhoneOptionalWindow`, а для
одного приложения — членом `ClaimCompletionPhoneOptionalWindow` его записи клиента (см.
[ключи в каталоге объявлений](/docs/ru/reference/configuration#ключи-в-каталоге-объявлений)). Окно не
заходит за срок транзакции: шаг пропускается не позже чем за 5 секунд до её истечения.

Если присланный номер завершает вход, в чате появляется обычная квитанция подтверждённого входа;
**Отменить вход** показывает квитанцию отклонённого.

## Что получает ваше приложение

* `phone_number` — в E.164: `+` и цифры. Номер, который не приводится к E.164, считается
  отсутствующим: он не выдаётся, а шаг ждёт так, будто пользователь не ответил.
* `phone_number_verified` — JSON boolean: `true`, только если канал доказал, что номер принадлежит
  отправившему его пользователю, иначе `false`.
* Оба claim выходят только под выданным scope `phone`.

Контакт, не прошедший проверку принадлежности в канале, — чужая карточка контакта, пересланный
контакт, отсутствующая или неверная подпись — не принимается, и бот спрашивает снова. Запрос,
который не удалось доставить в чат и после повторов, ничего не меняет: шаг ждёт так же, как без
ответа.

## По каналам

«Кто» — чей код получает номер: адаптер канала Veriqa или ваша собственная интеграция с
платформой. Для каналов, адаптера которых ещё нет в поставке, указано, что позволяет API платформы.

| Канал | Как получить номер | Принадлежность доказана | Кто | Официальные источники |
| - | - | - | - | - |
| MAX | кнопка `request_contact`; номер приходит в `vcf_info` контакта. **Только в режиме вебхука** | да — `hash` контакта совпадает с HMAC-SHA256 от `vcf_info` на токене бота | Veriqa | [клавиатура](https://dev.max.ru/docs-api/use-cases/sending-messages/keyboard), [вложения](https://dev.max.ru/docs-api/use-cases/sending-messages/another-attachments) |
| Telegram | кнопка `request_contact` reply-клавиатуры; только личные чаты | да — `user_id` контакта совпадает с отправителем, и сообщение не переслано | Veriqa | [Bot API: KeyboardButton](https://core.telegram.org/bots/api#keyboardbutton), [Log In With Telegram](https://core.telegram.org/bots/telegram-login) |
| WhatsApp | автоматически — номер отправителя (`from` / `wa_id`) в каждом сообщении; без него — интерактивное сообщение `request_contact_info` | да — номер из самого сообщения или контакт, отправленный по запросу (`origin = contact_request`) | Veriqa | [Business-scoped user IDs](https://developers.facebook.com/documentation/business-messaging/whatsapp/business-scoped-user-ids/) |
| BiP | автоматически — MSISDN абонента, если Turkcell разрешил сервису открытые номера (`receiver.type = 2`) | да — номер и есть аккаунт | Veriqa, когда выйдет адаптер | [отправка](https://bip.com/tr/gelistiriciler/kesfet-api/mesaj-gonderme/servisler/kullanici-bazli-mesaj-gonderimi/), [подписчики](https://bip.com/tr/gelistiriciler/kesfet-api/abone-islemleri/) |
| Viber | кнопка `share-phone` (API 3 и новее) | нет | Veriqa, когда выйдет адаптер | [клавиатуры](https://developers.viber.com/docs/tools/keyboards/) |
| Messenger | quick reply `user_phone_number` — номер из профиля пользователя | нет | Veriqa, когда выйдет адаптер | [quick replies](https://developers.facebook.com/docs/messenger-platform/send-messages/quick-replies) |
| Instagram Direct | quick reply `user_phone_number` | нет | Veriqa, когда выйдет адаптер | [quick replies](https://developers.facebook.com/documentation/business-messaging/instagram-messaging/features/quick-replies) |
| Slack | поле профиля `profile.phone`, произвольный текст | нет; значение не в E.164 не выдаётся | Veriqa, когда выйдет адаптер | [users.info](https://docs.slack.dev/reference/methods/users.info) |
| Microsoft Teams | Microsoft Graph `mobilePhone`, право `User.Read.All` с согласием администратора | нет | Veriqa, когда выйдет адаптер | [Graph user](https://learn.microsoft.com/en-us/graph/api/resources/user) |
| LINE | только LINE Login или LIFF со scope `phone` (LINE Profile+, юрлица Японии, по заявке) | — | вы | [LINE Profile+](https://developers.line.biz/en/docs/partner-docs/line-profile-plus/) |
| KakaoTalk | Kakao Login или Kakao Sync, пункт согласия `phone_number`, Biz App и одобрение | — | вы | [Kakao Login](https://developers.kakao.com/docs/en/kakaologin/utilize) |
| WeChat | мини-программа `getPhoneNumber`, верифицированное юрлицо, платно | — | вы | [getPhoneNumber](https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html) |
| Zalo | мини-приложение `getPhoneNumber` плюс серверный обмен токена | — | вы | [getPhoneNumber](https://docs.zaloplatforms.com/docs/MA/api/user/user-information/getPhoneNumber) |
| Discord | нет | — | — | [User](https://docs.discord.com/developers/resources/user) |
| Threema | нет | — | — | [Threema Gateway](https://gateway.threema.ch/en/developer/api) |
| Email | нет | — | — | — |

### MAX

Бот отправляет кнопку «поделиться номером» и callback-кнопку со вторым действием. Номер берётся из
`vcf_info`, только если совпала подпись `hash` контакта — она вычисляется на токене бота того
тенанта, который получил контакт.

Номер телефона запрашивается **только в режиме вебхука**. При `UpdateMode: Polling` адаптер MAX
телефон не объявляет и ничего не спрашивает: подпись читается из сырого тела вебхука, которого у
polling нет, поэтому каждый контакт был бы отклонён. `Required` номер в этом режиме исключает MAX
из окна входа.

### Telegram

Бот отправляет reply-клавиатуру: сверху кнопка «поделиться номером», под ней вторая кнопка; после
нажатия клавиатура скрывается. Veriqa принимает только собственный контакт пользователя: `user_id`
контакта должен совпадать с отправителем, а пересланный контакт или карточка из записной книжки
отклоняются.

Вход на сайт через Telegram ([Log In With Telegram](https://core.telegram.org/bots/telegram-login))
тоже умеет отдавать номер — это ваша собственная интеграция с Telegram, вне Veriqa.

<Warning>
  Если апдейты бота раздаёте вы сами — один бот на ваш код и Veriqa, и ваш код решает, какой апдейт
  отдать Veriqa, через `OwnsInboundEvent` (см.
  [телефон по запросу](/docs/ru/guides/custom-channel-adapter#телефон-по-запросу)), — кнопки
  **Пропустить** и **Отменить вход** уходят вашему боту, а не Veriqa: в Telegram это обычные
  текстовые кнопки без маркера, по которому их можно узнать. Сам присланный контакт узнаётся. `Optional` номер тогда
  пропускается по окну, а `Required` ждёт до истечения транзакции.
</Warning>

### WhatsApp

Сегодня номер приходит с каждым сообщением: WhatsApp узнаёт пользователя по номеру телефона, поэтому
токен несёт `phone_number` с `phone_number_verified: true`, и ничего не спрашивается.

Запрос нужен для пользователей, которых WhatsApp адресует без номера (business-scoped user IDs):
интерактивное сообщение `request_contact_info`, а следом отдельное сообщение со второй кнопкой —
своих кнопок у запроса нет. Карточка контакта, отправленная пользователем вручную
(`origin = other`), отклоняется. Запрос отправляет поставляемый провайдер Meta Cloud API;
собственный провайдер WhatsApp (`IWhatsAppProvider`) отправляет его, только если реализует
`SendContactRequestAsync`, — иначе запрос не доставляется, и шаг ждёт так же, как без ответа.

### LINE, KakaoTalk, WeChat и Zalo — ваша интеграция

Эти платформы отдают номер телефона только своему входу или мини-приложению, которые регистрируете
вы и одобряет платформа, — не боту. Veriqa номер там не получает. Если вашему приложению он нужен от
этих пользователей, получите его своим кодом через вход платформы и храните у себя.

### Discord и Threema

Ни одна из платформ не отдаёт боту номер телефона пользователя.

## Ограничения

* Окно `Optional` номера держится в памяти того экземпляра, который отправил запрос. Если
  экземпляр остановился раньше, чем окно истекло, шаг не пропускается, и транзакция ждёт до
  истечения.
* Запись, связывающая чат с ожидающим запросом, по умолчанию in-process. При нескольких репликах
  перенесите её в Redis вместе с остальными канальными хранилищами
  ([канальные хранилища](/docs/ru/guides/storage#канальные-хранилища-несколько-реплик)) — иначе номер,
  пришедший на другую реплику, запроса не найдёт.
* Когда в одном чате номера ждут два входа, номер достаётся тому, чей запрос пришёл последним;
  второй ждёт своего окна или истечения.
* Кнопки запроса остаются в чате, если шаг закончился без нажатия — истекло окно `Optional`
  номера, истёк вход. Veriqa их не убирает: в Telegram клавиатура остаётся под полем ввода, пока
  пользователь не нажмёт одну из её кнопок. Номер, отправленный из неё после этого, ожидающего
  запроса не находит и не принимается, бот на него не отвечает; нажатие второй кнопки тогда —
  обычное сообщение боту.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.