1、
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
package apis
|
package apis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go-admin/common/const/rediskey"
|
"go-admin/common/const/rediskey"
|
||||||
"go-admin/common/global"
|
"go-admin/common/global"
|
||||||
@ -284,7 +285,15 @@ func (e LinePreOrder) AddPreOrder(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userId := user.GetUserId(c)
|
||||||
|
|
||||||
|
if userId <= 0 {
|
||||||
|
e.Error(500, errors.New("用户不存在"), "用户不存在")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
req.SetCreateBy(userId)
|
||||||
errs := make([]error, 0)
|
errs := make([]error, 0)
|
||||||
errStr := make([]string, 0)
|
errStr := make([]string, 0)
|
||||||
var tickerSymbol string
|
var tickerSymbol string
|
||||||
@ -358,6 +367,13 @@ func (e LinePreOrder) BatchAddOrder(c *gin.Context) {
|
|||||||
p := actions.GetPermissionFromContext(c)
|
p := actions.GetPermissionFromContext(c)
|
||||||
errs := make([]error, 0)
|
errs := make([]error, 0)
|
||||||
errStr := make([]string, 0)
|
errStr := make([]string, 0)
|
||||||
|
userId := user.GetUserId(c)
|
||||||
|
|
||||||
|
if userId <= 0 {
|
||||||
|
e.Error(500, nil, "用户不存在")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetCreateBy(userId)
|
||||||
s.AddBatchPreOrder(&req, p, &errs)
|
s.AddBatchPreOrder(&req, p, &errs)
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
//e.Logger.Error(err)
|
//e.Logger.Error(err)
|
||||||
@ -392,7 +408,14 @@ func (e LinePreOrder) QuickAddPreOrder(c *gin.Context) {
|
|||||||
p := actions.GetPermissionFromContext(c)
|
p := actions.GetPermissionFromContext(c)
|
||||||
errs := make([]error, 0)
|
errs := make([]error, 0)
|
||||||
errStr := make([]string, 0)
|
errStr := make([]string, 0)
|
||||||
err = s.QuickAddPreOrder(&req, p, &errs)
|
userId := user.GetUserId(c)
|
||||||
|
|
||||||
|
if userId <= 0 {
|
||||||
|
e.Error(500, nil, "用户不存在")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.QuickAddPreOrder(&req, p, userId, &errs)
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
//e.Logger.Error(err)
|
//e.Logger.Error(err)
|
||||||
for _, err2 := range errs {
|
for _, err2 := range errs {
|
||||||
|
|||||||
@ -26,7 +26,6 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-admin-team/go-admin-core/logger"
|
"github.com/go-admin-team/go-admin-core/logger"
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
"github.com/go-admin-team/go-admin-core/sdk/api"
|
||||||
"github.com/shopspring/decimal"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -364,6 +363,11 @@ func (e LineUserApi) Info(c *gin.Context) {
|
|||||||
binanceAccount := service.BinanceAccount{Service: s.Service}
|
binanceAccount := service.BinanceAccount{Service: s.Service}
|
||||||
|
|
||||||
//获取用户资金账户资产
|
//获取用户资金账户资产
|
||||||
|
totalAsset, err := binanceAccount.GetTotalAsset(userId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Errorf("获取用户资金账户资产失败:%v", err)
|
||||||
|
}
|
||||||
resp, err := binanceAccount.GetFundingAsset(userId)
|
resp, err := binanceAccount.GetFundingAsset(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e.Logger.Error(500, err, err.Error())
|
e.Logger.Error(500, err, err.Error())
|
||||||
@ -375,28 +379,26 @@ func (e LineUserApi) Info(c *gin.Context) {
|
|||||||
if val != "" {
|
if val != "" {
|
||||||
sonic.Unmarshal([]byte(val), &tickerData)
|
sonic.Unmarshal([]byte(val), &tickerData)
|
||||||
}
|
}
|
||||||
var usdtBalance decimal.Decimal
|
// var usdtBalance decimal.Decimal
|
||||||
for i, asset := range resp {
|
for i, asset := range resp {
|
||||||
symbol := asset.Asset + "USDT"
|
symbol := asset.Asset + "USDT"
|
||||||
for _, datum := range tickerData {
|
for _, datum := range tickerData {
|
||||||
if datum.Symbol == symbol {
|
if datum.Symbol == symbol {
|
||||||
mul := utility.StringToDecimal(datum.Price).Mul(utility.StringToDecimal(asset.Free))
|
// mul := utility.StringToDecimal(datum.Price).Mul(utility.StringToDecimal(asset.Free))
|
||||||
usdtBalance = usdtBalance.Add(mul)
|
// usdtBalance = usdtBalance.Add(mul)
|
||||||
resp[i].UsdtValuation = datum.Price
|
resp[i].UsdtValuation = datum.Price
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if asset.Asset == "USDT" {
|
|
||||||
// usdt = asset.Free
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 邀请人数
|
// 邀请人数
|
||||||
//var inviteNum int64
|
var inviteNum int64
|
||||||
var userinfo models.LineUser
|
var userinfo models.LineUser
|
||||||
e.Orm.Model(&models.LineUser{}).Where("id = ?", userId).Find(&userinfo)
|
e.Orm.Model(&models.LineUser{}).Where("id = ?", userId).Find(&userinfo)
|
||||||
|
e.Orm.Model(&models.LineUser{}).Where("pid =? or top_referrer_id =?", userId, userId).Count(&inviteNum)
|
||||||
|
|
||||||
var apiUserinfo models.LineApiUser
|
var apiUserinfo models.LineApiUser
|
||||||
e.Orm.Model(&models.LineApiUser{}).Where("user_id = ?", userId).Find(&apiUserinfo)
|
e.Orm.Model(&models.LineApiUser{}).Where("user_id = ? ", userId).Find(&apiUserinfo)
|
||||||
var isAuth bool
|
var isAuth bool
|
||||||
if apiUserinfo.ApiKey != "" && apiUserinfo.ApiSecret != "" {
|
if apiUserinfo.ApiKey != "" && apiUserinfo.ApiSecret != "" {
|
||||||
isAuth = true
|
isAuth = true
|
||||||
@ -418,7 +420,7 @@ func (e LineUserApi) Info(c *gin.Context) {
|
|||||||
"avatar": userinfo.Avatar,
|
"avatar": userinfo.Avatar,
|
||||||
"user_id": userinfo.Id,
|
"user_id": userinfo.Id,
|
||||||
"user_name": userinfo.Nickname,
|
"user_name": userinfo.Nickname,
|
||||||
"invite_num": userinfo.RecommendNum,
|
"invite_num": inviteNum,
|
||||||
"open_status": apiUserinfo.OpenStatus,
|
"open_status": apiUserinfo.OpenStatus,
|
||||||
"is_auth": isAuth,
|
"is_auth": isAuth,
|
||||||
"invite_url": fmt.Sprintf("%s/invice_url?invite_code=%s", ext.ExtConfig.Domain, userinfo.InviteCode),
|
"invite_url": fmt.Sprintf("%s/invice_url?invite_code=%s", ext.ExtConfig.Domain, userinfo.InviteCode),
|
||||||
@ -428,7 +430,7 @@ func (e LineUserApi) Info(c *gin.Context) {
|
|||||||
"api_secret": inttostring.EncryptString(apiUserinfo.ApiSecret, 4, 4),
|
"api_secret": inttostring.EncryptString(apiUserinfo.ApiSecret, 4, 4),
|
||||||
}
|
}
|
||||||
returnMap := map[string]interface{}{
|
returnMap := map[string]interface{}{
|
||||||
"u_balance": usdtBalance.Truncate(2),
|
"u_balance": totalAsset.Truncate(2),
|
||||||
"margin": userinfo.Money,
|
"margin": userinfo.Money,
|
||||||
"userinfo": user,
|
"userinfo": user,
|
||||||
"funding_asset": fundingAsset,
|
"funding_asset": fundingAsset,
|
||||||
|
|||||||
@ -9,3 +9,9 @@ type FundingAsset struct {
|
|||||||
BtcValuation string `json:"btcValuation"`
|
BtcValuation string `json:"btcValuation"`
|
||||||
UsdtValuation string `json:"usdt_valuation"`
|
UsdtValuation string `json:"usdt_valuation"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BinanceWalletBalance struct {
|
||||||
|
Active bool `json:"active"`
|
||||||
|
Balance string `json:"balance"`
|
||||||
|
WalletName string `json:"walletName"`
|
||||||
|
}
|
||||||
|
|||||||
@ -3,12 +3,19 @@ package service
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/bytedance/sonic"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
|
||||||
"go-admin/app/admin/models"
|
"go-admin/app/admin/models"
|
||||||
|
"go-admin/common/const/rediskey"
|
||||||
|
"go-admin/common/global"
|
||||||
"go-admin/common/helper"
|
"go-admin/common/helper"
|
||||||
ext "go-admin/config"
|
ext "go-admin/config"
|
||||||
|
"go-admin/pkg/utility"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/bytedance/sonic"
|
||||||
|
"github.com/go-admin-team/go-admin-core/logger"
|
||||||
|
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ProxyType = "socks5"
|
const ProxyType = "socks5"
|
||||||
@ -62,3 +69,90 @@ func (e *BinanceAccount) GetFundingAsset(userId int) (resp []models.FundingAsset
|
|||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
获取钱包余额
|
||||||
|
|
||||||
|
- @param userId 用户id
|
||||||
|
- @param quoteAsset 币种 USDT, ETH, USDC, BNB等。 默认 BTC
|
||||||
|
- @return []models.FundingAsset 钱包余额
|
||||||
|
*/
|
||||||
|
func (e *BinanceAccount) GetWalletBalance(userId int, quoteAsset string) (resp []models.BinanceWalletBalance, err error) {
|
||||||
|
if quoteAsset == "" {
|
||||||
|
quoteAsset = "BTC"
|
||||||
|
}
|
||||||
|
|
||||||
|
var proxyUrl, proxyType string
|
||||||
|
var apiUser models.LineApiUser
|
||||||
|
url := "/sapi/v1/asset/wallet/balance"
|
||||||
|
err = e.Orm.Where(&models.LineApiUser{}).Where("user_id = ?", userId).Find(&apiUser).Error
|
||||||
|
if err != nil {
|
||||||
|
e.Log.Errorf("Service LineApiUser error:%s \r\n", err)
|
||||||
|
return []models.BinanceWalletBalance{}, err
|
||||||
|
}
|
||||||
|
if apiUser.Id <= 0 {
|
||||||
|
e.Log.Errorf("Service LineApiUser error:%s \r\n", "用户未找到")
|
||||||
|
return []models.BinanceWalletBalance{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ext.ExtConfig.ProxyUrl != "" {
|
||||||
|
proxyUrl = "127.0.0.1:7890"
|
||||||
|
proxyType = "http"
|
||||||
|
}
|
||||||
|
|
||||||
|
if apiUser.IpAddress != "" && apiUser.UserPass != "" {
|
||||||
|
proxyUrl = fmt.Sprintf("%s:%s", apiUser.IpAddress, apiUser.UserPass)
|
||||||
|
proxyType = ProxyType
|
||||||
|
}
|
||||||
|
clinet, err := helper.NewBinanceClient(apiUser.ApiKey, apiUser.ApiSecret, proxyType, proxyUrl)
|
||||||
|
if err != nil {
|
||||||
|
e.Log.Errorf("Service NewBinanceClient error:%s \r\n", err)
|
||||||
|
return []models.BinanceWalletBalance{}, err
|
||||||
|
}
|
||||||
|
req := map[string]string{
|
||||||
|
"quoteAsset": quoteAsset,
|
||||||
|
"recvWindow": "10000",
|
||||||
|
}
|
||||||
|
|
||||||
|
httpResp, statusCode, err := clinet.SendSpotAuth(url, "GET", req)
|
||||||
|
if err != nil {
|
||||||
|
e.Log.Errorf("Service SendSpotAuth error:%s \r\n", err)
|
||||||
|
return []models.BinanceWalletBalance{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if statusCode != http.StatusOK {
|
||||||
|
e.Log.Errorf("Service 请求失败 error:%s \r\n", err)
|
||||||
|
return []models.BinanceWalletBalance{}, errors.New("请求失败")
|
||||||
|
}
|
||||||
|
sonic.Unmarshal(httpResp, &resp)
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
获取用户总资产
|
||||||
|
*/
|
||||||
|
func (e *BinanceAccount) GetTotalAsset(userId int) (decimal.Decimal, error) {
|
||||||
|
key := fmt.Sprintf(rediskey.User_Total_Asset, global.EXCHANGE_BINANCE, userId)
|
||||||
|
totalStr, _ := helper.DefaultRedis.GetString(key)
|
||||||
|
result := decimal.Zero
|
||||||
|
if totalStr != "" {
|
||||||
|
result = utility.StrToDecimal(totalStr)
|
||||||
|
} else {
|
||||||
|
assets, err := e.GetWalletBalance(userId, "USDT")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("GetTotalAsset error:%s", err)
|
||||||
|
|
||||||
|
return decimal.Decimal{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, asset := range assets {
|
||||||
|
result = result.Add(utility.StrToDecimal(asset.Balance))
|
||||||
|
}
|
||||||
|
|
||||||
|
helper.DefaultRedis.SetStringExpire(key, result.String(), 30*time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|||||||
@ -209,6 +209,7 @@ type LineAddPreOrderReq struct {
|
|||||||
ReduceReTakeProfitRatio decimal.Decimal `json:"re_take_profit_ratio" comment:"减仓后亏损回本止盈百分比"`
|
ReduceReTakeProfitRatio decimal.Decimal `json:"re_take_profit_ratio" comment:"减仓后亏损回本止盈百分比"`
|
||||||
|
|
||||||
Ext []LineAddPreOrderExtReq `json:"ext" ` //拓展字段
|
Ext []LineAddPreOrderExtReq `json:"ext" ` //拓展字段
|
||||||
|
common.ControlBy
|
||||||
}
|
}
|
||||||
|
|
||||||
type LinePreOrderAddPositionReq struct {
|
type LinePreOrderAddPositionReq struct {
|
||||||
@ -389,6 +390,7 @@ type LineBatchAddPreOrderReq struct {
|
|||||||
ReduceTakeProfitRatio decimal.Decimal `json:"reduce_take_profit"` //主单减仓后止盈价百分比
|
ReduceTakeProfitRatio decimal.Decimal `json:"reduce_take_profit"` //主单减仓后止盈价百分比
|
||||||
ReduceStopLossRatio decimal.Decimal `json:"reduce_stop_price"` //主单减仓后止损价百分比
|
ReduceStopLossRatio decimal.Decimal `json:"reduce_stop_price"` //主单减仓后止损价百分比
|
||||||
Ext []LineAddPreOrderExtReq `json:"ext"` //拓展字段
|
Ext []LineAddPreOrderExtReq `json:"ext"` //拓展字段
|
||||||
|
common.ControlBy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (req LineBatchAddPreOrderReq) CheckParams() error {
|
func (req LineBatchAddPreOrderReq) CheckParams() error {
|
||||||
|
|||||||
@ -18,10 +18,12 @@ type LineSymbolGetPageReq struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type LineSymbolExportResp struct {
|
type LineSymbolExportResp struct {
|
||||||
Symbol string `json:"symbol" excel:"交易对"`
|
ExchangeType string `json:"exchangeType" excel:"交易所"`
|
||||||
Coin string `json:"coin" excel:"基础货币"`
|
Symbol string `json:"symbol" excel:"交易对"`
|
||||||
Currency string `json:"currency" excel:"计价货币"`
|
Coin string `json:"coin" excel:"基础货币"`
|
||||||
SymbolType string `json:"symbolType" excel:"交易对类型"`
|
Currency string `json:"currency" excel:"计价货币"`
|
||||||
|
SymbolType string `json:"symbolType" excel:"交易对类型"`
|
||||||
|
LastPrice string `json:"lastPrice" excel:"最新价"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LineSymbolOrder struct {
|
type LineSymbolOrder struct {
|
||||||
|
|||||||
@ -278,14 +278,15 @@ func (receiver FrontedLoginReq) CheckParams() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AddApiKeyReq struct {
|
type AddApiKeyReq struct {
|
||||||
ApiName string `json:"api_name"`
|
ExchangeType string `json:"exchange_type"`
|
||||||
ApiKey string `json:"api_key"`
|
ApiName string `json:"api_name"`
|
||||||
ApiSecret string `json:"api_secret"`
|
ApiKey string `json:"api_key"`
|
||||||
ApiIp string `json:"api_ip"`
|
ApiSecret string `json:"api_secret"`
|
||||||
|
ApiIp string `json:"api_ip"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AddApiKeyReq) CheckParams() int {
|
func (a AddApiKeyReq) CheckParams() int {
|
||||||
if a.ApiKey == "" || a.ApiSecret == "" {
|
if a.ExchangeType == "" || a.ApiKey == "" || a.ApiSecret == "" {
|
||||||
return statuscode.ParamErr
|
return statuscode.ParamErr
|
||||||
}
|
}
|
||||||
return statuscode.OK
|
return statuscode.OK
|
||||||
|
|||||||
@ -29,7 +29,7 @@ func (e *LineDirection) GetPage(c *dto.LineDirectionGetPageReq, p *actions.DataP
|
|||||||
Scopes(
|
Scopes(
|
||||||
cDto.MakeCondition(c.GetNeedSearch()),
|
cDto.MakeCondition(c.GetNeedSearch()),
|
||||||
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
|
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
|
||||||
actions.Permission(data.TableName(), p),
|
// actions.Permission(data.TableName(), p),
|
||||||
).
|
).
|
||||||
Find(list).Limit(-1).Offset(-1).
|
Find(list).Limit(-1).Offset(-1).
|
||||||
Count(count).Error
|
Count(count).Error
|
||||||
@ -45,9 +45,9 @@ func (e *LineDirection) Get(d *dto.LineDirectionGetReq, p *actions.DataPermissio
|
|||||||
var data models.LineDirection
|
var data models.LineDirection
|
||||||
|
|
||||||
err := e.Orm.Model(&data).
|
err := e.Orm.Model(&data).
|
||||||
Scopes(
|
// Scopes(
|
||||||
actions.Permission(data.TableName(), p),
|
// actions.Permission(data.TableName(), p),
|
||||||
).
|
// ).
|
||||||
First(model, d.GetId()).Error
|
First(model, d.GetId()).Error
|
||||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
err = errors.New("查看对象不存在或无权查看")
|
err = errors.New("查看对象不存在或无权查看")
|
||||||
|
|||||||
@ -391,6 +391,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
|
|||||||
Type: 1,
|
Type: 1,
|
||||||
Switch: "0",
|
Switch: "0",
|
||||||
}
|
}
|
||||||
|
saveTemplateParams.CreateBy = req.CreateBy
|
||||||
e.Orm.Model(&models.LineOrderTemplateLogs{}).Create(&saveTemplateParams)
|
e.Orm.Model(&models.LineOrderTemplateLogs{}).Create(&saveTemplateParams)
|
||||||
}
|
}
|
||||||
if req.SaveTemplate == "2" {
|
if req.SaveTemplate == "2" {
|
||||||
@ -426,6 +427,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddOrder.CreateBy = req.CreateBy
|
||||||
AddOrder.ExchangeType = req.ExchangeType
|
AddOrder.ExchangeType = req.ExchangeType
|
||||||
AddOrder.OrderCategory = 1
|
AddOrder.OrderCategory = 1
|
||||||
AddOrder.SignPriceType = "new"
|
AddOrder.SignPriceType = "new"
|
||||||
@ -598,6 +600,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
|
|||||||
ext.TotalBefore = mainParam.RemainingQuantity //初始数量
|
ext.TotalBefore = mainParam.RemainingQuantity //初始数量
|
||||||
ext.TotalAfter = calculateResp.RemainingQuantity //计算后数量
|
ext.TotalAfter = calculateResp.RemainingQuantity //计算后数量
|
||||||
ext.ReTakeRatio = calculateResp.Ratio
|
ext.ReTakeRatio = calculateResp.Ratio
|
||||||
|
ext.CreateBy = req.CreateBy
|
||||||
mainParam.LossBeginPercent = addPosition.PriceRatio
|
mainParam.LossBeginPercent = addPosition.PriceRatio
|
||||||
mainParam.RemainingQuantity = calculateResp.RemainingQuantity
|
mainParam.RemainingQuantity = calculateResp.RemainingQuantity
|
||||||
mainParam.TotalLossAmountU = calculateResp.TotalLossAmountU
|
mainParam.TotalLossAmountU = calculateResp.TotalLossAmountU
|
||||||
@ -637,18 +640,29 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
|
|||||||
|
|
||||||
//是否有止盈止损订单
|
//是否有止盈止损订单
|
||||||
if req.Profit != "" {
|
if req.Profit != "" {
|
||||||
if strings.ToUpper(req.Site) == "BUY" {
|
if req.PricePattern == "mixture" {
|
||||||
profitOrder.Site = "SELL"
|
mixturePrice := utility.StrToDecimal(req.Profit)
|
||||||
profitOrder.Price = decimal.NewFromFloat(utility.StringToFloat64(AddOrder.Price) * (1 + utility.StringToFloat64(req.Profit)/100)).Truncate(int32(tradeSet.PriceDigit)).String()
|
|
||||||
|
if mixturePrice.Cmp(decimal.Zero) <= 0 {
|
||||||
|
return fmt.Errorf("止盈价不能小于等于0")
|
||||||
|
}
|
||||||
|
|
||||||
|
profitOrder.Price = mixturePrice.Truncate(int32(tradeSet.PriceDigit)).String()
|
||||||
|
profitOrder.Rate = "0"
|
||||||
} else {
|
} else {
|
||||||
profitOrder.Site = "BUY"
|
if strings.ToUpper(req.Site) == "BUY" {
|
||||||
profitOrder.Price = decimal.NewFromFloat(utility.StringToFloat64(AddOrder.Price) * (1 - utility.StringToFloat64(req.Profit)/100)).Truncate(int32(tradeSet.PriceDigit)).String()
|
profitOrder.Site = "SELL"
|
||||||
|
profitOrder.Price = decimal.NewFromFloat(utility.StringToFloat64(AddOrder.Price) * (1 + utility.StringToFloat64(req.Profit)/100)).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||||
|
} else {
|
||||||
|
profitOrder.Site = "BUY"
|
||||||
|
profitOrder.Price = decimal.NewFromFloat(utility.StringToFloat64(AddOrder.Price) * (1 - utility.StringToFloat64(req.Profit)/100)).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||||
|
}
|
||||||
|
profitOrder.Rate = req.Profit
|
||||||
}
|
}
|
||||||
profitOrder.OrderSn = strconv.FormatInt(snowflakehelper.GetOrderId(), 10)
|
profitOrder.OrderSn = strconv.FormatInt(snowflakehelper.GetOrderId(), 10)
|
||||||
profitOrder.Pid = AddOrder.Id
|
profitOrder.Pid = AddOrder.Id
|
||||||
profitOrder.OrderType = 1
|
profitOrder.OrderType = 1
|
||||||
profitOrder.Status = 0
|
profitOrder.Status = 0
|
||||||
profitOrder.Rate = req.Profit
|
|
||||||
profitOrder.MainId = AddOrder.Id
|
profitOrder.MainId = AddOrder.Id
|
||||||
|
|
||||||
if req.ProfitNumRatio.Cmp(decimal.Zero) > 0 {
|
if req.ProfitNumRatio.Cmp(decimal.Zero) > 0 {
|
||||||
@ -673,12 +687,23 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
|
|||||||
}
|
}
|
||||||
|
|
||||||
if req.ReducePriceRatio.Cmp(decimal.Zero) > 0 {
|
if req.ReducePriceRatio.Cmp(decimal.Zero) > 0 {
|
||||||
if strings.ToUpper(req.Site) == "BUY" {
|
if req.PricePattern == "mixture" {
|
||||||
stopOrder.Site = "SELL"
|
if req.ReducePriceRatio.Cmp(decimal.Zero) <= 0 {
|
||||||
stopOrder.Price = utility.StrToDecimal(AddOrder.Price).Mul(decimal.NewFromInt(1).Sub(utility.SafeDiv(req.ReducePriceRatio, decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String()
|
return errors.New("检查价格不能小于等于0")
|
||||||
|
}
|
||||||
|
|
||||||
|
stopOrder.Price = req.ReducePriceRatio.Truncate(int32(tradeSet.PriceDigit)).String()
|
||||||
|
stopOrder.Rate = "0"
|
||||||
} else {
|
} else {
|
||||||
stopOrder.Site = "BUY"
|
if strings.ToUpper(req.Site) == "BUY" {
|
||||||
stopOrder.Price = utility.StrToDecimal(AddOrder.Price).Mul(decimal.NewFromInt(1).Add(utility.SafeDiv(req.ReducePriceRatio, decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String()
|
stopOrder.Site = "SELL"
|
||||||
|
stopOrder.Price = utility.StrToDecimal(AddOrder.Price).Mul(decimal.NewFromInt(1).Sub(utility.SafeDiv(req.ReducePriceRatio, decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||||
|
} else {
|
||||||
|
stopOrder.Site = "BUY"
|
||||||
|
stopOrder.Price = utility.StrToDecimal(AddOrder.Price).Mul(decimal.NewFromInt(1).Add(utility.SafeDiv(req.ReducePriceRatio, decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
stopOrder.Rate = req.ReducePriceRatio.String()
|
||||||
}
|
}
|
||||||
stopOrder.OrderSn = strconv.FormatInt(snowflakehelper.GetOrderId(), 10)
|
stopOrder.OrderSn = strconv.FormatInt(snowflakehelper.GetOrderId(), 10)
|
||||||
stopOrder.Pid = AddOrder.Id
|
stopOrder.Pid = AddOrder.Id
|
||||||
@ -686,7 +711,6 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
|
|||||||
stopOrder.OrderType = 4
|
stopOrder.OrderType = 4
|
||||||
stopOrder.Status = 0
|
stopOrder.Status = 0
|
||||||
stopOrder.BuyPrice = "0"
|
stopOrder.BuyPrice = "0"
|
||||||
stopOrder.Rate = req.ReducePriceRatio.String()
|
|
||||||
stopNum := utility.StrToDecimal(AddOrder.Num).Mul(req.ReduceNumRatio.Div(decimal.NewFromInt(100)).Truncate(4))
|
stopNum := utility.StrToDecimal(AddOrder.Num).Mul(req.ReduceNumRatio.Div(decimal.NewFromInt(100)).Truncate(4))
|
||||||
stopOrder.Num = stopNum.Truncate(int32(tradeSet.AmountDigit)).String()
|
stopOrder.Num = stopNum.Truncate(int32(tradeSet.AmountDigit)).String()
|
||||||
stopOrder.ExpireTime = time.Now().AddDate(10, 0, 0)
|
stopOrder.ExpireTime = time.Now().AddDate(10, 0, 0)
|
||||||
@ -1068,6 +1092,8 @@ func (e *LinePreOrder) AddBatchPreOrder(batchReq *dto.LineBatchAddPreOrderReq, p
|
|||||||
Type: 2,
|
Type: 2,
|
||||||
Switch: "0",
|
Switch: "0",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saveTemplateParams.CreateBy = p.UserId
|
||||||
e.Orm.Model(&models.LineOrderTemplateLogs{}).Create(&saveTemplateParams)
|
e.Orm.Model(&models.LineOrderTemplateLogs{}).Create(&saveTemplateParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1149,6 +1175,7 @@ func (e *LinePreOrder) AddBatchPreOrder(batchReq *dto.LineBatchAddPreOrderReq, p
|
|||||||
req.ReduceNumRatio = batchReq.ReduceNumRatio
|
req.ReduceNumRatio = batchReq.ReduceNumRatio
|
||||||
req.ReduceStopLossRatio = batchReq.ReduceStopLossRatio
|
req.ReduceStopLossRatio = batchReq.ReduceStopLossRatio
|
||||||
req.ReduceTakeProfitRatio = batchReq.ReduceTakeProfitRatio
|
req.ReduceTakeProfitRatio = batchReq.ReduceTakeProfitRatio
|
||||||
|
req.CreateBy = batchReq.CreateBy
|
||||||
|
|
||||||
e.AddPreOrder(&req, p, errs, tickerSymbol)
|
e.AddPreOrder(&req, p, errs, tickerSymbol)
|
||||||
}
|
}
|
||||||
@ -1162,7 +1189,7 @@ func (e *LinePreOrder) AddBatchPreOrder(batchReq *dto.LineBatchAddPreOrderReq, p
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QuickAddPreOrder 模板快速下单
|
// QuickAddPreOrder 模板快速下单
|
||||||
func (e *LinePreOrder) QuickAddPreOrder(quickReq *dto.QuickAddPreOrderReq, p *actions.DataPermission, errs *[]error) error {
|
func (e *LinePreOrder) QuickAddPreOrder(quickReq *dto.QuickAddPreOrderReq, p *actions.DataPermission, userId int, errs *[]error) error {
|
||||||
templateLogs := make([]models.LineOrderTemplateLogs, 0)
|
templateLogs := make([]models.LineOrderTemplateLogs, 0)
|
||||||
e.Orm.Model(&models.LineOrderTemplateLogs{}).Where("id in ?", strings.Split(quickReq.Ids, ",")).Find(&templateLogs)
|
e.Orm.Model(&models.LineOrderTemplateLogs{}).Where("id in ?", strings.Split(quickReq.Ids, ",")).Find(&templateLogs)
|
||||||
for _, log := range templateLogs {
|
for _, log := range templateLogs {
|
||||||
@ -1188,6 +1215,13 @@ func (e *LinePreOrder) QuickAddPreOrder(quickReq *dto.QuickAddPreOrderReq, p *ac
|
|||||||
if log.Type == 2 {
|
if log.Type == 2 {
|
||||||
var batchAddPreOrder dto.LineBatchAddPreOrderReq
|
var batchAddPreOrder dto.LineBatchAddPreOrderReq
|
||||||
sonic.Unmarshal([]byte(log.Params), &batchAddPreOrder)
|
sonic.Unmarshal([]byte(log.Params), &batchAddPreOrder)
|
||||||
|
|
||||||
|
if userId > 0 {
|
||||||
|
batchAddPreOrder.CreateBy = userId
|
||||||
|
} else {
|
||||||
|
batchAddPreOrder.CreateBy = log.CreateBy
|
||||||
|
}
|
||||||
|
|
||||||
e.AddBatchPreOrder(&batchAddPreOrder, p, errs)
|
e.AddBatchPreOrder(&batchAddPreOrder, p, errs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import (
|
|||||||
"go-admin/common/global"
|
"go-admin/common/global"
|
||||||
"go-admin/common/helper"
|
"go-admin/common/helper"
|
||||||
commonModels "go-admin/models"
|
commonModels "go-admin/models"
|
||||||
|
models2 "go-admin/models"
|
||||||
"go-admin/pkg/utility"
|
"go-admin/pkg/utility"
|
||||||
"go-admin/services/binanceservice"
|
"go-admin/services/binanceservice"
|
||||||
)
|
)
|
||||||
@ -37,7 +38,7 @@ func (e *LineSymbol) GetPage(c *dto.LineSymbolGetPageReq, p *actions.DataPermiss
|
|||||||
Scopes(
|
Scopes(
|
||||||
cDto.MakeCondition(c.GetNeedSearch()),
|
cDto.MakeCondition(c.GetNeedSearch()),
|
||||||
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
|
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
|
||||||
actions.Permission(data.TableName(), p),
|
// actions.Permission(data.TableName(), p),
|
||||||
).
|
).
|
||||||
Find(list).Limit(-1).Offset(-1).
|
Find(list).Limit(-1).Offset(-1).
|
||||||
Count(count).Error
|
Count(count).Error
|
||||||
@ -126,7 +127,7 @@ func (e *LineSymbol) ExportExcel(c *gin.Context, p *actions.DataPermission, req
|
|||||||
err := e.Orm.Model(&data).
|
err := e.Orm.Model(&data).
|
||||||
Scopes(
|
Scopes(
|
||||||
cDto.MakeCondition(req.GetNeedSearch()),
|
cDto.MakeCondition(req.GetNeedSearch()),
|
||||||
actions.Permission(data.TableName(), p),
|
// actions.Permission(data.TableName(), p),
|
||||||
).
|
).
|
||||||
Find(&list).Error
|
Find(&list).Error
|
||||||
|
|
||||||
@ -134,17 +135,64 @@ func (e *LineSymbol) ExportExcel(c *gin.Context, p *actions.DataPermission, req
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges := []string{}
|
||||||
|
exchangeFutMap := make(map[string]models2.TradeSet)
|
||||||
|
exchangeSpotMap := make(map[string]models2.TradeSet)
|
||||||
|
|
||||||
|
for _, v := range list {
|
||||||
|
if !utility.ContainsStr(exchanges, v.ExchangeType) {
|
||||||
|
key := fmt.Sprintf(global.TICKER_FUTURES, v.ExchangeType, "*")
|
||||||
|
key2 := fmt.Sprintf(global.TICKER_SPOT, v.ExchangeType, "*")
|
||||||
|
futs, _ := helper.DefaultRedis.GetAllKeysAndValues(key)
|
||||||
|
spots, _ := helper.DefaultRedis.GetAllKeysAndValues(key2)
|
||||||
|
trade := models2.TradeSet{}
|
||||||
|
|
||||||
|
for _, v2 := range futs {
|
||||||
|
if v2 != "" {
|
||||||
|
sonic.Unmarshal([]byte(v2), &trade)
|
||||||
|
|
||||||
|
if trade.LastPrice != "" {
|
||||||
|
exchangeFutMap[v.ExchangeType+"_"+trade.Coin+trade.Currency] = trade
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v2 := range spots {
|
||||||
|
if v2 != "" {
|
||||||
|
sonic.Unmarshal([]byte(v2), &trade)
|
||||||
|
|
||||||
|
if trade.LastPrice != "" {
|
||||||
|
exchangeSpotMap[v.ExchangeType+"_"+trade.Coin+trade.Currency] = trade
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exchanges = append(exchanges, v.ExchangeType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, v := range list {
|
for _, v := range list {
|
||||||
item := dto.LineSymbolExportResp{
|
item := dto.LineSymbolExportResp{
|
||||||
Symbol: v.Symbol,
|
ExchangeType: v.ExchangeType,
|
||||||
Coin: v.BaseAsset,
|
Symbol: v.Symbol,
|
||||||
Currency: v.QuoteAsset,
|
Coin: v.BaseAsset,
|
||||||
|
Currency: v.QuoteAsset,
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.Type == "1" {
|
if v.Type == "1" {
|
||||||
item.SymbolType = "现货"
|
item.SymbolType = "现货"
|
||||||
|
if v, ok := exchangeSpotMap[v.ExchangeType+"_"+v.Symbol]; ok {
|
||||||
|
if v.LastPrice != "" {
|
||||||
|
item.LastPrice = v.LastPrice
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
item.SymbolType = "合约"
|
item.SymbolType = "合约"
|
||||||
|
if v, ok := exchangeFutMap[v.ExchangeType+"_"+v.Symbol]; ok {
|
||||||
|
if v.LastPrice != "" {
|
||||||
|
item.LastPrice = v.LastPrice
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
datas = append(datas, item)
|
datas = append(datas, item)
|
||||||
|
|||||||
@ -51,7 +51,7 @@ func (e *LineUser) GetPage(c *dto.LineUserGetPageReq, p *actions.DataPermission,
|
|||||||
Scopes(
|
Scopes(
|
||||||
cDto.MakeCondition(c.GetNeedSearch()),
|
cDto.MakeCondition(c.GetNeedSearch()),
|
||||||
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
|
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
|
||||||
actions.Permission(data.TableName(), p),
|
// actions.Permission(data.TableName(), p),
|
||||||
).
|
).
|
||||||
Find(list).Limit(-1).Offset(-1).
|
Find(list).Limit(-1).Offset(-1).
|
||||||
Count(count).Error
|
Count(count).Error
|
||||||
@ -225,15 +225,16 @@ func (e *LineUser) AddApiKey(userId int, req *dto.AddApiKeyReq) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = e.Orm.Model(&models.LineApiUser{}).Create(&models.LineApiUser{
|
err = e.Orm.Model(&models.LineApiUser{}).Create(&models.LineApiUser{
|
||||||
UserId: int64(userId),
|
ExchangeType: req.ExchangeType,
|
||||||
ApiName: req.ApiName,
|
UserId: int64(userId),
|
||||||
ApiKey: req.ApiKey,
|
ApiName: req.ApiName,
|
||||||
ApiSecret: req.ApiSecret,
|
ApiKey: req.ApiKey,
|
||||||
Affiliation: 3,
|
ApiSecret: req.ApiSecret,
|
||||||
AdminShow: 0,
|
Affiliation: 3,
|
||||||
Site: "3",
|
AdminShow: 0,
|
||||||
Subordinate: "0",
|
Site: "3",
|
||||||
OpenStatus: 0,
|
Subordinate: "0",
|
||||||
|
OpenStatus: 0,
|
||||||
}).Error
|
}).Error
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -743,6 +744,8 @@ func (e *LineUser) OpenStatus(req *dto.OpenStatusReq, userId int) int {
|
|||||||
propperty := dto.LineUserPropertyResp{}
|
propperty := dto.LineUserPropertyResp{}
|
||||||
e.GetProperty(userId, &propperty)
|
e.GetProperty(userId, &propperty)
|
||||||
|
|
||||||
|
logger.Infof("合约可用资产:%v", propperty.FuturesFreeAmount)
|
||||||
|
logger.Infof("现货可用资产:%v", propperty.SpotFreeAmount)
|
||||||
//可用资产不足
|
//可用资产不足
|
||||||
if propperty.FuturesFreeAmount.Cmp(userSet.MinOrderAmount) < 0 && propperty.SpotFreeAmount.Cmp(userSet.MinOrderAmount) < 0 {
|
if propperty.FuturesFreeAmount.Cmp(userSet.MinOrderAmount) < 0 && propperty.SpotFreeAmount.Cmp(userSet.MinOrderAmount) < 0 {
|
||||||
return statuscode.PropertyInsufficient
|
return statuscode.PropertyInsufficient
|
||||||
|
|||||||
@ -142,7 +142,7 @@ func (t AutoPlaceOrder) Exec(arg interface{}) error {
|
|||||||
preOrderService.Orm = db
|
preOrderService.Orm = db
|
||||||
errs := make([]error, 0)
|
errs := make([]error, 0)
|
||||||
errStr := make([]string, 0)
|
errStr := make([]string, 0)
|
||||||
err := preOrderService.QuickAddPreOrder(&req, nil, &errs)
|
err := preOrderService.QuickAddPreOrder(&req, nil, 0, &errs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
6
common/const/rediskey/control.go
Normal file
6
common/const/rediskey/control.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package rediskey
|
||||||
|
|
||||||
|
const (
|
||||||
|
//用户总资产 {exchange_type,user_id}
|
||||||
|
User_Total_Asset = "u_total_asset:%s:%v"
|
||||||
|
)
|
||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/proxy"
|
"golang.org/x/net/proxy"
|
||||||
)
|
)
|
||||||
@ -20,7 +21,9 @@ import (
|
|||||||
*/
|
*/
|
||||||
func CreateHtppProxy(proxyType, proxyAddr string, client *http.Client) error {
|
func CreateHtppProxy(proxyType, proxyAddr string, client *http.Client) error {
|
||||||
// Set up proxy based on type (HTTP, HTTPS, SOCKS5)
|
// Set up proxy based on type (HTTP, HTTPS, SOCKS5)
|
||||||
transport := &http.Transport{}
|
transport := &http.Transport{
|
||||||
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
|
}
|
||||||
if proxyAddr != "" {
|
if proxyAddr != "" {
|
||||||
if !strings.HasPrefix(proxyAddr, "http://") && !strings.HasPrefix(proxyAddr, "https://") && !strings.HasPrefix(proxyAddr, "socks5://") {
|
if !strings.HasPrefix(proxyAddr, "http://") && !strings.HasPrefix(proxyAddr, "https://") && !strings.HasPrefix(proxyAddr, "socks5://") {
|
||||||
proxyAddr = proxyType + "://" + proxyAddr
|
proxyAddr = proxyType + "://" + proxyAddr
|
||||||
|
|||||||
@ -1,18 +1,13 @@
|
|||||||
package authservice
|
package authservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"go-admin/common/const/rediskey"
|
"go-admin/common/const/rediskey"
|
||||||
"go-admin/common/helper"
|
"go-admin/common/helper"
|
||||||
statuscode "go-admin/common/status_code"
|
statuscode "go-admin/common/status_code"
|
||||||
ext "go-admin/config"
|
|
||||||
"go-admin/pkg/cryptohelper/inttostring"
|
"go-admin/pkg/cryptohelper/inttostring"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bytedance/sonic"
|
|
||||||
log "github.com/go-admin-team/go-admin-core/logger"
|
log "github.com/go-admin-team/go-admin-core/logger"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@ -496,60 +491,8 @@ func SendGoToneSms(phone, area string, smsType int) int {
|
|||||||
}
|
}
|
||||||
//ext.ExtConfig.GoToneSmsConfig
|
//ext.ExtConfig.GoToneSmsConfig
|
||||||
// SmsRequest 用于构建发送短信请求的结构体
|
// SmsRequest 用于构建发送短信请求的结构体
|
||||||
type SmsRequest struct {
|
// todo 短信cangchu
|
||||||
Recipient string `json:"recipient"` // 收件人电话号码
|
|
||||||
Message string `json:"message"` // 短信内容
|
|
||||||
SenderId string `json:"sender_id"` // 发送者名称
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
// 创建请求数据
|
|
||||||
smsRequest := SmsRequest{
|
|
||||||
Recipient: "+" + area + phone,
|
|
||||||
SenderId: ext.ExtConfig.GoToneSmsConfig.SenderId,
|
|
||||||
Message: fmt.Sprintf("欢迎使用 GoTone SMS,高速稳定地发送短信至中国大陆及全球用户,体验验证码:%s。如非本人操作请忽略此信息", smsString),
|
|
||||||
Type: "plain",
|
|
||||||
}
|
|
||||||
// 将请求数据编码为 JSON
|
|
||||||
requestBody, err := sonic.Marshal(smsRequest)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("GoToneSms requestBody Error:", err)
|
|
||||||
return statuscode.ServerError
|
|
||||||
}
|
|
||||||
// 创建 HTTP 请求
|
|
||||||
req, err := http.NewRequest("POST", ext.ExtConfig.GoToneSmsConfig.APIEndpoint, bytes.NewBuffer(requestBody))
|
|
||||||
if err != nil {
|
|
||||||
log.Error("GoToneSms http.NewRequest Error:", err)
|
|
||||||
return statuscode.ServerError
|
|
||||||
}
|
|
||||||
// 设置请求头
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
req.Header.Set("Authorization", "Bearer "+ext.ExtConfig.GoToneSmsConfig.Authorization) // 使用 API 密钥进行身份验证
|
|
||||||
|
|
||||||
// 创建 HTTP 客户端并发送请求
|
|
||||||
client := &http.Client{
|
|
||||||
Timeout: 10 * time.Second, // 设置请求超时时间
|
|
||||||
}
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
fmt.Println("resp:", resp)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("GoToneSms do NewRequest Error:", err)
|
|
||||||
return statuscode.CaptchaFailInSend
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
// 检查响应状态
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
log.Error("GoToneSms do NewRequest Error:", err)
|
|
||||||
return statuscode.CaptchaFailInSend
|
|
||||||
}
|
|
||||||
// 读取响应体
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("读取响应体失败:", err)
|
|
||||||
fmt.Printf("响应体: %s", string(body))
|
|
||||||
return statuscode.CaptchaFailInSend
|
|
||||||
//return fmt.Errorf("读取响应体失败: %v", err)
|
|
||||||
}
|
|
||||||
// 打印响应内容(调试用)
|
// 打印响应内容(调试用)
|
||||||
//记录短信发送操作
|
//记录短信发送操作
|
||||||
helper.DefaultRedis.SetStringExpire(registerKey, "1", time.Second*60)
|
helper.DefaultRedis.SetStringExpire(registerKey, "1", time.Second*60)
|
||||||
|
|||||||
@ -16,11 +16,11 @@ type Extend struct {
|
|||||||
EmailConfig EmailConfig `mapstructure:"emailConfig"`
|
EmailConfig EmailConfig `mapstructure:"emailConfig"`
|
||||||
BinanceSet BinanceConfig `mapstructure:"binanceSet"` //binance配置
|
BinanceSet BinanceConfig `mapstructure:"binanceSet"` //binance配置
|
||||||
Domain string //网站域名
|
Domain string //网站域名
|
||||||
GoToneSmsConfig GoToneSmsConfig `mapstructure:"GoToneSmsConfig"`
|
|
||||||
UDunConfig UDunConfig `mapstructure:"UDunConfig"`
|
UDunConfig UDunConfig `mapstructure:"UDunConfig"`
|
||||||
ProxyUrl string //代理地址
|
ProxyUrl string //代理地址
|
||||||
CoinGate CoinGateConfig `mapstructure:"coingate"` //coingate钱包
|
CoinGate CoinGateConfig `mapstructure:"coingate"` //coingate钱包
|
||||||
|
GoToneSmsConfig GoToneSmsConfig `mapstructure:"GoToneSmsConfig"`
|
||||||
|
InnoPaas InnoPaasConfig `mapstructure:"innoPaas"` //创蓝短信
|
||||||
}
|
}
|
||||||
|
|
||||||
type CoinGateConfig struct {
|
type CoinGateConfig struct {
|
||||||
@ -70,6 +70,12 @@ type GoToneSmsConfig struct {
|
|||||||
Authorization string `json:"authorization"`
|
Authorization string `json:"authorization"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InnoPaasConfig struct {
|
||||||
|
Url string `json:"url"`
|
||||||
|
ApiKey string `json:"apiKey"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
type UDunConfig struct {
|
type UDunConfig struct {
|
||||||
UDunUrl string `json:"UDunUrl"`
|
UDunUrl string `json:"UDunUrl"`
|
||||||
UDunMerchantID string `json:"UDunMerchantID"`
|
UDunMerchantID string `json:"UDunMerchantID"`
|
||||||
|
|||||||
@ -11,7 +11,7 @@ settings:
|
|||||||
readtimeout: 1
|
readtimeout: 1
|
||||||
writertimeout: 2
|
writertimeout: 2
|
||||||
# 数据权限功能开关
|
# 数据权限功能开关
|
||||||
enabledp: false
|
enabledp: true
|
||||||
logger:
|
logger:
|
||||||
# 日志存放路径
|
# 日志存放路径
|
||||||
path: temp/logs
|
path: temp/logs
|
||||||
@ -82,6 +82,10 @@ settings:
|
|||||||
sender_id: "GoTone SMS"
|
sender_id: "GoTone SMS"
|
||||||
api_endpoint: "https://gosms.one/api/v3/sms/send"
|
api_endpoint: "https://gosms.one/api/v3/sms/send"
|
||||||
authorization: "CVZgh3iIAQpJuvaakQmxOo9q2uOb7Veqs7ls5KIX263d87ee"
|
authorization: "CVZgh3iIAQpJuvaakQmxOo9q2uOb7Veqs7ls5KIX263d87ee"
|
||||||
|
InnoPaas:
|
||||||
|
url: "http://intapi.sgap.253.com"
|
||||||
|
apiKey: "OI1706483"
|
||||||
|
password: "N4R84hhVvP6505"
|
||||||
|
|
||||||
#UDun 配置
|
#UDun 配置
|
||||||
UDunConfig:
|
UDunConfig:
|
||||||
|
|||||||
@ -739,7 +739,7 @@ func processTakeProfitAndStopLossOrders(db *gorm.DB, preOrder *models.LinePreOrd
|
|||||||
for _, order := range orders {
|
for _, order := range orders {
|
||||||
order.Num = num.String()
|
order.Num = num.String()
|
||||||
|
|
||||||
if fist && order.OrderCategory == 1 && order.OrderType == 1 && orderExt.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 && orderExt.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) != 0 {
|
if fist && (order.OrderCategory == 3 || order.OrderCategory == 1) && order.OrderType == 1 && orderExt.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 && orderExt.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) != 0 {
|
||||||
//主单第一次且止盈数量不是100% 止盈数量
|
//主单第一次且止盈数量不是100% 止盈数量
|
||||||
order.Num = num.Mul(orderExt.TakeProfitNumRatio.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit)).String()
|
order.Num = num.Mul(orderExt.TakeProfitNumRatio.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit)).String()
|
||||||
}
|
}
|
||||||
@ -761,7 +761,7 @@ func processTakeProfitAndStopLossOrders(db *gorm.DB, preOrder *models.LinePreOrd
|
|||||||
order.Rate = percentag.String()
|
order.Rate = percentag.String()
|
||||||
percentag = percentag.Div(decimal.NewFromInt(100))
|
percentag = percentag.Div(decimal.NewFromInt(100))
|
||||||
order.Price = price.Mul(decimal.NewFromInt(1).Add(percentag)).Truncate(int32(tradeSet.PriceDigit)).String()
|
order.Price = price.Mul(decimal.NewFromInt(1).Add(percentag)).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||||
} else if orderExt.Id > 0 {
|
} else if !fist && orderExt.TpTpPriceRatio.Cmp(decimal.Zero) > 0 {
|
||||||
percentag := orderExt.TpTpPriceRatio
|
percentag := orderExt.TpTpPriceRatio
|
||||||
order.Rate = percentag.String()
|
order.Rate = percentag.String()
|
||||||
order.Price = price.Mul(decimal.NewFromInt(1).Add(percentag.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String()
|
order.Price = price.Mul(decimal.NewFromInt(1).Add(percentag.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String()
|
||||||
|
|||||||
76
services/smsservice/gotone_service.go
Normal file
76
services/smsservice/gotone_service.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package smsservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
statuscode "go-admin/common/status_code"
|
||||||
|
"go-admin/config"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/bytedance/sonic"
|
||||||
|
"github.com/go-admin-team/go-admin-core/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GotoneService struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *GotoneService) SendSMS(area, phonenumber string, content string) int {
|
||||||
|
type SmsRequest struct {
|
||||||
|
Recipient string `json:"recipient"` // 收件人电话号码
|
||||||
|
Message string `json:"message"` // 短信内容
|
||||||
|
SenderId string `json:"sender_id"` // 发送者名称
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
// 创建请求数据
|
||||||
|
smsRequest := SmsRequest{
|
||||||
|
Recipient: "+" + area + phonenumber,
|
||||||
|
SenderId: config.ExtConfig.GoToneSmsConfig.SenderId,
|
||||||
|
Message: fmt.Sprintf("欢迎使用 GoTone SMS,高速稳定地发送短信至中国大陆及全球用户,体验验证码:%s。如非本人操作请忽略此信息", content),
|
||||||
|
Type: "plain",
|
||||||
|
}
|
||||||
|
// 将请求数据编码为 JSON
|
||||||
|
requestBody, err := sonic.Marshal(smsRequest)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("GoToneSms requestBody Error:", err)
|
||||||
|
return statuscode.ServerError
|
||||||
|
}
|
||||||
|
// 创建 HTTP 请求
|
||||||
|
req, err := http.NewRequest("POST", config.ExtConfig.GoToneSmsConfig.APIEndpoint, bytes.NewBuffer(requestBody))
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("GoToneSms http.NewRequest Error:", err)
|
||||||
|
return statuscode.ServerError
|
||||||
|
}
|
||||||
|
// 设置请求头
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("Authorization", "Bearer "+config.ExtConfig.GoToneSmsConfig.Authorization) // 使用 API 密钥进行身份验证
|
||||||
|
|
||||||
|
// 创建 HTTP 客户端并发送请求
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: 10 * time.Second, // 设置请求超时时间
|
||||||
|
}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
fmt.Println("resp:", resp)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("GoToneSms do NewRequest Error:", err)
|
||||||
|
return statuscode.CaptchaFailInSend
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// 检查响应状态
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
logger.Error("GoToneSms do NewRequest Error:", err)
|
||||||
|
return statuscode.CaptchaFailInSend
|
||||||
|
}
|
||||||
|
// 读取响应体
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("读取响应体失败:", err)
|
||||||
|
fmt.Printf("响应体: %s", string(body))
|
||||||
|
return statuscode.CaptchaFailInSend
|
||||||
|
//return fmt.Errorf("读取响应体失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return statuscode.OK
|
||||||
|
}
|
||||||
44
services/smsservice/innopass_service.go
Normal file
44
services/smsservice/innopass_service.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package smsservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
statuscode "go-admin/common/status_code"
|
||||||
|
"go-admin/config"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bytedance/sonic"
|
||||||
|
"github.com/go-admin-team/go-admin-core/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type InnopaasService struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *InnopaasService) SendSMS(area, phoneNumber string, message string) int {
|
||||||
|
// Implement the logic to send SMS using Innopass API
|
||||||
|
params := map[string]string{
|
||||||
|
"account": config.ExtConfig.InnoPaas.ApiKey,
|
||||||
|
"password": config.ExtConfig.InnoPaas.Password,
|
||||||
|
"mobile": area + phoneNumber,
|
||||||
|
"msg": message,
|
||||||
|
}
|
||||||
|
payload, _ := sonic.MarshalString(params) // strings.NewReader("{\"account\":\"I7145744\",\"password\":\"password\",\"mobile\":\"0012012074149,0012012074142\",\"msg\":\"Your verification code is 8888\"}")
|
||||||
|
|
||||||
|
req, _ := http.NewRequest("POST", config.ExtConfig.InnoPaas.Url, strings.NewReader(payload))
|
||||||
|
|
||||||
|
req.Header.Add("accept", "application/json")
|
||||||
|
req.Header.Add("content-type", "application/json")
|
||||||
|
|
||||||
|
res, _ := http.DefaultClient.Do(req)
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
body, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("读取响应体失败:", err)
|
||||||
|
fmt.Printf("响应体: %s", string(body))
|
||||||
|
return statuscode.CaptchaFailInSend
|
||||||
|
//return fmt.Errorf("读取响应体失败: %v", err)
|
||||||
|
}
|
||||||
|
return statuscode.OK
|
||||||
|
}
|
||||||
13
services/smsservice/sms_service.go
Normal file
13
services/smsservice/sms_service.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package smsservice
|
||||||
|
|
||||||
|
type SMSService interface {
|
||||||
|
// SendSMS 发送短信
|
||||||
|
// area 区号
|
||||||
|
// phoneNumber 手机号
|
||||||
|
// message 短信内容
|
||||||
|
SendSMS(area, phoneNumber string, message string) int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSMSService() SMSService {
|
||||||
|
return &GotoneService{}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user