BOT Framework Проактивное сообщение не работает - PullRequest
0 голосов
/ 17 июня 2019

Я работаю над проактивным сообщением для BOT, размещенного в IIS и зарегистрированного в Azure как BOT канала регистрации BOT.

Я получаю ошибку ниже,

Сообщение: операция вернула недопустимый код состояния «Не авторизован».

StackTrace: в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (Task задача) в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task задача) в Microsoft.Bot.Connector.ConversationsExtensions.d__17.MoveNext ()

Код приведен ниже,

- Notify.cs

public class Notify
    {
        private readonly IBotFrameworkHttpAdapter _adapter;
        private readonly string _appId;
        private readonly ConcurrentDictionary<string, ConversationReference> _conversationReferences;

        public Notify(IBotFrameworkHttpAdapter adapter, string appId, ConcurrentDictionary<string, ConversationReference> conversationReferences)
        {
            _adapter = adapter;
            _appId = appId;
            _conversationReferences = conversationReferences;
         }

        public async Task<IActionResult> Get()
        {
            try
            {
                foreach (var conversationReference in _conversationReferences.Values)
                {
                    await ((BotAdapter)_adapter).ContinueConversationAsync(_appId, conversationReference, BotCallback, default(CancellationToken));
                }

                // Let the caller know proactive messages have been sent
                return new ContentResult()
                {
                    Content = "<html><body><h1>Proactive messages have been sent.</h1></body></html>",
                    ContentType = "text/html",
                    StatusCode = (int)HttpStatusCode.OK,
                };
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        private async Task BotCallback(ITurnContext turnContext, CancellationToken cancellationToken)
        {
            await turnContext.SendActivityAsync("proactive hello");
        }
    }

Редактировать 1:

Я пытаюсь отправить проактивное сообщение боту, отображаемому в значок системного Мы создали приложение для Windows, с помощью которого мы отправляем уведомления Windows пользователям. Когда пользователь нажимает на уведомление открывает бот, присутствующий в значке в системном трее, и он должен отобразить то же сообщение с уведомлением о сообщении в BOT, что и проактивное сообщение.

Мы используем API прямой линии для создания ссылки на разговор. Мы проходят ту же ссылку на разговор и используют ContinueConversationAsync BotApadater для заполнения того же сообщения с открытого бота. Весь код form.cs и Notify.cs возвращается в приложении Windows, а бот размещается на IIS и регистрируется в Azure как БОТ Канал регистрации БОТ.

В настоящее время мы не получаем несанкционированную ошибку и код выполнено успешно, но мы не получаем активного сообщения от бота. Для открытия бота мы используем iframe URL в приложении Windows.

Пожалуйста, помогите мне понять, что я делаю не так, или предложите другие способы.

Окно systray приложения Form.cs Метод

using (HttpClient httpClient = new HttpClient())
            {
                httpClient.BaseAddress = new Uri("https://directline.botframework.com/api/tokens");
                httpClient.DefaultRequestHeaders.Accept.Clear();
                //httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("BotConnector", "Directline secret");     
                HttpResponseMessage response = httpClient.GetAsync(httpClient.BaseAddress).Result;


                if (response.IsSuccessStatusCode)
                {
                    var jsonString = response.Content.ReadAsStringAsync();
                    var token = jsonString.Result;
                    var finaltoken = token.Replace(@"\", string.Empty);
                    finaltoken = finaltoken.Replace('"', ' ').Trim();

                    HttpClient client = new HttpClient();
                    client.BaseAddress = new Uri("https://directline.botframework.com/v3/directline/conversations");
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(finaltoken);
                    var httptokenResponse = httpClient.PostAsync("/api/conversations/", new StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json"));
                    var tokenResponse = httptokenResponse.Result;
                    string convId = string.Empty;
                    string activityId = string.Empty;
                    HttpClient finalclient = new HttpClient();
                    Microsoft.Bot.Schema.Activity act = new Microsoft.Bot.Schema.Activity();
                    ConversationReference convRef = new ConversationReference();
                    if (tokenResponse.IsSuccessStatusCode)
                    {
                        var tokenjsonString = tokenResponse.Content.ReadAsStringAsync().Result;
                        var conversationToken = Newtonsoft.Json.JsonConvert.DeserializeObject<Conversation>(tokenjsonString.ToString());

                        HttpClient lastclient = new HttpClient();
                        lastclient.BaseAddress = new Uri("https://directline.botframework.com/v3/directline/conversations/" + conversationToken.conversationId + "/activities");
                        lastclient.DefaultRequestHeaders.Accept.Clear();
                        lastclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                        lastclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Directline secret");

                        string conversationUrl = conversationToken.conversationId + "/activities/";       
                        string msg2 = "User Message";

                        Rootobject rootobject = new Rootobject();
                        rootobject.type = "message";
                        rootobject.text = msg2;
                        From from = new From();
                        from.id = "User ID";
                        from.user = "User Name";
                        rootobject.from = from;

                        string json = "";
                        json = Newtonsoft.Json.JsonConvert.SerializeObject(rootobject);

                        var httpconvResponse = lastclient.PostAsync(lastclient.BaseAddress, new StringContent(json, System.Text.Encoding.UTF8, "application/json"));
                        var tokenconvResponse = httpconvResponse.Result;

                        if (tokenconvResponse.IsSuccessStatusCode)
                        {
                            var tokenconvjsonString = tokenconvResponse.Content.ReadAsStringAsync().Result;
                            var conversationconvToken = Newtonsoft.Json.JsonConvert.DeserializeObject<ConversationActivityInfo>(tokenconvjsonString.ToString());

                            convId = conversationToken.conversationId;
                            activityId = conversationconvToken.id.Split('|')[1];

                            finalclient.BaseAddress = new Uri("https://directline.botframework.com/v3/directline/conversations/" + conversationToken.conversationId + "/activities");
                            finalclient.DefaultRequestHeaders.Accept.Clear();
                            finalclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                            finalclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Directline Secret");

                            var httpconvfinalResponse = finalclient.GetAsync(finalclient.BaseAddress).Result;      
                            var jsonResponseString = httpconvfinalResponse.Content.ReadAsStringAsync();
                            var finalresponse = jsonResponseString.Result;
                            var activitiesObject = Newtonsoft.Json.JsonConvert.DeserializeObject<ActivitiesRO>(finalresponse);
                            act = activitiesObject.activities[1];

                            convRef = act.GetConversationReference();
            }


                    }
        string MicroSoftAppId = "YOUR Microsoft APP ID";
                    string MicroSoftAppPassword = "YOUR Microsoft APP PASSWORD";
        ICredentialProvider credentialProvider = new SimpleCredentialProvider(MicroSoftAppId, MicroSoftAppPassword);
        MicrosoftAppCredentials.TrustServiceUrl(convRef.ServiceUrl);

                    IBotFrameworkHttpAdapter adapter = new BotFrameworkHttpAdapter(credentialProvider);
                    ConcurrentDictionary<string, ConversationReference> conversationReferences = new ConcurrentDictionary<string, ConversationReference>();

                    convRef.Bot = new ChannelAccount("Bot ID", "Bot Name");

                    conversationReferences.GetOrAdd("test", convRef);

                    Notify notify = new Notify(adapter, MicroSoftAppId, conversationReferences);
                    Task<IActionResult> obj = notify.Get();

            }
        }

** Редактировать 2: ** Пожалуйста, смотрите ниже скриншот, мы получаем три идентификатора активности после отправки запроса на ниже URL, https://directline.botframework.com/v3/directline/conversations/" + разговорToken.conversationId + "/ деятельность"

Из которых мы используем действие Index 1 , так как оно содержит URL-адрес службы и сведения о пользователе, которым нужно отправить упреждающее сообщение, и не имеет сведений о BOT (свойство Bot), поэтому мы назначаем его вручную.

enter image description here

1 Ответ

0 голосов
/ 17 июня 2019

Я полагаю, что ваша проблема может заключаться в том, что вы пытаетесь создать ConversationReference для разговора, который не существует (хотя я не могу сказать, откуда взялся convoId).

Если это новый разговор, когда пользователь не взаимодействовал с ботом, вы можете использовать CreateConversationAsync . Вы можете увидеть, как мы делаем это в тестах, здесь :

var activity = new Activity()
{
    Type = ActivityTypes.Message,
    Recipient = User,
    From = Bot,
    Text = "TEST Create Conversation",
};

var param = new ConversationParameters()
{
    Members = new ChannelAccount[] { User },
    Bot = Bot,
    Activity = activity,
};

var convoId = await client.Conversations.CreateConversationAsync(param);

Примечание. Некоторые клиенты не допускают проактивные сообщения, когда пользователь никогда не общался с ботом (в основном это касается каналов электронной почты / SMS)

Если пользователь взаимодействовал с ботом , вы можете использовать Proactive Sample для справки. В частности, здесь :

var conversationReference = activity.GetConversationReference();

В качестве альтернативы возможно TrustServiceUrl Issue .

Вы можете исправить это, добавив ServiceUrls вашего канала в список доверенных URL:

var serviceUrl = <GetThisFrom Activity.ServiceUrl>;

MicrosoftAppCredentials.TrustServiceUrl(serviceUrl);

Вот определение метода . Примечание: для этого вы также можете добавить срок действия. В противном случае просмотр этих проблем должен помочь.

Также возможно, что ваш бот спит. Вы можете решить эту проблему, перейдя на Azure Portal > Your App Service > Configuration > General Settings > Always On <enable>

Примечание для других:

Эта «проблема с URL-адресом службы доверия» довольно распространена. Это происходит для многих других URL-адресов при попытке использовать Проактивные сообщения. Просто замените serviceUrl тем, что подходит для вашего случая использования. И да, если вы используете несколько каналов, вы можете добавить несколько URL-адресов при использовании MicrosoftAppCredentials.TrustServiceUrl(), вызывая его несколько раз.

...