using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using MyCode.Project.Domain.Message.Response.User; using MyCode.Project.Infrastructure.Constant; using MyCode.Project.WebApi.Controllers; using MyCode.Project.Domain.Config; using MyCode.Project.Services; using MyCode.Project.Infrastructure.Common; using MyCode.Project.Domain.Message.Request.User; using MyCode.Project.Infrastructure.Enumeration; using MyCode.Project.WebApi.App_Filter; using System.Web; using System.IO; using System.Text; using System.Xml; using Senparc.Weixin.MP; using Senparc.Weixin.MP.MessageHandlers; using Senparc.NeuChar.Context; using Senparc.NeuChar.Entities; using System.Xml.Linq; using MyCode.Project.Services.CustomMessageHandler; using MyCode.Project.Domain.Dtos.Common; using MyCode.Project.Domain.Message.Response.Wechat; using MyCode.Project.Infrastructure.Cache; using MyCode.Project.Infrastructure.Exceptions; namespace MyCode.Project.WebApi.Areas.Wechat.Controllers { public class WeController : BaseWechatController { private readonly IMyCodeCacheService _myCodeCacheService; private IMemberService _memberService; public WeController(IMyCodeCacheService myCodeCacheService , IMemberService memberService) { _myCodeCacheService = myCodeCacheService; _memberService = memberService; } #region WeCallBack(微信回调) /// /// 微信回调1 /// [AllowAnonymous, IgnoreResultHandle, HttpGet, HttpPost, ActionName("WeCallBack")] public void WeCallBack() { var context = CurrentHttpContext; string signature = context.Request["signature"]; string timestamp = context.Request["timestamp"]; string nonce = context.Request["nonce"]; string echostr = context.Request["echostr"]; //get method -检验是否微信的回调,不是则不执行 if (CheckSignature.Check(signature, timestamp, nonce, SystemConfig.WeToken)) { // string postStr = @" // //1576747572 // // // //"; Stream s = System.Web.HttpContext.Current.Request.InputStream;//此方法是对System.Web.HttpContext.Current.Request.InputStream的封装,可直接代码 string postStr = ""; if (s != null && s.Length > 0) { s.Position = 0; //当你读取完之后必须把stream的读取位置设为开始 StreamReader reader = new StreamReader(s, System.Text.Encoding.UTF8); postStr = reader.ReadToEnd().ToString(); } //byte[] b = new byte[s.Length]; //s.Read(b, 0, (int)s.Length); //string postStr = Encoding.UTF8.GetString(b); //LogHelper.Info(postStr); var weixinContext = MessageHandler>.GlobalWeixinContext.MessageQueue.FirstOrDefault(); var recordCount = MessageHandler>.GlobalWeixinContext.MaxRecordCount; if (string.IsNullOrEmpty(postStr)) { context.Response.Output.Write(echostr); context.Response.End(); return; } var doc = XDocument.Parse(postStr); var maxRecordCount = 1; var messageHandler = new CustomMessageHandler(doc, null, maxRecordCount); messageHandler.OmitRepeatedMessage = true; messageHandler.Execute(); //LogHelper.Info("RequestMessages:" + messageHandler.RequestMessage); if (messageHandler.TextResponseMessage != null) { //LogHelper.Info("ResponseMessages:" + messageHandler.TextResponseMessage); context.Response.Output.Write(messageHandler.TextResponseMessage); context.Response.End(); } } return; } #endregion #region 接收消息 /// /// 接收微信发送的XML消息并且解析 /// private void ReceiveXml() { Stream requestStream = System.Web.HttpContext.Current.Request.InputStream; byte[] requestByte = new byte[requestStream.Length]; requestStream.Read(requestByte, 0, (int)requestStream.Length); string requestStr = Encoding.UTF8.GetString(requestByte); if (!string.IsNullOrEmpty(requestStr)) { //封装请求类 XmlDocument requestDocXml = new XmlDocument(); requestDocXml.LoadXml(requestStr); XmlElement rootElement = requestDocXml.DocumentElement; WxXmlModel WxXmlModel2 = new WxXmlModel(); WxXmlModel2.ToUserName = rootElement.SelectSingleNode("ToUserName").InnerText; WxXmlModel2.FromUserName = rootElement.SelectSingleNode("FromUserName").InnerText; WxXmlModel2.CreateTime = rootElement.SelectSingleNode("CreateTime").InnerText; WxXmlModel2.MsgType = rootElement.SelectSingleNode("MsgType").InnerText; switch (WxXmlModel2.MsgType) { case "text"://文本 WxXmlModel2.Content = rootElement.SelectSingleNode("Content").InnerText; break; case "image"://图片 WxXmlModel2.PicUrl = rootElement.SelectSingleNode("PicUrl").InnerText; break; case "event"://事件 WxXmlModel2.Event = rootElement.SelectSingleNode("Event").InnerText; if (WxXmlModel2.Event != "TEMPLATESENDJOBFINISH")//关注类型 { WxXmlModel2.EventKey = rootElement.SelectSingleNode("EventKey").InnerText; } break; default: break; } ResponseXML(WxXmlModel2);//回复消息 } } #endregion #region 回复消息 private void ResponseXML(WxXmlModel WxXmlModel) { QrCodeApi QrCodeApi = new QrCodeApi(); string XML = ""; switch (WxXmlModel.MsgType) { case "text"://文本回复 XML = MyCode.Project.Infrastructure.Common.ResponseMessage.GetText(WxXmlModel.FromUserName, WxXmlModel.ToUserName, WxXmlModel.Content); break; case "event": switch (WxXmlModel.Event) { case "subscribe": if (string.IsNullOrEmpty(WxXmlModel.EventKey)) { XML = MyCode.Project.Infrastructure.Common.ResponseMessage.GetText(WxXmlModel.FromUserName, WxXmlModel.ToUserName, "关注成功"); } else { XML = MyCode.Project.Infrastructure.Common.ResponseMessage.SubScanQrcode(WxXmlModel.FromUserName, WxXmlModel.ToUserName, WxXmlModel.EventKey);//扫描带参数二维码先关注后推送事件 } break; case "SCAN": XML = MyCode.Project.Infrastructure.Common.ResponseMessage.ScanQrcode(WxXmlModel.FromUserName, WxXmlModel.ToUserName, WxXmlModel.EventKey);//扫描带参数二维码已关注 直接推送事件 break; } break; default://默认回复 break; } HttpContext.Current.Response.Write(XML); HttpContext.Current.Response.End(); } #endregion #region OpenId(获取OpenId,授权自动跳转;) /// /// H5授权token,获取OpenId,授权自动跳转; /// [AllowAnonymous, IgnoreResultHandle, HttpGet, HttpPost, ActionName("openid")] public void OpenId(string url, int? introcode = null) { //拿到code后的跳转链接 var redirectUrl = $"{SystemConfig.WeixinApiUrl}/api/Wechat/We/UserInfoCallback"; var openIdResp = new OpenIdResp(); var tempCacheKey = Guid.NewGuid(); //解码 url = HttpUtility.UrlDecode(url); //授权成功之后的跳转链接 openIdResp.RedirectUrl = url; _myCodeCacheService.Set(tempCacheKey.ToString(), openIdResp); //执行跳转链接,userinfo跳转 var weixinOAuth2Url = $"https://open.weixin.qq.com/connect/oauth2/authorize?appid={SystemConfig.WeAppid}&redirect_uri={HttpUtility.UrlEncode(redirectUrl)}&response_type=code&scope=snsapi_userinfo&state={tempCacheKey}#wechat_redirect"; CurrentHttpContext.Response.Redirect(weixinOAuth2Url); } #endregion #region UserInfoCallback(带用户信息的回调) [AllowAnonymous, IgnoreResultHandle, HttpGet, HttpPost, ActionName("UserInfoCallback")] public void UserInfoCallback(string code, string state) { if (string.IsNullOrEmpty(code)) { throw new BaseException("code为空"); } var redirectUrl = _memberService.GetWXOAuthRedirectUrlByUserInfo(state, code); CurrentHttpContext.Response.Redirect(redirectUrl); } #endregion } }