/// <summary>
        /// Parse the XDocument to RequestMessage, decrypt it if needed.
        /// </summary>
        /// <param name="requestStream">WeChat RequestBody stream.</param>
        /// <param name="secretInfo">The secretInfo used to decrypt the message.</param>
        /// <returns>Decrypted WeChat RequestMessage instance.</returns>
        private IRequestMessageBase GetRequestMessage(Stream requestStream, SecretInfo secretInfo)
        {
            if (requestStream.CanSeek)
            {
                requestStream.Seek(0, SeekOrigin.Begin);
            }

            using (var xr = XmlReader.Create(requestStream))
            {
                var postDataDocument = XDocument.Load(xr);

                // decrypt xml document message and parse to message
                var postDataStr = postDataDocument.ToString();
                var decryptDoc = postDataDocument;

                if (secretInfo != null
                    && !string.IsNullOrWhiteSpace(_settings.Token)
                    && postDataDocument.Root.Element("Encrypt") != null
                    && !string.IsNullOrEmpty(postDataDocument.Root.Element("Encrypt").Value))
                {
                    var msgCrype = new MessageCryptography(secretInfo, _settings);
                    var msgXml = msgCrype.DecryptMessage(postDataStr);

                    decryptDoc = XDocument.Parse(msgXml);
                }

                var requestMessage = WeChatMessageFactory.GetRequestEntity(decryptDoc, _logger);

                return requestMessage;
            }
        }
Exemple #2
0
        public static List <IRequestMessageBase> GetMockRequestMessageList()
        {
            var logger      = GetMockLogger();
            var requestList = new List <IRequestMessageBase>
            {
                WeChatMessageFactory.GetRequestEntity(XDocument.Parse(XmlText), logger),
                WeChatMessageFactory.GetRequestEntity(XDocument.Parse(XmlImage), logger),
                WeChatMessageFactory.GetRequestEntity(XDocument.Parse(XmlVoice), logger),
                WeChatMessageFactory.GetRequestEntity(XDocument.Parse(XmlVideo), logger),
                WeChatMessageFactory.GetRequestEntity(XDocument.Parse(XmlShortVideo), logger),
                WeChatMessageFactory.GetRequestEntity(XDocument.Parse(XmlLocation), logger),
                WeChatMessageFactory.GetRequestEntity(XDocument.Parse(XmlLink), logger),
                WeChatMessageFactory.GetRequestEntity(XDocument.Parse(XmlEventClick), logger),
                WeChatMessageFactory.GetRequestEntity(XDocument.Parse(XmlEventLocation), logger),
                WeChatMessageFactory.GetRequestEntity(XDocument.Parse(XmlEventView), logger),
                WeChatMessageFactory.GetRequestEntity(XDocument.Parse(XmlEventSubscribe), logger),
                WeChatMessageFactory.GetRequestEntity(XDocument.Parse(XmlEventScan), logger),
            };

            return(requestList);
        }
        public void GetResponseXmlTest()
        {
            {
                // Text
                var result = WeChatMessageFactory.ConvertResponseToXml(MockDataUtility.TextResponse);
                Assert.Equal(MockDataUtility.PassiveXmlText, result);
            }

            {
                // Image
                var result = WeChatMessageFactory.ConvertResponseToXml(MockDataUtility.ImageResponse);
                Assert.Equal(MockDataUtility.PassiveXmlImage, result);
            }

            {
                // Voice
                var result = WeChatMessageFactory.ConvertResponseToXml(MockDataUtility.VoiceResponse);
                Assert.Equal(MockDataUtility.PassiveXmlVoice, result);
            }

            {
                // Video
                var result = WeChatMessageFactory.ConvertResponseToXml(MockDataUtility.VideoResponse);
                Assert.Equal(MockDataUtility.PassiveXmlVideo, result);
            }

            {
                // Music
                var result = WeChatMessageFactory.ConvertResponseToXml(MockDataUtility.MusicResponse);
                Assert.Equal(MockDataUtility.PassiveXmlMusic, result);
            }

            {
                // News
                var result = WeChatMessageFactory.ConvertResponseToXml(MockDataUtility.NewsResponse);
                Assert.Equal(MockDataUtility.PassiveXmlNews, result);
            }
        }
        public void GetRequestEntityTest()
        {
            var logger = NullLogger.Instance;
            {
                // Text
                var doc    = XDocument.Parse(MockDataUtility.XmlText);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is TextRequest);
                MessageBaseTest(result as TextRequest);
                var textRequest = result as TextRequest;
                Assert.Equal(RequestMessageTypes.Text, result.MsgType);
                Assert.Equal("this is a test", textRequest.Content);
            }

            {
                // Image
                var doc    = XDocument.Parse(MockDataUtility.XmlImage);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is ImageRequest);
                Assert.Equal(RequestMessageTypes.Image, result.MsgType);
                MessageBaseTest(result as RequestMessage);
                var imageRequest = result as ImageRequest;
                Assert.Equal("this is a url", imageRequest.PicUrl);
                Assert.Equal("media_id", imageRequest.MediaId);
            }

            {
                // Voice
                var doc    = XDocument.Parse(MockDataUtility.XmlVoice);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is VoiceRequest);
                Assert.Equal(RequestMessageTypes.Voice, result.MsgType);
                MessageBaseTest(result as RequestMessage);
                var voiceRequest = result as VoiceRequest;
                Assert.Equal("media_id", voiceRequest.MediaId);
                Assert.Equal("Format", voiceRequest.Format);
            }

            {
                // Video
                var doc    = XDocument.Parse(MockDataUtility.XmlVideo);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is VideoRequest);
                Assert.Equal(RequestMessageTypes.Video, result.MsgType);
                MessageBaseTest(result as RequestMessage);
                var videoRequest = result as VideoRequest;
                Assert.Equal("media_id", videoRequest.MediaId);
                Assert.Equal("thumb_media_id", videoRequest.ThumbMediaId);
            }

            {
                // Short Video
                var doc    = XDocument.Parse(MockDataUtility.XmlShortVideo);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is ShortVideoRequest);
                Assert.Equal(RequestMessageTypes.ShortVideo, result.MsgType);
                MessageBaseTest(result as RequestMessage);
                var shortvideoRequest = result as ShortVideoRequest;
                Assert.Equal("media_id", shortvideoRequest.MediaId);
                Assert.Equal("thumb_media_id", shortvideoRequest.ThumbMediaId);
            }

            {
                // Location
                var doc    = XDocument.Parse(MockDataUtility.XmlLocation);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is LocationRequest);
                Assert.Equal(RequestMessageTypes.Location, result.MsgType);
                MessageBaseTest(result as RequestMessage);
                var locationRequest = result as LocationRequest;
                Assert.Equal(23.134521, locationRequest.Latitude);
                Assert.Equal(113.358803, locationRequest.Longtitude);
                Assert.Equal(20, locationRequest.Scale);
                Assert.Equal("LocationInfo", locationRequest.Label);
            }

            {
                // Link
                var doc    = XDocument.Parse(MockDataUtility.XmlLink);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is LinkRequest);
                Assert.Equal(RequestMessageTypes.Link, result.MsgType);
                MessageBaseTest(result as RequestMessage);
                var linkRequest = result as LinkRequest;
                Assert.Equal("This is a link", linkRequest.Title);
                Assert.Equal("This is a link", linkRequest.Description);
                Assert.Equal("url", linkRequest.Url);
            }

            {
                // Click Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventClick);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is ClickEvent);
                EventBaseTest(result as RequestEvent);
                var clickEvent = result as ClickEvent;
                Assert.Equal(EventTypes.Click, clickEvent.EventType);
                Assert.Equal(clickEvent.EventType, EventTypes.Click);
                Assert.Equal("EVENTKEY", clickEvent.EventKey);
            }

            {
                // Location Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventLocation);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is LocationEvent);
                EventBaseTest(result as RequestEvent);
                var locationEvent = result as LocationEvent;
                Assert.Equal(EventTypes.Location, locationEvent.EventType);
                Assert.Equal(23.104105, locationEvent.Latitude);
                Assert.Equal(113.320107, locationEvent.Longitude);
                Assert.Equal(65.000000, locationEvent.Precision);
            }

            {
                // View Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventView);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is ViewEvent);
                EventBaseTest(result as RequestEvent);
                var viewEvent = result as ViewEvent;
                Assert.Equal(EventTypes.View, viewEvent.EventType);
                Assert.Equal("www.qq.com", viewEvent.EventKey);
            }

            {
                // Subscribe Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventSubscribe);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is SubscribeEvent);
                EventBaseTest(result as RequestEvent);
                var subscribeEvent = result as SubscribeEvent;
                Assert.Equal(EventTypes.Subscribe, subscribeEvent.EventType);
                Assert.Equal("qrscene_123123", subscribeEvent.EventKey);
                Assert.Equal("TICKET", subscribeEvent.Ticket);
            }

            {
                // Scan Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventScan);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is ScanEvent);
                EventBaseTest(result as RequestEvent);
                var scanEvent = result as ScanEvent;
                Assert.Equal(EventTypes.Scan, scanEvent.EventType);
                Assert.Equal("SCENE_VALUE", scanEvent.EventKey);
                Assert.Equal("TICKET", scanEvent.Ticket);
            }

            {
                // ScanPush Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventScanPush);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is ScanPushEvent);
                EventBaseTest(result as RequestEvent);
                var scanPushEvent = result as ScanPushEvent;
                Assert.Equal(EventTypes.ScanPush, scanPushEvent.EventType);
                Assert.Equal("6", scanPushEvent.EventKey);
                Assert.Equal("qrcode", scanPushEvent.ScanCodeInfo.ScanType);
                Assert.Equal("1", scanPushEvent.ScanCodeInfo.ScanResult);
            }

            {
                // WaitScanPush Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventWaitScanPush);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is WaitScanPushEvent);
                EventBaseTest(result as RequestEvent);
                var waitScanPushEvent = result as WaitScanPushEvent;
                Assert.Equal(EventTypes.WaitScanPush, waitScanPushEvent.EventType);
                Assert.Equal("6", waitScanPushEvent.EventKey);
                Assert.Equal("qrcode", waitScanPushEvent.ScanCodeInfo.ScanType);
                Assert.Equal("2", waitScanPushEvent.ScanCodeInfo.ScanResult);
            }

            {
                // Camera Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventCamera);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is CameraEvent);
                EventBaseTest(result as RequestEvent);
                var cameraEvent = result as CameraEvent;
                Assert.Equal(EventTypes.Camera, cameraEvent.EventType);
                Assert.Equal("6", cameraEvent.EventKey);
                Assert.Equal(1, cameraEvent.SendPicsInfo.Count);
                Assert.Equal("1b5f7c23b5bf75682a53e7b6d163e185", cameraEvent.SendPicsInfo.PicList[0].Item.PicMD5Sum);
            }

            {
                // CameraOrAlbum Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventCameraOrAlbum);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is CameraOrAlbumEvent);
                EventBaseTest(result as RequestEvent);
                var cameraOrAlbumEvent = result as CameraOrAlbumEvent;
                Assert.Equal(EventTypes.CameraOrAlbum, cameraOrAlbumEvent.EventType);
                Assert.Equal("6", cameraOrAlbumEvent.EventKey);
                Assert.Equal(1, cameraOrAlbumEvent.SendPicsInfo.Count);
                Assert.Equal("5a75aaca956d97be686719218f275c6b", cameraOrAlbumEvent.SendPicsInfo.PicList[0].Item.PicMD5Sum);
            }

            {
                // WeChatAlbum Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventWeChatAlbum);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is WeChatAlbumEvent);
                EventBaseTest(result as RequestEvent);
                var wechatAlbumEvent = result as WeChatAlbumEvent;
                Assert.Equal(EventTypes.WeChatAlbum, wechatAlbumEvent.EventType);
                Assert.Equal("6", wechatAlbumEvent.EventKey);
                Assert.Equal(1, wechatAlbumEvent.SendPicsInfo.Count);
                Assert.Equal("5a75aaca956d97be686719218f275c6b", wechatAlbumEvent.SendPicsInfo.PicList[0].Item.PicMD5Sum);
            }

            {
                // SelectLocation Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventSelectLocation);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is SelectLocationEvent);
                EventBaseTest(result as RequestEvent);
                var selectLocationEvent = result as SelectLocationEvent;
                Assert.Equal(EventTypes.SelectLocation, selectLocationEvent.EventType);
                Assert.Equal("6", selectLocationEvent.EventKey);
                Assert.Equal("23", selectLocationEvent.SendLocationInfo.Latitude);
                Assert.Equal("113", selectLocationEvent.SendLocationInfo.Longtitude);
                Assert.Equal("15", selectLocationEvent.SendLocationInfo.Scale);
                Assert.Equal("No.328 Xinghu Street", selectLocationEvent.SendLocationInfo.Label);
                Assert.Equal("test", selectLocationEvent.SendLocationInfo.PoiName);
            }

            {
                // ViewMiniProgram Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventViewMiniProgram);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is ViewMiniProgramEvent);
                EventBaseTest(result as RequestEvent);
                var viewMiniProgramEvent = result as ViewMiniProgramEvent;
                Assert.Equal(EventTypes.ViewMiniProgram, viewMiniProgramEvent.EventType);
                Assert.Equal("pages/index/index", viewMiniProgramEvent.EventKey);
                Assert.Equal("MENUID", viewMiniProgramEvent.MenuId);
            }

            {
                // MassSendJobFinished Event
                var doc    = XDocument.Parse(MockDataUtility.XmlEventMassSendJobFinished);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is MassSendJobFinishedEvent);
                EventBaseTest(result as RequestEvent);
                var massSendJobFinishedEvent = result as MassSendJobFinishedEvent;
                Assert.Equal(EventTypes.MassSendJobFinished, massSendJobFinishedEvent.EventType);
                Assert.Equal(1000001625, massSendJobFinishedEvent.MsgID);
                Assert.Equal("err(30003)", massSendJobFinishedEvent.Status);
                Assert.Equal(0, massSendJobFinishedEvent.TotalCount);
                Assert.Equal(0, massSendJobFinishedEvent.FilterCount);
                Assert.Equal(0, massSendJobFinishedEvent.SentCount);
                Assert.Equal(0, massSendJobFinishedEvent.ErrorCount);
                Assert.Equal(2, massSendJobFinishedEvent.CopyrightCheckResult.Count);
                Assert.Equal(1, massSendJobFinishedEvent.CopyrightCheckResult.ResultList.Items[0].ArticleIdx);
                Assert.Equal(0, massSendJobFinishedEvent.CopyrightCheckResult.ResultList.Items[0].UserDeclareState);
                Assert.Equal(2, massSendJobFinishedEvent.CopyrightCheckResult.ResultList.Items[0].AuditState);
                Assert.Equal("Url_1", massSendJobFinishedEvent.CopyrightCheckResult.ResultList.Items[0].OriginalArticleUrl);
                Assert.Equal(1, massSendJobFinishedEvent.CopyrightCheckResult.ResultList.Items[0].OriginalArticleType);
                Assert.Equal(1, massSendJobFinishedEvent.CopyrightCheckResult.ResultList.Items[0].CanReprint);
                Assert.Equal(1, massSendJobFinishedEvent.CopyrightCheckResult.ResultList.Items[0].NeedReplaceContent);
                Assert.Equal(1, massSendJobFinishedEvent.CopyrightCheckResult.ResultList.Items[0].NeedShowReprintSource);
                Assert.Equal("Url_2", massSendJobFinishedEvent.CopyrightCheckResult.ResultList.Items[1].OriginalArticleUrl);
                Assert.Equal(2, massSendJobFinishedEvent.CopyrightCheckResult.CheckState);
            }

            {
                // TemplateSendFinished
                var doc    = XDocument.Parse(MockDataUtility.XmlEventTemplateSendFinished);
                var result = WeChatMessageFactory.GetRequestEntity(doc, logger);
                Assert.True(result is TemplateSendFinishedEvent);
                EventBaseTest(result as RequestEvent);
                var templateSendFinishedEvent = result as TemplateSendFinishedEvent;
                Assert.Equal(EventTypes.TemplateSendFinished, templateSendFinishedEvent.EventType);
                Assert.Equal(200163840, templateSendFinishedEvent.MsgID);
                Assert.Equal("failed:user block", templateSendFinishedEvent.Status);
            }
        }
        /// <summary>
        /// Process the request from WeChat.
        /// This method can be called from inside a POST method on any Controller implementation.
        /// </summary>
        /// <param name="httpRequest">The HTTP request object, typically in a POST handler by a Controller.</param>
        /// <param name="httpResponse">The HTTP response object.</param>
        /// <param name="bot">The bot implementation.</param>
        /// <param name="secretInfo">The secret info provide by WeChat.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A task that represents the work queued to execute.</returns>
        public async Task ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, SecretInfo secretInfo, CancellationToken cancellationToken = default(CancellationToken))
        {
            _logger.LogInformation("Receive a new request from WeChat.");
            if (httpRequest == null)
            {
                throw new ArgumentNullException(nameof(httpRequest));
            }

            if (httpResponse == null)
            {
                throw new ArgumentNullException(nameof(httpResponse));
            }

            if (bot == null)
            {
                throw new ArgumentNullException(nameof(bot));
            }

            if (secretInfo == null)
            {
                throw new ArgumentNullException(nameof(secretInfo));
            }

            if (!VerificationHelper.VerifySignature(secretInfo.WebhookSignature, secretInfo.Timestamp, secretInfo.Nonce, _settings.Token))
            {
                throw new UnauthorizedAccessException("Signature verification failed.");
            }

            // Return echo string when request is setting up the endpoint.
            if (!string.IsNullOrEmpty(secretInfo.EchoString))
            {
                await httpResponse.WriteAsync(secretInfo.EchoString, cancellationToken).ConfigureAwait(false);
                return;
            }

            // Directly return OK header to prevent WeChat from retrying.
            if (!_settings.PassiveResponseMode)
            {
                httpResponse.StatusCode = (int)HttpStatusCode.OK;
                httpResponse.ContentType = "text/event-stream";
                await httpResponse.WriteAsync(string.Empty).ConfigureAwait(false);
                await httpResponse.Body.FlushAsync().ConfigureAwait(false);
            }

            try
            {
                var wechatRequest = GetRequestMessage(httpRequest.Body, secretInfo);
                var wechatResponse = await ProcessWeChatRequest(
                                wechatRequest,
                                bot.OnTurnAsync,
                                cancellationToken).ConfigureAwait(false);

                // Reply WeChat(User) request have two ways, set response in http response or use background task to process the request async.
                if (_settings.PassiveResponseMode)
                {
                    httpResponse.StatusCode = (int)HttpStatusCode.OK;
                    httpResponse.ContentType = "text/xml";
                    var xmlString = WeChatMessageFactory.ConvertResponseToXml(wechatResponse);
                    await httpResponse.WriteAsync(xmlString).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Process WeChat request failed.");
                throw;
            }
        }
Exemple #6
0
        /// <summary>
        /// Process the request from WeChat.
        /// This method can be called from inside a POST method on any Controller implementation.
        /// </summary>
        /// <param name="httpRequest">The HTTP request object, typically in a POST handler by a Controller.</param>
        /// <param name="httpResponse">The HTTP response object.</param>
        /// <param name="bot">The bot implementation.</param>
        /// <param name="secretInfo">The secret info provide by WeChat.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A task that represents the work queued to execute.</returns>
        public async Task ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, SecretInfo secretInfo, CancellationToken cancellationToken = default(CancellationToken))
        {
            _logger.LogInformation("Receive a new request from WeChat.");
            if (httpRequest == null)
            {
                throw new ArgumentNullException(nameof(httpRequest));
            }

            if (httpResponse == null)
            {
                throw new ArgumentNullException(nameof(httpResponse));
            }

            if (bot == null)
            {
                throw new ArgumentNullException(nameof(bot));
            }

            if (secretInfo == null)
            {
                throw new ArgumentNullException(nameof(secretInfo));
            }

            if (false == string.IsNullOrEmpty(secretInfo.EchoString))
            {
                var wXBizMsgCrypt    = new WXBizMsgCrypt(_settings.Token, _settings.EncodingAesKey, _settings.CorpId);
                var replayEchoString = string.Empty;
                var code             = wXBizMsgCrypt.VerifyURL(secretInfo.MessageSignature, secretInfo.Timestamp, secretInfo.Nonce, secretInfo.EchoString, ref replayEchoString);
                if (code != 0)
                {
                    throw new UnauthorizedAccessException($"Signature verification failed. Code: {code}");
                }

                // Return echo string when request is setting up the endpoint.
                if (!string.IsNullOrEmpty(replayEchoString))
                {
                    await httpResponse.WriteAsync(replayEchoString, cancellationToken).ConfigureAwait(false);

                    return;
                }
            }

            // Directly return OK header to prevent WeChat from retrying.
            if (!_settings.PassiveResponseMode)
            {
                httpResponse.StatusCode  = (int)HttpStatusCode.OK;
                httpResponse.ContentType = "text/event-stream";
                await httpResponse.WriteAsync(string.Empty).ConfigureAwait(false);

                await httpResponse.Body.FlushAsync().ConfigureAwait(false);
            }

            try
            {
                var wechatRequest  = GetRequestMessage(httpRequest.Body, secretInfo);
                var wechatResponse = await ProcessWeChatRequest(
                    wechatRequest,
                    bot.OnTurnAsync,
                    cancellationToken).ConfigureAwait(false);

                // Reply WeChat(User) request have two ways, set response in http response or use background task to process the request async.
                if (_settings.PassiveResponseMode)
                {
                    httpResponse.StatusCode  = (int)HttpStatusCode.OK;
                    httpResponse.ContentType = "text/xml";
                    var xmlString = WeChatMessageFactory.ConvertResponseToXml(wechatResponse);
                    var response  = string.Empty;
                    var timestemp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
                    var nonce     = Guid.NewGuid().ToString("N");
                    new WXBizMsgCrypt(_settings.Token, _settings.EncodingAesKey, _settings.CorpId).EncryptMsg(xmlString, timestemp, nonce, ref response);

                    await httpResponse.WriteAsync(response).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Process WeChat request failed.");
                throw;
            }
        }