全局唯一随机邀请码实现方式

匿名 (未验证) 提交于 2019-12-02 23:55:01
  • 日常的网站开发中,会遇到网站的促销活动,就有涉及到邀请好礼的功能
  • 成功邀请好友,则获取相应奖励,这时候,就有邀请码的需求
  • 邀请码要求每个用户唯一
  • 方法一. 可根据用户的uid生成邀请码
  • 方法二. 邀请码可根据某个初始化id生成,用户主动请求,生成code,绑定uid
  • 方法二,这种方式,需额外记录uid和code关系
  • 方法一,根据uid生成,也可根据code反推出uid,不用额外查询,比较方便
  • 记录方法一的实现
  • 由长数字转换为特定长度的code,首先需确定code的字符范围
  • 可转换为 0-9A-Z 36进制数,或者更多字符可添加小写字符
  • 本次实现 转换为 32进制数
  • 去掉0 1 和 o 容易混淆的字符和补位字符F,剩余32字符
php实现
  /**  * Class ShareCodeUtils  *  * 邀请码生成器,基本原理  * 1)参数用户ID  * 2)使用自定义进制转换之后为:V  * 3)最小code长度为6位,若不足则在后面添加分隔字符'F':VF  * 4)在VF后面再随机补足4位,得到形如 VFAADD  * 5)反向转换时以'F'为分界线,'F'后面的不再解析  */ class ShareCodeUtils {      // 32个进制字符(0,1 没加入,容易和 o l 混淆,O 未加入,F 未加入,用于补位)     // 顺序可进行调整, 增加反推难度     private static $base = ['H', 'V', 'E', '8', 'S', '2', 'D', 'Z', 'X', '9', 'C', '7', 'P','5', 'I', 'K', '3', 'M', 'J', 'U', 'A', 'R', '4', 'W', 'Y', 'L', 'T', 'N', '6', 'B', 'G', 'Q'];      // F为补位字符,不能和上述字符重复     private static $pad = "F";      // 进制长度     private static $decimal_len = 32;      // 生成code最小长度     private static $code_min_len = 6;      /**      * id转为code      * 相除去模法      *      * @param $id      * @return string      */     public static function idToCode($id)     {         $result = "";         while (floor($id / static::$decimal_len) > 0){             $index = $id % static::$decimal_len;             $result.= static::$base[$index];             $id = floor($id / static::$decimal_len);         }         $index =  $id % static::$decimal_len;         $result.= static::$base[$index];         // code长度不足,则随机补全         $code_len = strlen($result);         if ($code_len  27      * 8 ---> 3      * 进制转换 27*32(0) + 3*32(1) = 123      * 32(0) ---> 320次方      * 32(1) ---> 321次方      *      * @param $code      * @return string      */     public static function codeToId($code)     {         $result = 0;         $base_flip_map = array_flip(static::$base);         $is_pad = strpos($code, static::$pad);         if (!empty($is_pad)) {             $len_real = $is_pad;         } else {             $len_real = strlen($code);         }         for ($i = 0; $i 
go实现
  package main  import (     "errors"     "fmt"     "math/rand"     "strings"     "time" )  type code struct {     base string // 进制的包含字符, string类型     decimal uint64 // 进制长度     pad string // 补位字符,若生成的code小于最小长度,则补位+随机字符, 补位字符不能在进制字符中     len int // code最小长度 }  // idתcode func (c *code) idToCode (id uint64) string {     mod := uint64(0)     res := ""     for id!=0 {         mod = id % c.decimal         id = id / c.decimal         res += string(c.base[mod])     }     resLen := len(res)     if resLen 
go实现2
  package main  import(     "container/list"     "errors"     "fmt" )  var baseStr string = "HVE8S2DZX9C7P5IK3MJUAR4WYLTN6BGQ" var base [] byte = []byte(baseStr) var baseMap map[byte] int   func InitBaseMap(){     baseMap = make(map[byte]int)     for i, v := range base {         baseMap[v] = i     } } func Base34(n uint64)([]byte){     quotient := n     mod := uint64(0)     l := list.New()     for quotient != 0 {         //fmt.Println("---quotient:", quotient)         mod = quotient%32         quotient = quotient/32         l.PushFront(base[int(mod)])         //res = append(res, base[int(mod)])         //fmt.Printf("---mod:%d, base:%s\n", mod, string(base[int(mod)]))     }     listLen := l.Len()      if listLen >= 6 {         res := make([]byte,0,listLen)         for i := l.Front(); i != nil ; i = i.Next(){             res = append(res, i.Value.(byte))         }         return res     } else {         res := make([]byte,0,6)         for i := 0; i =0; i-- {         v, ok := baseMap[str[i]]         if !ok {             fmt.Printf("")             return 0, errors.New("character is not base")         }         var b uint64 = 1         for j:=uint64(0); j
  • 本次实现由 php 和 go 两种语言实现
  • 最大的心得就是 go中的 类型转换是比较麻烦的,因为都是强类型
  • 和php 还不太一样
  • 但也算是进一步熟悉了go的语法代码
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!