Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
How I Reimplemented My Shopping Cart To Sell More Software, w/ Code (bingocardcreator.com)
74 points by patio11 on Feb 11, 2009 | hide | past | favorite | 19 comments


Hiya guys. I recently redid the shopping cart for my business. Then I spent a few hours writing it up for folks, with the hope somebody can use something.

Article includes:

+ Results of my A/B tests with previous ways of presenting software for sales to my customers.

+ How I use lightboxes to make a good deal of money

+ An AJAX cart I have used to good effect

+ How I went about designing and reimplementing a cart, in JS, to give the feel of the AJAXy one but improve its speed and UI

+ Code for everything, which I put in the public domain. Go nuts.


>So your shopping cart needs to be willing to continue the conversation with your customers.

Great advice, I like your insight into how users interact with shopping carts. I'll be taking this with me on my project!

FYI: the link to e-junkie at the end of the page is broken. It points to: http://www.e-junkie/


Maybe I've missed something, but it seems like you could completely eliminate the security flaw of letting your user's decide how much to pay for your software very easily. Just have the server send the price with an HMAC, check the HMAC on return, and voila.


This is a neat idea, but there is at least one subtlety: you need to make sure that it is not possible to cut-and-paste HMAC'd prices from one web page into another. Otherwise the user could ask for a page for an item with a price of $1, receive an HMAC on "$1", and paste that into a page for a different item.

Two possible ways to do this:

1) Use a different HMAC key for each page you generate. 2) HMAC the pair (price,nonce) where nonce never repeats from one page to another. The server has to keep the nonce, as well, i.e. is not obtained from the web page.


A simple one-way hash will provide sufficient security for most cases. Assuming you're representing items for sale in a Javascript array, you might send data like this to the browser:

  var forSale = {
    "book": {"price": 19.95, "description": "a book", "checksum": "c6da835c1fd2ee98d68eee3912dd199e41c82a32"}
  }
The value for 'checksum' is just a SHA1 hex digest of the ('book', '19.95', 'secret'), joined by tab characters. It can be included as a hidden form field or invisible element within your page; it doesn't matter so long as you can capture it and POST is along with the item + price.

In your order-processing logic, just check that the hash verifies with your secret key ('secret' in the above), and you know with a reasonable degree of certainty that the original page was one generated by your server.


That would work, but I don't do order fulfillment. e-junkie does. They get to keep the IPN and Google payment notification interfaces, an email server to send out registration keys, bunches o' reporting code, and integration to the company that stamps CDs for me.

The cart posts directly to them, so hypothetically assuming I generated a secret and passed it over, they'd process the order anyhow and then tell me "By the way, your website passed this secret with the order -- do whatever with it", after which point a) the customer would have a registration key and b) if they ordered a CD, it would be scheduled to ship already.

Which is a long way of saying "There are ways to make this setup more secure but they'd involve me having to rewrite large portions of my business processes." Like I mentioned: it would cost me a lot of time at a very minor increase in security.

Probably illusory, actually. No amount of securing my cart will protect me from this attack: buy the software, write me an email saying "You offer an unconditional guarantee. I'd like a refund." And there is absolutely nothing that anyone could say or do which would make me stop offering that unconditional guarantee, because it is practically a license to print money. (To anyone who produces a low-marginal-cost product or service: if you do not have a guarantee, start A/B testing one. Its the closest thing in life to free money.)


I remember reading one of the "hacking exposed" books (the exact one I can't remember now), where there was an incident where an online store used values in the webpage itself to handle the prices of goods. In the example in the book, the hackers had replaced $45 list price with $1 giving huge discounts to the purchasers. And to make things even worse, some of the hackers would order dozens of shirts (at $1 each) and then return them for full price.

It might have been an earlier edition of this one, but I do remember the bright red cover: http://www.amazon.com/Hacking-Exposed-Web-Applications-2nd/d...


Do you use the same secret for each page generated? If so, checking that the hash verifies with your secret key alone does not prevent a cut and paste attack where an adversary asks for a web page with the SHA1 digest of an item worth '1.00' and then pastes that item into the web page for an item worth '19.95'. You need some additional checking that the "forSale" supplied not only was created by you, but was created by you for use in this particular page and context.

A separate issue is that using this hash(message, secret) construction has problems if the underlying hash function has chosen-prefix collisions. MD5 has this problem already. While no one knows how to generate such collisions for SHA1, the fact that its design is close to MD5 is cause for concern. In contrast, if you use HMAC, you have confidence that the data was generated by you with much weaker assumptions on the hash function. The wikipedia page for HMAC has some useful discussion here and pseudocode: http://en.wikipedia.org/wiki/HMAC


Um, I'm not sure I'm reading this right but you hard-code your prices in JS to cut down on an AJAX call.

Why not just print your JS from server-side - i.e. you can still have your prices in your JS but have the server generate these?


Easy, fast, and clean all in one little packet of geek joy. I like this suggestion a lot. Thanks. (The whole code-generates-code thing is still taking me some time to get used to... even though I spent several hours yesterday writing code-generates-code-generates-essay.)


Accordingly, the fact that the same URL rewriting trick that lets me change the price to give users discounts could be used to reprice my software to a penny... really doesn't worry me that much.

Is this an invitation to get a 1 penny trial version of your software?


Does your cart fail gracefully if javascript is turned off, or is that not a concern for you?


Did you try it?

It should fall-through to e-junkie's traditional non-Javascript cart hosted offsite. I personally think the experience is decidedly suboptimal next to either of the JS carts but, honestly, I think the Internet is moving away from assuming that Javascript is optional.

(I would have a different opinion if I had to support a range of mobile browsers but, well, I sell downloadable software to elementary schoolteachers. Most of them don't think "Ooh great I loved this downloadable free trial! Let me write down the URL, get out my iPhone, type in the URL, then order a copy!")


> "Originally posted by monkeyfish at Hacker News: "

Should be mechanical_fish I think.


I'll fix that once I get back home. Good eye.


Good work, I admire your approach.


How I SEOed my website to make more sales!


The main reason it is on the website, as opposed to my blog, is because I am making extensive use of Rails as the world's most over-engineered templating system to write that. It wouldn't be interesting at all without the cart to play with, now would it? I'm all about avoiding sucky user experiences and "I am going to extensively discuss a feature of another website. Please open that website in a tab and follow along" is a sucky user experience.

But yeah, to the extent that people find this article as valuable and link to it, Google will see my site as more trustworthy and send me more frazzled teachers trying to get ready for fourth period.

I really don't have a problem with that: they get their prep work done, I get money, the rest of the world gets a few hours of engineer time writing what I hope was a useful article as a result of the cross-subsidy. The notion is quite similar to OSS. Its a win for everybody.


Don't get all defensive bro. It's cool to get paid.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: