今天碰到了一个很有趣的bug修复,在这里记录一下。
这个bug是由于接收订单推送接口没有记录住一个打印物流面单的API地址,每一个订单有一个物流追踪号和对应打印物流面单的地址,需要修复没有记录到的数据。API地址大概长这样:
留意到唯一的不同是data_param中的某一段不一样就可展示不同的物流面单
看着很有规律但是又一头雾水,总感觉是一个可反向解码的编码。运气很好的是拿其中一段去各种试,最后发现这种是base64的编码,而不一样的那一段就是追踪号,那就有戏了。下面是反向解码:
于是有了思路,数据库有追踪号,那就只需要把追踪号转换成base64码,再把前后拼回去就好了。
第一步,建encode函数。
发现sqlserver没有直接的base64函数,于是搜了一下,然后在数据库里建了2个函数。实际上这里只用到了encode函数。
CREATE FUNCTION [dbo].[f_base64_encode]
(@bin varbinary(max))
returns varchar(max)
as begin
return cast(N'' as xml).value('xs:base64Binary(xs:hexBinary(sql:variable("@bin")))', 'varchar(max)')
end
GO
CREATE FUNCTION [dbo].[f_base64_decode]
(@64 varchar(max))
returns varbinary(max)
as begin
return cast(N'' as xml).value('xs:base64Binary(sql:variable("@64"))', 'varbinary(max)')
end
GO
第二步,测试encode函数
很有意思的是,同一个encode函数,转换写死的追踪号和转换数据库中字段(这里cast和convert是同样效果的),出来的结果是不一样的。
当然第一反应是看一下,这第三个字段解码后是什么,发现居然每个都是帮我加了个空格,如下图。
这中间还出了一个小插曲,在第一个在线转换工具上解码后看起来和用字符串NjQwMDIyODUyODQ1
解码是一样的,实在不信邪换了一个工具才发现是不一样的,上图已经和第一个图中的在线解码工具不一样。
什么问题呢?
那当然是有问题,后来发现是nvarchar的使用问题,nvarchar每个字符用2个字节存储,而'640022852845'
的数据类型是varchar,强行被教育了一波varcahr和nvarchar的区别。
解决方案
怎么解决?想了各种办法,尝试了各种手段之后,发现改数据表中字段的数据类型为varchar就好了,因为存的是追踪号,不会有需要2个字节才能存的字符(如中文、韩文等非Unicode字符)。
第三步,更新数据
更新语句早就写好,就是拼上去,要不是被第二步的nvarchar和varchar问题卡住,1小时也就收工了。
UPDATE ODR_OrderMain SET Prediction_ERROR =
'http://api.yl-scm.com:22220/yunlu-order-web/rotaPrin/rotaPrintAction!doPrint.action?data_param=eyJjdXN0b21lcmlkIjoiUzAwMDAxQzEzNiIsImJpbGxjb2RlIjoi'
+ dbo.f_base64_encode(cast(TrackingNo as varbinary(50))) + 'IiwibGFuZ3VhZ2UiOiJNWVMifQ=='
WHERE Prediction_ERROR = 'http';
验证后发现数据库中的API能正常调用,那就OK啦~