turnley.dev

PHP and MySQL code for faucet operators

Tools & Calculators

REF-001

Generate referral codes that survive contact with users

Short, unambiguous, collision-checked, and not the username. The alphabet choice is what stops support tickets about codes that do not work.

Referral codes get read aloud, typed from screenshots and written on paper. Any alphabet containing both O and 0, or l and 1, guarantees a stream of people insisting a valid code is broken.

Using the username instead is worse: usernames change, they leak identity, and they let anyone guess another user's code and construct links that credit someone else.

Seven characters from an unambiguous alphabet gives billions of codes, which is more than enough with a uniqueness check on insert.

PHP
// No 0/O, no 1/I/l — the characters people transcribe wrongly.
const REF_ALPHABET = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';

function generate_ref_code(PDO $pdo, int $length = 7): string
{
    $max = strlen(REF_ALPHABET) - 1;

    for ($attempt = 0; $attempt < 10; $attempt++) {
        $code = '';
        for ($i = 0; $i < $length; $i++) {
            $code .= REF_ALPHABET[random_int(0, $max)];
        }

        $st = $pdo->prepare('SELECT 1 FROM users WHERE ref_code = ?');
        $st->execute([$code]);
        if ($st->fetchColumn() === false) {
            return $code;
        }
    }
    throw new RuntimeException('could not find a free referral code');
}

// Accept what users actually type: lowercase, spaces, the wrong letters.
function normalise_ref_code(string $input): string
{
    $code = strtoupper(preg_replace('~[^A-Za-z0-9]~', '', $input) ?? '');
    return strtr($code, ['O' => '0', 'I' => '1', 'L' => '1']);   // then match on the stored form
}

Using it

Put a UNIQUE index on the column as well as checking. The check narrows the race; the index closes it.

Normalise on input, not on storage. Someone typing a lowercase code with a space in it should just work.

Let users set a vanity code once, validated against the same alphabet and a reserved word list.

What bites people

random_int, not rand. Predictable referral codes let someone enumerate them and work out how many users you have.

Seven characters is short enough to guess in bulk if there is anything to gain per guess. Rate limit code lookups like any other endpoint.

Never derive the code from the user id. Sequential codes tell the world exactly how big your site is.

Also in Referrals