Tools.php
public static function generatePin($salt, $length = 6, $useMinutes = false)
    {
        $seed = sha1($salt . (new \DateTime('now', new \DateTimeZone('Europe/Prague')))->format('Ymd' . ($useMinutes ? 'i' : '')), true);
        for ($i = 0; $i <= (new \DateTime('now', new \DateTimeZone('Europe/Prague')))->format('G'); $i++) {
            $seed = sha1($seed . $i);
        }

        $data = unpack('V1/V2', $seed);
        $data[1] = $data[1] < 0 ? $data[1] * -1 : $data[1];
        $data[2] = $data[2] < 0 ? $data[2] * -1 : $data[2];
        $mask = $data[1] ^ $data[2];

        if ($mask % 1000000 === 0 || $mask % 1000000 === 999999) {
            return self::generatePin($salt . $seed, $length, $useMinutes);
        }

        return round((((float)($mask % 1000000) - 0.5 + ((float)($mask % 200) / 199)) / 999999) * (((10 ** $length) - 1) - (10 ** ($length - 1))) + (10 ** ($length - 1)));
    }
public static function generatePin($salt, $length = 6, $useMinutes = false)
    {
        $seed = sha1($salt . (new \DateTime('now', new \DateTimeZone('Europe/Prague')))->format('Ymd' . ($useMinutes ? 'i' : '')), true);
        for ($i = 0; $i <= (new \DateTime('now', new \DateTimeZone('Europe/Prague')))->format('G'); $i++) {
            $seed = sha1($seed . $i);
        }

        $data = unpack('V1/V2', $seed);
        $data[1] = $data[1] < 0 ? $data[1] * -1 : $data[1];
        $data[2] = $data[2] < 0 ? $data[2] * -1 : $data[2];
        $mask = $data[1] ^ $data[2];

        if ($mask % 1000000 === 0 || $mask % 1000000 === 999999) {
            return self::generatePin($salt . $seed, $length, $useMinutes);
        }

        return round((((float)($mask % 1000000) - 0.5 + ((float)($mask % 200) / 199)) / 999999) * (((10 ** $length) - 1) - (10 ** ($length - 1))) + (10 ** ($length - 1)));
    }
Generate random PIN based on

@param string $salt Salt
@param int $length PIN length
@param bool $useMinutes Generate different PIN each minute (default is each hour)
@return int Pin