2025-04-24 18:31:27 +08:00

241 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}
}