Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Olá pessoal,
Estou construindo um sistema e irá usar um "serial" para ativar.
Gostaria de saber como posso gerar um serial único com letras e números com 16 dígitos?
XXXX-XXXX-XXXX-XXXX
Fiz um, mas gostaria que o serial fosse único e seguro.
<?php
$cr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$max = strlen($cr)-1;
$gera = null;
for($i=0; $i < 16; $i++) {
$gera .= $cr{mt_rand(0, $max)};
}
$gera = str_split($gera, 4);
echo "$gera[0]-$gera[1]-$gera[2]-$gera[3]";
?>
Alguém sabe um método mais fácil ou tenha uma lógica pronta?
Obrigado!
Edit:
Vejo também a opção de utilizar:
<?php
echo md5(uniqid(time()));
?>
O uniqid time é realmente único?>
Estou construindo um sistema e irá usar um "serial" para ativar.
Você pode utilizar hash para fazer isso:
function getSerial( $name ){
$a = hash( 'crc32' , 'chave secreta' );
$b = hash( 'crc32' , sprintf( '%s%s' , md5( $name ) , md5( $a ) ) );
$c = sscanf( sprintf( '%s%s' , $a , $b ) , '%4s%4s%4s%4s' );
return vsprintf( '%s-%s-%s-%s' , $c );
}
var_dump( getSerial( 'Nome do cliente' ) ); //string(19) "71b0-8ee3-53b0-5a84"
Agora, se você precisar verificar se um serial é válido, você pode adicionar mais um módulo ao seu serial como verificador:
function getSerial( $name = null ){
$a = hash( 'crc32' , 'chave secreta' );
$b = hash( 'crc32' , sprintf( '%s%s' , md5( $name ) , md5( $a ) ) );
$c = sscanf( sprintf( '%s%s' , $a , $b ) , '%4s%4s%4s%4s' );
$d = 1;
for ( $i = 0 ; $i < 4 ; $i++ )
for ( $j = 0 ; $j < 4 ; $d += pow( ord( $c[ $i ]{ $j } ) , $i ) , $j++ );
$c[ 4 ] = $d;
return vsprintf( '%s-%s-%s-%s-%05x' , $c );
}
function validaSerial( $serial ){
$c = sscanf( $serial , '%4s-%4s-%4s-%4s' );
$d = 1;
for ( $i = 0 ; $i < 4 ; $i++ )
for ( $j = 0 ; $j < 4 ; $d += pow( ord( $c[ $i ]{ $j } ) , $i ) , $j++ );
$c[ 4 ] = $d;
return !strcmp( $serial , vsprintf( '%s-%s-%s-%s-%05x' , $c ) );
}
$serial = getSerial( 'Nome do cliente' );
if ( validaSerial( $serial ) ){
printf( 'O serial %s é válido.' , $serial );
} else {
print 'Serial inválido.';
}
A saída deverá ser: O serial 71b0-8ee3-53b0-5a84-154ace é válido.
Opa.. então Matias Rezendeo ruim que pelo MD5 gera uma quantidade muito grande de números e eu queria mais letras mesmo...
João Batista Neto, obrigado pelo codigo, mas pensando aqui, acho que não preciso de um codigo tão complexo já que não precisa validar ele e ficará salvo no banco de dados.
Pensei em fazer algo mais ou menos assim:
<?php
$cr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$max = strlen($cr)-1;
$gera = null;
for($i=0; $i < 16; $i++) {
$gera .= $cr{mt_rand(0, $max)};
}
$gera = str_split($gera, 4);
$serial = "$gera[0]-$gera[1]-$gera[2]-$gera[3]";
$exe = mysql_query("SELECT * FROM codigos WHERE codigo = '$serial'");
$cont = mysql_num_rows($exe);
if($cont != 0) {
// EXECUTA NOVAMENTE O SCRIPT DO SERIAL E A VERIFICAÇÃO.
}
else {
$sql = mysql_query("INSERT INTO `codigos` (`id`, `codigo`, `ativo`) VALUES ('', $serial, 0);");
echo "Serial Gerado com Sucesso!<br />Serial: $serial";
}
?>
Porem eu não sei como posso executar o codigo novamente se já existir o serial cadastrado no banco de dados...
Obrigado pelas respostas!
Alguém sabe como posso por um "looping" no código até o código gerado não ter no banco de dados sem atualizar a pagina?
Obrigado.
Basta Usar uma Flag
<?php
$flag=0;
do{
$cr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$max = strlen($cr)-1;
$gera = null;
for($i=0; $i < 16; $i++) {
$gera .= $cr{mt_rand(0, $max)};
}
$gera = str_split($gera, 4);
$serial = "$gera[0]-$gera[1]-$gera[2]-$gera[3]";
$exe = mysql_query("SELECT * FROM codigos WHERE codigo = '$serial'");
$cont = mysql_num_rows($exe);
if($cont == 0) {
$sql = mysql_query("INSERT INTO `codigos` (`id`, `codigo`, `ativo`) VALUES ('', $serial, 0);");
echo "Serial Gerado com Sucesso!<br />Serial: $serial";
$flag = 1;
}
}while($flag==1);
?>
O time é único a cada segundo, já que retorna o TIMESTAMP atual, ou seja, a cada segundo retorna um a mais.
Creio que a forma como ficou a última opção é melhor mesmo, mas olha o exemplo do manual do PHP.
$better_token = md5(uniqid(rand(), true));
http://br.php.net/uniqid
http://br.php.net/time
Carlos Eduardo