Beispiel #1
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);
        }
Beispiel #2
0
    /// <summary>
    /// 将消息加密,返回加密后字符串
    /// </summary>
    /// <param name="sReplyMsg">传递的消息体明文</param>
    /// <param name="sTimeStamp">时间戳</param>
    /// <param name="sNonce">随机字符串</param>
    /// <param name="sEncryptMsg">加密后的消息信息</param>
    /// <returns>成功0,失败返回对应的错误码</returns>
    public int EncryptMsg(string sReplyMsg, string sTimeStamp, string sNonce, ref string sEncryptMsg, ref string signature)
    {
        if (string.IsNullOrEmpty(sReplyMsg))
        {
            return((int)DingTalkCryptErrorCode.ENCRYPTION_PLAINTEXT_ILLEGAL);
        }
        if (string.IsNullOrEmpty(sTimeStamp))
        {
            return((int)DingTalkCryptErrorCode.ENCRYPTION_TIMESTAMP_ILLEGAL);
        }
        if (string.IsNullOrEmpty(sNonce))
        {
            return((int)DingTalkCryptErrorCode.ENCRYPTION_NONCE_ILLEGAL);
        }

        if (m_sEncodingAESKey.Length != AES_ENCODE_KEY_LENGTH)
        {
            return((int)DingTalkCryptErrorCode.AES_KEY_ILLEGAL);
        }

        string raw = "";

        try
        {
            raw = Cryptography.AES_encrypt(sReplyMsg, m_sEncodingAESKey, m_sSuiteKey);
        }
        catch (Exception)
        {
            return((int)DingTalkCryptErrorCode.AES_KEY_ILLEGAL);
        }

        string msgSigature = "";
        int    ret         = GenerateSignature(m_sToken, sTimeStamp, sNonce, raw, ref msgSigature);

        sEncryptMsg = raw;
        signature   = msgSigature;
        return(ret);
    }
        public async Task InvokeAsync(HttpContext context)
        {
            var request = context.Request;

            if (request.Path.Value.Contains(_options.Value.LazyWechatListener))
            {
                bool validation = Validate(out string signature, out string timestamp, out string nonce, out string echostr);

                var info = "signature:{0},timestamp:{1},nonce:{2},echostr:{3} received from wechat at {4}";
                _logger.LogInformation(info, signature, timestamp, nonce, echostr, DateTime.Now);

                var weChatMessager = new WeChatMessager
                {
                    signature  = signature,
                    timestamp  = timestamp,
                    nonce      = nonce,
                    echostr    = echostr,
                    validation = validation,
                    type       = _options.Value.Type,
                    method     = context.Request.Method
                };

                #region 以stream的方式获取微信post到监听程序的数据:数据类型为XML
                var inputContent = "";
                using (StreamReader stream = new StreamReader(request.Body, Encoding.UTF8))
                {
                    inputContent = await stream.ReadToEndAsync();
                }
                #endregion

                info = "inputXml:'{0}' received from wechat at {1}";
                _logger.LogInformation(info, inputContent, DateTime.Now);

                var encrypted = false;

                if (!string.IsNullOrEmpty(inputContent))
                {
                    dynamic messageBody = new ExpandoObject();
                    messageBody           = ParseMessage(inputContent, out MessageFormat format);
                    weChatMessager.format = format;

                    if (UtilRepository.IsPropertyExist(messageBody, "Encrypt"))
                    {
                        string decryptedMessage = Cryptography.AES_decrypt(messageBody.Encrypt, _options.Value.EncodingAESKey);
                        messageBody = ParseMessage(decryptedMessage, out _);
                        encrypted   = true;
                    }

                    weChatMessager.messageBody = messageBody;

                    if (UtilRepository.IsPropertyExist(messageBody, "FromUserName"))
                    {
                        _onMessageReceived?.Invoke(weChatMessager);
                    }

                    var json = JsonConvert.SerializeObject(weChatMessager);
                    _ = _messageQueue.Push(json);

                    info = "json format of message:'{0}' has been pushed into queue at {1}";
                    _logger.LogInformation(info, json, DateTime.Now);
                }

                var message = weChatMessager.message;

                if (encrypted && message.ToLower() != "success")
                {
                    var encryptMessage    = Cryptography.AES_encrypt(weChatMessager.message, _options.Value.EncodingAESKey, _options.Value.AppID);
                    var signatureResponse = generateSignature(timestamp, nonce, encryptMessage);
                    message = string.Format(MessageTemplateFactory.CreateInstance(weChatMessager.format == MessageFormat.Xml ? MessageType.Encrypt : MessageType.EncryptJson), encryptMessage, signatureResponse, timestamp, nonce);
                }

                info = "sent message:'{0}' has been logged at {1}";
                _logger.LogInformation(info, message, DateTime.Now);

                await context.Response.WriteAsync(message);
            }
            else
            {
                await _next(context);
            }

            bool Validate(out string signature, out string timestamp, out string nonce, out string echostr)
            {
                #region 微信在向监听程序发送数据的时候会同时发送signature,timestamp,nonce以及echostr供用户判断该请求是否来自微信端
                signature = string.IsNullOrEmpty(request.Query["signature"]) ? "" : request.Query["signature"].ToString();

                timestamp = string.IsNullOrEmpty(request.Query["timestamp"]) ? "" : request.Query["timestamp"].ToString();

                nonce = string.IsNullOrEmpty(request.Query["nonce"]) ? "" : request.Query["nonce"].ToString();

                echostr = string.IsNullOrEmpty(request.Query["echostr"]) ? "" : request.Query["echostr"].ToString();

                #endregion

                List <string> lstSort = new List <string> {
                    _options.Value.Token, timestamp, nonce
                };
                lstSort.Sort();
                var sha1 = string.Join(string.Empty, lstSort).SHA1();

                var validation = (sha1.ToUpper() == signature.ToUpper());
                return(validation);
            }

            string generateSignature(string timestamp, string nonce, string encryptMessage)
            {
                ArrayList AL = new ArrayList();

                AL.Add(_options.Value.Token);
                AL.Add(timestamp);
                AL.Add(nonce);
                AL.Add(encryptMessage);
                AL.Sort(new DictionarySort());
                string raw = "";

                for (int i = 0; i < AL.Count; ++i)
                {
                    raw += AL[i];
                }

                SHA1          sha;
                ASCIIEncoding enc;
                string        hash = "";

                sha = new SHA1CryptoServiceProvider();
                enc = new ASCIIEncoding();
                byte[] dataToHash = enc.GetBytes(raw);
                byte[] dataHashed = sha.ComputeHash(dataToHash);
                hash = BitConverter.ToString(dataHashed).Replace("-", "");
                hash = hash.ToLower();

                return(hash);
            }

            dynamic ParseMessage(string inputContent, out MessageFormat format)
            {
                inputContent = inputContent.Trim().Replace("\n", "");
                dynamic messageBody = new ExpandoObject();

                if (inputContent.StartsWith("<") && inputContent.EndsWith(">"))
                {
                    messageBody = UtilRepository.ParseAPIResult(JsonConvert.SerializeObject(inputContent.FromXml()));
                    format      = MessageFormat.Xml;
                }
                else if (inputContent.StartsWith("{") && inputContent.EndsWith("}"))
                {
                    messageBody = UtilRepository.ParseAPIResult(inputContent);
                    format      = MessageFormat.Json;
                }
                else
                {
                    throw new ArgumentException(nameof(inputContent));
                }
                return(messageBody);
            }
        }