Какой будет хорошая схема идентификатора заказа для решения для электронной коммерции или платного веб-сервиса? - PullRequest
7 голосов
/ 31 октября 2010

Учитывая следующее:

а) вам нужна некоторая конфиденциальность (например, не сообщая всем, сколько заказов вы получили).

b) вам нужна контрольная цифра (например, с использованием алгоритма Верхоффа) в конце, чтобы вы могли легко указывать опечатки и помогать устранять ошибки при сканировании штрих-кодов, если это так.

в) необходимо учитывать время, чтобы потребители могли отсортировать заказы.

d) должно быть все числовое или шестнадцатеричное и т. Д.?

e) что-то, что ваш потребитель может сказать по телефону в службу поддержки, и этого вполне достаточно для определения заказа, при этом персоналу не нужно запрашивать электронную почту и т. Д. Из-за соображений безопасности.

Я бы хотел услышать некоторые мнения.

PS: любой алгоритм, разработанный для решения этой проблемы, также будет считаться правильным ответом для меня.

Ответы [ 4 ]

5 голосов
/ 01 ноября 2010

Вот мое решение.

Три части xyz, где x - это отметка времени, y - случайный код, а z - контрольная цифра, полученная путем объединения x и y.Но чтобы упростить (сделать его меньше), x и y задаются в пользовательской базе вместо числовой базы 10, а z по-прежнему задается в базе 10.

Примеры идентификаторов, которые вы можете получить с помощью этого подхода:

  • 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 для создания «дружественных» ссылок в Твиттере и т. П. .

Ниже приведен Verhoeff :: calcsum Проверка Диэгера группы D5 Верхоффа 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» в предыдущем слове) определенно,Из-за этого я рекомендую вам использовать вместо этого следующий альтернативный base / upper_limit:

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

Обратите внимание, что если вы попытаетесь использовать большее число, вы достигнете верхнего предела PHP, а также лимита mt_rand,что можно увидеть с помощью mt_getrandmax ().Кроме того, я хотел бы сказать, что для того, что я вижу, энтропии mt_rand достаточно.

Если вам нужны большие числа для случайной части, я рекомендую просто добавить третью часть к этому с чем-то вроде mt_rand (i, j);где i и j - минимальные и максимальные значения для вашей базы, которые увеличат ваш идентификатор заказа на длину $ num-chars (на самом деле я сделал это, с указанной выше конфигурацией).

А на стороне БД этоуникальное поле, чтобы избежать столкновений.

Спасибо всем.

1 голос
/ 01 ноября 2010

java.util.UUID.randomUUID ()

1 голос
/ 31 октября 2010

Как насчет случайной строки любой длины, которую вы считаете подходящей? Используйте символы, которые нелегко спутать с другими символами, для чтения по телефону. Поэтому по каждому заказу звоните что-то вроде:

    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. И вы сохраните целостность в БД с уникальным ограничением, верно?

0 голосов
/ 31 октября 2010

Вы можете использовать GUID . Чтобы сжать его до удобной для пользователя строки, стоило бы пропустить значение через Base32 преобразователь, что привело бы к строке, содержащей 26 символов A-Z и цифры 2-7

Чтобы соответствовать другим критериям, вы можете добавить контрольную цифру к значению guid, и вам, вероятно, понадобится отдельный подлинный порядковый номер заказа в базе данных, чтобы гарантировать уникальность и разрешить естественную индексацию / сортировку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...