7

Go实战项目-给项目添加一个邀请码的功能【开源十年项目第9次更新】

 2 years ago
source link: https://studygolang.com/articles/35594
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Go实战项目-给项目添加一个邀请码的功能【开源十年项目第9次更新】

kaiyuan10nian · 大约3小时之前 · 64 次点击 · 预计阅读时间 5 分钟 · 大约8小时之前 开始浏览    

一个深漂近10年的程序员立志用未来10年时间去维护一个项目,这个项目的功能未定,用到什么就做什么,遇到什么就写什么。其主要目的有二,一为加深自己的技术深度,二为其他学习者提供参考。

感兴趣的可以跟着我一起做这个项目,不收费、不套路、人间自有真情在。

备注:前面项目中用到的代码已经分享到GitHub中去了,并且以后所有项目中会出现的代码都会提交上去,欢迎查阅。

地址:https://github.com/kaiyuan10nian/kaiyuan10nian 感兴趣的可以点个star哦~开源十年项目的更新首发于公众号:计算机自学平台,有兴趣的小伙伴可以持续关注,并欢迎各位加我的微信(kaiyuan10nian)跟我一起完成并推动项目的发展。


Go实战项目-给项目添加一个邀请码的功能

前面总结里面说过,我要给我们的blog项目添加一个邀请码的功能,因为这个项目做完之后我要部署出去的,虽说不靠这个东西去盈利,但是实战要有实战的样子至少把一个项目从0做到1的过程还是要有的。这里就涉及到一个很严重的问题:怎么控制内容?(在国内不可能不控制内容的)

  • 人工去审核(我没那么多时间)
  • 接入第三方内容审核(要花钱的)
  • 智能审核(没这个技术~后面也许可以考虑在开源十年中去实现它)

所以没有办法了,既然我控制不了内容,那我就从源头控制:直接控制输出内容的人。

所以我想到的办法就是在注册的时候做一个限制,不能让每个人都可以注册成功,只能让那些得到我们这个圈子成员信任的人才可以注册体验。那么实现的逻辑要提前去思考了:

  • 邀请码怎么来的?

​ 邀请码是系统生成的,由已注册会员手动生成,没给会员允许生成5个邀请码,每个邀请码只能使用1次。

  • 邀请码在哪使用?

​ 邀请码在新会员注册的时候使用(为必填项)

  • 邀请码怎么追溯?

​ 因为邀请码的生成是已注册会员手动生成的,所以我会在库里面去拉一张表单独去记录,如果有新会员使用了邀请码那么我也会记录下来,后面若想去追溯就很简单了

根据上面的思路,我们一步一步来实现其功能:

1、先写接口路由:

r.GET("/v1/account/invite", common.AuthMiddleware(),controller.Invite)

因为邀请码只能是已注册会员去生成,所以必须加上common.AuthMiddleware()权限限制。

2、实现邀请码的生成:

func RandomString(n int) string {
    var letters = []byte("23456789qwertyupkjhgfdsazxcvbnmMNBVCXZASDFGHJKPOUYTREWQ")
    result := make([]byte,n)
    rand.Seed(time.Now().Unix())
    for i := range result {
        result[i] = letters[rand.Intn(len(letters))]
    }
    return string(result)
}

这个其实就是一个生成随机值的函数,其中我把'0'、'1'、'i'、'l'、'I'、'L'等不容易辨认的字符都去掉了。

3、实现邀请码接口功能:

//创建用户邀请码
func Invite(ctx *gin.Context){
    udata ,_:= ctx.Get("user")//首先通过token去获取用户信息
    dto := dto.ToUserDto(udata.(model.User))
    DB := common.GetDB()
    var inviteCodes []model.InviteCode
    DB.Where("userid = ?",dto.ID).Find(&inviteCodes)//根据用户信息去查询这个用户有多少个邀请码
    fmt.Println(len(inviteCodes))
    if len(inviteCodes) < 5{//如果不够5个则允许他继续生成邀请码
        code := RandomString(5)
        newCode := model.InviteCode{
            Userid: dto.ID,
            Code: code,
            Status: 0,
        }
    //生成成功后把它记录进库表里面
        if err := DB.Create(&newCode).Error;err != nil{
            response.Response(ctx,http.StatusInternalServerError,500,nil,err.Error())
            return
        }
        response.Response(ctx,http.StatusOK,6000,gin.H{"inviteCode":code},"邀请码生成成功")
    }else{
        response.Response(ctx,http.StatusOK,60001,nil,"每个人只可以拥有5个邀请码")
        return
    }

}

上述提到了邀请码的创建,我们创建了一个表invitecode专门用来存储(下文有model代码)

4、去修改注册功能

原本我们的注册只需要手机号并设置密码即可,但是我们要控制注册了,那么要加几个验证条件:

1)推荐人是否存在?

2)邀请码是否存在?

3)邀请码是否和推荐人匹配?

4)邀请码是否被人使用过了?

这几个条件判断之后,如果都通过那么给予放行,放行后还要做一个操作:

1)标记该邀请码已被使用

2)把该邀请码跟注册账号进行关联

针对上述逻辑,首先针对库表进行设计和改造

直接在用户表新增了一个字段invitecode,目的就是把邀请码和注册者进行关联。

type User struct {
    gorm.Model
    Name      string `gorm:"type:varchar(20);not null"`
    Mobile    string `gorm:"varchar(11);not null;unique"`
    Password  string `gorm:"size:255;not null"`
    InviteCode string      `json:"invitecode" gorm:"not null"`
}

然后,新建了一个表,专门用来存我们生成的邀请码,以及记录邀请码和生成邀请码的用户进行关联

type InviteCode struct {
    gorm.Model
    Userid  uint      `json:"user_id" gorm:"not null"`
    Code    string      `json:"code" gorm:"not null"`
    Status  uint      `json:"status" gorm:"not null"`
}

库表建好了,下面就是在注册时,我们针对以上逻辑的代码实现:(全部代码请查看github)

    if isTelephoneExist(DB,recommender){//查询这个推荐者存不存在
        id := getRecommenderId(DB,recommender)//先获取推荐者的ID
        //判断其邀请码的准确性
        var inviteCodes []model.InviteCode
        DB.Where("userid = ?",id).Find(&inviteCodes)//根据id去查这个推荐者有多少邀请码
        isValid := false
        for _,inviteCode := range inviteCodes{//轮寻他所有邀请码
            isValid = strings.EqualFold(code,inviteCode.Code)//一一对比,查看注册者输入的是否和库里的一致
            if  isValid {
                if inviteCode.Status == 0 {//如果一致,则再验证这个是否已经被用了
                    DB.Model(&inviteCode).Update("status",1)
                    break
                }else{
                    response.Response(ctx,http.StatusOK,60002,nil,"邀请码已使用")
                    return
                }
            }
        }
        if !isValid {
            response.Response(ctx,http.StatusOK,60002,nil,"邀请码不存在")
            return
        }
    }else {
    //最后这个提示,我是想避免被人拿这个接口测试用户存在与否
        response.Response(ctx,http.StatusOK,60002,nil,"邀请码不存在")
        return
    }

好了,到这里我们基本就完成这个简单的小功能了,直接go run main.go 去亲自体验一下吧。

ok just this.see you next...


有疑问加站长微信联系(非本文作者))

280

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:701969077


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK