现在项目场景是, pc 客户端生成订单号传给后端,之前使用的是微秒级的时间+随机数,但是依旧发生了重复情况,现在想要优化这个算法,要求订单号中只包含数字,长度小于 30 。
后来想到两种方法: 1.YYMMDDhhmmss+mac 地址(转成 18 位十进制),经过讨论, mac 地址可以进行修改,时间也不一定是确定的,假设场景,客户在 12:00 支付完成之后,发现自己时间快了半小时,然后回调了,这样在 11:30 到 12:00 之间就有可能重复。
2.YYYYMMDDhhmiss+毫秒+微秒+IP 尾 4 位+6 位随机数,其中 6 位随机数种子采用( mac 地址前三位前补 00 )与( mac 地址后三位后补 00 )进行异或得出。这个方法大家觉得只是极大的减少的几率问题,但是并不能避免重复的问题
也有同事提到了, guid 来做,但是订单号要求纯数字,现问下如何解决此类问题,多谢 开发语言 c/c++
1
jugelizi 2016-08-23 15:56:02 +08:00
客户端。。。大作死啊
|
2
harry890829 OP @jugelizi 哎,现在这个事情已经不可逆了……要是再服务器生成订单号需要修改大量的模块……
|
3
loading 2016-08-23 16:00:37 +08:00 via Android
Uuid 算法
|
4
loading 2016-08-23 16:02:05 +08:00 via Android
不用大改吧……入服务器单独设置个接口,申请一个 id 返回,你后面的流程都没变……
|
5
egen 2016-08-23 16:02:57 +08:00
你们有 30 个数字, YYMMDDhhmm 长度只有 10 ,后面 20 个全部随机,重复的几率可以忽略,比你加毫秒 mac 什么的重复几率小多了
|
6
lincanbin 2016-08-23 16:02:59 +08:00
GUID 从二进制映射到十进制,大概需要 35 位整数,你要求长度小于 30 ,其实已经很接近了。
再多加几位,或者心大点,砍掉 GUID 的几位。 |
7
allce231 2016-08-23 16:03:35 +08:00
客户端。。。大作死啊!!!!
|
8
egen 2016-08-23 16:04:39 +08:00
因为客户端的时间不可信,记录秒和毫秒也没什么意义
|
9
harry890829 OP |
10
qian0206 2016-08-23 16:06:10 +08:00
在服务端弄个接口专门给客户端调用获取订单号不就行了
|
11
harry890829 OP |
12
lincanbin 2016-08-23 16:09:38 +08:00
订单号这种东西你们都敢客户端生成,心很大啊。
|
13
lincanbin 2016-08-23 16:17:39 +08:00
@harry890829
噫,我前面算错了, GUID 映射成十进制,是最多需要 39 位整数。 例如说 GUID ,{99D66A96-4CCD-2944-9A3C-9D583513897A},转十进制后就是 204485196726229962288084266002268806444 。 你看着办吧。 |
14
loading 2016-08-23 16:20:59 +08:00 via Android
如果让后台做个订单 id 的接口都搞不定,你们公司也就玩完了。
|
15
xinyewdz 2016-08-23 16:38:25 +08:00
用户 id+时间+随机数。这样还会重复?
|
16
terence4444 2016-08-23 16:45:51 +08:00 via iPhone
让客户端提交时检测是不是有重复号码,有的话重新生成一个?
|
17
dong3580 2016-08-23 17:08:26 +08:00
@harry890829
客户端怎么改都会有可能有重复,还是服务器端保存那里将收到的订单号运算一下 重新生成一下呀,不就好了, |
18
BuilderQiu 2016-08-23 17:14:18 +08:00
我比较关注价格也是客户端算好传过去的吗?
如果是,分享下客户端下载地址。 然后,客户端生成订单 ID 这种方案是谁批的。。。设计方案讨论能通过。。 治标就各种想办法减少重复数据,治本的办法还是服务器生成,沟通解决吧。 |
19
yao978318542 2016-08-23 17:19:31 +08:00
@allce231 你这个头像作大死
|
20
allce231 2016-08-23 17:19:59 +08:00
后端判断订单号重复 如果重复重新生成一个 id 给它
|
21
sunshinewu85 2016-08-23 17:34:21 +08:00
按楼主现在的意思,后端是不愿意提供任何生成及检测支持,全靠客户端去整,呵呵,这也理解,谁都不愿在自己管辖的地盘补上一脚,否则一出问题,把全问题都推过去了。。。可是在客户端无论怎么整,其实都已经在拆东墙补西墙了,还不是亡羊补牢。目前亡羊补牢靠谱的还是这两个方案较为合适吧:
1 、找个能拍板让服务端改的人来,从服务端拿 ID 。有些业务,纵使现状改起来麻烦,也好过后续引出更多麻烦; 2 、服务端不提供生成,那总得提供个检测吧~话说回来,都检测了,干脆服务端生成一起了吧,毕竟一劳永逸啊 <img src=" " class="embedded_image" border="0" /> |
22
xmh51 2016-08-23 17:34:56 +08:00
额。不是办法的办法,服务器生成订单号传给客户端,客户端再上传到服务器。另一种 YYMMDDhhmm +随机数。但是被你否了。 另外随机和重复不是等同的,随机值不能避免重复。你还是在服务器生成订单号比较好。客户端怎么也不可能知道服务器上面是否有重复的订单号。
|
23
finian 2016-08-23 18:03:53 +08:00
客户端再怎么整都可能会有问题(合法性、安全性),这事儿必须服务端来整。
|
24
harry890829 OP @lincanbin guid 的情况我再看看能不能支持,多谢
@loading @qian0206 @sunshinewu85 @xmh51 @finian 也不是没有想过服务端只开一个生成订单的接口,让客户端调用,但是本来一次的能够完成的动作变成了两次完成,这样失败的情况也就大幅度增加了,于是直接被否决 @xinyewdz 用户 id 是本地 id ,并不唯一,或者说大家都是重复的 @terence4444 @dong3580 @allce231 现在目前的情况是服务器收到相同的订单号就会直接拒绝,也就是说服务器收到的第二个订单会被拒绝并返回订单号重复,目前的解决就是让前端重新发起一笔 @BuilderQiu 哎,金额也是前端送的啊,不过我们后端有相应验证,并无大碍 感谢大家,我倾向于方案二来做了,毕竟几率已经很小,关于 guid 的情况,我上报一下,看看是不是有定论 |
25
sc3263 2016-08-23 18:29:30 +08:00
加个代理模块吧。客户端发消息到代理,代理那边计算好订单号,加到消息里,然后转发给服务端。
还是得服务端改。不过改动能小很多。 |
26
dong3580 2016-08-23 18:49:41 +08:00 via Android
@harry890829
订单重复谁发出的?服务器对吧,它都知道重复了还不自动重新生成一下订单号,也是醉了。 |
27
scnace 2016-08-23 19:03:38 +08:00 via Android
用户 id 做 hash?
|
29
hinate 2016-08-23 19:12:41 +08:00
客户端的时间戳是不可信的。。。
|
30
abelyao 2016-08-23 19:14:00 +08:00 via iPhone
客户端把不带订单号的数据提交给服务端,由服务端来生成订单号,反馈结果给客户端的时候,把订单号一起带上。这样仍然是一次请求。
|
31
guizer 2016-08-23 19:37:43 +08:00 via iPhone
前缀+时间+uid
应该淘宝差不多就这么干的 |
32
ck65 2016-08-23 19:43:59 +08:00
中心化的发号机,别让客户端生成 id 。
|
33
flyingfz 2016-08-23 20:31:33 +08:00
|
34
jon 2016-08-23 21:45:30 +08:00
客户端生成订单号服务端全盘接受吗,不检查怎么避免问题,检查了为什么不直接服务端生成
|
35
ihuotui 2016-08-23 22:03:57 +08:00
设计有问题,怎么补都不完美,再加一个接口,客户端获取服务器的全局唯一序号(不用别人教了吧,不过也不算很难或者很简单),然后剩下的逻辑和原来一样。
以后的项目再写第二版,重写。 |
36
popok 2016-08-23 22:55:18 +08:00
正常用户的用户使用出现重复的概率很小,就怕别有用心的人,毕竟你的订单号在客户端生成
|
37
caola 2016-08-23 23:50:18 +08:00
一切客户端传入的数据,都有可能是是不可靠的。要是你内部人员使用就无所谓,
如果是面向公众用户使用的话,做得安全一点是好的,毕竟可能会有那么一些别有用心之人。 |
38
ljbha007 2016-08-24 00:08:20 +08:00
客户端做的任何安全措施都是没有屌用的
|
40
wavingclear 2016-08-24 01:47:10 +08:00 via iPad
微秒级加随机数还有重复,这就是尝试攻击了,客户端还改啥
|
41
gkiwi 2016-08-24 03:20:43 +08:00
|
42
imnpc 2016-08-24 08:10:57 +08:00
客户端生成订单号 这么作大死的办法谁想出来的?
客户端只允许传输关键类数据 例如商品 ID 数量 其他涉及到安全的一律服务端控制... |
43
likai 2016-08-24 08:27:20 +08:00
客户端时间随便可以更改。拿来生成订单号合适么?
再一个。都知道重复了。后台啥事也不作? |
44
gkiwi 2016-08-24 08:54:54 +08:00
本来想写点的客户端怎么避免和处理的,但是这个锅不应该让客户端背!
|
45
GKLuke 2016-08-24 09:00:59 +08:00
客户端就不要调用本地时间了,调用网络时间或者服务器时间,那就不存在时间回调了。
当然,永远不要相信前台数据,起码都要滤一边真伪啊。 |
46
Clarencep 2016-08-24 09:04:48 +08:00
订单号居然在客户端生成,这是在开玩笑吗
|
48
yuankui 2016-08-24 09:34:04 +08:00
这种问题,网上解决方案不是一大堆吗?
你不是应该发一个帖子说你发现了哪些方案,然后让大家评价一下各个方案的优劣吗? |
49
GavinJ 2016-08-24 09:40:08 +08:00
客户端生成订单, 新鲜~~~~
|
51
killerv 2016-08-24 10:05:07 +08:00
客户端生成订单号,这是什么人想出来的……
|
52
ThreeBody 2016-08-24 10:23:19 +08:00 via Android
天啊,订单号让前端生成已经是很严重的设计缺陷了,金额也让前段发?你后台有验证还要前段发一次?
就这两个,我觉得你们系统可能还有很多坑。 我想问问,我看到你说前端的用户 id 是一样的,你们前端难道不用用户登录的?就是可以匿名下单? 是不是类似那种, 1688 元的 iphone 6s ,然后输入名字,地址,电话就直接下单那些? 微妙级的订单都可能重复,加个 uuid ,这样应该就够的了。 uuid 碰撞几率这么低,加时间前缀,应该是够的了。 |
53
pljhonglu 2016-08-24 10:45:38 +08:00
服务器的锅为什么要你来背。。。
|
54
southwolf 2016-08-24 10:54:23 +08:00
LZ 赶紧来爆一下产品名字,组织 V2 群众薅羊毛去啊…… iPhone6s 点击就送啊
|
55
damean 2016-08-24 11:00:08 +08:00
|
56
romisanic 2016-08-24 11:01:02 +08:00
如果改客户端订单号生成规则可行,意味着大家的客户端都要更新,既然如此,为什么不直接改成后端生成,这样所有客户端使用的订单号实际上是从一个位置生成的,也就不会再有重复的顾虑。哪怕后续有需要修改的地方,那也只需要直接修改服务端就可以了。
|
57
22too 2016-08-24 11:07:41 +08:00
我们目前的做法,毫秒级时间 + 随机数 + 用户 id 。也就是除非这个用户故意重复,用户直接是隔离的。目前没有发现问题。
|
58
williamx 2016-08-24 11:36:19 +08:00
上面的说得没错,把用户 id 加上,基本都不会出现重复的问题。
|
59
hitmanx 2016-08-24 12:52:32 +08:00
如果把本地时间换成通过网络服务器获取时间呢?这样精确到毫秒,应该没有重复性的问题了吧,除非用户 hack ,不过那就是是整个架构问题了,反正现在也有这个问题。
|
60
maxmilia 2016-08-24 13:25:20 +08:00
用户 ID 直接给的话会被人知道用户规模,所以加个密
|
61
SlipStupig 2016-08-24 14:06:44 +08:00
如果是单纯冲突的话转成 MD5 或者 SHA1 转一下,如果是破解,只能用 VMProtect 这类软件延缓一下,基本上在客户端是挡不住的
|
62
harry890829 OP |
63
harry890829 OP 上面各位不一一回复了,在这里感谢大家给出的建议……
|