1、确认提现

This commit is contained in:
2025-02-25 18:34:20 +08:00
parent 32ba6262cc
commit 3f85158eed
12 changed files with 364 additions and 83 deletions

View File

@ -1,7 +1,7 @@
package apis
import (
"fmt"
"fmt"
"github.com/gin-gonic/gin"
"github.com/go-admin-team/go-admin-core/sdk/api"
@ -30,18 +30,18 @@ type MemberWithdrawalLog struct {
// @Router /api/v1/member-withdrawal-log [get]
// @Security Bearer
func (e MemberWithdrawalLog) GetPage(c *gin.Context) {
req := dto.MemberWithdrawalLogGetPageReq{}
s := service.MemberWithdrawalLog{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
req := dto.MemberWithdrawalLogGetPageReq{}
s := service.MemberWithdrawalLog{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
p := actions.GetPermissionFromContext(c)
list := make([]models.MemberWithdrawalLog, 0)
@ -50,7 +50,7 @@ func (e MemberWithdrawalLog) GetPage(c *gin.Context) {
err = s.GetPage(&req, p, &list, &count)
if err != nil {
e.Error(500, err, fmt.Sprintf("获取用户提现记录失败,\r\n失败信息 %s", err.Error()))
return
return
}
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
@ -67,7 +67,7 @@ func (e MemberWithdrawalLog) GetPage(c *gin.Context) {
func (e MemberWithdrawalLog) Get(c *gin.Context) {
req := dto.MemberWithdrawalLogGetReq{}
s := service.MemberWithdrawalLog{}
err := e.MakeContext(c).
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
@ -83,10 +83,10 @@ func (e MemberWithdrawalLog) Get(c *gin.Context) {
err = s.Get(&req, p, &object)
if err != nil {
e.Error(500, err, fmt.Sprintf("获取用户提现记录失败,\r\n失败信息 %s", err.Error()))
return
return
}
e.OK( object, "查询成功")
e.OK(object, "查询成功")
}
// Insert 创建用户提现记录
@ -100,25 +100,25 @@ func (e MemberWithdrawalLog) Get(c *gin.Context) {
// @Router /api/v1/member-withdrawal-log [post]
// @Security Bearer
func (e MemberWithdrawalLog) Insert(c *gin.Context) {
req := dto.MemberWithdrawalLogInsertReq{}
s := service.MemberWithdrawalLog{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
req := dto.MemberWithdrawalLogInsertReq{}
s := service.MemberWithdrawalLog{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
// 设置创建人
req.SetCreateBy(user.GetUserId(c))
err = s.Insert(&req)
if err != nil {
e.Error(500, err, fmt.Sprintf("创建用户提现记录失败,\r\n失败信息 %s", err.Error()))
return
return
}
e.OK(req.GetId(), "创建成功")
@ -136,27 +136,27 @@ func (e MemberWithdrawalLog) Insert(c *gin.Context) {
// @Router /api/v1/member-withdrawal-log/{id} [put]
// @Security Bearer
func (e MemberWithdrawalLog) Update(c *gin.Context) {
req := dto.MemberWithdrawalLogUpdateReq{}
s := service.MemberWithdrawalLog{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
req := dto.MemberWithdrawalLogUpdateReq{}
s := service.MemberWithdrawalLog{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
req.SetUpdateBy(user.GetUserId(c))
p := actions.GetPermissionFromContext(c)
err = s.Update(&req, p)
if err != nil {
e.Error(500, err, fmt.Sprintf("修改用户提现记录失败,\r\n失败信息 %s", err.Error()))
return
return
}
e.OK( req.GetId(), "修改成功")
e.OK(req.GetId(), "修改成功")
}
// Delete 删除用户提现记录
@ -168,18 +168,18 @@ func (e MemberWithdrawalLog) Update(c *gin.Context) {
// @Router /api/v1/member-withdrawal-log [delete]
// @Security Bearer
func (e MemberWithdrawalLog) Delete(c *gin.Context) {
s := service.MemberWithdrawalLog{}
req := dto.MemberWithdrawalLogDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
s := service.MemberWithdrawalLog{}
req := dto.MemberWithdrawalLogDeleteReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
// req.SetUpdateBy(user.GetUserId(c))
p := actions.GetPermissionFromContext(c)
@ -187,7 +187,55 @@ func (e MemberWithdrawalLog) Delete(c *gin.Context) {
err = s.Remove(&req, p)
if err != nil {
e.Error(500, err, fmt.Sprintf("删除用户提现记录失败,\r\n失败信息 %s", err.Error()))
return
return
}
e.OK( req.GetId(), "删除成功")
e.OK(req.GetId(), "删除成功")
}
// 审核提现
func (e MemberWithdrawalLog) Process(c *gin.Context) {
s := service.MemberWithdrawalLog{}
req := dto.MemberWithdrawalLogApprovedReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
err = s.Process(&req)
if err != nil {
e.Error(500, err, fmt.Sprintf("审核提现失败,\r\n失败信息 %s", err.Error()))
return
}
e.OK(nil, "确认提现成功")
}
// 确认提现
func (e MemberWithdrawalLog) Confirm(c *gin.Context) {
s := service.MemberWithdrawalLog{}
req := dto.MemberWithdrawalLogConfirmReq{}
err := e.MakeContext(c).
MakeOrm().
Bind(&req).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(500, err, err.Error())
return
}
err = s.Confirm(&req)
if err != nil {
e.Error(500, err, fmt.Sprintf("确认到账失败,\r\n失败信息 %s", err.Error()))
return
}
e.OK(nil, "确认提现成功")
}

View File

@ -614,11 +614,23 @@ func (e LineUserApi) Logout(c *gin.Context) {
// 查询个人资产
func (e LineUserApi) GetProperty(c *gin.Context) {
s := service.LineUser{}
err := e.MakeContext(c).
MakeOrm().
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Error(statuscode.ServerError, nil, sysstatuscode.GetStatusCodeDescription(c, statuscode.ServerError))
}
var data dto.LineUserPropertyResp
userId := common.GetUserId(c)
code := s.GetProperty(userId, &data)
if code != statuscode.OK {
// e.Logger.Error(err)
e.Error(code, nil, sysstatuscode.GetStatusCodeDescription(c, code))
}
e.OK(data, "success")
}

View File

@ -34,6 +34,7 @@ func (e MemberWithdrawalLog) GetPage(c *gin.Context) {
var count int64
var list []dto.MemberWithdrawalLogResp
req.UserId = common.GetUserId(c)
code := s.GetPage(&req, &list, &count)
if code != statuscode.OK {

View File

@ -48,6 +48,8 @@ func frontedRegisterLinUserRouter(v1 *gin.RouterGroup) {
r.POST("/opStatus", middleware.FrontedAuth, api.OpenStatus) //开启或者关闭状态
r.DELETE("/logout", middleware.FrontedAuth, api.Logout) //退出登录
r.GET("/exchange-balance", middleware.FrontedAuth, api.GetProperty) //合约用户交易所u资产
//充值
r.POST("/notify", api.Notify) //uDun回调
r.POST("/rechargeNetworkList", middleware.FrontedAuth, api.RechargeNetworkList) //充值 通过充值币种选择主网络

View File

@ -344,3 +344,10 @@ type InviteLogResp struct {
NickName string `json:"nickName"`
Childs []InviteLogResp `json:"childs"`
}
type LineUserPropertyResp struct {
SpotTotalAmount decimal.Decimal `json:"spotTotalAmount"` //现货U总资产
SpotFreeAmount decimal.Decimal `json:"spotFreeAmount"` //现货U可用余额
FuturesTotalAmount decimal.Decimal `json:"futuresTotalAmount"` //合约U总资产
FuturesFreeAmount decimal.Decimal `json:"futuresFreeAmount"` //合约U可用余额
}

View File

@ -180,4 +180,17 @@ type MemberWithdrawalLogResp struct {
Status string `json:"status"`
CreateTimeUnix int64 `json:"createTime"`
ConfirmTimeUnix int64 `json:"confirmTime"`
Remark string `json:"remark"`
}
type MemberWithdrawalLogApprovedReq struct {
Id int `json:"id"`
Approval int `json:"approval"` // 1:通过 2:拒绝
Remark string `json:"remark" comment:"备注" `
}
type MemberWithdrawalLogConfirmReq struct {
Id int `json:"id"`
ConfirmVal int `json:"confirmVal"` // 1:成功 2:失败
Remark string `json:"remark"`
}

View File

@ -21,6 +21,7 @@ import (
"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"
"go.uber.org/zap"
@ -491,6 +492,7 @@ func (e *LineUser) PreOrder(userId int, req *dto.VtsRechargePreOrderReq, resp *d
return nil
}
// 模拟支付回调
func (e *LineUser) CallBack(req *coingatedto.OrderCallBackResponse) error {
token, err := aeshelper.PswEncrypt(fmt.Sprintf("%s:%s:%s", req.OrderID, utility.StringAsDecimal(req.PriceAmount), req.PriceCurrency))
@ -562,3 +564,21 @@ func (e *LineUser) CallBack(req *coingatedto.OrderCallBackResponse) error {
return err
}
// 获取用户资产
func (e *LineUser) GetProperty(userId int, data *dto.LineUserPropertyResp) int {
lineApiUser := models.LineApiUser{}
if err := e.Orm.Model(&lineApiUser).Where("user_id=?", userId).First(&lineApiUser).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return statuscode.UserApiUserNotBind
}
logger.Errorf("用户id %v 获取api用户失败:%v", userId, err)
return statuscode.ServerError
}
binanceservice.GetSpotUProperty(lineApiUser, data)
binanceservice.GetFuturesUProperty(lineApiUser, data)
return statuscode.OK
}

View File

@ -2,13 +2,15 @@ package service
import (
"errors"
"time"
"github.com/go-admin-team/go-admin-core/sdk/service"
"github.com/go-admin-team/go-admin-core/sdk/service"
"gorm.io/gorm"
"go-admin/app/admin/models"
"go-admin/app/admin/service/dto"
"go-admin/common/actions"
memberwithdrawallogstatus "go-admin/common/const/dicts/member_withdrawal_log_status"
cDto "go-admin/common/dto"
)
@ -59,9 +61,9 @@ func (e *MemberWithdrawalLog) Get(d *dto.MemberWithdrawalLogGetReq, p *actions.D
// Insert 创建MemberWithdrawalLog对象
func (e *MemberWithdrawalLog) Insert(c *dto.MemberWithdrawalLogInsertReq) error {
var err error
var data models.MemberWithdrawalLog
c.Generate(&data)
var err error
var data models.MemberWithdrawalLog
c.Generate(&data)
err = e.Orm.Create(&data).Error
if err != nil {
e.Log.Errorf("MemberWithdrawalLogService Insert error:%s \r\n", err)
@ -72,22 +74,22 @@ func (e *MemberWithdrawalLog) Insert(c *dto.MemberWithdrawalLogInsertReq) error
// Update 修改MemberWithdrawalLog对象
func (e *MemberWithdrawalLog) Update(c *dto.MemberWithdrawalLogUpdateReq, p *actions.DataPermission) error {
var err error
var data = models.MemberWithdrawalLog{}
e.Orm.Scopes(
actions.Permission(data.TableName(), p),
).First(&data, c.GetId())
c.Generate(&data)
var err error
var data = models.MemberWithdrawalLog{}
e.Orm.Scopes(
actions.Permission(data.TableName(), p),
).First(&data, c.GetId())
c.Generate(&data)
db := e.Orm.Save(&data)
if err = db.Error; err != nil {
e.Log.Errorf("MemberWithdrawalLogService Save error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权更新该数据")
}
return nil
db := e.Orm.Save(&data)
if err = db.Error; err != nil {
e.Log.Errorf("MemberWithdrawalLogService Save error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权更新该数据")
}
return nil
}
// Remove 删除MemberWithdrawalLog
@ -99,11 +101,69 @@ func (e *MemberWithdrawalLog) Remove(d *dto.MemberWithdrawalLogDeleteReq, p *act
actions.Permission(data.TableName(), p),
).Delete(&data, d.GetId())
if err := db.Error; err != nil {
e.Log.Errorf("Service RemoveMemberWithdrawalLog error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权删除该数据")
}
e.Log.Errorf("Service RemoveMemberWithdrawalLog error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权删除该数据")
}
return nil
}
// 审核
func (e *MemberWithdrawalLog) Process(req *dto.MemberWithdrawalLogApprovedReq) error {
data := models.MemberWithdrawalLog{}
if err := e.Orm.Model(&data).Where("id =?", req.Id).First(&data).Error; err != nil {
return err
}
if data.Status != memberwithdrawallogstatus.PENDING {
return errors.New("已审核请勿重复审核")
}
if req.Approval == 1 {
data.Status = memberwithdrawallogstatus.APPROVED
} else {
data.Status = memberwithdrawallogstatus.REJECTED
}
if err := e.Orm.Model(&data).
Where("status =?", memberwithdrawallogstatus.PENDING).
Updates(map[string]interface{}{"status": data.Status}).Error; err != nil {
return err
}
return nil
}
// 确认到账
func (e *MemberWithdrawalLog) Confirm(req *dto.MemberWithdrawalLogConfirmReq) error {
data := models.MemberWithdrawalLog{}
if err := e.Orm.Model(&data).Where("id =?", req.Id).First(&data).Error; err != nil {
return err
}
if data.Status != memberwithdrawallogstatus.APPROVED {
return errors.New("未审核请勿确认到账")
}
err := e.Orm.Transaction(func(tx *gorm.DB) error {
if err := e.Orm.Model(&data).
Where("status =?", memberwithdrawallogstatus.APPROVED).
Updates(map[string]interface{}{"status": data.Status, "confirm_time": time.Now()}).Error; err != nil {
return err
}
totalAmount := data.Amount.Add(data.Fee)
if err := tx.Exec("UPDATE member_balance set total_amount=total_amount-?,frozen_amount=frozen_amount-? where user_id=? and total_amount>=? and frozen_amount>=?", totalAmount, totalAmount, data.UserId, totalAmount, totalAmount).Error; err != nil {
return err
}
return nil
})
return err
}

View File

@ -8,4 +8,5 @@ const (
NetworkUnAvailable // 网络不可用
CanNotCancel // 无法取消
RenwalConfigDisabled // 续费配置不可用
UserApiUserNotBind // 用户未授权
)

View File

@ -74,3 +74,25 @@ type BinanceFutureOrder struct {
SelfTradePreventionMode string `json:"selfTradePreventionMode"` // 订单自成交保护模式
GoodTillDate int64 `json:"goodTillDate"` // 订单TIF为GTD时的自动取消时间
}
type BinanceSpotAccount struct {
Balances []BinanceSpotBalance `json:"balances"`
}
type BinanceSpotBalance struct {
Asset string `json:"asset"`
Free string `json:"free"`
Locked string `json:"locked"`
}
type BinanceFutureBalance struct {
AccountAlias string `json:"accountAlias"` // 账户唯一识别码
Asset string `json:"asset"` // 资产
Balance string `json:"balance"` // 总余额
CrossWalletBalance string `json:"crossWalletBalance"` // 全仓余额
CrossUnPnl string `json:"crossUnPnl"` // 全仓持仓未实现盈亏
AvailableBalance string `json:"availableBalance"` // 下单可用余额
MaxWithdrawAmount string `json:"maxWithdrawAmount"` // 最大可转出余额
MarginAvailable bool `json:"marginAvailable"` // 是否可用作联合保证金
UpdateTime int64 `json:"updateTime"` // 更新时间(时间戳)
}

View File

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
DbModels "go-admin/app/admin/models"
"go-admin/app/admin/service/dto"
"go-admin/common/const/rediskey"
commondto "go-admin/common/dto"
"go-admin/common/global"
@ -588,3 +589,51 @@ func (e SpotRestApi) GetOrderByOrderSnLoop(symbol, ordersn string, apiUserInfo D
return result, err
}
// 获取现货U资产
func GetSpotUProperty(apiUserInfo DbModels.LineApiUser, data *dto.LineUserPropertyResp) error {
endpoint := "/api/v3/account"
params := map[string]string{
"omitZeroBalances": "true",
}
balanceResp := binancedto.BinanceSpotAccount{}
client := GetClient(&apiUserInfo)
body, code, err := client.SendSpotAuth(endpoint, "GET", params)
if err != nil || code != 200 {
log.Error("查询现货资产 参数:", params)
log.Error("查询现货资产 code:", code)
log.Error("查询现货资产 err:", err)
dataMap := make(map[string]interface{})
if err.Error() != "" {
if err := sonic.Unmarshal([]byte(err.Error()), &dataMap); err != nil {
return fmt.Errorf("api_id:%d 查询资产失败:%+v", apiUserInfo.Id, err.Error())
}
}
code, ok := dataMap["code"]
if ok {
return fmt.Errorf("api_id:%d 查询资产失败:%s", apiUserInfo.Id, ErrorMaps[code.(float64)])
}
if strings.Contains(err.Error(), "Unknown order sent.") {
return fmt.Errorf("api_id:%d 查询资产失败:%+v", apiUserInfo.Id, ErrorMaps[-2011])
}
return fmt.Errorf("api_id:%d 查询资产失败:%+v", apiUserInfo.Id, err.Error())
}
sonic.Unmarshal(body, &balanceResp)
if len(balanceResp.Balances) > 0 {
for _, item := range balanceResp.Balances {
if strings.ToUpper(item.Asset) == "USDT" {
free := utility.StrToDecimal(item.Free)
lock := utility.StrToDecimal(item.Locked)
data.SpotFreeAmount = utility.StrToDecimal(item.Free)
data.SpotTotalAmount = free.Add(lock)
}
}
}
return nil
}

View File

@ -1000,3 +1000,49 @@ func (e FutRestApi) GetOrderByOrderSnLoop(symbol, ordersn string, apiUserInfo Db
return result, err
}
// 获取合约U资产
func GetFuturesUProperty(apiUserInfo DbModels.LineApiUser, data *dto.LineUserPropertyResp) error {
endpoint := "/fapi/v3/balance"
params := map[string]string{
"recvWindow": "5000",
}
balanceResp := make([]binancedto.BinanceFutureBalance, 0)
client := GetClient(&apiUserInfo)
body, code, err := client.SendFuturesAuth(endpoint, "GET", params)
if err != nil || code != 200 {
log.Error("查询合约资产 参数:", params)
log.Error("查询合约资产 code:", code)
log.Error("查询合约资产 err:", err)
dataMap := make(map[string]interface{})
if err.Error() != "" {
if err := sonic.Unmarshal([]byte(err.Error()), &dataMap); err != nil {
return fmt.Errorf("api_id:%d 查询资产失败:%+v", apiUserInfo.Id, err.Error())
}
}
code, ok := dataMap["code"]
if ok {
return fmt.Errorf("api_id:%d 查询资产失败:%s", apiUserInfo.Id, ErrorMaps[code.(float64)])
}
if strings.Contains(err.Error(), "Unknown order sent.") {
return fmt.Errorf("api_id:%d 查询资产失败:%+v", apiUserInfo.Id, ErrorMaps[-2011])
}
return fmt.Errorf("api_id:%d 查询资产失败:%+v", apiUserInfo.Id, err.Error())
}
sonic.Unmarshal(body, &balanceResp)
for _, v := range balanceResp {
if v.Asset == "USDT" {
free := utility.StrToDecimal(v.AvailableBalance)
data.FuturesFreeAmount = free
data.FuturesTotalAmount = utility.StrToDecimal(v.Balance)
}
}
return nil
}