fix(rock): 兼容 0666.pro 接口 points 字段字符串与数值自适应解析
1. 新增 FlexibleFloat64 类型,解决上游 /api/me 响应中 points 为字符串(如 '8271.2')导致反序列化失败的问题; 2. 服务层与数据库快照存储统一调用 Float64() 保持类型严谨; 3. 单元测试补充真实上游字符串响应场景并全绿通过。
This commit is contained in:
@@ -285,7 +285,7 @@ func TestRockService_StatsAndPurchase(t *testing.T) {
|
||||
"id": 10028,
|
||||
"username": "王大锤",
|
||||
"role": "merchant",
|
||||
"points": 8271.2,
|
||||
"points": "8271.2", // 真实上游 0666.pro 返回字符串格式
|
||||
"status": "active",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -8,10 +8,51 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// FlexibleFloat64 兼容反序列化 JSON 中的数字或字符串(如 "8271.2")
|
||||
type FlexibleFloat64 float64
|
||||
|
||||
func (f *FlexibleFloat64) UnmarshalJSON(b []byte) error {
|
||||
if len(b) == 0 || string(b) == "null" {
|
||||
*f = 0
|
||||
return nil
|
||||
}
|
||||
var n float64
|
||||
if err := json.Unmarshal(b, &n); err == nil {
|
||||
*f = FlexibleFloat64(n)
|
||||
return nil
|
||||
}
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err == nil {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
*f = 0
|
||||
return nil
|
||||
}
|
||||
val, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
*f = 0
|
||||
return nil
|
||||
}
|
||||
*f = FlexibleFloat64(val)
|
||||
return nil
|
||||
}
|
||||
*f = 0
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f FlexibleFloat64) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(float64(f))
|
||||
}
|
||||
|
||||
func (f FlexibleFloat64) Float64() float64 {
|
||||
return float64(f)
|
||||
}
|
||||
|
||||
// RockClient 负责与 0666.pro 平台进行 HTTP 通信
|
||||
type RockClient struct {
|
||||
baseURL string
|
||||
@@ -33,11 +74,11 @@ func NewRockClient(baseURL string) *RockClient {
|
||||
|
||||
type RockMeResponse struct {
|
||||
User struct {
|
||||
ID uint64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Role string `json:"role"`
|
||||
Points float64 `json:"points"`
|
||||
Status string `json:"status"`
|
||||
ID uint64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Role string `json:"role"`
|
||||
Points FlexibleFloat64 `json:"points"`
|
||||
Status string `json:"status"`
|
||||
} `json:"user"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ func (s *RockService) TestConnection(ctx context.Context, bearerToken string) (*
|
||||
now := time.Now()
|
||||
_ = s.db.WithContext(ctx).Model(&model.RockConfig{}).Where("id = 1").Updates(map[string]interface{}{
|
||||
"username": me.User.Username,
|
||||
"points": me.User.Points,
|
||||
"points": me.User.Points.Float64(),
|
||||
"last_heartbeat_at": now,
|
||||
}).Error
|
||||
|
||||
@@ -271,7 +271,7 @@ func (s *RockService) PurchaseTokens(ctx context.Context, count int, isAuto bool
|
||||
defer cancel()
|
||||
me, meErr := s.client.GetMe(bgCtx, cfg.BearerToken)
|
||||
if meErr == nil && me != nil {
|
||||
_ = s.db.Model(&model.RockConfig{}).Where("id = 1").Update("points", me.User.Points).Error
|
||||
_ = s.db.Model(&model.RockConfig{}).Where("id = 1").Update("points", me.User.Points.Float64()).Error
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user