241 lines
10 KiB
C#
241 lines
10 KiB
C#
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(微信回调)
|
||
/// <summary>
|
||
/// 微信回调1
|
||
/// </summary>
|
||
[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 = @" <xml><ToUserName><![CDATA[gh_9022339a2c40]]></ToUserName>
|
||
//<FromUserName><![CDATA[onGWJs5LvcR2NbYMJF2VyRhVH9XU]]></FromUserName>
|
||
//<CreateTime>1576747572</CreateTime>
|
||
//<MsgType><![CDATA[event]]></MsgType>
|
||
//<Event><![CDATA[subscribe]]></Event>
|
||
//<EventKey><![CDATA[]]></EventKey>
|
||
//</xml>";
|
||
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<MessageContext<IRequestMessageBase, IResponseMessageBase>>.GlobalWeixinContext.MessageQueue.FirstOrDefault();
|
||
var recordCount = MessageHandler<MessageContext<IRequestMessageBase, IResponseMessageBase>>.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 接收消息
|
||
/// <summary>
|
||
/// 接收微信发送的XML消息并且解析
|
||
/// </summary>
|
||
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,授权自动跳转;)
|
||
/// <summary>
|
||
/// H5授权token,获取OpenId,授权自动跳转;
|
||
/// </summary>
|
||
[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
|
||
|
||
}
|
||
}
|