C#校验时间格式的场景分析

C#校验时间格式的场景分析

目录

前言:

场景描述

前戏一

前戏二

正戏

尾戏

前言:

晚上打算睡觉的时候,群里反馈订单接收失败,开工排查问题,日志显示验签失败,发现一个蛮有意思的BUG,总算有了一个写作的素材

场景描述

本次的场景属于比较常见的收单API,对第三方的订单进行签名验证,然后持久化到数据库,签名规则大致是将参数key按照升序排序,然后根据key=value&进行字符串拼接,最后加上秘钥,按照指定的加密方式生成签名

前戏一

设计之初,肯定是怎么简单怎么来,粗略代码如下

[HttpPost] public async Task<IActionResult> TestSendOrder([FromBody] ReceiveOrderRequest request) { var secret_key = _options.Value.SecretKey; var url = _options.Value.Host; //1.将模型转成json格式字符串 var param = JsonConvert.SerializeObject(request); //2.将json格式字符串,序列化成有序字典 SortedDictionary<string, string> dict = JsonConvert.DeserializeObject<SortedDictionary<string, string>>(param); //3.循环字典,按规则拼接成待加密的明文字符串 var data = ""; foreach (var item in dict) { if (item.Key == "sign") continue; data += $"{item.Key}={item.Value}&"; } data += $"secret_key={secret_key}"; //4.生成签名 var sign = EncryptHelper.SHA1Encryption(data); request.sign = sign; //5.模拟订单推送 var res = await _httpClientHelper.PostData(url, JsonConvert.SerializeObject(request)); return Ok(res); }

不出意外,肯定是要出意外的,联调的时候,发现与第三方待加密的明文字符串不一致,问题出在JsonConvert序列化上,这里有两个问题

1. DateTime格式不一致 如: DateTime dt = "2022-07-30 12:26:56" 序列化后 dt=2022-07-30T12:26:56 2. decimal小数点后自动补0 如: decimal price = 10 序列化后 price=10.0

针对第一个问题,很好解决,我们在序列化的时候,指定DateTime的格式即可

var iso = new IsoDateTimeConverter(); iso.DateTimeFormat = "yyyy-MM-dd HH:mm:ss"; var param = JsonConvert.SerializeObject(request, iso);

针对第二个问题,处理起来就比较麻烦了,要重写底层的一些东西(主要是我不会),这不符合"简单"的定义,得换个方案

前戏二

通过反射遍历对象,然后将属性名称与值,丢到有序字典里面,这里我写了个方法来判断值是否为时间,如果是时间类型,则格式化,代码如下

public string GetFmortDateTime(string strDate) { DateTime dt; if (DateTime.TryParse(strDate, out dt)) { return dt.ToString("yyyy-MM-dd HH:mm:ss"); } else { return strDate; } }

不出意外,肯定是要出意外的,不然也不会有这个素材去水一篇博客了

正戏

有个字段的值是9.9,结果被序列化成了 2022-09-09 00:00:00,吃了一惊,看来是把这个数字格式化成月份日份了,真有意思,又GET到一个新姿势,发现问题解决问题就简单多了,因为定义了数据模型,我们直接在反射的时候,获取该值的类型做判断即可

public static async Task<bool> CheckSign(dynamic request, string secret) { SortedDictionary<string, string> dict = new SortedDictionary<string, string>(); foreach (PropertyInfo p in request.GetType().GetProperties()) { var value = p.GetValue(request); if (value == null) { dict[p.Name] = ""; } else { var valueType = value.GetType(); if (valueType.Name == "DateTime") { dict[p.Name] = Convert.ToDateTime(value).ToString("yyyy-MM-dd HH:mm:ss"); } else { dict[p.Name] = value.ToString(); } } } var sign = dict["sign"]; dict.Remove("sign"); var data = ""; foreach (var item in dict) { data += $"{item.Key}={item.Value}&"; } data += $"secret_key={secret}"; var new_sign = EncryptHelper.SHA1Encryption(data); return new_sign.ToLower() == sign.ToLower(); } 尾戏

看到这里,可能就有小伙伴有话要说了,你这定义了一个模型,还要通过循环两次,才能生成待加密的明文字符串,不符合"简单",干脆直接用个有序字典去接收参数好了,这样只用循环一次

秒啊,秒啊,秒啊,妙蛙种子都没有你秒,这种做法不是不行,但是后面维护的人估计要抓狂了,按照规约,我们是不推荐这么干的,这次就破例这么干一次,抛出另一个问题,一个字符串,如何判断它是一个我们约定的时间格式,很显然9.9并不是约定的时间格式

这里推荐 DateTime.ParseExact方法,可以根据我们自定义的方式,来格式化时间,舒坦了...

public static string GetFmortDateTime(string strDate) { string[] format = { "yyyy-MM-ddTHH:mm:ss" }; DateTime dt; if (DateTime.TryParseExact(strDate,format,CultureInfo.InvariantCulture,DateTimeStyles.None,out dt)) { return dt.ToString("yyyy-MM-dd HH:mm:ss"); } else { return strDate; } }

到此这篇关于C#里如何简单的校验时间格式的文章就介绍到这了,更多相关C#校验时间格式内容请搜索易知道(ezd.cc)以前的文章或继续浏览下面的相关文章希望大家以后多多支持易知道(ezd.cc)!

推荐阅读

    foreach的用法c语言和c#

    foreach的用法c语言和c#,数组,遍历,本文目录foreach的用法c语言和c#详细讲解foreach循环的用法C#中的foreach 怎么用啊foreach用法C#中的f

    params 是什么意思,c#里

    params 是什么意思,c#里,参数,数组,本文目录params 是什么意思,c#里params.add跟params.put有区别吗C#中ref,out和params有什么区别发送请

    C# 基于StackExchange.Redis.dll利用Redis实现分布式Session

    C# 基于StackExchange.Redis.dll利用Redis实现分布式Session,令牌,客户端,最近在研发一款O2O产品,考虑到分布式架构的需要,以前那一套.NET的

    360手机助手校验dex优化文件失败怎么办

    360手机助手校验dex优化文件失败怎么办,手机助手,文件,支持,音乐,智能手机,获取,  360手机助手校验dex优化文件失败,有可能是手机内存不足了。

    crc校验错误怎么办

    crc校验错误怎么办,校验,输入,系统,错误,硬件,文件,crc校验错误的解决办法:1、重新下载个安装包;2、在解压时勾选“保留错误文件”,然后查看杀毒软

    c#中 (ToolStrip

    c#中 (ToolStrip,窗体,控件,本文目录c#中 (ToolStrip)控件是做什么用的winform窗体问题 toolstrip怎么重用,每个窗体都要用到同样的工具栏窗体

    C#取得DataTable最大值、最小值

    C#取得DataTable最大值、最小值,最大值,最小值,C#取得DataTable最大值、最小值int max=int.Parse((dtItemsAll.Compute("Max(CPITEMS_SOR

    如何校验SQL查询结果是否准确

    如何校验SQL查询结果是否准确,订单,数据,总结平常工作中几种校验数据的思路 1、对比其他渠道数据结果查询需求:从Hive端查询20190909当天的

    ECC校验是什么

    ECC校验是什么,错误,内存,校验,内存错误,纠错,发现,  ECC内存即纠错内存,简单的说,其具有发现错误,纠正错误的功能,一般多应用在高档台式电脑/服