Files
exchange_go/services/excservice/binancereceive.go

130 lines
3.6 KiB
Go
Raw Normal View History

2025-02-06 11:14:33 +08:00
package excservice
import (
2025-10-14 19:58:59 +08:00
"fmt"
2025-02-06 11:14:33 +08:00
"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-合约
*/
2025-10-14 19:58:59 +08:00
// ReceiveListen 处理用户订单订阅
// 返回:
// - reconnect: bool, 是否需要立即重连 (通常用于 listenKey 过期)
// - fatal: bool, 是否是致命错误 (例如认证失败),需要停止整个服务
// - err: error, 解析或处理过程中的错误
func ReceiveListen(msg []byte, listenType int, apiKey string) (reconnect bool, fatal bool, err error) {
2025-02-06 11:14:33 +08:00
var dataMap map[string]interface{}
err = sonic.Unmarshal(msg, &dataMap)
if err != nil {
log.Error("接收ws 反序列化失败:", err)
2025-10-14 19:58:59 +08:00
return false, false, err
2025-02-06 11:14:33 +08:00
}
2025-10-14 19:58:59 +08:00
// 检查是否是币安的错误消息, 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
}
2025-02-06 11:14:33 +08:00
2025-10-14 19:58:59 +08:00
event, exits := dataMap["e"]
2025-02-06 11:14:33 +08:00
if !exits {
2025-10-14 19:58:59 +08:00
// 如果没有 event 字段,但也不是一个错误消息,则可能是一个未知的消息格式
log.Warn("收到的消息中不存在event字段: %s", string(msg))
return false, false, nil
2025-02-06 11:14:33 +08:00
}
switch event {
//listenKey过期
case "listenKeyExpired":
log.Info("listenKey过期", string(msg))
2025-10-14 19:58:59 +08:00
return true, false, nil
2025-02-06 11:14:33 +08:00
//订单变更
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))
2025-10-14 19:58:59 +08:00
return true, false, nil
2025-02-06 11:14:33 +08:00
default:
log.Info("未知事件 内容:", string(msg))
log.Info("未知事件", event)
2025-10-14 19:58:59 +08:00
return false, false, nil
2025-02-06 11:14:33 +08:00
}
2025-10-14 19:58:59 +08:00
return false, false, nil
2025-02-06 11:14:33 +08:00
}