C#校验时间格式的场景分析_第1页
C#校验时间格式的场景分析_第2页
C#校验时间格式的场景分析_第3页
C#校验时间格式的场景分析_第4页
C#校验时间格式的场景分析_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第C#校验时间格式的场景分析目录前言:场景描述前戏一前戏二正戏尾戏

前言:

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

场景描述

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

前戏一

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

[HttpPost]

publicasyncTaskIActionResultTestSendOrder([FromBody]ReceiveOrderRequestrequest)

varsecret_key=_options.Value.SecretKey;

varurl=_options.Value.Host;

//1.将模型转成json格式字符串

varparam=JsonConvert.SerializeObject(request);

//2.将json格式字符串,序列化成有序字典

SortedDictionarystring,stringdict=JsonConvert.DeserializeObjectSortedDictionarystring,string(param);

//3.循环字典,按规则拼接成待加密的明文字符串

vardata="";

foreach(varitemindict)

if(item.Key=="sign")continue;

data+=$"{item.Key}={item.Value}

data+=$"secret_key={secret_key}";

//4.生成签名

varsign=EncryptHelper.SHA1Encryption(data);

request.sign=sign;

//5.模拟订单推送

varres=await_httpClientHelper.PostData(url,JsonConvert.SerializeObject(request));

returnOk(res);

}

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

1.DateTime格式不一致

如:DateTimedt="2025-07-3012:26:56"

序列化后dt=2025-07-30T12:26:56

2.decimal小数点后自动补0

如:decimalprice=10

序列化后price=10.0

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

variso=newIsoDateTimeConverter();

iso.DateTimeFormat="yyyy-MM-ddHH:mm:ss";

varparam=JsonConvert.SerializeObject(request,iso);

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

前戏二

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

publicstringGetFmortDateTime(stringstrDate)

DateTimedt;

if(DateTime.TryParse(strDate,outdt))

returndt.ToString("yyyy-MM-ddHH:mm:ss");

else

returnstrDate;

}

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

正戏

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

publicstaticasyncTaskboolCheckSign(dynamicrequest,stringsecret)

SortedDictionarystring,stringdict=newSortedDictionarystring,string

foreach(PropertyInfopinrequest.GetType().GetProperties())

varvalue=p.GetValue(request);

if(value==null)

dict[p.Name]="";

else

varvalueType=value.GetType();

if(valueType.Name=="DateTime")

dict[p.Name]=Convert.ToDateTime(value).ToString("yyyy-MM-ddHH:mm:ss");

else

dict[p.Name]=value.ToString();

varsign=dict["sign"];

dict.Remove("sign");

vardata="";

foreach(varitemindict)

data+=$"{item.Key}={item.Value}

data+=$"secret_key={secret}";

varnew_sign=EncryptHelper.SHA1Encryption(data);

returnnew_sign.ToLower()==sign.ToLower();

}

尾戏

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

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

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

publicstaticstringGetFmortDateTime(stringstrDate)

string[]format={"yyyy-MM-ddTHH:mm:ss"};

DateTimedt;

if(DateTim

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论