Files
exchange_go/services/excservice/binancereceive.go
2025-10-14 19:58:59 +08:00

130 lines
3.6 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 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
}