102 lines
2.5 KiB
Go
102 lines
2.5 KiB
Go
package minigame
|
|
|
|
import (
|
|
"backend/client"
|
|
"backend/msg"
|
|
"crypto/md5"
|
|
"fmt"
|
|
"reflect"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type RewardRequest struct {
|
|
AppId int `json:"appId" form:"appId" binding:"required" description:"cp应用ID"`
|
|
ServerId int `json:"serverId" form:"serverId" binding:"required" description:"cp服务器ID"`
|
|
UserID int64 `json:"userId" form:"userId" binding:"required" description:"用户uid"`
|
|
GameID int32 `json:"gameId" form:"gameId" binding:"required" description:"小游戏ID"`
|
|
TimeStamp int64 `json:"timeStamp" form:"timeStamp" binding:"required" description:"时间戳,单位毫秒"`
|
|
Score int32 `json:"score" form:"score" binding:"required" description:"游戏得分"`
|
|
Code string `json:"code" form:"code" binding:"required" description:"回调签名"`
|
|
}
|
|
|
|
const (
|
|
APP_KEY = "8001bd25832553c39d4b443f56480841"
|
|
)
|
|
|
|
func Reward(c *gin.Context) {
|
|
var req RewardRequest
|
|
if err := c.ShouldBind(&req); err != nil {
|
|
c.JSON(400, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
expectedCode := req.Sign()
|
|
if expectedCode != req.Code {
|
|
c.JSON(400, gin.H{"error": "invalid code"})
|
|
return
|
|
}
|
|
res, err := client.MiniGame(req.AppId, req.ServerId, &msg.ReqMiniGame{
|
|
Uid: req.UserID,
|
|
Id: req.GameID,
|
|
Score: req.Score,
|
|
})
|
|
if err != nil {
|
|
c.JSON(500, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(200, gin.H{"reward": res})
|
|
}
|
|
|
|
func (r *RewardRequest) Sign() string {
|
|
// 收集参数到 map[key]=string(value)
|
|
params := make(map[string]string)
|
|
val := reflect.ValueOf(*r)
|
|
typ := reflect.TypeOf(*r)
|
|
for i := 0; i < typ.NumField(); i++ {
|
|
field := typ.Field(i)
|
|
// 使用 json tag 作为键名,若为空则 fallback 到字段名
|
|
tag := field.Tag.Get("json")
|
|
key := strings.Split(tag, ",")[0]
|
|
if key == "" {
|
|
key = field.Name
|
|
}
|
|
// 排除 code
|
|
if key == "code" {
|
|
continue
|
|
}
|
|
fv := val.Field(i)
|
|
var s string
|
|
if fv.Kind() == reflect.String {
|
|
s = fv.String()
|
|
} else {
|
|
s = fmt.Sprintf("%v", fv.Interface())
|
|
}
|
|
params[key] = s
|
|
}
|
|
|
|
// 排序键名
|
|
keys := make([]string, 0, len(params))
|
|
for k := range params {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
|
|
// 拼接签名源字符串
|
|
var b strings.Builder
|
|
for i, k := range keys {
|
|
if i > 0 {
|
|
b.WriteByte('&')
|
|
}
|
|
b.WriteString(k)
|
|
b.WriteByte('=')
|
|
b.WriteString(params[k])
|
|
}
|
|
checkstr := b.String()
|
|
checkstr = APP_KEY + checkstr + APP_KEY
|
|
// 计算 MD5 并返回小写十六进制字符串
|
|
sum := md5.Sum([]byte(checkstr))
|
|
return fmt.Sprintf("%x", sum)
|
|
}
|