Question

By using python language, what would be a clever / efficient way of generating promotion codes. Like to be used for generating special numbers for discount coupons. like: 1027828-1

Thanks

Was it helpful?

Solution

1027828-1 is extremely small. An attacker can make a ~million guesses using only a couple lines of code and maybe a few days.

This is a good way to produce a hard to predict number using python, it works under linux and windows. It is base64'ed for binary safety, depending what you are doing with it you might want to urllib.urlencode() but I would avoid base10 because it doesn't store as much information.

import os
import base64

def secure_rand(len=8):
    token=os.urandom(len)
    return base64.b64encode(token)

print(secure_rand())

As a side note this is generating a full byte, which is base256. 256^8 is 18446744073709551616 which should be large enough.

As it was pointed out base64 isn't a very good token for humans to use. Consider an alternate encoding like url-safe base64 or perhaps humanhash as they would be easier to type in.

OTHER TIPS

The following isn't particularly pythonic or particularly efficient, but it might suffice:

 import random
 def get_promo_code(num_chars):
     code_chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
     code = ''
     for i in range(0, num_chars):
         slice_start = random.randint(0, len(code_chars) - 1)
         code += code_chars[slice_start: slice_start + 1]
     return code

if you need a 6-digit # you could do this until you found a unique value:

import random
print str(random.randint(100000, 999999))

or go sequentially...

I've come up with an answer for this that I think is fairly clever, but relies on a couple of assumptions that might not be true for your situation.

  • The resulting code is purely numeric.
  • The resulting code is technically variable-length; [10, 20].

If these work for you, then so might this solution:

def code(seed = None):
    if (not seed) or (type(seed) != str) or (len(seed) < 10):
        seed = str(uuid.uuid4())[:10]

    code = ""
    for character in seed:
        value = str(ord(character))
        code += value

    return code[:20]

In this function, a string-typed seed is used as the base of the code. For each character in the string, convert it into its ASCII representation, then append it to the code.

By default, the function yields codes like this: '97534957569756524557', and can be invoked with any arbitrary seed. For example...

code("pcperini's answer") == '11299112101114105110'
code(str(time.time())) == '49524956514950505257'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top