diff --git a/server/adminserver/api/v1/system/giftcode.go b/server/adminserver/api/v1/system/giftcode.go index c8ab3ac3..5d5662c4 100644 --- a/server/adminserver/api/v1/system/giftcode.go +++ b/server/adminserver/api/v1/system/giftcode.go @@ -7,14 +7,22 @@ import ( "main/model/system" "net/http" "q5" + "strings" "github.com/gin-gonic/gin" ) type GiftCodeApi struct { + accountlocks q5.ConcurrentMap[string, int32] + codelocks q5.ConcurrentMap[string, int32] } -func (aca *GiftCodeApi) GenCode(c *gin.Context) { +func (gca *GiftCodeApi) Init() { + gca.accountlocks = q5.ConcurrentMap[string, int32]{} + gca.codelocks = q5.ConcurrentMap[string, int32]{} +} + +func (gca *GiftCodeApi) GenCode(c *gin.Context) { var maxbatchid int32 = 0 gameid := q5.SafeToInt32(c.DefaultQuery("gameid", "1")) typeid := q5.SafeToInt32(c.DefaultQuery("type", "")) @@ -63,13 +71,22 @@ func (aca *GiftCodeApi) GenCode(c *gin.Context) { codelist := map[string]int{} nowsecs := int32(f5.GetApp().GetRealSeconds()) batchcodeinfo := []*system.GiftCode{} + fixcode := fmt.Sprintf("%03x", batchid) + sb := strings.Builder{} for i := 0; i < int(count); { if tryCount > 10000*10 { f5.RspErr2(c, 1, "internal error") return } - code := genCode(8) + sb.Reset() + code := genCode(6) + sb.WriteByte(fixcode[0]) + sb.WriteString(code[0:3]) + sb.WriteByte(fixcode[1]) + sb.WriteString(code[3:6]) + sb.WriteByte(fixcode[2]) + code = sb.String() _, exist := codelist[code] if exist { tryCount++ @@ -104,7 +121,7 @@ func (aca *GiftCodeApi) GenCode(c *gin.Context) { }) } -func (this *GiftCodeApi) List(c *gin.Context) { +func (gca *GiftCodeApi) List(c *gin.Context) { req := struct { GameId int32 `json:"gameid"` BatchId int32 `json:"batch_id"` @@ -144,7 +161,7 @@ func (this *GiftCodeApi) List(c *gin.Context) { }) } -func (this *GiftCodeApi) DownloadFile(c *gin.Context) { +func (gca *GiftCodeApi) DownloadFile(c *gin.Context) { gameid := q5.SafeToInt32(c.DefaultQuery("gameid", "")) batchid := q5.SafeToInt32(c.DefaultQuery("batchid", "")) if gameid < 1 || batchid < 1 { @@ -174,9 +191,9 @@ func (this *GiftCodeApi) DownloadFile(c *gin.Context) { }) } -func (this *GiftCodeApi) ListType(c *gin.Context) { +func (gca *GiftCodeApi) ListType(c *gin.Context) { req := struct { - GameId int32 `json:"gameid"` + GameId int32 `binding:"required" json:"gameid"` PageDto system.PageDto `json:"page_dto"` }{} if err := c.ShouldBindJSON(&req); err != nil { @@ -213,11 +230,11 @@ func (this *GiftCodeApi) ListType(c *gin.Context) { }) } -func (this *GiftCodeApi) AddType(c *gin.Context) { +func (gca *GiftCodeApi) AddType(c *gin.Context) { req := struct { - GameId int32 `json:"gameid"` - Limit int32 `json:"limit"` - Content string `json:"content"` + GameId int32 `binding:"required" json:"gameid"` + Limit int32 `binding:"required" json:"limit"` + Content string `binding:"required" json:"content"` }{} if err := c.ShouldBindJSON(&req); err != nil { f5.RspErr2(c, 1, err.Error()) @@ -268,3 +285,92 @@ func (this *GiftCodeApi) AddType(c *gin.Context) { "message": "成功生成", }) } + +func (gca *GiftCodeApi) QueryCode(c *gin.Context) { + req := struct { + GameId int32 `binding:"required" json:"gameid"` + Code string `binding:"required" json:"code"` + }{} + if err := c.ShouldBindJSON(&req); err != nil { + f5.RspErr2(c, 1, err.Error()) + return + } + + rspObj := struct { + ErrCode int32 `json:"errcode"` + ErrMsg string `json:"errmsg"` + CodeStatus int32 `json:"status"` //0:可用;1:已用;2:不存在 + }{} + codeinfo := new(system.GiftCode) + db := f5.GetApp().GetOrmDb(constant.ACCOUNT_DB).Table(codeinfo.TableName()).Take(codeinfo, "gameid = ? AND gift_code = '?'", req.GameId, req.Code) + err := db.Error + if err != nil { + if !f5.IsOrmErrRecordNotFound(err) { + f5.RspErr2(c, 1, err.Error()) + return + } + rspObj.CodeStatus = 2 + } else if codeinfo.Limit > 0 && codeinfo.Count > 0 { + rspObj.CodeStatus = 1 + } + + c.JSON(http.StatusOK, rspObj) +} + +func (gca *GiftCodeApi) UseCode(c *gin.Context) { + req := struct { + GameId int32 `binding:"required" json:"gameid"` + AccountId string `binding:"required" json:"account_id"` + Code string `binding:"required" json:"code"` + }{} + if err := c.ShouldBindJSON(&req); err != nil { + f5.RspErr2(c, 1, err.Error()) + return + } + + _, exist := gca.accountlocks.LoadOrStore(req.AccountId, 1) + if exist { + f5.RspErr2(c, 2, "system busy") + return + } + defer gca.accountlocks.Delete(req.AccountId) + + _, exist = gca.codelocks.LoadOrStore(req.Code, 1) + if exist { + f5.RspErr2(c, 3, "system busy 2") + } + defer gca.codelocks.Delete(req.Code) + + rspObj := struct { + ErrCode int32 `json:"errcode"` + ErrMsg string `json:"errmsg"` + CodeStatus int32 `json:"status"` //0:可用;1:已用;2:不存在 + Limit int32 `json:"limit"` + Content string `json:"content"` + }{} + codeinfo := new(system.GiftCode) + db := f5.GetApp().GetOrmDb(constant.ACCOUNT_DB).Table(codeinfo.TableName()).Take(codeinfo, "gameid = ? AND gift_code = '?'", req.GameId, req.Code) + err := db.Error + if err != nil { + if !f5.IsOrmErrRecordNotFound(err) { + f5.RspErr2(c, 1, err.Error()) + return + } + rspObj.CodeStatus = 2 + } else if codeinfo.Limit > 0 && codeinfo.Count >= codeinfo.Limit { + rspObj.CodeStatus = 1 + } else { + rspObj.Limit = codeinfo.Limit + rspObj.Content = codeinfo.Content + } + + c.JSON(http.StatusOK, rspObj) + + if rspObj.CodeStatus == 0 && codeinfo.Limit > 0 { + codeinfo.Count++ + err := f5.GetApp().GetOrmDb(constant.ACCOUNT_DB).Table(codeinfo.TableName()).Where("gameid = ?", req.GameId).Where("gift_code = '?'", req.Code).UpdateColumn("count", codeinfo.Count).Error + if err != nil { + f5.GetSysLog().Error("update gift code error:%s, %s", req.AccountId, req.Code) + } + } +}