254 lines
8.6 KiB
Go
254 lines
8.6 KiB
Go
package router
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"chatapp3-golang/internal/config"
|
|
"chatapp3-golang/internal/service/gameking"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// registerGameKingRoutes 注册 Yumi H5、运营后台和外部 cron 内部触发接口。
|
|
func registerGameKingRoutes(engine *gin.Engine, cfg config.Config, javaClient authGateway, service *gameking.Service) {
|
|
if service == nil {
|
|
return
|
|
}
|
|
|
|
h5 := engine.Group("/app/h5/game-king/yumi")
|
|
h5.Use(authMiddleware(javaClient))
|
|
h5.GET("/detail", func(c *gin.Context) {
|
|
resp, err := service.Detail(c.Request.Context(), mustAuthUser(c), parseGameKingID(c.Query("activityId")))
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
h5.GET("/me", func(c *gin.Context) {
|
|
resp, err := service.Me(c.Request.Context(), mustAuthUser(c), parseGameKingID(c.Query("activityId")))
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
h5.POST("/draw", func(c *gin.Context) {
|
|
var req gameking.DrawRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
writeError(c, gameking.NewAppError(http.StatusBadRequest, "bad_request", err.Error()))
|
|
return
|
|
}
|
|
resp, err := service.Draw(c.Request.Context(), mustAuthUser(c), req)
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
h5.GET("/ranking", func(c *gin.Context) {
|
|
limit, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("limit", "30")))
|
|
resp, err := service.Ranking(c.Request.Context(), mustAuthUser(c), parseGameKingID(c.Query("activityId")), c.Query("rankingType"), c.Query("period"), limit)
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
h5.GET("/draw-records", func(c *gin.Context) {
|
|
limit, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("limit", "20")))
|
|
resp, err := service.DrawRecords(c.Request.Context(), mustAuthUser(c), parseGameKingID(c.Query("activityId")), limit)
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
|
|
admin := engine.Group("/resident-activity/game-king")
|
|
admin.Use(consoleAuthMiddleware(javaClient), consoleMenuMiddleware(javaClient, "ResidentGameKingActivity"))
|
|
admin.GET("/list", func(c *gin.Context) {
|
|
resp, err := service.ListActivities(c.Request.Context())
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
admin.GET("/detail/:id", func(c *gin.Context) {
|
|
resp, err := service.ManageDetail(c.Request.Context(), parseGameKingID(c.Param("id")))
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
admin.POST("/save", consolePermissionMiddleware(javaClient, "resident-activity:yumi-game-king:edit"), func(c *gin.Context) {
|
|
var req gameking.SaveActivityRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
writeError(c, gameking.NewAppError(http.StatusBadRequest, "bad_request", err.Error()))
|
|
return
|
|
}
|
|
resp, err := service.SaveActivity(c.Request.Context(), req)
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
admin.PUT("/enable/:id", consolePermissionMiddleware(javaClient, "resident-activity:yumi-game-king:enable"), func(c *gin.Context) {
|
|
raw, exists := c.GetQuery("enabled")
|
|
if !exists {
|
|
writeError(c, gameking.NewAppError(http.StatusBadRequest, "enabled_required", "enabled query is required"))
|
|
return
|
|
}
|
|
enabled, err := parseGameKingBool(raw, "enabled")
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
if err := service.EnableActivity(c.Request.Context(), parseGameKingID(c.Param("id")), enabled); err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, gin.H{"success": true})
|
|
})
|
|
admin.GET("/prizes/:id", func(c *gin.Context) {
|
|
resp, err := service.ListPrizes(c.Request.Context(), parseGameKingID(c.Param("id")))
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
admin.PUT("/prizes/:id", consolePermissionMiddleware(javaClient, "resident-activity:yumi-game-king:edit"), func(c *gin.Context) {
|
|
var req gameking.SavePrizesRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
writeError(c, gameking.NewAppError(http.StatusBadRequest, "bad_request", err.Error()))
|
|
return
|
|
}
|
|
if err := service.SavePrizes(c.Request.Context(), parseGameKingID(c.Param("id")), req); err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, gin.H{"success": true})
|
|
})
|
|
admin.GET("/rank-rewards/:id", func(c *gin.Context) {
|
|
resp, err := service.ListRankRewards(c.Request.Context(), parseGameKingID(c.Param("id")))
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
admin.PUT("/rank-rewards/:id", consolePermissionMiddleware(javaClient, "resident-activity:yumi-game-king:edit"), func(c *gin.Context) {
|
|
var req gameking.SaveRankRewardsRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
writeError(c, gameking.NewAppError(http.StatusBadRequest, "bad_request", err.Error()))
|
|
return
|
|
}
|
|
if err := service.SaveRankRewards(c.Request.Context(), parseGameKingID(c.Param("id")), req); err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, gin.H{"success": true})
|
|
})
|
|
admin.GET("/draw-records/:id", func(c *gin.Context) {
|
|
limit, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("limit", "100")))
|
|
resp, err := service.ManageDrawRecords(c.Request.Context(), parseGameKingID(c.Param("id")), c.Query("deliveryStatus"), limit)
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
admin.POST("/draw/retry/:recordId", consolePermissionMiddleware(javaClient, "resident-activity:yumi-game-king:reconcile"), func(c *gin.Context) {
|
|
if err := service.RetryDraw(c.Request.Context(), parseGameKingID(c.Param("recordId"))); err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, gin.H{"success": true})
|
|
})
|
|
admin.GET("/settlement-records/:id", func(c *gin.Context) {
|
|
resp, err := service.SettlementRecords(c.Request.Context(), parseGameKingID(c.Param("id")))
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
admin.POST("/settlement/:id", consolePermissionMiddleware(javaClient, "resident-activity:yumi-game-king:settle"), func(c *gin.Context) {
|
|
if err := service.Settle(c.Request.Context(), parseGameKingID(c.Param("id"))); err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, gin.H{"success": true})
|
|
})
|
|
admin.POST("/settlement/retry/:recordId", consolePermissionMiddleware(javaClient, "resident-activity:yumi-game-king:reconcile"), func(c *gin.Context) {
|
|
if err := service.RetrySettlement(c.Request.Context(), parseGameKingID(c.Param("recordId"))); err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, gin.H{"success": true})
|
|
})
|
|
admin.POST("/delivery-item/resolve/:itemId", consolePermissionMiddleware(javaClient, "resident-activity:yumi-game-king:reconcile"), func(c *gin.Context) {
|
|
raw, exists := c.GetQuery("delivered")
|
|
if !exists {
|
|
writeError(c, gameking.NewAppError(http.StatusBadRequest, "delivered_required", "delivered query is required"))
|
|
return
|
|
}
|
|
delivered, err := parseGameKingBool(raw, "delivered")
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
if err := service.ResolveUnknownDeliveryItem(c.Request.Context(), parseGameKingID(c.Param("itemId")), delivered); err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, gin.H{"success": true})
|
|
})
|
|
admin.POST("/backfill/:id", consolePermissionMiddleware(javaClient, "resident-activity:yumi-game-king:backfill"), func(c *gin.Context) {
|
|
lastID := parseGameKingID(c.DefaultQuery("lastId", "0"))
|
|
limit, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("limit", "200")))
|
|
resp, err := service.Backfill(c.Request.Context(), parseGameKingID(c.Param("id")), lastID, limit)
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
|
|
internal := engine.Group("/internal/game-king")
|
|
// 结算入口会冻结榜单并产生真实奖励副作用,必须与 Yumi 礼物挑战保持相同的
|
|
// fail-closed 边界:服务端未配置密钥时直接拒绝,不能沿用历史内部接口的空密钥兼容行为。
|
|
internal.Use(requiredInternalSecretMiddleware(cfg.HTTP.InternalCallbackSecret))
|
|
internal.POST("/settle-due", func(c *gin.Context) {
|
|
resp, err := service.SettleDue(c.Request.Context())
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, resp)
|
|
})
|
|
}
|
|
|
|
func parseGameKingID(value string) int64 {
|
|
parsed, _ := strconv.ParseInt(strings.TrimSpace(value), 10, 64)
|
|
return parsed
|
|
}
|
|
|
|
func parseGameKingBool(value, field string) (bool, error) {
|
|
switch strings.ToLower(strings.TrimSpace(value)) {
|
|
case "true", "1":
|
|
return true, nil
|
|
case "false", "0":
|
|
return false, nil
|
|
default:
|
|
// resolve delivered=false 会立即重发,因此不能把拼写错误或空值默认为 false。
|
|
return false, gameking.NewAppError(http.StatusBadRequest, field+"_invalid", field+" must be true, false, 1 or 0")
|
|
}
|
|
}
|