【问题标题】:Initiate a message from bot to user on BotFramework在 BotFramework 上从 bot 向用户发送消息
【发布时间】:2017-03-16 17:11:23
【问题描述】:

我有一个基于 BotFramework 3.5 构建并作为 WebApp 托管在 Azure 上的机器人。在实现机器人需要响应用户输入的场景时,我没有遇到任何问题。然而,有必要教他按某个时间表开始对话。 为了达到这个目标,我创建了一个 WebJob,它基本上是一个简单的控制台应用程序。这是用于从机器人向用户发起消息的代码:

            var botAccount = new ChannelAccount(id: from);
            var userAccount = new ChannelAccount(id: to);
            var conversation = new ConversationAccount(false, conversationId);

            var connector = new ConnectorClient(serviceUrl);

            IMessageActivity message = Activity.CreateMessageActivity();
            message.From = botAccount;
            message.Recipient = userAccount;
            message.Conversation = conversation;
            message.Text = text;
            message.Locale = locale;
            await connector.Conversations.SendToConversationAsync((Activity)message);

from, to, serviceUrl, conversationId - 取自之前的对话,所以我希望它们是有效的。但是在SendToConversationAsync 上抛出异常:

System.UnauthorizedAccessException: Authorization for Microsoft App ID 3a26a4d4-f75a-4feb-b3e0-37a7fa24e5fc failed with status code Unauthorized and reason phrase 'Unauthorized' ---> System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized)

app.config 文件包含与原始机器人 API 相同的值,包括 AppId 和 AppSecret。我看到了一些关于同一主题的问题,但没有找到答案。

我错过了什么吗?从控制台应用程序代表机器人发送消息是一种有效的方法吗?

【问题讨论】:

  • 你的webapp是否使用认证、授权?
  • 它使用 web.config 中定义的 3 个身份验证参数(AppId、AppPassword 和 BotId)。将相同的值注入控制台应用程序
  • 你能发布配置身份验证的webapp的代码吗?你如何对 webapp 进行身份验证?你在发送令牌吗?

标签: c# .net botframework azure-webjobs


【解决方案1】:

根据您的描述,我按照此tutorial 开始使用连接器,并按照此tutorial 发送和接收活动。

根据你的代码,我创建了我的控制台应用程序,我可以重现同样的问题,然后我找到了一个关于类似问题的 git issue。经过一些试验,我可以让它按我的预期工作,你可以参考它:

MicrosoftAppCredentials.TrustServiceUrl("{ServiceUrl}", DateTime.Now.AddDays(7));
var account=new MicrosoftAppCredentials("MicrosoftAppIdKey", "MicrosoftAppPasswordKey");
var connector = new ConnectorClient(new Uri("{ServiceUrl}"),account);

或

实现你的 DelegatingHandler

public class MyDelegatingHandler : DelegatingHandler
{
    private string _token;
    public MyDelegatingHandler(string token)
    {
        _token = token;
    }

    protected override Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _token);
        return base.SendAsync(request, cancellationToken);
    }
}

然后,您需要按如下方式构建您的ConnectorClient:

var account=new MicrosoftAppCredentials("{MicrosoftAppIdKey}", "{MicrosoftAppPasswordKey}");
var jwtToken=await account.GetTokenAsync();
var connector = new ConnectorClient(new Uri("{serviceUrl}"),handlers:new MyDelegatingHandler(jwtToken));

这是我的控制台应用代码sn-p,你可以参考一下:

try
{
    var userAccount = new ChannelAccount() { Id = "default-user", Name = "user" };
    var botAccount = new ChannelAccount() { Id = "934493jn5f6f348f", Name = "console-Bot" };
    string url = "{serviceUrl}";

    MicrosoftAppCredentials.TrustServiceUrl(url, DateTime.Now.AddDays(7));
    var account = new MicrosoftAppCredentials("{MicrosoftAppIdKey}", "{MicrosoftAppPasswordKey}");
    var connector = new ConnectorClient(new Uri(url), account);

    IMessageActivity message = Activity.CreateMessageActivity();
    message.From = botAccount;
    message.Recipient = userAccount;
    message.Conversation = new ConversationAccount() { Id = "{conversationId}" };
    message.Text = "Message sent from console application!!!";
    message.Locale = "en-us";
    var response = await connector.Conversations.SendToConversationAsync((Activity)message);
    Console.WriteLine($"response:{response.Id}");
}
catch (Exception e)
{
    Console.WriteLine($"exception:{e.Message}\r\n{e.StackTrace}");
}

结果

【讨论】:

  • 您的帖子帮助我在发送主动消息时克服了身份验证问题,非常感谢您。但是我发现可以注释掉您在上面发布的两行 JWT 访问令牌代码,重新启动我的测试服务器应用程序并在发送主动消息时仍然成功验证。
  • 不能支持这个!
  • 超级!! ..这很棒..但是想知道如果另一个机器人而不是控制台应用程序以及所有用户和频道详细信息尝试向用户发送消息,同样的事情会起作用吗?(使用 MicrosoftAppIdKey 和它自己的秘密)?。
  • 优秀的答案!
  • 调用MicrosoftAppCredentials.TrustServiceUrl 会开始新的 7 天到期还是继续现有的到期?谢谢
【解决方案2】:

尝试像这样创建一个新对话:

var conversationId = await connector.Conversations.CreateDirectConversationAsync(botAccount, userAccount);

【讨论】:

  • 我确实做到了。它不起作用。显然错误与创建对话的方式无关
猜你喜欢
  • 1970-01-01
  • 2018-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-10
  • 1970-01-01
  • 2017-10-18
相关资源
最近更新 更多