views:

188

answers:

7

I have a backend that generates gift codes, each with a certain number of uses. Give these to a blogger or whatever, and their readership can redeem the code for a promotional item.

I'm working on the best way to check a codes validity without having collisions/dupes, or anything like that. I need to 1) validate the code 2) collect shipping info

My first draft was

A) Check code via a form, if good, proceed to address input. When input is received, save code and address/name etc.

This fails because if there are 74 uses on a 75 use code, 25 people could "validate" but not enter their address yet, and we'd end up with more than 75 valid redemptions.

My current solution looks more like:

B) Just have the code as the first field in the information gathering form, and when a valid code is typed in, ajaxify that and live check it against the DB. If the code is valid, it then shows the rest of the form, and that entry of the code is "claimed" for half an hour or something. If no DB entry w/in half an hour, it's then released.

This seems pretty complex, and I'm wondering if I'd need to do throttling against the ajax attempts to make sure people don't brute force a valid code.

Is this method secure, and/or are there any other blatantly obvious patterns I'm missing for this type of application?

+6  A: 

Let everyone enter their gift-code and address, and then submit

In the backend, verify the address and the gift-code.

If the gift-code is valid and not exhausted, congratulate the user. Else apologise to them and suggest they buy it instead anyway.

Does it have to be more complicated than that?

Will
I like this solution, because It still gives you a chance to make a sell even if code doesn't work.
GSto
My only complaint against this from a UI standpoint would be the "awful" (on the scale of how bad a User Interaction can be, which is, admittedly, not too awful) experience of carefully inputting all of your address info only to find out your code has been rejected. "What a waste of time!" they say.
Alex Mcp
+1  A: 

Why don't you just have one form with all the information (redemption code and shipping info)?

Then, when the user submits, atomically (using transactions on your database) check if it's valid and commit the user's information.

If the code is no longer valid, just show a message like "Sorry, the redemption code you used has been depleted and is no longer valid."

Ben S
A: 

Your current solution looks like the proper one, although I think you left out the method by which you associate the user association with the code. Still, providing the functionality of "reserving" a redemption of the code for a user is a good solution.

McWafflestix
A: 

Option B seems reasonable. Just use a captcha rather than trying to throttle it. Captchas aren't perfect but it's less obnoxious than say misreading the code three times and then being denied the ability to try another for 24 hours. This will work particularly well if you're already planning on doing it AJAXy.

So -
User will fill in code field and captcha.
You'll confirm the captcha, then confrim the code.
Once successful, the user will fill in the other info and submit.

Using this method you could also probably only lock the code for something more like 5 minutes (ticket agency style) and show a timer on the form somewhere notifying the user.

John South
A: 

Your A method (Check code via a form, if good, proceed to address input) looks very reasonable. Just combine it with B's "code is "claimed" for half an hour or something", and everything should work as you expect.

That is:

  • Customer enters code
  • Check code – if valid, and not already used MAX+ times, add an extra entry in code use table, with a timestamp that expires after x minutes.
  • Collect other info
  • On submit, permanently mark the code as used (remove entry expiration)
  • If customer never makes the order, the timestamped entry is removed (or ignored) after time x, and released for others to use.
Joel L
A: 

We do a low end encryption (RC4) with a checksum added for this type of thing. Because RC4 generates a problematic character set, we also converted it to HEX. The combination is relatively secure and self checking. The decrypted value is just a number that we can verify in the database. This works with both our eMail reminders and gift certificates.

Dave
+1  A: 

Just wanted to add, if you're worried about bruteforcing attempts, you can require a captcha or javascript based hashcash value to be submitted along with the gift code. If you want to be as unobtrusive as possible, you can only require this for subsequent attempts after the first failed one.

One thing you might consider, is after the user enters a gift code, create an intermediate page that has more details about the offer, shows the number of claims remaining, and has some information about what will be required to complete the offer (address, creditcard, whatever). If the user chooses to claim the offer, have a 10-15 minute countdown (updated via javascript) on the data entry page for the address and other personal information, so the user knows that the offer might expire if they don't enter their information immediately.

Another thing to consider is implementing a "cancel" button that indicates the user can make the offer available for another user, without waiting for the countdown to expire.

ironchefpython