Skip to content

BotStartedUpdate теряет поле payload (deep-link аргумент команды /start) #29

@IlyaUhlianitsa

Description

@IlyaUhlianitsa

Проблема

Когда пользователь стартует бота по диплинку (/start <arg> или https://max.ru/<bot>?start=<arg>), в событии bot_started приходит поле payload — аргумент диплинка. SDK его теряет: после десериализации этот аргумент недоступен, и реферальные/онбординговые сценарии ломаются.

Корневая причина

Класс BotStartedUpdate содержит только UpdateId, Timestamp, ChatId, User, UserLocale. Поле Payload отсутствует. Корневой Update тоже не имеет этого свойства, поэтому фабрика Update.BotStartedUpdate физически не может его пробросить:

return new BotStartedUpdate
{
    UpdateId = UpdateId,
    Timestamp = Timestamp,
    ChatId = ChatId,
    User = User,
    UserLocale = UserLocale
    // payload теряется
};

Реальный формат API

Захваченный через runtime debugger ответ /updates:

{
  "update_type": "bot_started",
  "timestamp": 1730000000000,
  "chat_id": 12345,
  "user": { "user_id": 67890, "name": "...", "is_bot": false },
  "payload": "ref-abc123",
  "user_locale": "ru"
}

Официальный Go SDK от команды Max — max-messenger/max-bot-api-client-go — описывает событие так:

type BotStarted struct {
    Update
    ChatID     int64  `json:"chat_id"`
    User       User   `json:"user"`
    Payload    string `json:"payload,omitempty"`
    UserLocale string `json:"user_locale,omitempty"`
}

Шаги воспроизведения

  1. Получить ссылку на бота c диплинк-параметром: https://max.ru/<bot_username>?start=ref-abc123.
  2. Открыть её в Max-клиенте, нажать «Запустить».
  3. В обработчике BotStartedUpdate попытаться прочитать аргумент диплинка — поля для него нет, значение недоступно.

Предлагаемое исправление

  1. Добавить свойство Payload (string?, [JsonPropertyName("payload")]) в BotStartedUpdate.
  2. Добавить теневое поле Payload в Update (по аналогии с тем, как там сейчас живут ChatId, Timestamp, User, UserLocale) и пробросить его в фабрике Update.BotStartedUpdate.

Workaround

Сейчас приходится перехватывать сырой JSON /updates через DelegatingHandler и вытягивать payload по (timestamp, chat_id), чтобы передать его в обработчик после парсинга SDK.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions