22

我的在线商店中的每个订单都有一个面向用户的订单号。我想知道生成它们的最佳方法。标准包括:

  • 短的
  • 容易在电话中说出来(例如,“m”和“n”有歧义)
  • 独特
  • 校验和(矫枉过正?有用吗?)
  • 编辑:不透露总共有多少订单(客户可能会发现下订单感到不安)

现在我正在使用以下方法(无校验和):

def generate_number                
    possible_values = 'abfhijlqrstuxy'.upcase.split('') | '123456789'.split('')

    record = true
    while record
        random = Array.new(5){possible_values[rand(possible_values.size)]}.join
        record = Order.find(:first, :conditions => ["number = ?", random])
    end          
    self.number = random
end
4

13 回答 13

18

作为客户,我会很高兴:

year-month-day/short_uid

例如:

2009-07-27/KT1E

它为每天大约 33^4 ~ 100 万个订单提供了空间。

于 2009-07-24T19:51:38.393 回答
5

这是我在之前的问题中提出的系统的实现:

MAGIC = [];
29.downto(0) {|i| MAGIC << 839712541[i]}

def convert(num)
  order = 0
  0.upto(MAGIC.length - 1)  {|i| order = order << 1 | (num[i] ^ MAGIC[i]) }
  order
end

它只是一个廉价的哈希函数,但它让普通用户很难确定已经处理了多少订单,或者另一个订单的数量。在您完成 2 30个订单之前,它不会用完空间,您不会很快完成订单。

以下是convert(x)1 到 10 的结果:

1:  302841629
2:  571277085
3:   34406173
4:  973930269
5:  437059357
6:  705494813
7:  168623901
8:  906821405
9:  369950493
10: 638385949
于 2009-07-24T20:03:47.947 回答
3

在我以前的地方是这样的:

客户 ID(从 1001 开始),他们下订单的顺序,然后是 Orders 表中的唯一 ID。这给了我们一个至少 6 位的长数字,并且因为有两个主键,所以它是独一无二的。

我想如果您在其中添加破折号或空格,您甚至可以让我们对客户的购买习惯有所了解。不介意令人难以置信的安全,我猜订单 ID 是可以猜到的,但我不确定这是否存在安全风险。

于 2009-07-24T18:55:15.840 回答
2

好的,这个怎么样?

依次从某个数字 (2468) 开始,然后向其添加一些其他数字,例如下订单的月份中的哪一天。

这个数字总是增加(直到你超过整数类型的容量,但到那时你可能不在乎,因为你会非常成功并且会在某个遥远的岛屿天堂啜饮玛格丽塔酒)。它实现起来很简单,而且它把事情混在一起,足以让你猜测你有多少订单。

于 2009-07-24T18:57:17.990 回答
2

我宁愿提交号码 347 并在一个较小的风度翩翩的网站上获得优质的客户服务,而不是:在大型网站上的 G-84e38wRD-45OM 并被忽略一周。

您不希望它作为系统 ID 或链接的一部分,而是作为一个用户友好的数字,它可以工作。

于 2009-07-24T19:13:50.310 回答
2

您可以尝试创建一个不会显示系统中订单数量的加密版本,而不是生成和存储一个数字。这是一篇关于这一点的文章。

于 2009-07-24T20:22:10.877 回答
2

Douglas Crockford 的 Base32 Encoding 非常适合这一点。

http://www.crockford.com/wrmg/base32.html

将 ID 本身作为自动递增整数存储在数据库中,从 100000 等适当大的值开始,然后简单地将编码值公开给客户/接口。

5 个角色将帮助您完成最初的约 3200 万个订单,同时表现非常出色并满足这些要求中的大部分。但是,它不允许排除相似的发音字符。

于 2016-02-08T22:19:10.143 回答
1

像这样的东西:

  1. 获取顺序订单号。或者,也许,一个 UNIX 时间戳加上两个或三个随机数字(当同时下两个订单时)也可以。
  2. 将其与一些半秘密值按位异或,以使数字出现“伪随机”。这是原始的,不会阻止那些真正想调查您有多少订单的人,但是对于真正的“随机性”,您需要保留一个(大)排列表。或者你需要有很大的随机数,这样你就不会受到生日悖论的影响。
  3. 使用Verhoeff 算法添加校验位(我不确定它对 base33 有这么好的属性,但应该不错)。
  4. 将数字转换为 - 例如 - 基数 33(“0-9A-Z”,“O”、“Q”和“L”除外,它们可能被误认为“0”和“1”)或类似的东西。易于发音意味着排除更多的字母。
  5. 将结果分组为一些视觉可读的模式,如 XXX-XXX-XX,这样用户就不必用手指或鼠标指针跟踪位置。
于 2009-07-24T19:06:47.673 回答
0

依次从 1 开始?那有什么问题?

(注意:这个答案是在 OP 编辑​​问题之前给出的。)

于 2009-07-24T18:46:09.213 回答
0

只有一个 Rube Goldberg 风格的想法:

您可以生成一个表,其中包含一组与随机时间段相关的随机数字:

Time Period          Interleaver
next 2 weeks:        442
following 8 days:    142
following 3 weeks:   580

等等......这给了你无限数量的交织器,并且不会让任何人知道你的订单率,因为你的时间段可能是几天的数量级,你的交织器正在做很多低技术的“混搭” “ 为你。

您可以生成此表一次,并确保所有交织器都是唯一的。您可以通过简单地将更多字符添加到集合中来确保不会用完交织器,或者从定义更长的交织器开始。

因此,您通过获取序列号生成订单 ID,并使用今天的 Interleaver 值,将其数字(因此,名称)交错在每个序列号的数字之间。保证独一无二 - 保证令人困惑。

示例

Today I have a sequential number 1, so I will generate the order ID:  4412
The next order will be 4422
The next order will be 4432
The 10th order will be 41402

In two weeks my interleaver will change to 142, 
The 200th order will be 210402
The 201th order will be 210412

Eight days later, my interleaver changes to 580:
The 292th order will be 259820

这将是完全混乱但完全确定的。您可以从 1 的位置开始删除所有其他数字。(除非您的订单 ID 仅比您的交织器长一位)

我没有说这是最好的方法——只是周五的想法。

于 2009-07-24T19:11:01.423 回答
0

您可以像使用邮政编码一样:2b2 b2b

这样它就有某种校验和(不是真的,但至少你知道如果有 2 个连续的数字或字母是错误的)。它很容易通过电话读出,而且它并没有说明系统中有多少订单。

于 2009-07-24T20:08:23.697 回答
0

http://blog.logeek.fr/2009/7/2/creating-small-unique-tokens-in-ruby

>> rand(36**8).to_s(36)
=> "uur0cj2h"
于 2009-07-24T20:12:40.597 回答
-3

以毫秒为单位获取当前时间并将其用作您的订单 ID 怎么样?

于 2009-07-24T19:07:25.190 回答