/// <summary>
        /// 钉钉加密解密
        /// </summary>
        /// <param name="Msignature"></param>
        /// <param name="Mtimestamp"></param>
        /// <param name="Mnonce"></param>
        /// <param name="MencryptStr"></param>
        public string DingTalkCrypto(string Msignature, string Mtimestamp, string Mnonce, string MencryptStr)
        {
            DingTalkCrypt dingTalk = new DingTalkCrypt(token, aes_key, corpid);
            string PlainText = string.Empty;
            dingTalk.DecryptMsg(Msignature, Mtimestamp, Mnonce, MencryptStr, ref PlainText);
            Hashtable tb = (Hashtable)JsonConvert.DeserializeObject(PlainText, typeof(Hashtable));
            string EventType = tb["EventType"].ToString();
            //switch (EventType)
            //{
            //    default:
            //        break;
            //}

            CallbackEvent(tb);
            string timestamp = TopUtils.GetCurrentTimeMillis().ToString();
            string encrypt = "";
            string signature = "";
            string res = "success";//传递的消息体明文
            dingTalk = new DingTalkCrypt(token, aes_key, corpid);
            dingTalk.EncryptMsg(res, timestamp, Mnonce, ref encrypt, ref signature);
            Hashtable jsonMap = new Hashtable
                {
                    {"msg_signature", signature},
                    {"encrypt", encrypt},
                    {"timeStamp", timestamp},
                    {"nonce", Mnonce}
                };
            string result = JsonConvert.SerializeObject(jsonMap);
            LogHelper.Log("ReceiveCallbackSerivce result: " + result);
            return result;
        }
示例#2
0
        public object EncryptMsg(string sReplyMsg)
        {
            DingTalkCrypt dtc           = new DingTalkCrypt(Token, AesKey, _oper.CorpId);
            string        msg_signature = "128790jkdjkhdfkaue8819823712837912837608";
            string        timeStamp     = _oper.TimeStamp();
            string        nonce         = "998013";
            string        encrypt       = "";

            dtc.EncryptMsg(sReplyMsg, timeStamp, nonce, ref encrypt, ref msg_signature);
            var obj = new { msg_signature, timeStamp, nonce, encrypt };

            return(obj);
        }
示例#3
0
        public void ProcessRequest(HttpContext context)
        {
            try
            {
                #region 获取套件配置参数
                string mToken          = ConfigurationManager.AppSettings["Token"];
                string mSuiteKey       = "";
                string mEncodingAesKey = ConfigurationManager.AppSettings["EncodingAESKey"];
                //mSuiteKey = "suite4xxxxxxxxxxxxxxx";
                #endregion

                #region 获取回调URL里面的参数
                //url中的签名
                string msgSignature = context.Request["signature"];
                //url中的时间戳
                string timeStamp = context.Request["timestamp"];
                //url中的随机字符串
                string nonce = context.Request["nonce"];
                //post数据包数据中的加密数据
                string encryptStr = GetPostParam(context);
                #endregion

                string sEchoStr = "";

                #region 验证回调的url
                SuiteAuth suiteAuth = new SuiteAuth();

                var ret = suiteAuth.VerifyURL(mToken, mEncodingAesKey, msgSignature, timeStamp, nonce, encryptStr,
                                              ref mSuiteKey);

                if (ret != 0)
                {
                    Helper.WriteLog("ERR: VerifyURL fail, ret: " + ret);
                    return;
                }
                #endregion

                #region
                //构造DingTalkCrypt
                DingTalkCrypt dingTalk = new DingTalkCrypt(mToken, mEncodingAesKey, mSuiteKey);

                string plainText = "";
                dingTalk.DecryptMsg(msgSignature, timeStamp, nonce, encryptStr, ref plainText);
                Hashtable tb        = (Hashtable)JsonConvert.DeserializeObject(plainText, typeof(Hashtable));
                string    eventType = tb["EventType"].ToString();
                string    res       = "success";
                Helper.WriteLog("plainText:" + plainText);
                Helper.WriteLog("eventType:" + eventType);
                switch (eventType)
                {
                case "suite_ticket":    //定时推送Ticket
                    ConfigurationManager.AppSettings["SuiteTicket"] = tb["SuiteTicket"].ToString();
                    mSuiteKey = tb["SuiteKey"].ToString();
                    suiteAuth.SaveSuiteTicket(tb);
                    break;

                case "tmp_auth_code":    //钉钉推送过来的临时授权码
                    ConfigurationManager.AppSettings["TmpAuthCode"] = tb["AuthCode"].ToString();
                    suiteAuth.SaveTmpAuthCode(tb);
                    break;

                case "change_auth":    // do something;
                    break;

                case "check_update_suite_url":
                    res       = tb["Random"].ToString();
                    mSuiteKey = tb["TestSuiteKey"].ToString();
                    break;
                }

                timeStamp = Helper.GetTimeStamp().ToString();
                string encrypt   = "";
                string signature = "";
                dingTalk = new DingTalkCrypt(mToken, mEncodingAesKey, mSuiteKey);
                dingTalk.EncryptMsg(res, timeStamp, nonce, ref encrypt, ref signature);
                Hashtable jsonMap = new Hashtable
                {
                    { "msg_signature", signature },
                    { "encrypt", encrypt },
                    { "timeStamp", timeStamp },
                    { "nonce", nonce }
                };
                string result = JsonConvert.SerializeObject(jsonMap);
                context.Response.Write(result);
                #endregion
            }
            catch (Exception ex)
            {
                Helper.WriteLog(DateTime.Now + ex.Message);
            }
        }
示例#4
0
        public JsonResult Receive(string signature, string timestamp, string nonce, PostBody body)
        {
            LogHelper.WriteProgramLogInFolder(DateTime.Now.ToString() + " 接收回调!", "DDCallBack");
            Dictionary <int, string> dic = new Dictionary <int, string>();

            dic.Add(900001, "加密明文文本非法");
            dic.Add(900002, "加密时间戳参数非法");
            dic.Add(900003, "加密随机字符串参数非法");
            dic.Add(900004, "不合法的aeskey");
            dic.Add(900005, "签名不匹配");
            dic.Add(900006, "计算签名错误");
            dic.Add(900007, "计算加密文字错误");
            dic.Add(900008, "计算解密文字错误");
            dic.Add(900009, "计算解密文字长度不匹配");
            dic.Add(900010, "计算解密文字suiteKey不匹配");

            //接收encrypt参数
            string encryptStr = body.encrypt.Replace("{\"encrypt\":\"", "").Replace("\"}", "");

            //注册时填写的token、aes_key、suitekey
            string token = ConfigurationManager.AppSettings["SuiteToken"];
            //token = "123456";//钉钉测试文档中的token
            string aes_key = ConfigurationManager.AppSettings["Suiteaes_key"];
            //aes_key = "4g5j64qlyl3zvetqxz5jiocdr586fn2zvjpa8zls3ij";//钉钉测试文档中的aes_key
            string suitekey = ConfigurationManager.AppSettings["DD_corpid"];

            //suitekey = "suite4xxxxxxxxxxxxxxx";//钉钉测试文档中的suitekey

            #region 验证回调的url
            DingTalkCrypt dingTalk = new DingTalkCrypt(token, aes_key, suitekey);
            string        sEchoStr = "";
            int           ret      = dingTalk.VerifyURL(signature, timestamp, nonce, encryptStr, ref sEchoStr);
            if (ret != 0)
            {
                string message = "";
                if (dic.ContainsKey(ret))
                {
                    message = dic.Where(e => e.Key == ret).FirstOrDefault().Value;
                }

                LogHelper.WriteProgramLogInFolder(DateTime.Now.ToString() + " 验证回调发生错误,错误代码为:" + ret + " " + message, "DDCallBack");
                return(Json(new object()));
            }
            #endregion

            #region 解密接受信息,进行事件处理
            string plainText = "";
            ret = dingTalk.DecryptMsg(signature, timestamp, nonce, encryptStr, ref plainText);
            if (ret != 0)
            {
                string message = "";
                if (dic.ContainsKey(ret))
                {
                    message = dic.Where(e => e.Key == ret).FirstOrDefault().Value;
                }

                LogHelper.WriteProgramLogInFolder(DateTime.Now.ToString() + " 解密信息发生错误,错误代码为:" + ret + " " + message, "DDCallBack");
                return(Json(new object()));
            }

            Hashtable tb        = (Hashtable)JsonConvert.DeserializeObject(plainText, typeof(Hashtable));
            string    eventType = tb["EventType"].ToString();
            string    res       = "success";

            LogHelper.WriteProgramLogInFolder(DateTime.Now.ToString() + " 接收到的事件类型为:" + eventType, "DDCallBack");
            switch (eventType)
            {
            case "bpms_task_change":    //审批任务开始,结束,转交
                #region 执行代码 在此处添加业务逻辑代码,处理获取的审批单信息
                ApproveModel modelTask = JsonConvert.DeserializeObject <ApproveModel>(plainText);
                #endregion
                break;

            case "bpms_instance_change":    //审批实例开始,结束
                #region 执行代码 在此处添加业务逻辑代码,处理获取的审批单信息
                ApproveModel modelInstance = JsonConvert.DeserializeObject <ApproveModel>(plainText);
                #endregion
                break;

            default:
                break;
            }

            timestamp = DateTime.Now.GetTimeStamp().ToString();
            string encrypt    = "";
            string signature2 = "";
            dingTalk = new DingTalkCrypt(token, aes_key, suitekey);
            ret      = dingTalk.EncryptMsg(res, timestamp, nonce, ref encrypt, ref signature2);
            if (ret != 0)
            {
                string message = "";
                if (dic.ContainsKey(ret))
                {
                    message = dic.Where(e => e.Key == ret).FirstOrDefault().Value;
                }

                LogHelper.WriteProgramLogInFolder(DateTime.Now.ToString() + " 解密信息发生错误,错误代码为:" + ret + " " + message, "DDUserInfoUpdate");
                return(Json(new object()));
            }

            Hashtable jsonMap = new Hashtable
            {
                { "msg_signature", signature2 },
                { "encrypt", encrypt },
                { "timeStamp", timestamp },
                { "nonce", nonce }
            };

            return(Json(jsonMap));

            #endregion
        }
示例#5
0
        public ResponseModel Post(string signature, string timestamp, string nonce, [FromBody] RequestModel model)
        {
            ResponseModel result = new ResponseModel();
            var           Ddb    = DBHelper.Ddb;
            var           Edb    = DBHelper.Edb;

            _log.Info("请求参数为: signature=" + signature + "&timestamp=" + timestamp + "&nonce=" + nonce + ", FromBody=" + JsonHelper.JsonSerializer(model) + "\n");

            DingTalkCrypt dingTalkCrypt   = new DingTalkCrypt(JsonConfigurationHelper.GetAppSettings("DingTalkSettings", "CallBack_Token"), JsonConfigurationHelper.GetAppSettings("DingTalkSettings", "CallBack_SuiteKey"), JsonConfigurationHelper.GetAppSettings("DingTalkSettings", "CorpID"));
            int           decryptMsgcount = 1;
            int           encryptMsgCount = 1;
            string        dd_result       = "";
            string        sEncryptMsg     = "";
            string        msg_signature   = "";

            decryptMsgcount = dingTalkCrypt.DecryptMsg(signature, timestamp, nonce, model.encrypt, ref dd_result);

            result.timeStamp = timestamp;
            result.nonce     = nonce;
            try
            {
                if (decryptMsgcount == 0)
                {
                    ContactsEventModel contactsEventModel = JsonConvert.DeserializeObject <ContactsEventModel>(dd_result);
                    if (contactsEventModel.EventType == "check_url")
                    {
                        encryptMsgCount      = dingTalkCrypt.EncryptMsg("success", timestamp, nonce, ref sEncryptMsg, ref msg_signature);
                        result.encrypt       = sEncryptMsg;
                        result.msg_signature = msg_signature;
                        _log.Error(JsonConvert.SerializeObject(result));
                        return(result);
                    }

                    List <DingTalkCallBackLog> LogList = new List <DingTalkCallBackLog>();
                    int sqlExeCount = 0;
                    if (contactsEventModel.UserId != null)
                    {
                        foreach (var item in contactsEventModel.UserId)
                        {
                            DingTalkCallBackLog log = new DingTalkCallBackLog
                            {
                                UserId    = item,
                                EventType = contactsEventModel.EventType,
                                TimeStamp = contactsEventModel.TimeStamp
                            };
                            LogList.Add(log);
                        }
                        if (LogList.Count > 0)
                        {
                            sqlExeCount = Ddb.Insertable(LogList).ExecuteCommand();
                        }
                        if (sqlExeCount > 0)
                        {
                            encryptMsgCount = dingTalkCrypt.EncryptMsg("success", timestamp, nonce, ref sEncryptMsg, ref msg_signature);
                            if (encryptMsgCount == 0)
                            {
                                List <DingTalkCallBackOperation> userList = new List <DingTalkCallBackOperation>();
                                //日志记录成功后,根据钉钉回调的员工,检查hr中该员工状态为在职的人员
                                var user = Edb.Queryable <V_EmployeeToDingTalk>().Where(it => contactsEventModel.UserId.Contains(it.UserId) && it.Enabled == 1).ToList();
                                foreach (var item in user)
                                {
                                    //将员工为在职的人员重新添加到钉钉中
                                    bool b = EmployeeForDingTalkBll.AddEmployee(Edb, Ddb, item);
                                    DingTalkCallBackOperation DD_User = new DingTalkCallBackOperation();
                                    DD_User.EventType  = contactsEventModel.EventType;
                                    DD_User.TimeStamp  = contactsEventModel.TimeStamp;
                                    DD_User.UserId     = item.UserId;
                                    DD_User.CreateDate = DateTime.Now;
                                    if (b)
                                    {
                                        DD_User.IsOperation = 1;
                                    }
                                    userList.Add(DD_User);
                                }
                                if (userList.Count > 0)
                                {
                                    sqlExeCount = Ddb.Insertable(userList).ExecuteCommand();
                                    _log.Debug(sqlExeCount + "条数据执行成功\n");
                                }
                                result.encrypt       = sEncryptMsg;
                                result.msg_signature = msg_signature;
                            }
                            else
                            {
                                _log.Error("将消息加密,返回加密后字符串失败,返回加密前的参数为:" + dd_result + ",返回编码为: " + encryptMsgCount + "\n");
                            }
                        }
                    }
                    else
                    {
                        _log.Error("钉钉传递的UserList为空,返回解密前的参数为:" + JsonHelper.JsonSerializer(model) + ",返回编码为: " + decryptMsgcount + "\n");
                    }
                }
                else
                {
                    _log.Error("回调失败,请求参数为: signature = " + signature + " & timestamp = " + timestamp + " & nonce = " + nonce + ", FromBody = " + JsonHelper.JsonSerializer(model) + "\n错误详情如下:\n");
                }
            }
            catch (Exception ex)
            {
                _log.Error("回调失败,请求参数为: signature = " + signature + " & timestamp = " + timestamp + " & nonce = " + nonce + ", FromBody = " + JsonHelper.JsonSerializer(model) + "\n错误详情如下:\n" + ex);
            }

            return(result);
        }
示例#6
0
    protected void Page_Load(object sender, EventArgs e)
    {
        //正确的获取参数
        //签名的来源是使用时间戳,随机数,内容体和token 通过算法加密得到的
        //系统拿到这样几个参数后,首先要计算出签名与传递过来的签名是否相同,相同则说明是正确执行,不相同则说明传递的消息有可能被篡改
        string signature = Request["signature"]; //消息签名
        string timeStamp = Request["timestamp"]; //时间戳
        string nonce     = Request["nonce"];     //随机号
        string encrypt   = "";

        #region 得到内容体
        Stream sm        = Request.InputStream;           //获取post正文
        int    len       = (int)sm.Length;                //post数据长度
        byte[] inputByts = new byte[len];                 //字节数据,用于存储post数据
        sm.Read(inputByts, 0, len);                       //将post数据写入byte数组中
        sm.Close();                                       //关闭IO流
        string data = Encoding.UTF8.GetString(inputByts); //转为String
        encrypt = data.Replace("{\"encrypt\":\"", "").Replace("\"}", "");
        #endregion

        #region 日志
        Helper.WriteLog("===========================1、服务器方发送回来的值===========================");
        Helper.WriteLog("1、signature:" + signature);
        Helper.WriteLog("2、timeStamp:" + timeStamp);
        Helper.WriteLog("3、nonce:" + nonce);
        Helper.WriteLog("4、encrypt:" + encrypt);
        Helper.WriteLog("==========================================================================");
        #endregion

        #region 验证签名
        string newSignature = "";
        DingTalkCrypt.GenerateSignature(Config.Token, timeStamp, nonce, encrypt, ref newSignature);
        Helper.WriteLog("===========================3、新签名===========================");
        Helper.WriteLog("1、newSignature:" + newSignature + "\r\n");

        if (signature == newSignature)
        {
            Helper.WriteLog("太好了!签名验证通过!");
        }
        else
        {
            Helper.WriteLog("消息有可能被篡改!签名验证错误!");
            return;
        }
        Helper.WriteLog("==========================================================================");
        #endregion

        #region   解密服务器端发送回来的数据
        DingTalkCrypt dingTalk = new DingTalkCrypt(Config.Token, Config.ENCODING_AES_KEY, Config.SUITE_KEY);

        string plainText = "";
        dingTalk.DecryptMsg(signature, timeStamp, nonce, encrypt, ref plainText);
        Hashtable tb        = (Hashtable)JsonConvert.DeserializeObject(plainText, typeof(Hashtable));
        string    eventType = tb["EventType"].ToString();

        Helper.WriteLog("===========================4、解密服务器端发送回来的数据===========================");
        Helper.WriteLog("plainText:" + plainText);
        Helper.WriteLog("eventType:" + eventType);

        Helper.WriteLog("==========================================================================");
        #endregion


        //根据回调的不同类型做出相应的响应,这里要求要细看开发文档中的   接入指南-ISV接入-5:回调接口(分为五个回调类型)这一篇
        string res = "";

        if (eventType == "check_create_suite_url")
        {
            //验证有效性
            string random = tb["Random"].ToString();
            res = random;
        }
        else if (eventType == "suite_ticket")
        {
            //验证Ticket推送状态
            string ticket = tb["SuiteTicket"].ToString();   //回调推送过来的票证

            //拿票去换取后台的套件访问令牌
            string    surl  = "https://oapi.dingtalk.com/service/get_suite_token";
            string    param = "{\"suite_key\":\"" + Config.SUITE_KEY + "\",\"suite_secret\":\"" + Config.SUITE_KEY_SECRET + "\",\"suite_ticket\":\"" + ticket + "\"}";
            string    suite_access_token_result = HttpHelper.Post(surl, param);//套件的访问令牌
            Hashtable tb_suite_access_token     = (Hashtable)JsonConvert.DeserializeObject(suite_access_token_result, typeof(Hashtable));

            string suite_access_token = tb_suite_access_token["suite_access_token"].ToString();
            Application["suite_access_token"] = suite_access_token;
            Helper.WriteLog("suite_access_token:" + suite_access_token);
            res = "success";
        }
        else if (eventType == "tmp_auth_code")
        {
            //模拟授权
            string tmp_auth_code = tb["AuthCode"].ToString();
            Helper.WriteLog("临时授权码:" + tmp_auth_code);


            #region 激活授权套件
            if (Application["suite_access_token"] != null)
            {
                string suite_access_token = Application["suite_access_token"].ToString();

                //获取永久的授权码
                string surl             = "https://oapi.dingtalk.com/service/get_permanent_code?suite_access_token=" + suite_access_token;
                string param            = "{\"tmp_auth_code\":\"" + tmp_auth_code + "\"}";
                string permanentcodestr = HttpHelper.Post(surl, param);


                Helper.WriteLog("企业的永久授权码:" + permanentcodestr);
                Hashtable tb_permanentcode = (Hashtable)JsonConvert.DeserializeObject(permanentcodestr, typeof(Hashtable));
                Helper.WriteLog("permanent_code:" + tb_permanentcode["permanent_code"]);
                Helper.WriteLog("auth_corp_info:" + tb_permanentcode["auth_corp_info"]);
                string    permanent_code    = tb_permanentcode["permanent_code"].ToString();
                string    auth_corp_info    = tb_permanentcode["auth_corp_info"].ToString();
                Hashtable tb_auth_corp_info = (Hashtable)JsonConvert.DeserializeObject(auth_corp_info, typeof(Hashtable));
                //拿到授权企业的corpId
                string corpid = tb_auth_corp_info["corpid"].ToString();
                Helper.WriteLog("corpid:" + corpid);


                //得到授权企业的access_token
                surl = "https://oapi.dingtalk.com/service/get_corp_token?suite_access_token=" + suite_access_token;
                string param1      = "{\"auth_corpid\":\"" + corpid + "\",\"permanent_code\":\"" + permanent_code + "\"}";
                string accesstoken = HttpHelper.Post(surl, param1);//获取企业授权的access_token
                Helper.WriteLog("企业access_token:" + accesstoken);
                Hashtable tb_access_token = (Hashtable)JsonConvert.DeserializeObject(accesstoken, typeof(Hashtable));
                Helper.WriteLog("access_token:" + tb_access_token["access_token"]);
                Helper.WriteLog("expires_in:" + tb_access_token["expires_in"]);

                //激活企业授权套件
                surl = "https://oapi.dingtalk.com/service/activate_suite?suite_access_token=" + suite_access_token;
                string param2      = "{\"suite_key\":\"" + Config.SUITE_KEY + "\",\"auth_corpid\":\"" + corpid + "\",\"permanent_code\":\"" + permanent_code + "\"}";
                string oauth_suite = HttpHelper.Post(surl, param2);//套件的访问令牌
                Helper.WriteLog("永久授权套件:" + oauth_suite);
                Hashtable tb_suite_access_token = (Hashtable)JsonConvert.DeserializeObject(oauth_suite, typeof(Hashtable));

                res = "success";
            }
            else
            {
                Helper.WriteLog("暂时未拿到套件的授权码!");
            }



            #endregion
        }
        else
        {
            //还有其它的看具体的文档具体写。激活套件之后的开发与企业的开发基本一样
        }



        //以下是返回结果
        nonce     = Helper.randNonce();
        timeStamp = Helper.timeStamp();
        string encrypt1   = "";
        string signature1 = "";

        dingTalk.EncryptMsg(res, timeStamp, nonce, ref encrypt1, ref signature1);
        Hashtable jsonMap = new Hashtable
        {
            { "msg_signature", signature1 },
            { "encrypt", encrypt1 },
            { "timeStamp", timeStamp },
            { "nonce", nonce }
        };
        string result = JsonConvert.SerializeObject(jsonMap);
        Response.Write(result);
    }
示例#7
0
        public void ProcessRequest(HttpContext context)
        {
            string mToken          = Db.Models.Allocation.Token;
            string mSuiteKey       = Db.Models.Allocation.CorpId;
            string mEncodingAesKey = Db.Models.Allocation.EncodingAESKey;

            //mSuiteKey = "suite4xxxxxxxxxxxxxxx";
            #region 获取回调URL里面的参数
            //url中的签名
            string msgSignature = context.Request["signature"];
            //url中的时间戳
            string timeStamp = context.Request["timestamp"];
            //url中的随机字符串
            string nonce = context.Request["nonce"];
            //post数据包数据中的加密数据
            string encryptStr = GetPostParam(context);
            #endregion
            //string sEchoStr = "";
            DingTalkCrypt dingTalk  = new DingTalkCrypt(mToken, mEncodingAesKey, mSuiteKey);
            string        plainText = "";
            int           bools     = dingTalk.DecryptMsg(msgSignature, timeStamp, nonce, encryptStr, ref plainText);
            string        res       = "success";
            #region 处理钉钉回调返回的数据
            try
            {
                LogHelper.WriteLog("钉钉审批回调返回数据格式" + plainText);
                //获取token
                var DinToken = GetToken();
                LogHelper.WriteLog("回调token" + DinToken);
                Callback cb = Newtonsoft.Json.JsonConvert.DeserializeObject <Callback>(plainText);
                switch (cb.EventType)
                {
                case "bpms_instance_change":
                    #region 审批实列
                    LogHelper.WriteLog("审批实列");
                    var KsCusmoterReal = dbContext.KS_Customer.FirstOrDefault(p => p.DingTalkApproval == cb.processInstanceId);
                    if (cb.result == "refuse")
                    {
                        //客诉审批状态为拒绝
                        KsCusmoterReal.State = 4;
                    }
                    else if (cb.result == "agree")
                    {
                        //客诉审批状态为完成
                        KsCusmoterReal.State = 2;
                    }
                    #endregion
                    break;

                case "bpms_task_change":
                    #region 审批任务
                    if (cb.type == "finish")
                    {
                        var KsCusmoter = dbContext.KS_Customer.FirstOrDefault(p => p.DingTalkApproval == cb.processInstanceId);
                        if (KsCusmoter != null)
                        {
                            //获取审批实列详情
                            var ApprovalDetail = Db.ThirdSystem.AccessToken.ApprovalDetails(cb.processInstanceId, DinToken);
                            if (ApprovalDetail.Errcode != 0)
                            {
                                LogHelper.WriteLog("获取用户详情失败::" + ApprovalDetail.Errmsg);
                            }
                            //把json格式的审批实列详情转换为实体类
                            var data = Newtonsoft.Json.JsonConvert.DeserializeObject <Help.Root>(ApprovalDetail.Body);
                            LogHelper.WriteLog("【审批任务】" + ApprovalDetail.Body);
                            //实例化审批记录表
                            KS_Customer_Approval KsCusApp = new KS_Customer_Approval();
                            var OrPerson = dbContext.OR_Person.FirstOrDefault(p => p.PsnNum == cb.staffId);
                            //审批人
                            LogHelper.WriteLog("审批人" + KsCusApp.IdPerson);
                            if (OrPerson != null)
                            {
                                KsCusApp.IdPerson = OrPerson.Id;
                                KsCusApp.Name     = OrPerson.Name;
                            }
                            KsCusApp.IdCustomer = KsCusmoter.Id;
                            var FinishTime = Helper.DateTimeToStamp(cb.finishTime);
                            KsCusApp.FinishTime = FinishTime;
                            foreach (var item in data.process_instance.tasks)
                            {
                                if (KsCusApp.FinishTime == item.create_time)
                                {
                                    //获取tasks集合中第一个用户id,就是下个审批人的用户id
                                    var PersonApproval = dbContext.OR_Person.FirstOrDefault(p => p.PsnNum == item.userid);
                                    if (PersonApproval != null)
                                    {
                                        KsCusmoter.IdPersonApproval = PersonApproval.Id;
                                    }
                                }
                            }
                            //type="finish"并且result== "redirect为审批任务转交
                            if (data.process_instance.status == "RUNNING")
                            {
                                //客诉审批记录为同意
                                KsCusApp.state = 1;
                            }
                            //type="finish"并且result== "refuse"为审批任务拒绝
                            else if (data.process_instance.result == "refuse")
                            {
                                //status: "COMPLETED"
                                //客诉审批记录为拒绝
                                KsCusApp.state = 2;
                                //拒绝理由
                            }
                            //type="finish"为审批完成
                            else if (data.process_instance.status == "COMPLETED")
                            {
                                LogHelper.WriteLog("审批任务完成");
                                //客诉审批记录为同意
                                KsCusApp.state      = 1;
                                KsCusApp.FinishTime = DateTime.Now;
                            }
                            KsCusApp.Remark = cb.remark;
                            dbContext.KS_Customer_Approval.Add(KsCusApp);
                        }
                    }
                    else if (cb.type == "start")
                    {
                        var KsCusmoter = dbContext.KS_Customer.FirstOrDefault(p => p.DingTalkApproval == cb.processInstanceId);
                        //获取审批实列详情
                        var ApprovalDetail = Db.ThirdSystem.AccessToken.ApprovalDetails(cb.processInstanceId, DinToken);
                        if (ApprovalDetail.Errcode != 0)
                        {
                            LogHelper.WriteLog("获取用户详情失败::" + ApprovalDetail.Errmsg);
                        }
                        LogHelper.WriteLog("【发起审批】" + ApprovalDetail.Body);
                        //把json格式的审批实列详情转换为实体类
                        var data = Newtonsoft.Json.JsonConvert.DeserializeObject <Help.Root>(ApprovalDetail.Body);
                        foreach (var item in data.process_instance.tasks)
                        {
                            if (data.process_instance.create_time == item.create_time)
                            {
                                //获取tasks集合中第一个用户id,就是下个审批人的用户id
                                var PersonApproval = dbContext.OR_Person.FirstOrDefault(p => p.PsnNum == item.userid);
                                if (PersonApproval != null)
                                {
                                    KsCusmoter.IdPersonApproval = PersonApproval.Id;
                                }
                            }
                        }
                    }
                    #endregion
                    break;

                case "user_add_org":
                case "user_modify_org":
                case "user_leave_org":
                    #region 用户回调
                    foreach (var item in cb.UserId)
                    {
                        LogHelper.WriteLog("用户Id::" + item);
                        var DdPersonInfo = Db.ThirdSystem.AccessToken.CallbackUserInfo(item, DinToken);
                        if (DdPersonInfo.Errcode != 0)
                        {
                            LogHelper.WriteLog("获取用户详情失败::" + DdPersonInfo.Errmsg);
                        }
                        var PersonInfo = dbContext.OR_Person.FirstOrDefault(p => p.PsnNum == item);
                        //找到回调的用户
                        if (PersonInfo != null)
                        {
                            //判断为user_modify_org是更改用户信息
                            //否则就是用户离职
                            if (cb.EventType == "user_modify_org")
                            {
                                //修改用户
                                PersonInfo.Name           = DdPersonInfo.Name;
                                PersonInfo.PsnMobilePhone = DdPersonInfo.Mobile;
                                PersonInfo.PsnEmail       = DdPersonInfo.Email;
                                PersonInfo.HeadUrl        = DdPersonInfo.Extattr;
                                PersonInfo.CodeDepartment = DdPersonInfo.Department[0].ToString();
                            }
                            else
                            {
                                //删除用户
                                PersonInfo.LeaveDate      = DateTime.Now;
                                PersonInfo.CodeDepartment = "1";
                            }
                        }
                        else
                        {
                            //新增用户
                            OR_Person OrPerson = new OR_Person();
                            OrPerson.PsnNum           = item;
                            OrPerson.LoginName        = item;
                            PersonInfo.Name           = DdPersonInfo.Name;
                            PersonInfo.PsnMobilePhone = DdPersonInfo.Mobile;
                            PersonInfo.PsnEmail       = DdPersonInfo.Email;
                            PersonInfo.HeadUrl        = DdPersonInfo.Extattr;
                            PersonInfo.CodeDepartment = DdPersonInfo.Department[0].ToString();
                            PersonInfo.CreateTime     = DateTime.Now;
                            PersonInfo.Sex            = 0;
                            dbContext.OR_Person.Add(OrPerson);
                        }
                    }
                    #endregion
                    break;

                case "org_dept_create":
                case "org_dept_modify":
                case "org_dept_remove":
                    #region 部门回调
                    foreach (var item in cb.DeptId)
                    {
                        var DdDepInfo = Db.ThirdSystem.AccessToken.CallbackDepInfo(item, DinToken);
                        if (DdDepInfo.Errcode != 0)
                        {
                            LogHelper.WriteLog("获取用户详情失败::" + DdDepInfo.Errmsg);
                        }
                        var DelDepInfo = dbContext.OR_Department.FirstOrDefault(p => p.Code == item);
                        //判断是否找到该部门
                        //否则就是创建部门
                        if (DelDepInfo != null)
                        {
                            //找到判断是更改部门信息
                            //还是删除部门
                            if (cb.EventType == "org_dept_modify")
                            {
                                //修改部门
                                DelDepInfo.Name           = DdDepInfo.Name;
                                DelDepInfo.CodeDepartment = DdDepInfo.Parentid.ToString();
                            }
                            else
                            {
                                //删除部门
                                dbContext.OR_Department.Remove(DelDepInfo);
                            }
                        }
                        else
                        {
                            //新增部门
                            OR_Department OrDepInfo = new OR_Department();
                            OrDepInfo.Name           = DdDepInfo.Name;
                            OrDepInfo.Code           = DdDepInfo.Id.ToString();
                            OrDepInfo.CodeDepartment = DdDepInfo.Parentid.ToString();
                            OrDepInfo.CreateTime     = DateTime.Now;
                            dbContext.OR_Department.Add(OrDepInfo);
                        }
                    }
                    #endregion
                    break;
                }
                LogHelper.WriteLog("回调执行完成,");
                dbContext.SaveChanges();
                LogHelper.WriteLog("回调成功,保存成功");
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("回调异常信息:" + ex.Message);
            }
            #endregion
            //DingTalk_call_back_tag.call_back_tag(bools, plainText);
            timeStamp = Help.DingTalkCrypt.GetTimeStamp().ToString();
            string encrypt   = "";
            string signature = "";
            dingTalk = new DingTalkCrypt(mToken, mEncodingAesKey, mSuiteKey);
            dingTalk.EncryptMsg(res, timeStamp, nonce, ref encrypt, ref signature);
            Hashtable jsonMap = new Hashtable
            {
                { "msg_signature", signature },
                { "encrypt", encrypt },
                { "timeStamp", timeStamp },
                { "nonce", nonce }
            };
            string result = JsonConvert.SerializeObject(jsonMap);
            context.Response.Write(result);
        }