对于电子商务解决方案或付费网络服务来说,什么是好的订单 ID 方案?

发布于 2024-09-29 22:58:13 字数 326 浏览 0 评论 0原文

考虑以下因素:

a) 您需要一定程度的保密性(例如不告诉每个人您收到了多少订单)。

b) 您希望在末尾有一个校验位(例如,使用 Verhoeff 算法),以便在扫描条形码时轻松辨别拼写错误并帮助处理错误(如果是这种情况)。

c) 你必须考虑时间,以便消费者可以对订单进行排序。

d) 应该是全数字还是十六进制等?

e) 您的消费者可以通过电话向支持团队说出的内容,并且足以识别订单,而工作人员出于安全考虑无需索要电子邮件等。

我很想听听一些意见。

PS:任何为解决这个问题而设计的算法对我来说也被认为是有效的答案。

Considering the following:

a) you want some confidentiality (as in not telling everybody how many orders you've received).

b) you want a check digit (e.g., using the Verhoeff algorithm) at the end so you can easily tell misspells and help dealing with errors when scanning barcodes, if this is the case.

c) you've to consider time so consumers can sort the order of the orders.

d) should it be all numeric or hexdec, etc?.

e) something that your consumer can say over the phone to the support team and is just enough for identifying the order without the staff having to ask for e-mail, etc, because of security concern.

I'd love to hear some opinions.

PS: any algorithm designed for solving this problem also would be considered a valid answer for me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

孤蝉 2024-10-06 22:58:14

这是我的解决方案。

有一个三部分 xyz,其中 x 是时间戳,y 是随机代码,z 是 x 和 y 连接产生的校验位。但为了简化(使其更小),x 和 y 以自定义基数给出,而不是数字基数 10,但 z 仍以基数 10 给出。

通过此方法可以获得的 ID 示例:

  • LP9NTX-8D41-QW6R- 9
  • LP9NTY-5H3L-BFS7-5
  • LP9NTZ-RWL3-D619-8
  • LP9NVB-BW74-788W-6
  • LP9NVW-G17D-4911-8

因此,您可以按时间戳排序(注意它是如何按“增量字母数字”顺序排列的,如果你不知道什么是数字基数)。

为此,我使用了 base58 (最后我用小写还是大写都没关系),这是base62,没有一些令人困惑的字符。 Flickr、bit.ly 和其他公司使用 base58 来制作 Twitter 的“友好”链接等< /a>.

下面的 Verhoeff::calcsum 是 Verhoeff 的 Dihedral Group D5 Check by Dahnielson。 唯一的我所做的编辑是将他的代码放在一个类中,所以它是一样的。

这是一些代码:(*对我在上面所承诺的内容进行了一些修改^)

<?php
    $time_divisor = 3;
    $base = "123456789ABCDEFGHJKLMNPQRSTUVWXYZ";//consider using another base **see note below**
    $lower_limit = 50000;//just to avoiding to confuse the user with a lower number
    $upper_limit = 1291467968;//1291467968 == ZZZZZZ in this base I used
    //you can check the limit with base_decode("ZZZZZZ", $base);
    $ptime = (int)($_SERVER['REQUEST_TIME']/$time_divisor);//or time();
    $rand1 = mt_rand($lower_limit, $upper_limi);
    $rand2 = mt_rand($lower_limit, $upper_limi);
    $ptime_b = base_encode($time, $base);
    $rand1_b = base_encode($rand1, $base);
    $rand2_b = base_encode($rand2, $base);

    $order_id = $ptime_b.$rand1_b.$rand2_b.Verhoeff::calcsum($time.$rand1.$rand2);
    echo $order_id;
?>

就在我写完这篇文章后,我想到了另一个可能出错的事情。我记得您不希望您的消费者感到受到侮辱。因此,即使认为像“f?ck”或“4ss”这样的坏词最终出现可能没问题(而且几乎肯定会出现),但明确的词(例如将前一个词中的“4”改为“a”)绝对不是。 。因此,我建议您使用以下备用基数/上限:

<?php
    $lower_limit = 27000;//=2111
    $upper_limit = 809999;//=ZZZZ
    $base = "123456789BCDFGHJKLMNPQRSTVWXYZ";//erased -a -e -u
?>

请注意,如果您尝试使用更大的数字,您将达到 PHP 的 int 上限以及 mt_rand 限制,这可以通过 mt_getrandmax() 看到。另外,我想说,就我所见,mt_rand 的熵就足够了。

如果您需要更大的数字作为随机部分,我建议仅在其中附加第三部分,例如 mt_rand(i, j);其中 i 和 j 是您的基础的最小值和最大值,这将增加您的订单 ID(以 $num-chars 长度表示)(实际上是我用上面的配置制作的)。

在数据库端,它是一个独特的字段,以避免冲突。

谢谢大家。

Here is my solution.

Have a three portion x-y-z where x is the timestamp, y the random code and z is the check digit produced by the concatenation of x and y. But to simplify (make it smaller), x and y are given in a custom base, instead of numeric base 10, but z is still given at base 10.

Examples of IDs you can get with this approach:

  • LP9NTX-8D41-QW6R-9
  • LP9NTY-5H3L-BFS7-5
  • LP9NTZ-RWL3-D619-8
  • LP9NVB-BW74-788W-6
  • LP9NVW-G17D-4911-8

So you can sort by the timestamp (notice how it goes in 'an incremental alphanumeric' order, if you don't know exactly what a numeric base is).

For this I used the digits + uppercase letters of base58 (in the end it won't matter if I used lowercase or upper), which is base62 without some confusing characters. Flickr, bit.ly and others use base58 for making Twitter 'friendly' links and the like.

The Verhoeff::calcsum below is Verhoeff’s Dihedral Group D5 Check by Dahnielson. The only editing I made was to put his code inside a class, so it's just the same.

Here is some code: (*somewhat modified from what I've promised at the lines up there ^)

<?php
    $time_divisor = 3;
    $base = "123456789ABCDEFGHJKLMNPQRSTUVWXYZ";//consider using another base **see note below**
    $lower_limit = 50000;//just to avoiding to confuse the user with a lower number
    $upper_limit = 1291467968;//1291467968 == ZZZZZZ in this base I used
    //you can check the limit with base_decode("ZZZZZZ", $base);
    $ptime = (int)($_SERVER['REQUEST_TIME']/$time_divisor);//or time();
    $rand1 = mt_rand($lower_limit, $upper_limi);
    $rand2 = mt_rand($lower_limit, $upper_limi);
    $ptime_b = base_encode($time, $base);
    $rand1_b = base_encode($rand1, $base);
    $rand2_b = base_encode($rand2, $base);

    $order_id = $ptime_b.$rand1_b.$rand2_b.Verhoeff::calcsum($time.$rand1.$rand2);
    echo $order_id;
?>

Just after I finished writing this another possibly of things going wrong came to my mind. I remembered you don't want your consumers feeling insulted. So even thought bad words such as 'f?ck' or '4ss' eventually appearing maybe ok (and they almost certainly will), explicit words (as in changing the '4' for 'a' in the previous word) are definitely not. Because of this I recommend you to use the following alternate base/upper_limit instead:

<?php
    $lower_limit = 27000;//=2111
    $upper_limit = 809999;//=ZZZZ
    $base = "123456789BCDFGHJKLMNPQRSTVWXYZ";//erased -a -e -u
?>

Please note that if you try to use bigger numbers you'll reach PHP's upper int limit as well as the mt_rand limit, which can be seen with mt_getrandmax(). Also, I'd like to say that for what I see mt_rand's entropy is enough.

If you need larger numbers for the random part I recommend just appending a third part to that with something like mt_rand(i, j); where i and j are the min and max values for your base that will increase your order id in $num-chars length (actually I made this, w/ the configuration above).

And at the DB side it's a unique field as to avoid collisions.

Thank you all.

幸福%小乖 2024-10-06 22:58:14

您认为合适的任意长度的随机字符串怎么样?使用不易与其他字符混淆的字符用于通过电话阅读。因此,在每个订单上调用类似以下内容的内容:

    public static string GetRandomString(int length)
    {
        char[] chars = "ACDEFGHJKMNPQRTWXY34679".ToCharArray();
        var crypto = new RNGCryptoServiceProvider();
        var data = new byte[length];
        crypto.GetNonZeroBytes(data);
        var result = new StringBuilder(length);
        for (int i = 0; i < data.Length; i++)
        {
            result.Append(chars[data[i] % chars.Length]);
        }

        return result.ToString();
    }

猜测从上述方法返回的 8 个字符是 1/282429536481 的机会。并且您将通过唯一约束来保持数据库的完整性,对吗?

How about random string of whatever length you see fit? Use characters that aren't easily confused with other characters for reading over the phone purposes. So on each order call something like:

    public static string GetRandomString(int length)
    {
        char[] chars = "ACDEFGHJKMNPQRTWXY34679".ToCharArray();
        var crypto = new RNGCryptoServiceProvider();
        var data = new byte[length];
        crypto.GetNonZeroBytes(data);
        var result = new StringBuilder(length);
        for (int i = 0; i < data.Length; i++)
        {
            result.Append(chars[data[i] % chars.Length]);
        }

        return result.ToString();
    }

Guessing 8 characters returned from the above method is a 1/282429536481 chance. And you'll keep integrity in the db with a unique constraint right?

宣告ˉ结束 2024-10-06 22:58:14

java.util.UUID.randomUUID()

java.util.UUID.randomUUID()

糖粟与秋泊 2024-10-06 22:58:14

您可以使用 GUID。要将其缩小为客户友好的字符串,值得通过 Base32 转换器运行该值,该转换器将生成一个包含 26 个 AZ 字符和数字 2-7 的字符串。

为了满足您的其他条件,您可以将校验位附加到 guid 值,并且您可能需要在数据库中使用单独的真实增量订单号来保证唯一性并允许自然索引/排序。

You could use a GUID. To shrink it down to a customer friendly string it would be worth running the value through a Base32 converter which would result in a string containing 26 characters of A-Z and digits 2-7

To meet your other criteria, you could append a check digit to the guid value, and you'd probably need a separate genuine incremental order number in the database to guarantee uniqueness and allow natural indexing/sorting.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文