拉比小新  

首先什么是GDPR?

  GDPR是 (The European) General Data Protection Regulation 的缩写,即通用数据保护条例。是欧盟议会和欧盟理事会在 2016 年 4 月通过,在 2018 年 5 月开始强制实施的规定。

  GDPR 意义在于推动强制执行隐私条例,规定了企业在对用户的数据收集、存储、保护和使用时新的标准;另一方面,对于自身的数据,也给予了用户更大处理权。

总而言之,对OP部署的国际化CRM项目(数据库部署在中国)的影响就是欧洲数据联系人等实体敏感数据(电话、邮箱、地址、年龄等),不能直接明文存储在数据库中。否则就会有相关部门上门请喝茶。。

 

常见解决方案

  方案一 敏感字段数据加密后存储在数据库中。

    在Plugin中实现逻辑,Create或者Update之前,将敏感字段加密,然后存储在数据库中;Retrieve和RetrieveMultiple后,对加密字段进行解密,然后显示

  方案二 敏感字段分离存储在海外单独部署的数据库中,实现敏感数据不出境。

    a.确定需要脱敏实体、字段,以及何种条件下需要将数据存储在海外数据库

    b.实现接口读写海外数据库

    c.Create或者Update之前,将敏感字段加密调用接口存储到海外数据库,同时清空上下文实体中的字段数据,防止保存到本地数据库;Retrieve和RetrieveMultiple后调用接口对当前上下文的敏感字段重新赋值

 

方案二具体实现【例】

  1.联系人实体根据联系人类型判断,当联系人类型为海外联系人时,联系方式、邮箱等字段存在海外数据库,其他不做处理

  2.实现接口 WebAPI

        /// <summary>
        /// 保存联系人
        /// </summary>
        /// <param name="contact"></param>
        [HttpPost, Route("SaveContact")]
        public void SaveContact(Dictionary<string,object> contact)
        {
            new ContactCommand().SaveContact(contact);
        }
        /// <summary>
        /// 查询联系人
        /// </summary>
        /// <param name="contact"></param>
        [HttpGet, Route("GetContact")]
        public Contact GetContact(Guid id)
        {
            return new ContactCommand().GetContact(id);
        }

        /// <summary>
        /// 获取联系人列表
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpPost, Route("GetContactList")]
        public List<Contact> GetContactList(List<Guid> ids)
        {
            return new ContactCommand().GetContactList(ids);
        }

  3.实现Create/Update之前逻辑

  PreCreateAndUpdate.cs

protected override void ExecutePlugin()
        {
            try
            {
                //判断实体是否满足脱敏条件
                if(CommonHelper.CheckOverseaContact(Entity, OrganizationServiceAdmin))
                {
                    //调用接口保存数据
                    //Entity.Id = Guid.NewGuid();
                    var dic = new Dictionary<string, object>();
                    dic.Add("id", Entity.Id.ToString());
                    //职务 string
                    if (Entity.Contains("new_duty"))
                    {
                        dic.Add("new_duty", Entity.GetAttributeValue<string>("new_duty"));
                    }//联系人属性 int
                    if (Entity.Contains("new_contactsattribute"))
                    {
                        dic.Add("new_contactsattribute", Entity.GetAttributeValue<OptionSetValue>("new_contactsattribute")?.Value);
                    }
                    //是否潜在客户 bool
                    if (Entity.Contains("new_islatentcontacts"))
                    {
                        dic.Add("new_islatentcontacts", Entity.GetAttributeValue<bool>("new_islatentcontacts"));
                    }//保存至海外数据库
                    InterfaceCommonHelper.Post("api/Contact/SaveContact", "DataMask", JsonHelper.Serialize(dic), OrganizationServiceAdmin);
                    //清空敏感子弹
                    //职务 string
                    Entity["new_duty"] = null;
                    //称谓 int
                    Entity["new_appellation"] = null;//是否潜在客户 bool
                    Entity["new_islatentcontacts"] = null;
                }
            }
            catch (Exception ex)
            {
                throw new InvalidPluginExecutionException(ex.Message);
            }
        }

  4.实现查询逻辑

查询需要考虑两个部分一个是单独查询数据retrieve,另一种就是retrievemultiple。需要注意的是在特定类型联系人下才调用接口。

  PostRetrieve.cs

protected override void ExecutePlugin()
        {
            if (Context.MessageName.ToLower() == "retrieve")
            {
                Entity entity = Context.OutputParameters["BusinessEntity"] as Entity;
                //包含客户类型
                if (entity.Contains("new_contactlogtype") && entity["new_contactlogtype"] != null)
                {
                    if (entity.GetAttributeValue<OptionSetValue>("new_contactlogtype").Value != 5 &&
                        entity.GetAttributeValue<OptionSetValue>("new_contactlogtype").Value != 6)
                    {
                        return;
                    }
                }
                else
                {
                    var contactObj = OrganizationServiceAdmin.Retrieve("contact",entity.Id,new Microsoft.Xrm.Sdk.Query.ColumnSet("new_contactlogtype"));
                    if (contactObj.GetAttributeValue<OptionSetValue>("new_contactlogtype").Value != 5 &&
                        contactObj.GetAttributeValue<OptionSetValue>("new_contactlogtype").Value != 6)
                    {
                        return;
                    }
                }

                //读取接口记录
                var contactStr = InterfaceCommonHelper.Get("api/Contact/GetContact?id=" + entity.Id.ToString(), "DataMask", OrganizationServiceAdmin);
                var result = JsonHelper.Deserialize<Result>(contactStr);
                if (result.ErrorCode == 0)
                {
                    var contact = JsonHelper.Deserialize<Contact>(result.Data.ToString());
                    //职务 string
                    entity["new_duty"] = contact.new_duty;
                    //称谓 int
                    if (contact.new_appellation > 0)
                        entity["new_appellation"] = new OptionSetValue(contact.new_appellation);
                    //联系人属性 int
                    if (contact.new_contactsattribute > 0)
                        entity["new_contactsattribute"] = new OptionSetValue(contact.new_contactsattribute);
                    //是否潜在客户 bool
                    entity["new_islatentcontacts"] = contact.new_islatentcontacts;
                }
            }
            if (Context.MessageName.ToLower() == "retrievemultiple")
            {
                EntityCollection ec = Context.OutputParameters["BusinessEntityCollection"] as EntityCollection;
                var ids = (from e in ec.Entities
                           select e.Id).ToList();
                //调用接口
                var contactListStr = InterfaceCommonHelper.Post("api/Contact/GetContactList", "DataMask", JsonHelper.Serialize(ids), OrganizationServiceAdmin);
                var contactListResult = JsonHelper.Deserialize<Result>(contactListStr);
                if (contactListResult.ErrorCode == 0)
                {
                    var list = JsonHelper.Deserialize<List<Contact>>(contactListResult.Data.ToString());
                    if (list.Count <= 0)
                    {
                        return;
                    }
                    foreach (var ent in ec.Entities)
                    {
                        var contact = (from c in list
                                       where c.id == ent.Id
                                       select c).FirstOrDefault();
                        if (contact != null)
                        {
                            //文本
                            ent["new_duty"] = contact.new_duty;
                            //邮箱
                            ent["emailaddress1"] = contact.emailaddress1;
                            //电话
                            ent["new_phone"] = contact.new_phone;
                            //picklist
                            if (contact.new_appellation > 0)
                            {
                                ent["new_appellation"] = new OptionSetValue(contact.new_appellation);
                            }

                        }
                    }
                }

            }
        }

 

posted on 2022-01-19 14:59  拉比小新  阅读(240)  评论(0编辑  收藏  举报