Files
大灰灰 94e5145b7b !92 调整redis队列,删除盛派【Senparc】相关组件等更新
* 1、【后端】移除业务逻辑中的【MediatR】及中介者模式,启用【Redis队列】处理。
* Merge branch 'develop' into dahuihui/develop
* 升级编辑器为CKEditor5
* Merge branch 'develop' into dahuihui/develop
* Merge branch 'develop' into dahuihui/develop
* 【后端】优化后端设置权限角色,反射controller和action的效率问题。
* 【后端】修复后端编辑商品问题。
* 【后端】修复腾讯云cos存储未调用bucket问题。#I42DF0
* Merge branch 'develop' into dahuihui/develop
* 启用新域名及演示平台
* Merge branch 'develop' into dahuihui/develop
* Merge branch 'develop' into dahuihui/develop
* 调整说明
* Merge branch 'develop' into dahuihui/develop
* 删除不需要的菜单
* 修复域名转发获取ip地址长度过长问题。
* 1、【后端】调整全局错误返回提示语。2、【数据库】修复20日删除3个表后,未清理干净问题。
* Merge branch 'develop' into dahuihui/develop
* Merge branch 'develop' into dahuihui/develop
* 调整全局错误返回提示语
* 修复商品批量处理报错的问题并优化展示界面。#I3X8PP
* Merge branch 'develop' into dahuihui/develop
* Merge branch 'develop' into dahuihui/develop
* 增加过滤敏感词的功能。#I3W6CM
* 增加Issue 和 Pull Request 模板
* 修复自定义上传路径上传至站点根目录,而非wwwroot的问题 #I41TD1
* Merge branch 'develop' into dahuihui/develop
* 修复自定义上传路径的表单命名异常问题
* 使用新数据库
* 【数据库】修复mysql数据库decimal类型未带小数的问题。#I3WAUY
* 更新数据库及脚本
* 2021-07-20
* Merge branch 'develop' into dahuihui/develop
* 修复webapi不进入调试断点的问题。
* Merge branch 'develop' into dahuihui/develop
* 修复后台前后端分离table面板启用自定义域名问题。
* 修复后台前后端分离域名未增加到html问题。
* Merge branch 'develop' into dahuihui/develop
* 【后端】修复修改登录用户真实姓名长度问题。
* 修复后台管理配送方式维护错误问题
* 1、修复小程序注册问题,导致交互事情。不然盛派的组件有bug,在不注册微信公众号只注册微信小程序的时候,进行小程序消息操作,默认还是走的是微…
* 修复消息模板不推送的问题
* Merge branch 'develop' into dahuihui/develop
* Merge branch 'develop' into dahuihui/develop
* 修复过期失效文档
* 调整代码生成器,增加初始化事务
* 调整接口端提示界面
* 修复弹窗不居中问题
* 调整一些命名方式
* 修复uni-app前端,用户订单列表【确认收货】按钮失效问题
* 1、修复mysql数据库下,报表统计sql的语法错误。2、为方便前端在不部署接口及后端的情况下测试uni-app前端,默认增加了测试接口地址…
* Merge branch 'develop' into dahuihui/develop
* 调整命名
* 增加docker-compose部署
* Merge branch 'develop' into dahuihui/develop
* 修复因linux下存在数据与文件名称大小写不对应,导致找不到数据库表的问题,特重新发布一份表名与实体名称一一对应脚本。
* 新mysql表名存在大小写问题
2021-08-01 09:47:47 +00:00

222 lines
8.4 KiB
C#
Raw Permalink 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections;
//using System.Web;
using System.Security.Cryptography;
//-40001 : 签名验证错误
//-40002 : xml解析失败
//-40003 : sha加密生成签名失败
//-40004 : AESKey 非法
//-40005 : appid 校验错误
//-40006 : AES 加密失败
//-40007 : AES 解密失败
//-40008 : 解密后得到的buffer非法
//-40009 : base64加密异常
//-40010 : base64解密异常
namespace CoreCms.Net.WeChat.Service.Utilities
{
public class WXBizMsgCrypt
{
string m_sToken;
string m_sEncodingAESKey;
string m_sAppID;
enum WXBizMsgCryptErrorCode
{
WXBizMsgCrypt_OK = 0,
WXBizMsgCrypt_ValidateSignature_Error = -40001,
WXBizMsgCrypt_ParseXml_Error = -40002,
WXBizMsgCrypt_ComputeSignature_Error = -40003,
WXBizMsgCrypt_IllegalAesKey = -40004,
WXBizMsgCrypt_ValidateAppid_Error = -40005,
WXBizMsgCrypt_EncryptAES_Error = -40006,
WXBizMsgCrypt_DecryptAES_Error = -40007,
WXBizMsgCrypt_IllegalBuffer = -40008,
WXBizMsgCrypt_EncodeBase64_Error = -40009,
WXBizMsgCrypt_DecodeBase64_Error = -40010
};
//构造函数
// @param sToken: 公众平台上,开发者设置的Token
// @param sEncodingAESKey: 公众平台上,开发者设置的EncodingAESKey
// @param sAppID: 公众帐号的appid
public WXBizMsgCrypt(string sToken, string sEncodingAESKey, string sAppID)
{
m_sToken = sToken;
m_sAppID = sAppID;
m_sEncodingAESKey = sEncodingAESKey;
}
// 检验消息的真实性,并且获取解密后的明文
// @param sMsgSignature: 签名串,对应URL参数的msg_signature
// @param sTimeStamp: 时间戳,对应URL参数的timestamp
// @param sNonce: 随机串,对应URL参数的nonce
// @param sPostData: 密文,对应POST请求的数据
// @param sMsg: 解密后的原文,当return返回0时有效
// @return: 成功0,失败返回对应的错误码
public int DecryptMsg(string sMsgSignature, string sTimeStamp, string sNonce, string sPostData, ref string sMsg)
{
if (m_sEncodingAESKey.Length != 43)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
}
XmlDocument doc = new XmlDocument();
XmlNode root;
string sEncryptMsg;
try
{
doc.LoadXml(sPostData);
root = doc.FirstChild;
sEncryptMsg = root["Encrypt"].InnerText;
}
catch (Exception)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ParseXml_Error;
}
//verify signature
int ret = 0;
ret = VerifySignature(m_sToken, sTimeStamp, sNonce, sEncryptMsg, sMsgSignature);
if (ret != 0)
return ret;
//decrypt
string cpid = "";
try
{
sMsg = Cryptography.AES_decrypt(sEncryptMsg, m_sEncodingAESKey, ref cpid);
}
catch (FormatException)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecodeBase64_Error;
}
catch (Exception)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecryptAES_Error;
}
if (cpid != m_sAppID)
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateAppid_Error;
return 0;
}
//将企业号回复用户的消息加密打包
// @param sReplyMsg: 企业号待回复用户的消息,xml格式的字符串
// @param sTimeStamp: 时间戳,可以自己生成,也可以用URL参数的timestamp
// @param sNonce: 随机串,可以自己生成,也可以用URL参数的nonce
// @param sEncryptMsg: 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串,
// 当return返回0时有效
// return:成功0,失败返回对应的错误码
public int EncryptMsg(string sReplyMsg, string sTimeStamp, string sNonce, ref string sEncryptMsg)
{
if (m_sEncodingAESKey.Length != 43)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
}
string raw = "";
try
{
raw = Cryptography.AES_encrypt(sReplyMsg, m_sEncodingAESKey, m_sAppID);
}
catch (Exception)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_EncryptAES_Error;
}
string MsgSigature = "";
int ret = 0;
ret = GenarateSinature(m_sToken, sTimeStamp, sNonce, raw, ref MsgSigature);
if (0 != ret)
return ret;
sEncryptMsg = "";
string EncryptLabelHead = "<Encrypt><![CDATA[";
string EncryptLabelTail = "]]></Encrypt>";
string MsgSigLabelHead = "<MsgSignature><![CDATA[";
string MsgSigLabelTail = "]]></MsgSignature>";
string TimeStampLabelHead = "<TimeStamp><![CDATA[";
string TimeStampLabelTail = "]]></TimeStamp>";
string NonceLabelHead = "<Nonce><![CDATA[";
string NonceLabelTail = "]]></Nonce>";
sEncryptMsg = sEncryptMsg + "<xml>" + EncryptLabelHead + raw + EncryptLabelTail;
sEncryptMsg = sEncryptMsg + MsgSigLabelHead + MsgSigature + MsgSigLabelTail;
sEncryptMsg = sEncryptMsg + TimeStampLabelHead + sTimeStamp + TimeStampLabelTail;
sEncryptMsg = sEncryptMsg + NonceLabelHead + sNonce + NonceLabelTail;
sEncryptMsg += "</xml>";
return 0;
}
public class DictionarySort : System.Collections.IComparer
{
public int Compare(object oLeft, object oRight)
{
string sLeft = oLeft as string;
string sRight = oRight as string;
int iLeftLength = sLeft.Length;
int iRightLength = sRight.Length;
int index = 0;
while (index < iLeftLength && index < iRightLength)
{
if (sLeft[index] < sRight[index])
return -1;
else if (sLeft[index] > sRight[index])
return 1;
else
index++;
}
return iLeftLength - iRightLength;
}
}
//Verify Signature
private static int VerifySignature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, string sSigture)
{
string hash = "";
int ret = 0;
ret = GenarateSinature(sToken, sTimeStamp, sNonce, sMsgEncrypt, ref hash);
if (ret != 0)
return ret;
//System.Console.WriteLine(hash);
if (hash == sSigture)
return 0;
else
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateSignature_Error;
}
}
public static int GenarateSinature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, ref string sMsgSignature)
{
ArrayList AL = new ArrayList();
AL.Add(sToken);
AL.Add(sTimeStamp);
AL.Add(sNonce);
AL.Add(sMsgEncrypt);
AL.Sort(new DictionarySort());
string raw = "";
for (int i = 0; i < AL.Count; ++i)
{
raw += AL[i];
}
SHA1 sha;
ASCIIEncoding enc;
string hash = "";
try
{
sha = new SHA1CryptoServiceProvider();
enc = new ASCIIEncoding();
byte[] dataToHash = enc.GetBytes(raw);
byte[] dataHashed = sha.ComputeHash(dataToHash);
hash = BitConverter.ToString(dataHashed).Replace("-", "");
hash = hash.ToLower();
}
catch (Exception)
{
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ComputeSignature_Error;
}
sMsgSignature = hash;
return 0;
}
}
}