思路误区:随机字符串,MD5截取等,这种方法存在一定重复率。需要做唯一验证。
正确思路:
1,唯一性:根据用户ID,生成唯一的对应的邀请码。
2,高进制:高进制可以用更短的字符长度表达更大的数值。
3,理想值:平常用的字符有0-9A-Z,所以比较理想的进制是36进制。
4,可行性:(36进制)ZZZ =(10进制)46655,(36进制)ZZZZ =(10进制)1679615,(36进制)ZZZZZ =(10进制)60466175,(36进制)ZZZZZZ =(10进制)2176782335
在转成36进制的情况下 4位邀请码已经可以满足绝大部分公司了,能用到6位邀请码的公司屈指可数。
5,加强
5.1,不满4位左补0。
5.2,如果只是进制转换,是可以逆的,别人可以算出真实的用户ID。解决方法:把表示36进制的字符 0-9A-Z 顺序打乱,正常进制转换后,再用新的字符顺序转换一下,在不知道这个打乱的字符顺序时,就不可能解析出正确的用户id.
废话不多说,直接上代码。
/**
* 生成自定义36进制对应关系
* @return type
*/
function invite_code_seed() {
$str = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$seed = str_split($str);
$newkeys = array_flip($seed);
shuffle($seed);
foreach ($newkeys as $key => $val) {
$newkeys[$key] = $seed[$val];
}
return $newkeys;
}
/**
* 根据用户ID生成邀请码
* @param type $id
* @param type $seed
* @return type
*/
function create_invite_code($id, $seed) {
$thirtySix = strtoupper(base_convert($id, 10, 36));
if (strlen($thirtySix) < 4) {
$thirtySix = str_pad($thirtySix, 4, 0, STR_PAD_LEFT);
}
$code = '';
for ($i = 0; $i < strlen($thirtySix); $i++) {
$code .= $seed[$thirtySix[$i]];
}
return $code;
}
/**
* 解析邀请码
* @param type $code
* @param type $seed
* @return type
*/
function decode_invite_code($code, $seed) {
$thirtySix = '';
$newkeys = array_flip($seed);
$_code = strtoupper($code);
for ($i = 0; $i < strlen($_code); $i++) {
$thirtySix .= $newkeys[$_code[$i]];
}
return base_convert($thirtySix, 36, 10);
}
发表评论 取消回复