新野县12345_后端

WXBizMsgCrypt.cs 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Xml;
  6. using System.Collections;
  7. //using System.Web;
  8. using System.Security.Cryptography;
  9. //-40001 : 签名验证错误
  10. //-40002 : xml解析失败
  11. //-40003 : sha加密生成签名失败
  12. //-40004 : AESKey 非法
  13. //-40005 : appid 校验错误
  14. //-40006 : AES 加密失败
  15. //-40007 : AES 解密失败
  16. //-40008 : 解密后得到的buffer非法
  17. //-40009 : base64加密异常
  18. //-40010 : base64解密异常
  19. namespace CallCenterAPI.WechatSDK.Code
  20. {
  21. public class WXBizMsgCrypt
  22. {
  23. string m_sToken;
  24. string m_sEncodingAESKey;
  25. string m_sAppID;
  26. enum WXBizMsgCryptErrorCode
  27. {
  28. WXBizMsgCrypt_OK = 0,
  29. WXBizMsgCrypt_ValidateSignature_Error = -40001,
  30. WXBizMsgCrypt_ParseXml_Error = -40002,
  31. WXBizMsgCrypt_ComputeSignature_Error = -40003,
  32. WXBizMsgCrypt_IllegalAesKey = -40004,
  33. WXBizMsgCrypt_ValidateAppid_Error = -40005,
  34. WXBizMsgCrypt_EncryptAES_Error = -40006,
  35. WXBizMsgCrypt_DecryptAES_Error = -40007,
  36. WXBizMsgCrypt_IllegalBuffer = -40008,
  37. WXBizMsgCrypt_EncodeBase64_Error = -40009,
  38. WXBizMsgCrypt_DecodeBase64_Error = -40010
  39. };
  40. //构造函数
  41. // @param sToken: 公众平台上,开发者设置的Token
  42. // @param sEncodingAESKey: 公众平台上,开发者设置的EncodingAESKey
  43. // @param sAppID: 公众帐号的appid
  44. public WXBizMsgCrypt(string sToken, string sEncodingAESKey, string sAppID)
  45. {
  46. m_sToken = sToken;
  47. m_sAppID = sAppID;
  48. m_sEncodingAESKey = sEncodingAESKey;
  49. }
  50. // 检验消息的真实性,并且获取解密后的明文
  51. // @param sMsgSignature: 签名串,对应URL参数的msg_signature
  52. // @param sTimeStamp: 时间戳,对应URL参数的timestamp
  53. // @param sNonce: 随机串,对应URL参数的nonce
  54. // @param sPostData: 密文,对应POST请求的数据
  55. // @param sMsg: 解密后的原文,当return返回0时有效
  56. // @return: 成功0,失败返回对应的错误码
  57. public int DecryptMsg(string sMsgSignature, string sTimeStamp, string sNonce, string sPostData, ref string sMsg)
  58. {
  59. if (m_sEncodingAESKey.Length != 43)
  60. {
  61. return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
  62. }
  63. XmlDocument doc = new XmlDocument();
  64. XmlNode root;
  65. string sEncryptMsg;
  66. try
  67. {
  68. doc.LoadXml(sPostData);
  69. root = doc.FirstChild;
  70. sEncryptMsg = root["Encrypt"].InnerText;
  71. }
  72. catch (Exception)
  73. {
  74. return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ParseXml_Error;
  75. }
  76. //verify signature
  77. int ret = 0;
  78. ret = VerifySignature(m_sToken, sTimeStamp, sNonce, sEncryptMsg, sMsgSignature);
  79. if (ret != 0)
  80. return ret;
  81. //decrypt
  82. string cpid = "";
  83. try
  84. {
  85. sMsg = Cryptography.AES_decrypt(sEncryptMsg, m_sEncodingAESKey, ref cpid);
  86. }
  87. catch (FormatException)
  88. {
  89. return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecodeBase64_Error;
  90. }
  91. catch (Exception)
  92. {
  93. return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecryptAES_Error;
  94. }
  95. if (cpid != m_sAppID)
  96. return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateAppid_Error;
  97. return 0;
  98. }
  99. //将企业号回复用户的消息加密打包
  100. // @param sReplyMsg: 企业号待回复用户的消息,xml格式的字符串
  101. // @param sTimeStamp: 时间戳,可以自己生成,也可以用URL参数的timestamp
  102. // @param sNonce: 随机串,可以自己生成,也可以用URL参数的nonce
  103. // @param sEncryptMsg: 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串,
  104. // 当return返回0时有效
  105. // return:成功0,失败返回对应的错误码
  106. public int EncryptMsg(string sReplyMsg, string sTimeStamp, string sNonce, ref string sEncryptMsg)
  107. {
  108. if (m_sEncodingAESKey.Length != 43)
  109. {
  110. return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
  111. }
  112. string raw = "";
  113. try
  114. {
  115. raw = Cryptography.AES_encrypt(sReplyMsg, m_sEncodingAESKey, m_sAppID);
  116. }
  117. catch (Exception)
  118. {
  119. return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_EncryptAES_Error;
  120. }
  121. string MsgSigature = "";
  122. int ret = 0;
  123. ret = GenarateSinature(m_sToken, sTimeStamp, sNonce, raw, ref MsgSigature);
  124. if (0 != ret)
  125. return ret;
  126. sEncryptMsg = "";
  127. string EncryptLabelHead = "<Encrypt><![CDATA[";
  128. string EncryptLabelTail = "]]></Encrypt>";
  129. string MsgSigLabelHead = "<MsgSignature><![CDATA[";
  130. string MsgSigLabelTail = "]]></MsgSignature>";
  131. string TimeStampLabelHead = "<TimeStamp><![CDATA[";
  132. string TimeStampLabelTail = "]]></TimeStamp>";
  133. string NonceLabelHead = "<Nonce><![CDATA[";
  134. string NonceLabelTail = "]]></Nonce>";
  135. sEncryptMsg = sEncryptMsg + "<xml>" + EncryptLabelHead + raw + EncryptLabelTail;
  136. sEncryptMsg = sEncryptMsg + MsgSigLabelHead + MsgSigature + MsgSigLabelTail;
  137. sEncryptMsg = sEncryptMsg + TimeStampLabelHead + sTimeStamp + TimeStampLabelTail;
  138. sEncryptMsg = sEncryptMsg + NonceLabelHead + sNonce + NonceLabelTail;
  139. sEncryptMsg += "</xml>";
  140. return 0;
  141. }
  142. public class DictionarySort : System.Collections.IComparer
  143. {
  144. public int Compare(object oLeft, object oRight)
  145. {
  146. string sLeft = oLeft as string;
  147. string sRight = oRight as string;
  148. int iLeftLength = sLeft.Length;
  149. int iRightLength = sRight.Length;
  150. int index = 0;
  151. while (index < iLeftLength && index < iRightLength)
  152. {
  153. if (sLeft[index] < sRight[index])
  154. return -1;
  155. else if (sLeft[index] > sRight[index])
  156. return 1;
  157. else
  158. index++;
  159. }
  160. return iLeftLength - iRightLength;
  161. }
  162. }
  163. //Verify Signature
  164. private static int VerifySignature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, string sSigture)
  165. {
  166. string hash = "";
  167. int ret = 0;
  168. ret = GenarateSinature(sToken, sTimeStamp, sNonce, sMsgEncrypt, ref hash);
  169. if (ret != 0)
  170. return ret;
  171. //System.Console.WriteLine(hash);
  172. if (hash == sSigture)
  173. return 0;
  174. else
  175. {
  176. return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateSignature_Error;
  177. }
  178. }
  179. public static int GenarateSinature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, ref string sMsgSignature)
  180. {
  181. ArrayList AL = new ArrayList();
  182. AL.Add(sToken);
  183. AL.Add(sTimeStamp);
  184. AL.Add(sNonce);
  185. AL.Add(sMsgEncrypt);
  186. AL.Sort(new DictionarySort());
  187. string raw = "";
  188. for (int i = 0; i < AL.Count; ++i)
  189. {
  190. raw += AL[i];
  191. }
  192. SHA1 sha;
  193. ASCIIEncoding enc;
  194. string hash = "";
  195. try
  196. {
  197. sha = new SHA1CryptoServiceProvider();
  198. enc = new ASCIIEncoding();
  199. byte[] dataToHash = enc.GetBytes(raw);
  200. byte[] dataHashed = sha.ComputeHash(dataToHash);
  201. hash = BitConverter.ToString(dataHashed).Replace("-", "");
  202. hash = hash.ToLower();
  203. }
  204. catch (Exception)
  205. {
  206. return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ComputeSignature_Error;
  207. }
  208. sMsgSignature = hash;
  209. return 0;
  210. }
  211. }
  212. }