admin_backend/sdk/ship/model/test/test.go
2025-11-14 16:08:42 +08:00

156 lines
3.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package test
import (
"backend/msg"
"backend/sdk/ship/model/base"
"backend/util"
"crypto/md5"
"encoding/json"
"fmt"
"log"
"reflect"
"sort"
"strings"
"time"
"github.com/gin-gonic/gin"
)
type TestModel struct {
}
type ChargeRequest struct {
AppID string `json:"appId" form:"appId" binding:"required" description:"途游应用id"`
ClientID string `json:"clientId" form:"clientId" binding:"required" description:"途游客户端包id"`
UserID string `json:"userId" form:"userId" binding:"required" description:"途游用户id"`
ProductID string `json:"productId" form:"productId" binding:"required" description:"途游商品id"`
AppInfo string `json:"appInfo" form:"appInfo" description:"项目组透传参数"`
Code string `json:"code" form:"code" binding:"required" description:"接口签名"`
}
// 增加 Sign 方法:按 json tag 名称收集参数,排除 code按 ASCII 升序拼接 key=value 用 & 连接,最后 MD5 并返回小写十六进制字符串。
func (r *ChargeRequest) Sign() string {
if r == nil {
return ""
}
// 收集参数到 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()
// 计算 MD5 并返回小写十六进制字符串
sum := md5.Sum([]byte(checkstr))
return fmt.Sprintf("%x", sum)
}
func Charge(c *gin.Context) {
var req ChargeRequest
if err := c.ShouldBind(&req); err != nil {
log.Print("binding error:", err)
c.JSON(400, gin.H{"error": err.Error()})
return
}
expectedSign := req.Sign()
if req.Code != expectedSign {
// log.Printf("invalid signature: got %s, expected %s", req.Code, expectedSign)
// c.JSON(401, gin.H{"error": "invalid signature"})
// return
}
// {"appId":1,"uid":100100476,"serverId":1,"orderId":"order_100100002_20250820142941DBLbNB"}
var AppInfo base.Param
if err := json.Unmarshal([]byte(req.AppInfo), &AppInfo); err != nil {
log.Print("unmarshal AppInfo error:", err)
c.JSON(400, gin.H{"error": "invalid AppInfo"})
return
}
AppInfo.ChannelOrderId = req.ProductID
err := AppInfo.ChangeOrderStatus()
if err != nil {
log.Print("change order status error:", err)
c.JSON(500, gin.H{"error": "failed to change order status"})
return
}
go Shipping(AppInfo)
c.JSON(200, gin.H{"code": 0, "message": "success"})
}
func Shipping(AppInfo base.Param) {
Adminreq := &msg.ReqAdminShipping{
OrderSn: AppInfo.OrderId,
Status: 1,
ChannelOrderSn: AppInfo.ChannelOrderId,
}
num := 0
for {
num++
if num > 100 {
log.Print("charge shipping break infinite loop")
}
ws, err := util.GetWebsocket(AppInfo.AppId, AppInfo.ServerId)
if err != nil {
time.Sleep(time.Second)
continue
}
r, err := util.SendAdminMsg(ws, Adminreq)
// close the websocket immediately to avoid accumulating defers in the loop
if closeErr := ws.Close(); closeErr != nil {
log.Printf("failed to close websocket: %v", closeErr)
}
if err != nil {
time.Sleep(time.Second)
continue
}
if r != nil {
log.Printf("charge shipping:orderSn:%s;res:%v", AppInfo.OrderId, r)
break
}
}
}
func (t *TestModel) VerifyToken(Uid string, Token string) error {
return nil
}