如何使用实际订单ID生成唯一订单ID(仅显示touser)?

再次编辑:我不想再创建另一个问题,所以问这里。 我有同样的情况。 但是这次我需要C语言的算法。 有谁能够帮我。

我有下表。

CREATE TABLE IF NOT EXISTS `j741_order` ( `order_id` int(11) NOT NULL AUTO_INCREMENT, `buyer_id` int(11) NOT NULL, `subtotal` decimal(15,5) DEFAULT '0.00000', `discount` decimal(15,5) NOT NULL DEFAULT '0.00000', `shipping` decimal(15,5) DEFAULT '0.00000', `tax` decimal(15,5) DEFAULT '0.00000', `total` decimal(15,5) NOT NULL DEFAULT '0.00000', `currency` char(3) DEFAULT NULL, `status` int(11) NOT NULL DEFAULT '0', `created_date` datetime NOT NULL, `modified_date` datetime NOT NULL, PRIMARY KEY (`order_id`), KEY `idx_buyer_id` (`buyer_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 

我想生成一个唯一的订单ID,(只是向用户显示),以便用户无法猜出下一个订单ID。

如何从原始订单中获取该唯一随机订单ID

并从该随机订单ID获取原始订单ID?

编辑: 我不想创建任何其他字段。

如果您的要求是:

  • 它必须是可逆的(即给出“随机”ID,你可以找到原始的order_id)
  • 没有额外的列
  • 您根本不想向用户显示原始/内部order_id

那我建议采用某种双向加密方式。 哈希不会起作用,因为您无法从哈希中找到原始值。

我还补充说它应该是人性化的,例如有人可以通过电话给你打电话

我将使用一个非常简单的双向加密类,这是由Tony Marston编写的。

我们希望解决方案是人性化的,所以让我们删除一些争夺字符。 我只留下了大写字母,数字以及空格和短划线符号。 所有这些都可以使用标准的拼音字母轻松传达,强制使用大写可以消除任何关于角色是什么的混淆。

这些是我使用的争夺字符串(我使用这个在线单词扰码器,而不是试图自己拼写字符串):

  $this->scramble1 = '0123456789-ABCDEFGHIJKLMNOPQRSTUVWXYZ '; $this->scramble2 = 'UKAH652LMOQ FBDIEG03JT17N4C89XPV-WRSYZ'; 

因此,创建我们的人性化订单ID的代码是:

 encrypt($key, $order_id, $min_length); print "Encrypted: " . $encrypt_result . PHP_EOL; // DECRYPT $decrypt_result = $crypt->decrypt($key, $encrypt_result); print "Decrypted: " . $decrypt_result . PHP_EOL; ?> 

(您需要在本地下载并保存* encryption_class *文件,并将其包含在内)。

我从命令行运行该代码并收到以下输出:

 Original: 123456789 Encrypted: 2UD5UIK9S Decrypted: 123456789 

现在我们有一个简短的,人性化的order_id,可以在http://myapp.example.com/order/view/2UD5UIK9S这样的URL中使用,您永远不需要向用户显示或传达内部order_id 。

笔记:

一旦您的order_id是唯一的,加密代码将是唯一的(因为它将是PK)

这不应该用作密码加密/解密例程 – 不存储密码,存储哈希值。

确保您的密钥是随机的,复杂的,并且包含$ scramble变量中的字符。

它仅对order_id进行模糊处理。

编辑:

虽然填充输入字符串(order_id)会产生一定程度的ramdomness,但您可以将其与@ biakaveron的答案结合起来创建一个URL,如http://myapp.example.com/order/view/5cc46aea44e898c3b4e1303eb18d8161302cd367/2UD5UIK9S

  1. 创建您的密钥(任何字符串)并保存在配置文件(或DB配置)中。
  2. 创建唯一ID: $newId = hash_hmac('sha1', $orderId, $secret_key).'-'.$orderId; 。 因此,您的订单页面将显示为http://example.com/order/show/123456...absdef-123
  3. 您可以快速获取原始订单ID并进行检查:
  list($hash, $original) = explode($newId, '-', 2); if (hash_hmac('sha1', $original, $secret_key).'-'.$original === $hash) { // its a correct ID } else { // wrong hash, ignore it! } 

这种方式原始ID是公共的,但由于未知的散列字符串(唯一ID的第一部分),用户无法在站点地址中替换它。

首先,你应该将order_id作为数据库中的物理标识符:该字段是一个整数,它运行良好(你的代码设计使用它 – 并且整数提供比字符串键更好的性能)

但是您可以添加另一个字段作为用户的标识符:

  • varchar(something)char(something)字段,可以获得更好的显示效果,并且更难猜测,
  • 它会显示给用户,
  • 它上面会有一个UNIQUE索引,
  • 但它对你的代码没有任何技术意义。

GUID可能是一个想法 – 但我觉得它可能有点太长了……

基于用户姓名的第一个字母,日期和一些随机数的内容怎么办?
这很难猜测,对用户来说还有一点意义……

当然,您将无法从该字符串标识符计算order_id – 但如果该字符串标识符是唯一的,那么您将获得order_id:

 select order_id from your_table where nice_looking_id = '...'; 

你可以捏造它,但我完全建议添加另一列。 这是我用PHP做的。

 // do your insert // Retrieve last insert id $orderId = mysql_insert_id(); // get the current timestamp $time = time(); // Intersperse the $orderId into the $time to get a new "hash" $orderId = explode("", (string)$orderId); $time = explode("", (string)$time); $orderIdLength = sizeof($orderId); $newOrderId = ""; for ($i = 0; $i < $orderIdLength; ++$i) { $newOrderId .= $orderId[$i] . $time[$i]; } $newOrderId = (int)$newOrderId; 

因此,如果您的实际订单ID为489,并且当前时间戳为1300778794,您最终会得到一个类似于418390的订单ID。如果您的客户随后使用该订单ID进行任何操作,您只需将其分解为:

 $newOrderId = explode("", (string)$newOrderId); $length = sizeof($newOrderId); $oldOrderId = ""; for ($i = 0; $i < $length; $i = $i + 2) { $oldOrderId .= $newOrderId[$i]; } $oldOrderId = (int)$oldOrderId; 

这不是一个非常复杂的方法,并非100%万无一失。 但是为了轻轻地模糊你的订单ID,我认为它可以充分发挥作用。

编辑:就像快速一样,您可以使用一些其他方法生成一些半随机数来填充除time()之外的id。 例如,您可以执行rand(pow(10, log10($orderId)), pow(10, log10($orderId)+1)) ,这将始终返回一些与orderId长度相同的随机数。

另一个非常简单的方法是对OrderID进行base64编码。 您将base64编码的ID传递给客户端而不是实际ID,然后在ID返回时对其进行解码。 我建议从编码字符串的末尾删除等号。

优点:

  • 真正快速简单地混淆实际ID

缺点:

  • 你必须记住解码它
  • 一个聪明的用户很容易弄明白

$ original_id = [无论如何];

 $salt = [very big private number/string/value]; $checksum = hexdec(substr(md5($original_id . $salt)), 0, 4); // Generate 16 bit checksum while(strlen($checksum) < 5) // make sure it's five digits long $checksum = "0" . $checksum; $user_facing_id = $checksum . $original_id; // Prepend original with checksum 

您可以使用substr($ user_facing_id,5)获取原始ID,您甚至可以通过检查dechex(substr($ user_facing_id,0,5))和substr()之间的相等性来检查它是否是有效的订单ID而不询问您的数据库( md5(substr($ user_facing_id,5)。$ salt)。

正如其他人所说,您可以简单地使用已知的盐生成订单ID的哈希值 – 而计算机并不真正关心订单号是否为

854bf1176798d77ecaf6b66cbe71a8fc1b0c1847

要么

36698

湿软件有很大的不同。

这样用户就无法猜出下一个订单ID是什么。

你真的想避免在这里做什么? 我本以为你只是想阻止用户看到其他人的订单 – 在这种情况下你只需要使用订单ID和用户标识符的组合来选择订单。

当然,订单总量可能被视为敏感信息 – 在这种情况下,只需使用与用户ID绑定的序列号。 虽然您没有明确说明您使用的是哪个DBMS,但我认为它是基于引擎的mysql或衍生产品 – 但以下内容也适用于大多数关系型DBMS:

如果向表中添加一个描述默认值为0的用户的列,则可以在订单表上添加触发器,以自动获取,增加和更新订单表上每个插入的值 – 即代码不需要更改除了支持“外部”订单参考之外的其他地方。 当然,您需要将此值与已经放置的相关订单数量相关联 – 例如….

 ALTER TABLE buyers ADD COLUMN buy_ref_last INTEGER DEFAULT 0; ALTER TABLE orders ADD COLUMN buyer_order_ref INTEGER; UPDATE orders o SET buyer_order_ref = (SELECT COUNT(*) FROM orders r WHERE r.buyer_id=o.buyer_id AND r.order_id 

(注意我怀疑上面不会直接在MySQL中运行,它不喜欢与更新/删除在同一个表上的子选项 - 你需要将逻辑展开到一个过程中)

和....

 UPDATE buyers b SET buy_ref_last=(SELECT MAX(buyer_order_ref) FROM orders o WHERE o.buyer_id=b.id);