You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C#实现Telegram Bot通过Webhook处理问答(含/userinfo示例)

用C#开发Telegram Bot(Webhook模式)实现问答流程

我来一步步带你搞定这个需求——用C#做一个Telegram Bot,通过Webhook接收消息,当用户发/userinfo时,依次询问名字、姓氏,最后汇总信息。

准备工作

先搞定几个前置条件:

  • 去Telegram的BotFather那里创建一个Bot,拿到专属的API Token(这个是核心,别随便泄露)。
  • 要有一个公网可访问的HTTPS地址,因为Telegram的Webhook只支持HTTPS。本地开发的话,可以用ngrok把本地端口转发成公网HTTPS地址,比如执行ngrok http 5000就能生成临时地址。
  • 创建一个ASP.NET Core Web API项目(Webhook需要一个HTTP端点来接收Telegram的请求)。

安装依赖

在你的项目里安装官方的Telegram Bot NuGet包:

Install-Package Telegram.Bot

或者用.NET CLI命令:

dotnet add package Telegram.Bot

配置Webhook和Bot客户端

首先在appsettings.json里添加你的Bot Token:

{
  "TelegramBotToken": "你的BotToken这里填"
}

然后在Program.cs里配置Telegram Bot客户端,把它注册成服务:

var builder = WebApplication.CreateBuilder(args);

// 注册Telegram Bot客户端
var botToken = builder.Configuration["TelegramBotToken"];
builder.Services.AddHttpClient<TelegramBotClient>(client =>
{
    client.BaseAddress = new Uri($"https://api.telegram.org/bot{botToken}/");
});

builder.Services.AddControllers();

var app = builder.Build();

// 启动后自动设置Webhook(替换成你的公网HTTPS地址+webhook端点)
using (var scope = app.Services.CreateScope())
{
    var botClient = scope.ServiceProvider.GetRequiredService<TelegramBotClient>();
    var webhookUrl = new Uri("https://你的ngrok地址/webhook"); 
    await botClient.SetWebhookAsync(webhookUrl);
}

app.MapControllers();
app.Run();

核心:状态管理(跟踪用户问答步骤)

要记住每个用户当前处于哪个提问环节,咱们得用线程安全的存储结构。这里用ConcurrentDictionary来存用户的状态和输入的数据:

先定义一个枚举表示用户当前的步骤:

public enum UserInfoStep
{
    Start, // 初始状态
    WaitingForFirstName, // 等待用户输入名字
    WaitingForLastName // 等待用户输入姓氏
}

再定义一个存储用户信息的模型:

public class UserInfo
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

然后在控制器里声明两个静态的ConcurrentDictionary:

private static readonly ConcurrentDictionary<long, UserInfoStep> _userSteps = new();
private static readonly ConcurrentDictionary<long, UserInfo> _userData = new();

实现Webhook端点和消息处理

创建一个TelegramBotController,添加Webhook的POST端点,处理Telegram发来的消息更新:

[ApiController]
[Route("[controller]")]
public class TelegramBotController : ControllerBase
{
    private readonly TelegramBotClient _botClient;

    public TelegramBotController(TelegramBotClient botClient)
    {
        _botClient = botClient;
    }

    [HttpPost("webhook")]
    public async Task<IActionResult> Post([FromBody] Update update)
    {
        if (update.Message == null) return Ok();

        var chatId = update.Message.Chat.Id;
        var messageText = update.Message.Text;

        // 获取用户当前状态,默认是初始状态
        _userSteps.TryGetValue(chatId, out var currentStep);

        switch (currentStep)
        {
            case UserInfoStep.Start:
                await HandleStartCommand(chatId, messageText);
                break;
            case UserInfoStep.WaitingForFirstName:
                await HandleFirstNameInput(chatId, messageText);
                break;
            case UserInfoStep.WaitingForLastName:
                await HandleLastNameInput(chatId, messageText);
                break;
        }

        return Ok();
    }

    private async Task HandleStartCommand(long chatId, string messageText)
    {
        if (messageText.Equals("/userinfo", StringComparison.OrdinalIgnoreCase))
        {
            // 发送第一个问题
            await _botClient.SendTextMessageAsync(chatId, "你的名字?");
            // 更新用户状态为等待名字输入
            _userSteps[chatId] = UserInfoStep.WaitingForFirstName;
            // 初始化用户数据存储
            _userData[chatId] = new UserInfo();
        }
        else
        {
            // 提示用户输入正确命令
            await _botClient.SendTextMessageAsync(chatId, "请发送 /userinfo 命令开始填写信息~");
        }
    }

    private async Task HandleFirstNameInput(long chatId, string firstName)
    {
        // 保存用户输入的名字
        _userData[chatId].FirstName = firstName;
        // 发送第二个问题
        await _botClient.SendTextMessageAsync(chatId, "你的姓氏?");
        // 更新状态为等待姓氏输入
        _userSteps[chatId] = UserInfoStep.WaitingForLastName;
    }

    private async Task HandleLastNameInput(long chatId, string lastName)
    {
        // 保存用户输入的姓氏
        _userData[chatId].LastName = lastName;
        // 汇总信息回复用户
        var userInfo = _userData[chatId];
        await _botClient.SendTextMessageAsync(chatId, $"已收到你的信息:\n名字:{userInfo.FirstName}\n姓氏:{userInfo.LastName}");
        
        // 重置用户状态和数据,准备下一次交互
        _userSteps.TryRemove(chatId, out _);
        _userData.TryRemove(chatId, out _);
    }
}

测试流程

  1. 启动你的ASP.NET Core项目,默认端口一般是5000。
  2. 用ngrok转发端口:执行ngrok http 5000,拿到类似https://xxxx-xx-xx-xx-xx.ngrok.io的临时公网地址。
  3. 设置Webhook:在浏览器里访问https://api.telegram.org/bot<你的BotToken>/setWebhook?url=https://xxxx-xx-xx-xx-xx.ngrok.io/telegrambot/webhook(替换成你的Token和ngrok地址)。
  4. 打开Telegram,给你的Bot发/userinfo,然后按照提示回复名字和姓氏,就能看到汇总信息啦!

注意事项

  • 线程安全:因为Web API是多线程的,必须用ConcurrentDictionary来存用户状态和数据,避免并发冲突。
  • 持久化:如果Bot重启后不想丢失用户的未完成状态,可以把状态和数据存到数据库(比如SQLite、Redis),而不是内存里的字典。
  • 异常处理:可以在代码里添加try-catch块,处理Telegram API调用失败的情况,比如网络波动问题。

内容的提问来源于stack exchange,提问作者probaumak _

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:17:58