package excservice import ( "fmt" "go-admin/models/futuresdto" "go-admin/pkg/utility" "go-admin/services/binanceservice" "strconv" "github.com/bytedance/sonic" log "github.com/go-admin-team/go-admin-core/logger" ) /* 用户订单订阅处理 - @msg 消息内容 - @listenType 订阅类型 0-现货 1-合约 */ // ReceiveListen 处理用户订单订阅 // 返回: // - reconnect: bool, 是否需要立即重连 (通常用于 listenKey 过期) // - fatal: bool, 是否是致命错误 (例如认证失败),需要停止整个服务 // - err: error, 解析或处理过程中的错误 func ReceiveListen(msg []byte, listenType int, apiKey string) (reconnect bool, fatal bool, err error) { var dataMap map[string]interface{} err = sonic.Unmarshal(msg, &dataMap) if err != nil { log.Error("接收ws 反序列化失败:", err) return false, false, err } // 检查是否是币安的错误消息, e.g. {"code":-2015,"msg":"Invalid API-key, IP, or permissions for action."} if code, ok := dataMap["code"].(float64); ok && code != 0 { errMsg, _ := dataMap["msg"].(string) log.Errorf("收到币安错误码: %d, 消息: %s, API Key: %s", int(code), errMsg, apiKey) // -2015 是无效API Key的错误码,这是一个致命错误,不需要重连 if int(code) == -2015 { return false, true, fmt.Errorf("币安认证失败 (code: %d): %s", int(code), errMsg) } // 其他错误码可能也需要特殊处理,但暂时我们只将-2015视为致命错误 return false, false, nil } event, exits := dataMap["e"] if !exits { // 如果没有 event 字段,但也不是一个错误消息,则可能是一个未知的消息格式 log.Warn("收到的消息中不存在event字段: %s", string(msg)) return false, false, nil } switch event { //listenKey过期 case "listenKeyExpired": log.Info("listenKey过期", string(msg)) return true, false, nil //订单变更 case "ORDER_TRADE_UPDATE": log.Info("ORDER_TRADE_UPDATE 推送:", string(msg)) //现货 if listenType == 0 { var mapData map[string]interface{} err = sonic.Unmarshal(msg, &mapData) if err != nil { log.Error("订单变更处理失败", err) break } utility.SafeGo(func() { binanceservice.ChangeSpotOrder(mapData) }) } else { var data futuresdto.OrderTradeUpdate err = sonic.Unmarshal(msg, &data) if err != nil { log.Error("订单变更处理失败", err) break } utility.SafeGo(func() { binanceservice.ChangeFutureOrder(data.OrderDetails) }) } //订单更新 case "executionReport": log.Info("executionReport 推送:", string(msg)) if listenType == 0 { //现货 binanceservice.ChangeSpotOrder(dataMap) } else if listenType == 1 { //合约 binanceservice.ChangeFutureOrder(dataMap) } else { log.Error("executionReport 不支持的订阅类型", strconv.Itoa(listenType)) } //杠杆倍数等账户配置 更新推送 case "ACCOUNT_CONFIG_UPDATE": log.Info(string(msg)) //追加保证金 case "MARGIN_CALL": log.Info(string(msg)) //条件订单(TP/SL)触发后拒绝更新推送 case "CONDITIONAL_ORDER_TRIGGER_REJECT": or, exits := dataMap["or"].(string) if exits { var data futuresdto.OrderTriggerReject sonic.UnmarshalString(or, &data) if data.OrderNo > 0 { log.Info("订单号【%v】止盈止损触发后被拒绝:%s", data.OrderNo, data.Reason) } } case "eventStreamTerminated": log.Info("账户数据流被终止 type:", getWsTypeName(listenType)) return true, false, nil default: log.Info("未知事件 内容:", string(msg)) log.Info("未知事件", event) return false, false, nil } return false, false, nil }