2025-04-21 14:10:27 +08:00

475 lines
17 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 MyCode.Project.Domain.Message.Response.EnterpriseWechat;
using MyCode.Project.Domain.Message.Response.Wechat;
using MyCode.Project.Infrastructure.Cache;
using MyCode.Project.Infrastructure.Common;
using MyCode.Project.Infrastructure.Constant;
using MyCode.Project.Infrastructure.Exceptions;
using MyCode.Project.Infrastructure.WebPost;
using Senparc.CO2NET.Extensions;
using Senparc.Weixin;
using Senparc.Weixin.MP.Entities;
using Senparc.Weixin.MP.Helpers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
namespace MyCode.Project.OutSideService.Implementation
{
public class EnterpriseWechatService : IEnterpriseWechatService
{
private readonly string apiUrl = "https://qyapi.weixin.qq.com/";
private readonly IMyCodeCacheService _myCodeCacheService;
public EnterpriseWechatService(
IMyCodeCacheService myCodeCacheService
)
{
_myCodeCacheService = myCodeCacheService;
}
#region
#region Get(Get方法)
/// <summary>
/// 进一步封装Get方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="url"></param>
/// <returns></returns>
private T Get<T>(string url) where T : BaseEnterpriseResp
{
var webUtils = new WebUtils();
var resp = webUtils.DoGet<T>(url, null);
resp.CheckResult();
return resp;
}
#endregion
#region ToDepartmentHasChild()
public List<DepartmentHasChild> ToDepartmentHasChild(List<DepartmentInfo> listDepartmentInfo)
{
if (listDepartmentInfo == null || listDepartmentInfo.Count == 0) { return null; }
//公司节点
var rootList = listDepartmentInfo.FindAll(p => p.Parentid == 0);
var returnList = new List<DepartmentHasChild>();
//子节点
foreach (var root in rootList)
{
var item = new DepartmentHasChild
{
Id = root.Id,
Name = root.Name,
Parentid = root.Parentid
};
item.ListChild = GetDepartmentChild(listDepartmentInfo, root.Id);
returnList.Add(item);
}
return returnList;
}
#endregion
#region GetDepartmentChild()
/// <summary>
/// 得到子节点
/// </summary>
/// <param name="listDepartmentInfo"></param>
/// <param name="parentId"></param>
/// <returns></returns>
public List<DepartmentHasChild> GetDepartmentChild(List<DepartmentInfo> listDepartmentInfo, int parentId)
{
var list = listDepartmentInfo.FindAll(p => p.Parentid == parentId);
var returnList = new List<DepartmentHasChild>();
if (list == null || list.Count == 0) { return new List<DepartmentHasChild> { }; }
foreach (var child in list)
{
var item = new DepartmentHasChild
{
Id = child.Id,
Name = child.Name,
Parentid = child.Parentid,
Order = child.Order
};
item.ListChild = GetDepartmentChild(listDepartmentInfo, child.Id);
returnList.Add(item);
}
return returnList;
}
#endregion
#endregion
#region GetAccessToken(AccessToken7200)
/// <summary>
/// 得到AccessToken有效期7200秒
/// </summary>
/// <param name="corpId">企业id</param>
/// <param name="secret"></param>
/// <returns></returns>
public string GetAccessToken(string corpId, string secret)
{
var cacheKey = $"{CacheKey.EnterpriseWechatTokenKey}{corpId}{secret}";
if (_myCodeCacheService.Exists(cacheKey))
{
return _myCodeCacheService.Get<string>(cacheKey);
}
var url = $"{apiUrl}cgi-bin/gettoken?corpid={corpId}&corpsecret={secret}";
var resp = Get<GetTokenResp>(url);
var token = resp.Access_token;
_myCodeCacheService.Set(cacheKey, token, new TimeSpan(1, 0, 0));
return token;
}
#endregion
#region GetTicket(Ticket)
/// <summary>
/// 获取企业微信Ticket
/// </summary>
/// <param name="accessToken">对应的应用的token</param>
/// <returns></returns>
private string GetTicket(string accessToken)
{
var cacheKey = $"{accessToken}";
if (_myCodeCacheService.Exists(cacheKey))
{
return _myCodeCacheService.Get<string>(cacheKey);
}
var url = string.Format(apiUrl + "cgi-bin/get_jsapi_ticket?access_token={0}", accessToken.AsUrlData());
JsApiTicketResult result = Senparc.CO2NET.HttpUtility.Get.GetJson<JsApiTicketResult>(url);
if (result.errcode != ReturnCode.) { throw new BaseException(result.ToJson()); }
_myCodeCacheService.Set(cacheKey, result.ticket, new TimeSpan(1, 0, 0));
return result.ticket;
}
#endregion
#region GetApplicationTicket(jsapi_ticket)
/// <summary>
/// 应用的jsapi_ticket
/// </summary>
/// <param name="accessToken">对应的应用的token</param>
/// <returns></returns>
private string GetApplicationTicket(string accessToken)
{
var cacheKey = $"{accessToken}2";
if (_myCodeCacheService.Exists(cacheKey))
{
return _myCodeCacheService.Get<string>(cacheKey);
}
var url = string.Format(apiUrl + "cgi-bin/ticket/get?access_token={0}&type=agent_config", accessToken.AsUrlData());
JsApiTicketResult result = Senparc.CO2NET.HttpUtility.Get.GetJson<JsApiTicketResult>(url);
if (result.errcode != ReturnCode.) { throw new BaseException(result.ToJson()); }
_myCodeCacheService.Set(cacheKey, result.ticket, new TimeSpan(1, 0, 0));
return result.ticket;
}
#endregion
#region GetJsSdk(JsSdk相关参数值)
/// <summary>
/// 取得微信JsSdk相关参数值
/// </summary>
/// <param name="appId">微信应用ID</param>
/// <param name="ticket">JsTicket</param>
/// <param name="url">需要授权Url地址</param>
/// <returns></returns>
private JsSdkResp GetJsSdk(string appId, string ticket, string url)
{
var decodeUrl = HttpUtility.UrlDecode(url);
string timeStamp = JSSDKHelper.GetTimestamp();
string nonceStr = JSSDKHelper.GetNoncestr();
string signature = "";
var paySignReqHandler = new Senparc.Weixin.TenPay.V2.RequestHandler(null);
paySignReqHandler.SetParameter("jsapi_ticket", ticket);
paySignReqHandler.SetParameter("noncestr", nonceStr);
paySignReqHandler.SetParameter("timestamp", timeStamp);
paySignReqHandler.SetParameter("url", decodeUrl);
signature = paySignReqHandler.CreateSHA1Sign();
return new JsSdkResp
{
AppId = appId,
Timestamp = timeStamp,
NonceStr = nonceStr,
Signature = signature
};
}
#endregion
#region JS-SDK权限验证的签名Signature
/// <summary>
/// 获取企业微信的JS-SDK权限验证的签名Signature
/// </summary>
/// <param name="jsapi_ticket">jsapi_ticket</param>
/// <param name="noncestr">随机字符串(必须与wx.config中的nonceStr相同)</param>
/// <param name="timestamp">时间戳(必须与wx.config中的timestamp相同)</param>
/// <param name="url">当前网页的URL不包含#及其后面部分(必须是调用JS接口页面的完整URL)</param>
/// <returns></returns>
private string GetSignature(string jsapi_ticket, string noncestr, long timestamp, string url)
{
StringBuilder sb = new StringBuilder();
sb.Append("jsapi_ticket=").Append(jsapi_ticket).Append("&")
.Append("noncestr=").Append(noncestr).Append("&")
.Append("timestamp=").Append(timestamp).Append("&")
.Append("url=").Append(url.IndexOf("#") >= 0 ? url.Substring(0, url.IndexOf("#")) : url);
string dddd = sb.ToString();
LogHelper.Info("Signature: " + dddd);
return Senparc.CO2NET.Helpers.EncryptHelper.GetSha1(sb.ToString()).ToLower();
}
#endregion
//#region GetJsSdk(取得企业微信某个应用的JsSdk相关参数值)
///// <summary>
///// 取得企业微信某个应用的JsSdk相关参数值
///// </summary>
///// <param name="url"></param>
///// <param name="tokenType">第一步传 1 第二步传2</param>
///// <returns></returns>
//public EnterpriseWechatJsSdkResp GetJsSdk(string url, int tokenType = 1)
//{
// EnterpriseWechatJsSdkResp result = new EnterpriseWechatJsSdkResp();
// string corpId = companyConfig.Corpid;
// string agentId = companyConfig.CustomerAgentidId.Replace("\r\n", "");
// string secret = companyConfig.CustomerDetailSecret;
// string ticket = "";
// string token = GetAccessToken(corpId, secret);
// long timeStamp = 0;
// string nonceStr = "";
// if (tokenType == 1)
// {
// ticket = GetTicket(token);
// timeStamp = long.Parse(JSSDKHelper.GetTimestamp());
// nonceStr = JSSDKHelper.GetNoncestr();
// }
// else if (tokenType == 2)
// {
// result = _myCodeCacheService.Get<EnterpriseWechatJsSdkResp>(companyConfig.Corpid + "1");
// ticket = GetApplicationTicket(token);
// timeStamp = long.Parse(result.Timestamp);
// nonceStr = result.NonceStr;
// }
// else
// {
// return null;
// }
// //var decodeUrl = HttpUtility.UrlDecode(url);
// string signature = GetSignature(ticket, nonceStr, timeStamp, url);
// result.CorpId = corpId;
// result.AgentId = agentId;
// result.NonceStr = nonceStr;
// result.Signature = signature;
// result.Timestamp = timeStamp.ToString();
// //LogHelper.Info("result:");
// //LogHelper.Info(result);
// _myCodeCacheService.Set(cacheKey, result, new TimeSpan(1, 0, 0));
// return result;
//}
//#endregion
#region GetDepartmentList()
/// <summary>
/// 取得通讯录的部门列表使用通讯录Token
/// </summary>
/// <param name="accessToken">Token</param>
/// <returns></returns>
public List<DepartmentHasChild> GetDepartmentList(string accessToken, string corpId, string secret)
{
if (string.IsNullOrWhiteSpace(accessToken))
{
accessToken = GetAccessToken(corpId, secret);
}
var url = $"{apiUrl}cgi-bin/department/list?access_token={accessToken}";
var resp = Get<DepartmentResp>(url);
if (resp.Department == null || resp.Department.Count == 0) { return new List<DepartmentHasChild> { }; }
return GetDepartmentChild(resp.Department, 0);
}
#endregion
#region GetDepartmentMemberList()
/// <summary>
/// 得到部门的员工列表
/// </summary>
/// <param name="accessToken">通讯录的token</param>
/// <param name="departmentId">部门id</param>
/// <param name="fetch_child">是否递归获取子部门下面的成员1-递归获取0-只获取本部门</param>
/// <returns></returns>
public List<DepartmentMemberInfo> GetDepartmentMemberList(string accessToken, long departmentId, string corpId, string secret, int fetch_child = 0)
{
//if (departmentId == 0) { throw new BaseException("部门id不能为0"); }
if (string.IsNullOrWhiteSpace(accessToken))
{
accessToken = GetAccessToken(corpId, secret);
}
var url = $"{apiUrl}cgi-bin/user/simplelist?access_token={accessToken}&department_id={departmentId}&fetch_child={fetch_child}";//是否递归获取子部门下面的成员1-递归获取0-只获取本部门
var resp = Get<DepartmentMemberInfoResp>(url);
if (resp.Userlist == null || resp.Userlist.Count == 0) { return new List<DepartmentMemberInfo> { }; }
return resp.Userlist;
}
#endregion
#region GetEmployeeInfo()
/// <summary>
/// 获取员工信息
/// </summary>
/// <param name="userId">员工id</param>
/// <returns></returns>
public EnterpriseEmployeeInfo GetEmployeeInfo(string userId, string corpId, string secret)
{
if (string.IsNullOrWhiteSpace(userId)) { throw new BaseException("员工id不能为空"); }
var accessToken = GetAccessToken(corpId, secret);
var url = $"{apiUrl}/cgi-bin/user/get?access_token={accessToken}&userid={userId}";
var webUtils = new WebUtils();
var resp = webUtils.DoGet<EnterpriseEmployeeInfo>(url, null);
return resp;
}
#endregion
//#region GetLoginUserInfo(获取登录用户信息)
///// <summary>
///// 获取登录用户信息
///// </summary>
///// <param name="code"></param>
///// <param name="corpId"></param>
///// <param name="secret">自建应用secret</param>
///// <returns></returns>
//public UserInfoResp GetLoginUserInfo(string code, string corpId = "", string secret = "")
//{
// var accessToken = GetAccessToken(corpId, secret);
// var url = $"{apiUrl}/cgi-bin/user/getuserinfo?access_token={accessToken}&code={code}";
// var result = Get<UserInfoResp>(url);
// return result;
//}
//#endregion
#region url读取内容到内存Stream流中
/// <summary>
/// 从url读取内容到内存Stream流中
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public Stream DownLoadFielToStream(string url)
{
var wreq = HttpWebRequest.Create(url) as HttpWebRequest;
HttpWebResponse response = wreq.GetResponse() as HttpWebResponse;
MemoryStream ms = null;
using (var stream = response.GetResponseStream())
{
Byte[] buffer = new Byte[response.ContentLength];
int offset = 0, actuallyRead = 0;
do
{
actuallyRead = stream.Read(buffer, offset, buffer.Length - offset);
offset += actuallyRead;
}
while (actuallyRead > 0);
ms = new MemoryStream(buffer);
}
response.Close();
return ms;
}
#endregion
//#region openid转userid
///// <summary>
///// openid转userid
///// </summary>
///// <param name="openid"></param>
///// <param name="corpId"></param>
///// <param name="secret">通讯录secret</param>
///// <returns></returns>
//public OpenIdChangeUseridResp GetUseridByOpenid(string openid, string corpId = "", string secret = "")
//{
// var accessToken = GetAccessToken(corpId, secret);
// var url = $"{apiUrl}cgi-bin/user/convert_to_userid?access_token={accessToken}";
// var webUtils = new WebUtils();
// var resp = webUtils.DoGet<OpenIdChangeUseridResp>(url, null);
// return resp;
//}
//#endregion
#region userid转openid
/// <summary>
/// userid转openid
/// </summary>
/// <param name="openid"></param>
/// <param name="corpId"></param>
/// <param name="secret">通讯录secret</param>
/// <returns></returns>
public UserIdChangeOpenIdResp GetOpenidByUserid(string userId, string corpId = "", string secret = "")
{
var accessToken = GetAccessToken(corpId, secret);
var url = $"{apiUrl}cgi-bin/user/convert_to_openid?access_token={accessToken}";
string json = $@"{{
""userid"": ""{userId}""
}}";
var webUtils = new WebUtils();
var resp = webUtils.DoPostJson(url, json);
UserIdChangeOpenIdResp resut = JsonHelper.ToObject<UserIdChangeOpenIdResp>(resp);
return resut;
}
#endregion
}
}