The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Account Number Generation

Looking for a bit of advise...

We are in the early stages of designing an on-line portal for customers to pay their bills (online bill pay).

Our buisness is a little unique in that when we close a deal, we have roughly 80-100 customers we need to begin billing right away.  A brief background on the business.

Our business is a WIFI service that we provide to private communities where there are associations.  Associations are just private communities who essentially & collectively control who picks up their trash, provides  Broadband services, etc...  We just signed our first deal last week and I have roughly 10 months to implement the online billing aspects of the online bill pay system.

During the next 10 months we will be implementing infrastructure since the community is not 100% developed yet.  And for the next 2 months we will be getting things set up.  Roughly 2-3 months from now, we will start a paper billing system for the residents currently living there.

On the paper invoices, we want to eventually advertise to our customers that they can pay online; when that is complete.

Suffice it to say we are not *just* doing WIFI services but other types of services I won't get into here -- it will add nothing to this post anyway.  That said, we are very well received with our service and ideas.  I am quite confident we will be picking up at least 3 more deals like this and larger over the rest of 2006 with other communities we presented our services too.

Due to the number of customers we will be needing to handle at a time, I am curious about how I could generate customer account numbers in such bulk as well as ongoing adds & changes.

My initial thought was to enumerate from some starting point for each community.

1-xxxxx where 1 is the community code and xxxx is the enumerated customers in that community.  Database table wise, we would have 2 tables.  One for the community details and one for the customer details. 

My concern is the billing system and someone trying to establish an erroneous customer number or hack the sequenece.  Granted I've not thought this through in terms of what they could do with the information.  I mean what good is a customer account number anyway unless you are willing to pay someone elses bill for them?

I worry about, for example, a customer siging up for online bill pay with the wrong customer account number and somehow paying someone else's bill instead of their own bill; maybe s/he fat fingers the account number during entry and because account numbers iteratively close, we would just accept the entry as valid.

My 2nd thought was to use a sort of date/time stamp for each customer as they are added to the underlying database.  This would still be enumerable but probably be a bit cumbersome with such long string of digits.

My 3rd thought is to just use a random number generator of 10 digits or so.  Maybe alpha-numberic to create enough randomness that a fat finger entry would be hard to allow through.

Is there any rhyme or reason behind the structure of account numbers that you use in your software?

What methodologies do you use to generate the account number? (enumerate, random, date/time stamp, other?)  Such that later the end user enters the account number and confirms their billing information.

Some systems use an email notfication type system but that seems OK for the simple fat finger case but also seems a bit dangerous too.
Friday, April 21, 2006
oh, and my reason for bringing all this up.

I was an AT&T cellular customer when AT&T bought out Cingular.  I got a new account number and so I started using it.

Next thing I knew, I was getting notices of my phone being shut off due to non-payment.  Turns out some glitch had my payments going to my old account number.  On the AT&T customer login web page, it would show 2 account numbers; my new and old.

Later, I was told this was a unique problem to customers that had more than 1 line which I did.  I had 2 phones with 2 phone lines and my 2nd phone didn't "upgrade" with the new account number.

So this is what prompted me in the OP to ask around...

Thanks for your time & feedback.
Friday, April 21, 2006
If you just want to guard against simple data entry errors with your account numbers, then I'd suggest that you just tack on a checksum digit to the end of the account number. The scheme used for ISBNs (International Standard Book Numbers) is quite good. You should be able to find the details with a quick Google search.

Before you do anything with an account number, you first verify that the checksum is consistent. This is a simple algorithm: you don't need a list of valid account numbers (and it could be easily done on the client side for a web application). If the checksum is incosistent, assume a data entry error and proceed no further. The ISBN algorithm will reject 100% of numbers with a single wrong digit, and 100% of numbers with a two digits transposed - these are the two most common types of manual data entry errors. Furthermore, it will reject 90% of numbers with multiple errors.

Using a checksum solves the data entry problem, but doesn't impose any requirements on the rest of the number, so you can assign these using whatever rules are convenient for your application.
Stephen C. Steel Send private email
Friday, April 21, 2006
I always use random number generators, with a check digit whenever I needed account numbers.  It may seem like a waste, and it is kindof difficult initially for csr's to understand the reasoning, but it is always better than doing a structured account #.  The reason I say that is that people DO notice that, and you will find unscrupulous people who will try to take advantage of it.
Matt Secoske Send private email
Friday, April 21, 2006
+1 for check digit(s)

You could also hash (use a non-reversible hash so people can't figure out a pattern) something unique (phone number? SSN?) about the customer to form the base account number - instead of randomly/sequently generating the number.  This would give you a 2nd layer of checking above the check digit(s)
S. Tanna
Friday, April 21, 2006
I would just allocate sequential numbers to your customers starting at some predetermined start, e.g. 10001 and then stick a check digit on the end.

If you want to prefix with some code to determine the community, why not use alphanumerics instead of a number range? e.g. AB10019

The random suggestion gives me the heeby-jeebies.
Tim Hastings Send private email
Friday, April 21, 2006
Tim, are you concerned about collisions?

Maybe a third alternative, is to combine 3 bits into one number

Something like XXXXYYYYZ, where XXXX = sequential number, YYYY = random or hash generated, Z = check digits

This way you can never have collisions, but people still can't guess the next/previous person's account number
S. Tanna
Friday, April 21, 2006
Thank you all for the suggestions thus far.

"The random suggestion gives me the heeby-jeebies."

My words exactly -- nice to know other developers have this same gut instinc. (smile)

Stephen C. Steel,
That's a good idea -- using the CRC and ISBN.  Any code examples of such an algo you know of?  Very interested in this.

"The reason I say that is that people DO notice that, and you will find unscrupulous people who will try to take advantage of it."

Yes -- this was my thought too.  I'm a bit relieved you and the others "read" my concerns.  Although I'm not sure what one could do with knowing an account number and that their neighbor next door would have the increment of their account number would do with that information so why not put a little time into randomizing it a bit.  It's the whole "heeby-jeebies" thing.(smile) 

My back-end CGI scripts will most likely be perl code.  But since I'm in the design phase, I could do just about anything such as PHP... The platform will be Linux + Apache.

I really like your idea too.  Coupled with the ISBN number this seems exactly what I'm after.  I'm not a cryptologist so I'll need to learn a bit of CRC and Hashing -- are you aware of any good Perl code snippets to learn from?

Thank you all, so much!
Friday, April 21, 2006
+1 check digits.
+1 Matt.

At a previous gig, part of the business was an MLM, so folks could see what their "downline" was doing, and more than a couple noticed that the account number (account number/customerID were sequentially issued) was in the querystring, so they typed in a few numbers. One could hear the VPs screaming from miles away.

The technique chosen was to encode the customerID and hide it in chaff. Easily crackable, quick to deploy (asp.classic), and outside the skill range of the userbase (to break). So ?id=123 got mangled into something quite different: 123 turned into yU* and chaff was added so you'd see something more like ?id=xxxxxyxxxxxxUxxxxx*xxx where x would be some random characters that would remain the same for the duration of *this* session. If I were implementing this nowadays, I'd do something closer to the below methods.

Some project articles to get you started:

It might be helpful to generate the customer numbers in advance (randomly if you want, call them something other than random if Tim is looking ;) ), toss them into a table where you "cross them off" when used.
Friday, April 21, 2006
I like check digits (its funny how they are so often misconstrued to be a relic of overnight batch processing systems), but don't you make them enter a password (or something similar) prior to showing them anything remotely sensitive? In that case, assuming each customer has no more than a handful of account numbers, a check digit isn't necessary... though you may still want it for administrator-type users that have access to all billion accounts in the system.

On a possibly related note, there was a case in Ontario a while back where the phone company inadvertently gave access to phone bills of the "other spouse" in a dissolving marriage situation. Spouse B used it to do all sorts of bad things to Spouse A, and Spouse B in turn sued the pants off the phone company. And rightly so. The point is, even a mundane bill paying app can be sensitive, if it shows this level of detail.
NetFreak Send private email
Friday, April 21, 2006
For an easy way to generate the base number, I've simply hashed the DB unique id, then taken the first X characters from the hash as my "unique" number.  It never occured to me to add a checksum digit -- what a great idea.  I never really needed true uniqueness for mine since my numbers were temporary invitation codes, not permanent acct numbers, but that's a good pointer for future reference.
Brian Moeskau Send private email
Saturday, April 22, 2006
Top hit on Google to a search on the three words "ISBN checksum algorithm" was this wikipedia page

which lists a number of suitable candidates: ISBNs, Luhn algorithm (credit card numbers and Canadian social insurance card numbers), etc.
Stephen C. Steel Send private email
Sunday, April 23, 2006
Account numbers can often be found in the trash, printed on bills.  If guessing a valid account number is a problem then you're really assigning a fixed password, not an account number.

Tuesday, April 25, 2006
This design doesn't make any sense. You want a strong account number but no password? What you want is an account number (plus a check-digit if you are worried about data entry errors) and a strong password.
MBJ Send private email
Friday, April 28, 2006
How does a check digit work?
Pete B.
Friday, April 28, 2006
Monday, May 08, 2006
+1 check digit
+1 MBJ

Okay so I agree with MBJ that if you have sensitive data a password is necessary, therefore a check digit would be there for perhaps adminstrative data entry errors.

Say I have an account number like this: 10000-11

Id = 10000
Check digit = 11

Is it redundant to store the check digit in the database? If not do I store the Id and Check digit together in the database, or store them in seperate fields?
Chris Lee Send private email
Monday, May 15, 2006

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
Powered by FogBugz