微信公衆號的開發,園子裏有不少資料,這裏簡述。
雖然說是智能,如今是彷彿智障,不少是hard code邏輯,往後將逐步加入LUIS,如今一些經常使用的打招呼(你好,您好,hi,hey,hello,how are you等識別比較好)。json
業務性的處理,更可能是邏輯上,好比經常使用的回覆1,2,3,4而後返回對應的消息。這裏涉及多輪會話,要求對上文的記憶,否則容易回答串題了。api
還有就是一些分詞技術,這個目前對空格敏感,還有就是南京市長江大橋,是南京市長,仍是長江大橋?這個是往後話題了。服務器
驗證微信服務器地址的方法:微信
[HttpGet] [Route("api/wechat")] public IActionResult Get(string signature, string timestamp, string nonce, string echostr) { var token = ConfigReader.TokenStr;//微信公衆平臺後臺設置的Token if (string.IsNullOrEmpty(token)) { return NotFound("請先設置Token!"); //return new HttpResponseMessage() { Content = new StringContent("請先設置Token!", Encoding.GetEncoding("UTF-8"), "application/x-www-form-urlencoded") }; } var ent = ""; if (!BasicAPI.CheckSignature(signature, timestamp, nonce, token, out ent)) { return NotFound("驗證微信簽名失敗!"); //return new HttpResponseMessage() { Content = new StringContent("參數錯誤!", Encoding.GetEncoding("UTF-8"), "application/x-www-form-urlencoded") }; } //返回隨機字符串則表示驗證經過 return Ok(echostr); //return new HttpResponseMessage() { Content = new StringContent(echostr, Encoding.GetEncoding("UTF-8"), "application/x-www-form-urlencoded") }; }
驗證成功以後,全部消息,微信會轉到這個方法:markdown
用戶發送消息後,微信平臺自動Post一個請求到這裏,並等待響應XML。 [HttpPost] [Route("api/wechat")] public async Task<IActionResult> Post() { WeChatMessage message = null; string signature = HttpContext.Request.Query["signature"].ToString(); string timestamp = HttpContext.Request.Query["timestamp"].ToString(); string nonce = HttpContext.Request.Query["nonce"].ToString(); string echostr = HttpContext.Request.Query["echostr"].ToString(); var safeMode = HttpContext.Request.Query["encrypt_type"].ToString() == "aes"; using (var streamReader = new StreamReader(HttpContext.Request.Body, Encoding.UTF8)) { var decryptMsg = string.Empty; var msg = streamReader.ReadToEnd(); #region 解密 if (safeMode) { var msg_signature = HttpContext.Request.Query["msg_signature"]; var wechatBizMsgCrypt = new WeChatMsgCrypt(ConfigReader.TokenUrl, ConfigReader.EncodingAESKey, ConfigReader.AppId); var ret = wechatBizMsgCrypt.DecryptMsg(msg_signature, timestamp, nonce, msg, ref decryptMsg); if (ret != 0)//解密失敗 { //TODO:失敗的業務處理邏輯 } } else { decryptMsg = msg; } #endregion message = ParseMessageType.Parse(decryptMsg); } var response = await new WeChatExecutor(repo).Execute(message); var encryptMsg = string.Empty; #region 加密 if (safeMode) { var msg_signature = HttpContext.Request.Query["msg_signature"]; var wxBizMsgCrypt = new WeChatMsgCrypt(ConfigReader.TokenUrl, ConfigReader.EncodingAESKey, ConfigReader.AppId); var ret = wxBizMsgCrypt.EncryptMsg(response, timestamp, nonce, ref encryptMsg); if (ret != 0)//加密失敗 { //TODO:開發者加密失敗的業務處理邏輯 } } else { encryptMsg = response; } #endregion return Ok(encryptMsg); //return new HttpResponseMessage() //{ // Content = new StringContent(encryptMsg, Encoding.GetEncoding("UTF-8"), "application/x-www-form-urlencoded") // //ContentType = "text/xml", //}; }
public async static Task<string> PostMessage(string message, string openId) { HttpClient client; HttpResponseMessage response; bool IsReplyReceived = false; string ReceivedString = null; client = new HttpClient(); client.BaseAddress = new Uri("https://directline.botframework.com/api/conversations/"); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); //bot-int WeChat channel client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("BotConnector", ConfigReader.BotSecretKey); response = await client.GetAsync("/api/tokens/"); if (response.IsSuccessStatusCode) { var conversation = new Conversation(); response = await client.PostAsJsonAsync("/api/conversations/", conversation); if (response.IsSuccessStatusCode) { Conversation ConversationInfo = response.Content.ReadAsAsync(typeof(Conversation)).Result as Conversation; var contentString = response.Content.ReadAsStringAsync(); string conversationUrl = ConversationInfo.conversationId + "/messages/"; Message msg = new Message() { text = message, from = openId, channelData = "WeChat" }; response = await client.PostAsJsonAsync(conversationUrl, msg); if (response.IsSuccessStatusCode) { response = await client.GetAsync(conversationUrl); if (response.IsSuccessStatusCode) { MessageSet BotMessage = response.Content.ReadAsAsync(typeof(MessageSet)).Result as MessageSet; ReceivedString = BotMessage.messages[1].text; IsReplyReceived = true; } } } } return ReceivedString; }
public class Conversation { public string conversationId { get; set; } public string token { get; set; } public int expires_in { get; set; } } public class MessageSet { public Message[] messages { get; set; } public string watermark { get; set; } public string eTag { get; set; } } public class Message { public string id { get; set; } public string conversationId { get; set; } public DateTime created { get; set; } public string from { get; set; } public string text { get; set; } public string channelData { get; set; } public string[] images { get; set; } public Attachment[] attachments { get; set; } public string eTag { get; set; } } public class Attachment { public string url { get; set; } public string contentType { get; set; } }
public virtual async Task<HttpResponseMessage> Post([FromBody] Activity activity) { if (activity != null && activity.GetActivityType() == ActivityTypes.Message) { logger.Information(new ConversationEvent { EventType = LogEventType.ChatBotActivity, Message = $"ChatBot message controller receives a message, content: {activity.Text}", Activity = activity }); var isAgent = await ServiceManager.AgentManager.IsAgent(activity.From.Id); var context = await ServiceManager.ContextManager.GetUserContext(activity, isAgent); var activityLogger = new Logger.CosmosDbActivityLogger(); if (await ServiceManager.CommandMessageHandler.HandleCommandAsync(activity, isAgent) == false) { if (!string.IsNullOrEmpty(activity.Text) && activity.Text.ToLower().Contains(CommandRequestConnection)) { var contextManager = ServiceManager.ContextManager; var messageRouterResultHandler = ServiceManager.MessageRouterResultHandler; var result = await contextManager.RequestConnection(context, activity); await activityLogger.LogAsync(activity); // Handle the result, if required await messageRouterResultHandler.HandleResultAsync(result); } else { if (isAgent) { IAgentActor agentActor = SFHelper.GetActor<IAgentActor>(activity); await activityLogger.LogAsync(activity); await agentActor.MessagePost(context, new ActivityDataContract(activity)); } else { ICustomerActor customerActor = SFHelper.GetActor<ICustomerActor>(activity); await customerActor.MessagePost(context, new ActivityDataContract(activity)); if (activity.Text.Equals("沒有解決") || activity.Text.Equals("解決了")) { await ServiceManager.InquiryManager.CloseInquiryAsync(context); } } } } } else { HandleSystemMessage(activity); } return new HttpResponseMessage(HttpStatusCode.Accepted); }
public static Activity BuildProactiveGreeting(Activity context) { var responseMessage = context.CreateReply(); // TODO: Move to MenuManager via DataReposotry to persist to CosmosDB var topLevelMenuItems = new List<CardActionItem> { new CardActionItem() { Title = "技術支持", ActionType = ActionTypes.ImBack }, new CardActionItem() { Title = "帳單/訂閱/配額支持", ActionType = ActionTypes.ImBack }, new CardActionItem() { Title = "產品諮詢", ActionType = ActionTypes.ImBack }, new CardActionItem() { Title = "註冊問題", ActionType = ActionTypes.ImBack } }; // TODO: make sure we get correct name from wechat channel string cardTitleText = "Hi,我是您的智能客服,等您好久啦~猜您可能對如下內容感興趣:"; var heroCard = BuildHeroCardWithActionButtons(cardTitleText, topLevelMenuItems); responseMessage.AttachmentLayout = AttachmentLayoutTypes.List; responseMessage.Attachments = new List<Attachment>() { heroCard.ToAttachment() }; return responseMessage; }
var client = new ConnectorClient(new Uri(message.ServiceUrl), new MicrosoftAppCredentials()); var reply = GreetingHelper.BuildProactiveGreeting(message); client.Conversations.ReplyToActivityAsync(reply);
就是打招呼的時候,會回覆一個簡單得產品介紹,暫時沒有多輪會話,由於上下文理解出現一些問題,就不獻醜了(滑稽)。app
往後還有個切換到人工客服,當輸入人工客服時,調用微信公衆號的客服消息接口,每兩小時(過時時間7200s)獲取一次token,
而後根據用戶的OPENID,將微信支持的消息格式,發送到粉絲端,獲取token的IP必須添加到白名單中。
這個要求公衆號是認證的,我的的沒有受權。微信公衆平臺