Как создать код ваучера в С#?

Мне нужно создать код ваучера [от 5 до 10 цифр] для одноразового использования. Каков наилучший способ генерации и проверки, если они были использованы?

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

Ответы

Ответ 1

При создании кодов ваучеров - вы должны подумать о том, действительно ли то, что вы хотите прогнозировать, действительно то, что вы хотите.

Например, коды ваучеров: ABC101, ABC102, ABC103 и т.д. достаточно предсказуемы. Пользователь может легко догадаться о кодах ваучеров.

Чтобы защитить от этого - вам нужен способ предотвращения случайных догадок.

Два подхода:

  • Вставьте контрольную сумму в коды ваучера.

    Последний номер на кредитной карте - контрольная сумма (контрольная цифра) - когда вы добавляете другие номера определенным образом, вы можете убедиться, что кто-то правильно ввел номер. См. http://www.beachnet.com/~hstiles/cardtype.html (первая ссылка из Google), как это делается для кредитных карт.

  • Имейте большое пространство ключа, которое только малонаселено.

    Например, если вы хотите создать 1000 ваучеров, тогда ключевое пространство в 1 000 000 означает, что вы должны иметь возможность использовать случайное генерирование (с дублированием и последовательной проверкой), чтобы было сложно угадать другой код ваучера.

Здесь пример приложения, использующего большой подход к ключевому пространству:

    static Random random = new Random();

    static void Main(string[] args)
    {
        int vouchersToGenerate = 10;
        int lengthOfVoucher = 10; 


        List<string> generatedVouchers = new List<string>();
        char[] keys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890".ToCharArray();


        Console.WriteLine("Vouchers: ");
        while(generatedVouchers.Count < vouchersToGenerate)
        {
            var voucher = GenerateVoucher(keys, lengthOfVoucher); 
            if (!generatedVouchers.Contains(voucher))
            {
                generatedVouchers.Add(voucher);
                Console.WriteLine("\t[#{0}] {1}", generatedVouchers.Count, voucher);
            }
        }

        Console.WriteLine("done");

        Console.ReadLine();
    }

    private static string GenerateVoucher(char[] keys, int lengthOfVoucher)
    {
        return Enumerable
            .Range(1, lengthOfVoucher) // for(i.. ) 
            .Select(k => keys[random.Next(0, keys.Length - 1)])  // generate a new random char 
            .Aggregate("", (e, c) => e + c); // join into a string
    }

Ответ 2

Основываясь на ответах Уилла Хьюза и Shekhar_Pro (и только потому, что я нашел этот вопрос интересным), здесь была другая реализация, но я был немного либеральным с вашим требованием о длине кода ваучера.

Используя base 32 encoder, я обнаружил, что вы можете использовать значение Tick для генерации буквенно-цифровых строк. Кодирование количества галочек до базы 32 создает 13-значную строку, которая может быть отформатирована, чтобы сделать ее более читаемой.

    public void GenerateCodes()
    {
        Random random = new Random();
        DateTime timeValue = DateTime.MinValue;
        // Create 10 codes just to see the random generation.
        for(int i=0; i<10; ++i)
        {
            int rand = random.Next(3600)+1; // add one to avoid 0 result.
            timeValue = timeValue.AddMinutes(rand);
            byte[] b = System.BitConverter.GetBytes(timeValue.Ticks);
            string voucherCode = Transcoder.Base32Encode(b);
            Console.WriteLine(string.Format("{0}-{1}-{2}", 
                              voucherCode.Substring(0,4),
                              voucherCode.Substring(4,4),
                              voucherCode.Substring(8,5)));
        }
    }

Здесь вывод

AARI-3RCP-AAAAA
ACOM-AAZF-AIAAA
ABIH-LV7W-AIAAA
ADPL-26FL-AMAAA
ABBL-W6LV-AQAAA
ADTP-HFIR-AYAAA
ACDG-JH5K-A4AAA
ADDE-GTST-BEAAA
AAWL-3ZNN-BIAAA
AAGK-4G3Y-BQAAA

Если вы используете известное семя для объекта Random и помните, сколько кодов вы уже создали, вы можете продолжать генерировать коды; например если вам нужно больше кодов и вы хотите быть уверенными, что не будете генерировать дубликаты.

Ответ 3

Здесь один из способов: создать кучу уникальных номеров между 10000 и 9999999999, поместив их в базу данных. Каждый раз, когда вы даете его пользователю, помечайте его как использованный (или удаляйте его, если вы пытаетесь сэкономить место).

РЕДАКТИРОВАТЬ: Генерировать уникальные альфа-числовые значения в начале. Вероятно, вам придется держать их для проверки (как указывали другие).

Ответ 4

Если ваше приложение ограничено использованием только числовых цифр, я думаю, что временные метки (DateTime.Now.Ticks) могут быть хорошим способом получить уникальный код каждый раз. Вы можете использовать случайные числа, но у них будет накладные расходы на проверку каждого числа, которое оно было выпущено уже или нет. Если вы можете использовать алфавиты, тогда обязательно используйте GUID.

Чтобы проверить, использовалось или нет, вам необходимо поддерживать базу данных и запрашивать ее для проверки действительности.

Ответ 5

Если вы предпочитаете буквенно-цифровой формат, вы можете использовать метод Guid.NewGuid():

Guid g =  Guid.NewGuid();
Random rn = new Random();
string gs = g.ToString();
int randomInt = rn.Next(5,10+1);
Console.WriteLine(gs.Substring(gs.Length - randomInt - 1, randomInt));

Чтобы проверить, не был ли он использован, сохраните somwhere ранее сгенерированные коды и сравните.

Ответ 6

private void AutoPurchaseVouNo1()
    {
        try
        {
            int Num = 0;
            con.Close();
            con.Open();
            string incre = "SELECT MAX(VoucherNoint+1) FROM tbl_PurchaseAllCompany";
            SqlCommand command = new SqlCommand(incre, con);

            if (Convert.IsDBNull(command.ExecuteScalar()))
            {
                Num = 100;
                txtVoucherNoInt1.Text = Convert.ToString(Num);
                txtVoucherNo1.Text = Convert.ToString("ABC" + Num);
            }
            else
            {
                Num = (int)(command.ExecuteScalar());
                txtVoucherNoInt1.Text = Convert.ToString(Num);
                txtVoucherNo1.Text = Convert.ToString("ABC" + Num);
            }
            con.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error: " + ex, "Error !!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

Попробуйте этот метод для создания номера ваучера, такого как ABC100, ABC101, ABC102 и т.д.