首先谈一下我的思路,我准备用0-9,A-Z,a-z 共62个字符组成8位邀请码,也就是一个62进制数
无疑会用到进制转换,在此奉上两个进制转换函数
//其它进制转十进制
function NumBinTo($num,$bin=62,$start=’0′){
$str=”0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz”;
$arr=explode($start,$str);
$strD=$start.””.$arr[1].””.$arr[0];
$arrD=array_flip(str_split($strD));
$numArr=(str_split($num));
$rs=0;
$count=count($numArr);
for ($i = 0; $i < $count; $i++) {
$rs=intval($arrD[$numArr[$i]])*pow($bin,$count-$i-1) + $rs;
}
return $rs;
}
//十进制转 其他 进制 $count 返回数据长度 $bin <= 62
function NumToBin($num,$bin=62,$count=0,$start=’0′){
$str=”0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz”;
$arr=explode($start,$str);
$strD=$start.””.$arr[1].””.$arr[0];
$arrD=str_split($strD);
$bytelen=$count; //返回字符长度
$t=””;
$num=intval($num);
if($num===0)continue;
while($num>0){
$t=$arrD[$num%$bin].$t;
$num=floor($num/$bin);
}
$tlen=strlen($t);
if ($count) {
if($tlen%$bytelen!=0){
$pad_len=$bytelen-$tlen%$bytelen;
$t=str_pad(“”,$pad_len,$start,STR_PAD_LEFT).$t; //不足一个字节长度,自动前面补充0
}
}
return $t;
}
邀请码的生成数据来源于数据表中的一个自增字段,当然它也是唯一的;为了降低辨识度必须给它进行加密,在此我想到了一个简单的算法,5位(数据)+1位(随机)+2位(排序);5位62进制能够表达最大的数字是:916,132,831,9亿,一般不是大型数据表足够使用了;随机字符用来定义进制的起始,第一位是0?,A?,a?,随机吧;剩下两位就是将5位主数据进行排列组合,43210(5)<62*62 刚好可以
加密函数:
//格式化输出 A+12345+B+C
//B:起始字符 AC:排序规则
function decto_bin_encode($datalist){
$strD=”0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz”;
$rand=rand(0,61);
$start=substr($strD,$rand,1);
$str_62=NumToBin($datalist,62,5,$start);
$str_62_arr=str_split($str_62);
$arr=array(‘0′,’1′,’2′,’3′,’4’);
shuffle($arr);//乱序
//$arr 转十进制
$sorkStr_10=NumBinTo(implode(”,$arr),5);
$sork_62=NumToBin($sorkStr_10,62,2,”0″);
$sorkArr=str_split($sork_62);
$sorkStr=implode(”, $arr);
$strArr_sork=array();
$strArr=explode($start, $strD);
foreach ($arr as $k=>$v) {
$strArr_sork[$v]=$str_62_arr[$k];
}
$r_str_62=”;
for ($j = 0; $j < 5; $j++) {
$r_str_62.=$strArr_sork[$j];
}
return $sorkArr[0].$r_str_62.$start.$sorkArr[1];
}
当然这也是可以解密的
function decto_bin_decode($str){
$strD=”0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz”;
//获取解码参数
$key=substr($str,-2,1);
$arr=explode($key,$strD);
$strD=$key.””.$arr[1].””.$arr[0];
$arrD=array_flip(str_split($strD));
//排序参数
$sorkCode=substr($str,0,1).substr($str,-1,1);
$sorkCode_10=NumBinTo($sorkCode);
//转5进制
$jmNum=NumToBin($sorkCode_10,5,5);
$jmStr=substr($str,1,5);
//还原排序
$arr=str_split($str);
$realArr=”;
foreach (str_split($jmNum) as $val) {
$k=4-intval($val);
$realArr.=substr($jmStr,$val,1);
}
$idArr=str_split($realArr);
$rs=NumBinTo($realArr,$bin=62,$key);
return $rs;
}
测试代码:
$codeStr=decto_bin_encode(5201314);
echo $codeStr.”<br>”;
echo decto_bin_decode($codeStr);
当然每次运行的结果都可能不一样
未经允许不得转载:极速云 » 如何实现一个简短的注册邀请码