1、在线支付
Some checks failed
Build / build (push) Has been cancelled
CodeQL / Analyze (go) (push) Has been cancelled
build / Build (push) Has been cancelled
GitHub Actions Mirror / mirror_to_gitee (push) Has been cancelled
GitHub Actions Mirror / mirror_to_gitlab (push) Has been cancelled
Issue Close Require / issue-close-require (push) Has been cancelled
Some checks failed
Build / build (push) Has been cancelled
CodeQL / Analyze (go) (push) Has been cancelled
build / Build (push) Has been cancelled
GitHub Actions Mirror / mirror_to_gitee (push) Has been cancelled
GitHub Actions Mirror / mirror_to_gitlab (push) Has been cancelled
Issue Close Require / issue-close-require (push) Has been cancelled
2、查询平台剩余字符数
This commit is contained in:
@ -116,6 +116,12 @@ func (e TmPlatform) Insert(c *gin.Context) {
|
|||||||
e.Error(500, err, err.Error())
|
e.Error(500, err, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err1 := req.Validate(); err1 != nil {
|
||||||
|
e.Error(500, err1, err1.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 设置创建人
|
// 设置创建人
|
||||||
req.SetCreateBy(user.GetUserId(c))
|
req.SetCreateBy(user.GetUserId(c))
|
||||||
|
|
||||||
@ -152,6 +158,12 @@ func (e TmPlatform) Update(c *gin.Context) {
|
|||||||
e.Error(500, err, err.Error())
|
e.Error(500, err, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err1 := req.Validate(); err1 != nil {
|
||||||
|
e.Error(500, err1, err1.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
req.SetUpdateBy(user.GetUserId(c))
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
p := actions.GetPermissionFromContext(c)
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
|
||||||
|
|||||||
@ -190,3 +190,28 @@ func (e TmPlatformAccount) Delete(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
e.OK(req.GetId(), "删除成功")
|
e.OK(req.GetId(), "删除成功")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkRemain 查询剩余翻译条数
|
||||||
|
func (e TmPlatformAccount) QueryRemain(c *gin.Context) {
|
||||||
|
req := dto.TmPlatformAccountQueryRemainReq{}
|
||||||
|
s := service.TmPlatformAccount{}
|
||||||
|
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)
|
||||||
|
err = s.QueryRemain(&req, p)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, fmt.Sprintf("查询剩余翻译条数失败,\r\n失败信息 %s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(nil, "查询成功")
|
||||||
|
}
|
||||||
|
|||||||
@ -60,19 +60,22 @@ func (e TmRechargeLog) CreateOrder(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userId := user.GetUserId(c)
|
||||||
apiKey := c.GetString("apiKey")
|
apiKey := c.GetString("apiKey")
|
||||||
|
|
||||||
if code := req.Validate(); code != statuscode.Success {
|
if code := req.Validate(); code != statuscode.Success {
|
||||||
e.Error(code, nil, statuscode.ErrorMessage[code])
|
e.Error(code, nil, statuscode.ErrorMessage[code])
|
||||||
}
|
}
|
||||||
|
|
||||||
code := s.CreateOrder(&req, apiKey)
|
req.UserId = userId
|
||||||
|
resp := dto.CustomCreateOrderResp{}
|
||||||
|
code := s.CreateOrder(&req, &resp, apiKey)
|
||||||
if code != statuscode.Success {
|
if code != statuscode.Success {
|
||||||
e.OK(code, statuscode.ErrorMessage[code])
|
e.Error(code, nil, statuscode.ErrorMessage[code])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
e.OK(nil, "success")
|
e.OK(resp, "success")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 后台充值
|
// 后台充值
|
||||||
@ -107,6 +110,29 @@ func (e TmRechargeLog) ManagerRecharge(c *gin.Context) {
|
|||||||
e.OK(nil, "充值成功")
|
e.OK(nil, "充值成功")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 后台扣除
|
||||||
|
func (e TmRechargeLog) ManagerDeduct(c *gin.Context) {
|
||||||
|
s := service.TmRechargeLog{}
|
||||||
|
req := dto.TmRechargeManageDeductReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.ManagerDeduct(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(nil, "扣除成功")
|
||||||
|
}
|
||||||
|
|
||||||
// 获取即将过期充值记录
|
// 获取即将过期充值记录
|
||||||
func (e TmMember) GetMemberAdvent(c *gin.Context) {
|
func (e TmMember) GetMemberAdvent(c *gin.Context) {
|
||||||
s := service.TmRechargeLog{}
|
s := service.TmRechargeLog{}
|
||||||
|
|||||||
@ -42,7 +42,7 @@ func (e Translate) Translate(c *gin.Context) {
|
|||||||
|
|
||||||
if code != statuscode.Success {
|
if code != statuscode.Success {
|
||||||
e.Logger.Error(err)
|
e.Logger.Error(err)
|
||||||
e.OK(code, statuscode.ErrorMessage[code])
|
e.Error(code, nil, statuscode.ErrorMessage[code])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,13 +9,15 @@ import (
|
|||||||
type TmPlatform struct {
|
type TmPlatform struct {
|
||||||
models.Model
|
models.Model
|
||||||
|
|
||||||
Name string `json:"name" gorm:"type:varchar(20);comment:平台名称"`
|
Name string `json:"name" gorm:"type:varchar(20);comment:平台名称"`
|
||||||
ShowName string `json:"showName" gorm:"type:varchar(20);comment:展示名称"`
|
ShowName string `json:"showName" gorm:"type:varchar(20);comment:展示名称"`
|
||||||
ApiBaseUrl string `json:"apiBaseUrl" gorm:"type:varchar(500);comment:平台接口地址"`
|
ApiBaseUrl string `json:"apiBaseUrl" gorm:"type:varchar(500);comment:平台接口地址"`
|
||||||
Description string `json:"description" gorm:"type:varchar(255);comment:描述"`
|
Description string `json:"description" gorm:"type:varchar(255);comment:描述"`
|
||||||
Code string `json:"code" gorm:"type:varchar(20);comment:平台编码(字典 tm_platform)"`
|
Code string `json:"code" gorm:"type:varchar(20);comment:平台编码(字典 tm_platform)"`
|
||||||
Character int `json:"character" gorm:"type:int;comment:字符数"`
|
Character int `json:"character" gorm:"type:int;comment:字符数"`
|
||||||
Price decimal.Decimal `json:"price" gorm:"type:decimal(10,2);comment:单价"`
|
Price decimal.Decimal `json:"price" gorm:"type:decimal(10,2);comment:单价"`
|
||||||
|
BlockChain string `json:"blockChain" gorm:"type:varchar(20);comment:区块链(全小写)"`
|
||||||
|
ReceiveAddress string `json:"receiveAddress" gorm:"type:varchar(100);comment:接收地址"`
|
||||||
models.ModelTime
|
models.ModelTime
|
||||||
models.ControlBy
|
models.ControlBy
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,8 +26,9 @@ func registerTmMemberRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddl
|
|||||||
r.DELETE("", api.Delete)
|
r.DELETE("", api.Delete)
|
||||||
|
|
||||||
// r.POST("recharge", actions.PermissionAction(), api.Recharge) //字符充值
|
// r.POST("recharge", actions.PermissionAction(), api.Recharge) //字符充值
|
||||||
r.POST("manager-recharge", actions.PermissionAction(), rechargeApi.ManagerRecharge)
|
r.POST("manager-recharge", actions.PermissionAction(), rechargeApi.ManagerRecharge) //手动充值
|
||||||
r.PUT("status", actions.PermissionAction(), api.ChangeStatus) //状态变更
|
r.PUT("manager-deduct", actions.PermissionAction(), rechargeApi.ManagerDeduct) //手动扣除
|
||||||
|
r.PUT("status", actions.PermissionAction(), api.ChangeStatus) //状态变更
|
||||||
}
|
}
|
||||||
|
|
||||||
r2 := v1.Group("/tm-member").Use(authMiddleware.MiddlewareFunc())
|
r2 := v1.Group("/tm-member").Use(authMiddleware.MiddlewareFunc())
|
||||||
@ -35,5 +36,7 @@ func registerTmMemberRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddl
|
|||||||
r2.GET("/api-key", api.GetMyApiKey)
|
r2.GET("/api-key", api.GetMyApiKey)
|
||||||
r2.GET("platforms", api.GetPlatforms)
|
r2.GET("platforms", api.GetPlatforms)
|
||||||
r2.GET("member-advent", api.GetMemberAdvent) //获取用户即将过期的充值信息
|
r2.GET("member-advent", api.GetMemberAdvent) //获取用户即将过期的充值信息
|
||||||
|
|
||||||
|
r2.POST("recharge", rechargeApi.CreateOrder) //用户发起充值
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,8 @@ import (
|
|||||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
||||||
|
|
||||||
"go-admin/app/admin/apis"
|
"go-admin/app/admin/apis"
|
||||||
"go-admin/common/middleware"
|
|
||||||
"go-admin/common/actions"
|
"go-admin/common/actions"
|
||||||
|
"go-admin/common/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -23,5 +23,7 @@ func registerTmPlatformAccountRouter(v1 *gin.RouterGroup, authMiddleware *jwt.Gi
|
|||||||
r.POST("", api.Insert)
|
r.POST("", api.Insert)
|
||||||
r.PUT("/:id", actions.PermissionAction(), api.Update)
|
r.PUT("/:id", actions.PermissionAction(), api.Update)
|
||||||
r.DELETE("", api.Delete)
|
r.DELETE("", api.Delete)
|
||||||
|
|
||||||
|
r.PUT("query-remain/:id", actions.PermissionAction(), api.QueryRemain) //查询平台剩余字符
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,9 +1,11 @@
|
|||||||
package dto
|
package dto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"go-admin/app/admin/models"
|
"go-admin/app/admin/models"
|
||||||
"go-admin/common/dto"
|
"go-admin/common/dto"
|
||||||
common "go-admin/common/models"
|
common "go-admin/common/models"
|
||||||
|
"go-admin/utils/chainhelper"
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
)
|
)
|
||||||
@ -40,17 +42,43 @@ func (m *TmPlatformGetPageReq) GetNeedSearch() interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TmPlatformInsertReq struct {
|
type TmPlatformInsertReq struct {
|
||||||
Id int `json:"-" comment:"平台id"` // 平台id
|
Id int `json:"-" comment:"平台id"` // 平台id
|
||||||
Name string `json:"name" comment:"平台名称"`
|
Name string `json:"name" comment:"平台名称"`
|
||||||
ShowName string `json:"showName" comment:"展示名称"`
|
ShowName string `json:"showName" comment:"展示名称"`
|
||||||
ApiBaseUrl string `json:"apiBaseUrl" comment:"平台接口地址"`
|
ApiBaseUrl string `json:"apiBaseUrl" comment:"平台接口地址"`
|
||||||
Description string `json:"description" comment:"描述"`
|
Description string `json:"description" comment:"描述"`
|
||||||
Code string `json:"code" comment:"平台编码(字典 tm_platform)"`
|
Code string `json:"code" comment:"平台编码(字典 tm_platform)"`
|
||||||
Character int `json:"character" comment:"字符数"`
|
Character int `json:"character" comment:"字符数"`
|
||||||
Price decimal.Decimal `json:"price" comment:"单价"`
|
Price decimal.Decimal `json:"price" comment:"单价"`
|
||||||
|
BlockChain string `json:"blockChain" comment:"链区块"`
|
||||||
|
ReceiveAddress string `json:"receiveAddress" comment:"接收地址"`
|
||||||
common.ControlBy
|
common.ControlBy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TmPlatformInsertReq) Validate() error {
|
||||||
|
if s.BlockChain == "" {
|
||||||
|
return errors.New("收款区块不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.ReceiveAddress == "" {
|
||||||
|
return errors.New("接收地址不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Name == "" {
|
||||||
|
return errors.New("平台名称不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.ShowName == "" {
|
||||||
|
return errors.New("展示名称不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Code == "" {
|
||||||
|
return errors.New("平台编码不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
return chainhelper.JudgeChainAddress(s.BlockChain, s.ReceiveAddress)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TmPlatformInsertReq) Generate(model *models.TmPlatform) {
|
func (s *TmPlatformInsertReq) Generate(model *models.TmPlatform) {
|
||||||
if s.Id == 0 {
|
if s.Id == 0 {
|
||||||
model.Model = common.Model{Id: s.Id}
|
model.Model = common.Model{Id: s.Id}
|
||||||
@ -63,6 +91,8 @@ func (s *TmPlatformInsertReq) Generate(model *models.TmPlatform) {
|
|||||||
model.Character = s.Character
|
model.Character = s.Character
|
||||||
model.Price = s.Price
|
model.Price = s.Price
|
||||||
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
|
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
|
||||||
|
model.BlockChain = s.BlockChain
|
||||||
|
model.ReceiveAddress = s.ReceiveAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TmPlatformInsertReq) GetId() interface{} {
|
func (s *TmPlatformInsertReq) GetId() interface{} {
|
||||||
@ -77,17 +107,43 @@ type TmPlatformListResp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TmPlatformUpdateReq struct {
|
type TmPlatformUpdateReq struct {
|
||||||
Id int `uri:"id" comment:"平台id"` // 平台id
|
Id int `uri:"id" comment:"平台id"` // 平台id
|
||||||
Name string `json:"name" comment:"平台名称"`
|
Name string `json:"name" comment:"平台名称"`
|
||||||
ShowName string `json:"showName" comment:"展示名称"`
|
ShowName string `json:"showName" comment:"展示名称"`
|
||||||
ApiBaseUrl string `json:"apiBaseUrl" comment:"平台接口地址"`
|
ApiBaseUrl string `json:"apiBaseUrl" comment:"平台接口地址"`
|
||||||
Description string `json:"description" comment:"描述"`
|
Description string `json:"description" comment:"描述"`
|
||||||
Code string `json:"code" comment:"平台编码(字典 tm_platform)"`
|
Code string `json:"code" comment:"平台编码(字典 tm_platform)"`
|
||||||
Character int `json:"character" comment:"字符数"`
|
Character int `json:"character" comment:"字符数"`
|
||||||
Price decimal.Decimal `json:"price" comment:"单价"`
|
Price decimal.Decimal `json:"price" comment:"单价"`
|
||||||
|
BlockChain string `json:"blockChain" comment:"链区块"`
|
||||||
|
ReceiveAddress string `json:"receiveAddress" comment:"接收地址"`
|
||||||
common.ControlBy
|
common.ControlBy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TmPlatformUpdateReq) Validate() error {
|
||||||
|
if s.BlockChain == "" {
|
||||||
|
return errors.New("收款区块不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.ReceiveAddress == "" {
|
||||||
|
return errors.New("接收地址不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Name == "" {
|
||||||
|
return errors.New("平台名称不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.ShowName == "" {
|
||||||
|
return errors.New("展示名称不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Code == "" {
|
||||||
|
return errors.New("平台编码不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
return chainhelper.JudgeChainAddress(s.BlockChain, s.ReceiveAddress)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TmPlatformUpdateReq) Generate(model *models.TmPlatform) {
|
func (s *TmPlatformUpdateReq) Generate(model *models.TmPlatform) {
|
||||||
if s.Id == 0 {
|
if s.Id == 0 {
|
||||||
model.Model = common.Model{Id: s.Id}
|
model.Model = common.Model{Id: s.Id}
|
||||||
@ -100,6 +156,8 @@ func (s *TmPlatformUpdateReq) Generate(model *models.TmPlatform) {
|
|||||||
model.Character = s.Character
|
model.Character = s.Character
|
||||||
model.Price = s.Price
|
model.Price = s.Price
|
||||||
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
|
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
|
||||||
|
model.BlockChain = s.BlockChain
|
||||||
|
model.ReceiveAddress = s.ReceiveAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TmPlatformUpdateReq) GetId() interface{} {
|
func (s *TmPlatformUpdateReq) GetId() interface{} {
|
||||||
|
|||||||
@ -95,3 +95,7 @@ type TmPlatformAccountDeleteReq struct {
|
|||||||
func (s *TmPlatformAccountDeleteReq) GetId() interface{} {
|
func (s *TmPlatformAccountDeleteReq) GetId() interface{} {
|
||||||
return s.Ids
|
return s.Ids
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TmPlatformAccountQueryRemainReq struct {
|
||||||
|
Id int `uri:"id"`
|
||||||
|
}
|
||||||
|
|||||||
@ -109,16 +109,45 @@ type TmRechargeCreateOrderReq struct {
|
|||||||
common.ControlBy
|
common.ControlBy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 后台扣除字符
|
||||||
|
type TmRechargeManageDeductReq struct {
|
||||||
|
MemberId int `json:"memberId" comment:"会员id"`
|
||||||
|
UserId int `json:"userId" comment:"用户id"`
|
||||||
|
PlatformId int `json:"platformId" comment:"平台id"`
|
||||||
|
TotalChars decimal.Decimal `json:"totalChars" comment:"扣减字符"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *TmRechargeManageDeductReq) Generate(entity *models.TmRechargeLog) error {
|
||||||
|
if entity == nil {
|
||||||
|
entity = &models.TmRechargeLog{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.MemberId <= 0 {
|
||||||
|
return errors.New("会员不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.PlatformId <= 0 {
|
||||||
|
return errors.New("平台不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.MemberId = e.MemberId
|
||||||
|
entity.UserId = e.UserId
|
||||||
|
entity.PlatformId = e.PlatformId
|
||||||
|
entity.Type = 3
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// 用户充值订单创建请求参数
|
// 用户充值订单创建请求参数
|
||||||
type CustomCreateOrderReq struct {
|
type CustomCreateOrderReq struct {
|
||||||
UserId int `json:"userId" comment:"用户id"`
|
UserId int `json:"userId" comment:"用户id"`
|
||||||
Amount decimal.Decimal `json:"amount" comment:"充值金额"`
|
PlatformId int `json:"platformId" comment:"平台id"`
|
||||||
PlatformId int `json:"platformId" comment:"平台id"`
|
Count int `json:"count" comment:"购买数量"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *CustomCreateOrderReq) Validate() int {
|
func (e *CustomCreateOrderReq) Validate() int {
|
||||||
if e.Amount.Cmp(decimal.Zero) <= 0 {
|
if e.Count <= 0 {
|
||||||
return statuscode.RechargeAmountMustBeGreaterThanZero
|
return statuscode.RechargeNumberMustBeGreaterThanZero
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.PlatformId <= 0 {
|
if e.PlatformId <= 0 {
|
||||||
@ -128,6 +157,14 @@ func (e *CustomCreateOrderReq) Validate() int {
|
|||||||
return statuscode.Success
|
return statuscode.Success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CustomCreateOrderResp struct {
|
||||||
|
OrderNo string `json:"orderNo"`
|
||||||
|
Amount string `json:"amount"`
|
||||||
|
BlockChain string `json:"blockChain"`
|
||||||
|
ReceiveAddress string `json:"receiveAddress"`
|
||||||
|
ExpireUnix int64 `json:"expireUnix" comment:"过期时间戳 秒"`
|
||||||
|
}
|
||||||
|
|
||||||
func (e *TmRechargeCreateOrderReq) Validate() error {
|
func (e *TmRechargeCreateOrderReq) Validate() error {
|
||||||
if e.ExpireDays <= 0 {
|
if e.ExpireDays <= 0 {
|
||||||
return errors.New("过期天数必须大于0")
|
return errors.New("过期天数必须大于0")
|
||||||
|
|||||||
@ -21,6 +21,106 @@ type TmPlatformAccount struct {
|
|||||||
service.Service
|
service.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e TmPlatformAccount) QueryRemain(req *dto.TmPlatformAccountQueryRemainReq, p *actions.DataPermission) error {
|
||||||
|
var entity models.TmPlatformAccount
|
||||||
|
err := e.Orm.Model(&entity).
|
||||||
|
Scopes(
|
||||||
|
actions.Permission(entity.TableName(), p),
|
||||||
|
).
|
||||||
|
First(&entity, req.Id).Error
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("查看对象不存在或无权查看")
|
||||||
|
}
|
||||||
|
|
||||||
|
platformService := TmPlatform{Service: e.Service}
|
||||||
|
|
||||||
|
platform, err := platformService.GetById(entity.PlatformId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
e.Log.Errorf("获取翻译平台消息失败 %v", err)
|
||||||
|
return errors.New("获取翻译平台消息失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
provider := map[string]interface{}{
|
||||||
|
entity.PlatformKey: map[string]interface{}{
|
||||||
|
"apiKey": entity.ApiKey,
|
||||||
|
"endpoint": platform.ApiBaseUrl,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
config := TranslatorServiceConfig{
|
||||||
|
DefaultProvider: "deepseek",
|
||||||
|
ProviderConfigs: provider,
|
||||||
|
}
|
||||||
|
|
||||||
|
translator, err := NewTranslatorService(&config)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
e.Log.Errorf("创建翻译服务失败 %v", err)
|
||||||
|
return errors.New("创建翻译服务失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
remainCount, err := translator.providers[entity.PlatformKey].GetRemainCount()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
e.Log.Errorf("获取翻译平台剩余字符失败 %v", err)
|
||||||
|
return errors.New("获取翻译平台剩余字符失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
if remainCount > 0 {
|
||||||
|
key := fmt.Sprintf(rediskey.TM_PLATEFORM_ACCOUNT_REMAIN_KEY, entity.PlatformKey, entity.ApiKey)
|
||||||
|
|
||||||
|
redishelper.DefaultRedis.SetString(key, strconv.Itoa(remainCount))
|
||||||
|
|
||||||
|
//如果为禁用则写入队列
|
||||||
|
if entity.Status == 2 {
|
||||||
|
listKey := fmt.Sprintf(rediskey.TM_PLATFORM_ACCOUNT_LIST_KEY, entity.PlatformKey)
|
||||||
|
vals, err := redishelper.DefaultRedis.GetAllList(listKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
e.Log.Errorf("获取redis列表失败 %v", err)
|
||||||
|
return errors.New("获取redis列表失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
item := models.TmPlatformAccount{}
|
||||||
|
hasData := false
|
||||||
|
|
||||||
|
for _, val := range vals {
|
||||||
|
sonic.UnmarshalString(val, &item)
|
||||||
|
|
||||||
|
if item.ApiKey == entity.ApiKey {
|
||||||
|
hasData = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasData {
|
||||||
|
entity.Status = 1
|
||||||
|
val, err := sonic.MarshalString(entity)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if err1 := redishelper.DefaultRedis.RPushList(listKey, val); err1 != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err1 := tx.Model(entity).Update("status", 1).Error; err1 != nil {
|
||||||
|
return err1
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetPage 获取TmPlatformAccount列表
|
// GetPage 获取TmPlatformAccount列表
|
||||||
func (e *TmPlatformAccount) GetPage(c *dto.TmPlatformAccountGetPageReq, p *actions.DataPermission, list *[]models.TmPlatformAccount, count *int64) error {
|
func (e *TmPlatformAccount) GetPage(c *dto.TmPlatformAccountGetPageReq, p *actions.DataPermission, list *[]models.TmPlatformAccount, count *int64) error {
|
||||||
var err error
|
var err error
|
||||||
@ -38,6 +138,18 @@ func (e *TmPlatformAccount) GetPage(c *dto.TmPlatformAccountGetPageReq, p *actio
|
|||||||
e.Log.Errorf("TmPlatformAccountService GetPage error:%s \r\n", err)
|
e.Log.Errorf("TmPlatformAccountService GetPage error:%s \r\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if list != nil {
|
||||||
|
for index, item := range *list {
|
||||||
|
keu := fmt.Sprintf(rediskey.TM_PLATEFORM_ACCOUNT_REMAIN_KEY, item.PlatformKey, item.ApiKey)
|
||||||
|
val, err := redishelper.DefaultRedis.GetString(keu)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
(*list)[index].RemainChars, _ = strconv.Atoi(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,8 +16,10 @@ import (
|
|||||||
"go-admin/utils/utility"
|
"go-admin/utils/utility"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/bytedance/sonic"
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/service"
|
"github.com/go-admin-team/go-admin-core/sdk/service"
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
@ -28,6 +30,26 @@ type TmRechargeLog struct {
|
|||||||
service.Service
|
service.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 清理过期订单
|
||||||
|
func (e TmRechargeLog) CleanExpiredOrder() error {
|
||||||
|
expireTime := time.Now().Add(5 * time.Minute)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
err := e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if err1 := tx.Model(&models.TmRechargeLog{}).Where("order_expire_time <? and status =1", expireTime).Updates(map[string]interface{}{"status": 6, "updated_at": time.Now()}).Error; err1 != nil {
|
||||||
|
return err1
|
||||||
|
}
|
||||||
|
|
||||||
|
if err1 := receiveaddressmanager.CleanExpiredAmountLocks(ctx, redishelper.DefaultRedis.GetClient()); err1 != nil {
|
||||||
|
return err1
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// 首页获取即将过期的数据
|
// 首页获取即将过期的数据
|
||||||
func (e *TmRechargeLog) GetMemberAdvent(req *dto.TmRechargeLogFrontReq, resp *[]dto.TmRechargeLogFrontResp, userId int) int {
|
func (e *TmRechargeLog) GetMemberAdvent(req *dto.TmRechargeLogFrontReq, resp *[]dto.TmRechargeLogFrontResp, userId int) int {
|
||||||
var datas []models.TmRechargeLog
|
var datas []models.TmRechargeLog
|
||||||
@ -68,7 +90,7 @@ func (e *TmRechargeLog) GetMemberAdvent(req *dto.TmRechargeLogFrontReq, resp *[]
|
|||||||
func (e *TmRechargeLog) ManagerRecharge(req *dto.TmRechargeCreateOrderReq, p *actions.DataPermission) error {
|
func (e *TmRechargeLog) ManagerRecharge(req *dto.TmRechargeCreateOrderReq, p *actions.DataPermission) error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
var data models.TmRechargeLog
|
var data models.TmRechargeLog
|
||||||
member, platform, memberPlatform, code := e.CreateOrderJudge(req)
|
member, platform, _, code := e.CreateOrderJudge(req.MemberId, req.PlatformId)
|
||||||
if code != statuscode.Success {
|
if code != statuscode.Success {
|
||||||
return errors.New(statuscode.ErrorMessage[code])
|
return errors.New(statuscode.ErrorMessage[code])
|
||||||
}
|
}
|
||||||
@ -79,6 +101,7 @@ func (e *TmRechargeLog) ManagerRecharge(req *dto.TmRechargeCreateOrderReq, p *ac
|
|||||||
data.Type = 2
|
data.Type = 2
|
||||||
data.Status = 2
|
data.Status = 2
|
||||||
data.UserId = member.UserId
|
data.UserId = member.UserId
|
||||||
|
data.MemberId = member.Id
|
||||||
data.ExpireAt = time.Now().AddDate(0, 0, req.ExpireDays)
|
data.ExpireAt = time.Now().AddDate(0, 0, req.ExpireDays)
|
||||||
data.PayTime = &now
|
data.PayTime = &now
|
||||||
|
|
||||||
@ -96,10 +119,10 @@ func (e *TmRechargeLog) ManagerRecharge(req *dto.TmRechargeCreateOrderReq, p *ac
|
|||||||
return err1
|
return err1
|
||||||
}
|
}
|
||||||
|
|
||||||
//更新用户翻译可用字符
|
// //更新用户翻译可用字符
|
||||||
if err1 := tx.Model(&models.TmMemberPlatform{}).Where("id =?", memberPlatform.Id).Update("remaining_character", data.TotalChars).Error; err1 != nil {
|
// if err1 := tx.Model(&models.TmMemberPlatform{}).Where("id =?", memberPlatform.Id).Update("remaining_character", data.TotalChars).Error; err1 != nil {
|
||||||
return err1
|
// return err1
|
||||||
}
|
// }
|
||||||
|
|
||||||
//写入可用字符
|
//写入可用字符
|
||||||
if err1 := qmgr.AddQuota(ctx, member.ApiKey, platform.Code, rechargeData); err1 != nil {
|
if err1 := qmgr.AddQuota(ctx, member.ApiKey, platform.Code, rechargeData); err1 != nil {
|
||||||
@ -112,11 +135,50 @@ func (e *TmRechargeLog) ManagerRecharge(req *dto.TmRechargeCreateOrderReq, p *ac
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 后台扣除字符
|
||||||
|
func (e *TmRechargeLog) ManagerDeduct(req *dto.TmRechargeManageDeductReq) error {
|
||||||
|
ctx := context.Background()
|
||||||
|
var data models.TmRechargeLog
|
||||||
|
|
||||||
|
member, platform, _, code := e.CreateOrderJudge(req.MemberId, req.PlatformId)
|
||||||
|
if code != statuscode.Success {
|
||||||
|
return errors.New(statuscode.ErrorMessage[code])
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Generate(&data)
|
||||||
|
now := time.Now()
|
||||||
|
data.OrderNo = utility.GenerateTraceID()
|
||||||
|
data.Status = 2
|
||||||
|
data.UserId = member.UserId
|
||||||
|
data.ExpireAt = time.Now().AddDate(0, 0, 30)
|
||||||
|
data.PayTime = &now
|
||||||
|
data.TotalChars = int(req.TotalChars.Mul(decimal.NewFromInt(10000)).IntPart())
|
||||||
|
|
||||||
|
qmgr := quota_manager.NewQuotaManager(redishelper.DefaultRedis.GetClient())
|
||||||
|
|
||||||
|
// 事务处理
|
||||||
|
err := e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||||
|
//写入充值记录
|
||||||
|
if err1 := e.Orm.Create(&data).Error; err1 != nil {
|
||||||
|
return err1
|
||||||
|
}
|
||||||
|
|
||||||
|
//写入可用字符
|
||||||
|
if _, err1 := qmgr.Deduct(ctx, member.ApiKey, platform.Code, int64(data.TotalChars)); err1 != nil {
|
||||||
|
return err1
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// 新增充值校验
|
// 新增充值校验
|
||||||
func (e *TmRechargeLog) CreateOrderJudge(req *dto.TmRechargeCreateOrderReq) (models.TmMember, *models.TmPlatform, models.TmMemberPlatform, int) {
|
func (e *TmRechargeLog) CreateOrderJudge(memberId int, platformId int) (models.TmMember, *models.TmPlatform, models.TmMemberPlatform, int) {
|
||||||
memberService := TmMember{Service: e.Service}
|
memberService := TmMember{Service: e.Service}
|
||||||
member := models.TmMember{}
|
member := models.TmMember{}
|
||||||
if err := memberService.GetById(req.MemberId, &member); err != nil {
|
if err := memberService.GetById(memberId, &member); err != nil {
|
||||||
return models.TmMember{}, nil, models.TmMemberPlatform{}, statuscode.NotFindMember
|
return models.TmMember{}, nil, models.TmMemberPlatform{}, statuscode.NotFindMember
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +187,7 @@ func (e *TmRechargeLog) CreateOrderJudge(req *dto.TmRechargeCreateOrderReq) (mod
|
|||||||
}
|
}
|
||||||
|
|
||||||
platformService := TmPlatform{Service: e.Service}
|
platformService := TmPlatform{Service: e.Service}
|
||||||
platform, err := platformService.GetById(req.PlatformId)
|
platform, err := platformService.GetById(platformId)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e.Log.Errorf("获取平台信息失败:%s \r\n", err.Error())
|
e.Log.Errorf("获取平台信息失败:%s \r\n", err.Error())
|
||||||
@ -136,10 +198,15 @@ func (e *TmRechargeLog) CreateOrderJudge(req *dto.TmRechargeCreateOrderReq) (mod
|
|||||||
return models.TmMember{}, nil, models.TmMemberPlatform{}, statuscode.PlatformNotSupport
|
return models.TmMember{}, nil, models.TmMemberPlatform{}, statuscode.PlatformNotSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if platform.BlockChain == "" || platform.ReceiveAddress == "" {
|
||||||
|
e.Log.Error("翻译平台未配置收款信息")
|
||||||
|
return models.TmMember{}, nil, models.TmMemberPlatform{}, statuscode.PlatformNotSupport
|
||||||
|
}
|
||||||
|
|
||||||
memberPlatformService := TmMemberPlatform{Service: e.Service}
|
memberPlatformService := TmMemberPlatform{Service: e.Service}
|
||||||
memberPlatform, err := memberPlatformService.GetOrInsert(&dto.TmRechargeLogInsertOrUpdateReq{
|
memberPlatform, err := memberPlatformService.GetOrInsert(&dto.TmRechargeLogInsertOrUpdateReq{
|
||||||
MemberId: req.MemberId,
|
MemberId: memberId,
|
||||||
PlatformId: req.PlatformId,
|
PlatformId: platformId,
|
||||||
PlatformKey: platform.Code,
|
PlatformKey: platform.Code,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -155,7 +222,7 @@ func (e *TmRechargeLog) CreateOrderJudge(req *dto.TmRechargeCreateOrderReq) (mod
|
|||||||
|
|
||||||
// 用户自己发起充值
|
// 用户自己发起充值
|
||||||
// return code
|
// return code
|
||||||
func (e TmRechargeLog) CreateOrder(req *dto.CustomCreateOrderReq, apiKey string) int {
|
func (e TmRechargeLog) CreateOrder(req *dto.CustomCreateOrderReq, resp *dto.CustomCreateOrderResp, apiKey string) int {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
var amountStr string
|
var amountStr string
|
||||||
// var errReturn bool
|
// var errReturn bool
|
||||||
@ -202,16 +269,22 @@ func (e TmRechargeLog) CreateOrder(req *dto.CustomCreateOrderReq, apiKey string)
|
|||||||
return statuscode.ServerError
|
return statuscode.ServerError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, platform, _, code := e.CreateOrderJudge(member.Id, req.PlatformId)
|
||||||
|
|
||||||
|
if code != statuscode.Success {
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
createReq := dto.TmRechargeCreateOrderReq{}
|
createReq := dto.TmRechargeCreateOrderReq{}
|
||||||
createReq.MemberId = member.Id
|
createReq.MemberId = member.Id
|
||||||
createReq.Amount = req.Amount
|
createReq.Amount = platform.Price.Mul(decimal.NewFromInt(int64(req.Count)))
|
||||||
createReq.PlatformId = req.PlatformId
|
createReq.PlatformId = req.PlatformId
|
||||||
createReq.ReceiveAddress = config.ConfigValue
|
createReq.ReceiveAddress = platform.ReceiveAddress
|
||||||
createReq.ReceiveChannel = "TRX"
|
createReq.ReceiveChannel = platform.BlockChain
|
||||||
createReq.Type = 1
|
createReq.Type = 1
|
||||||
createReq.UserId = req.UserId
|
createReq.UserId = req.UserId
|
||||||
|
|
||||||
amountStr, err = receiveaddressmanager.AllocatePaymentAmount(ctx, redishelper.DefaultRedis.GetClient(), req.Amount.InexactFloat64(), timeInterval)
|
amountStr, err = receiveaddressmanager.AllocatePaymentAmount(ctx, redishelper.DefaultRedis.GetClient(), createReq.Amount.InexactFloat64(), timeInterval)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e.Log.Errorf("分配可用金额失败:%v \r\n", err)
|
e.Log.Errorf("分配可用金额失败:%v \r\n", err)
|
||||||
@ -225,12 +298,6 @@ func (e TmRechargeLog) CreateOrder(req *dto.CustomCreateOrderReq, apiKey string)
|
|||||||
return statuscode.ServerError
|
return statuscode.ServerError
|
||||||
}
|
}
|
||||||
|
|
||||||
_, platform, _, code := e.CreateOrderJudge(&createReq)
|
|
||||||
|
|
||||||
if code != statuscode.Success {
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
data := models.TmRechargeLog{}
|
data := models.TmRechargeLog{}
|
||||||
data.Amount = createReq.Amount
|
data.Amount = createReq.Amount
|
||||||
platformCharacter := int64(platform.Character * 1000000)
|
platformCharacter := int64(platform.Character * 1000000)
|
||||||
@ -240,6 +307,7 @@ func (e TmRechargeLog) CreateOrder(req *dto.CustomCreateOrderReq, apiKey string)
|
|||||||
data.Type = createReq.Type
|
data.Type = createReq.Type
|
||||||
data.Status = 1
|
data.Status = 1
|
||||||
data.UserId = member.UserId
|
data.UserId = member.UserId
|
||||||
|
data.MemberId = member.Id
|
||||||
data.PlatformId = platform.Id
|
data.PlatformId = platform.Id
|
||||||
data.ReceiveAddress = createReq.ReceiveAddress
|
data.ReceiveAddress = createReq.ReceiveAddress
|
||||||
data.ReceiveChannel = createReq.ReceiveChannel
|
data.ReceiveChannel = createReq.ReceiveChannel
|
||||||
@ -266,13 +334,30 @@ func (e TmRechargeLog) CreateOrder(req *dto.CustomCreateOrderReq, apiKey string)
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return statuscode.ServerError
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.Amount = data.Amount.String()
|
||||||
|
resp.ReceiveAddress = data.ReceiveAddress
|
||||||
|
resp.OrderNo = data.OrderNo
|
||||||
|
resp.BlockChain = strings.ToUpper(data.ReceiveChannel)
|
||||||
|
resp.ExpireUnix = data.OrderExpireTime.Unix()
|
||||||
|
|
||||||
return statuscode.Success
|
return statuscode.Success
|
||||||
}
|
}
|
||||||
|
|
||||||
// 充值回调
|
// 充值回调
|
||||||
func (e *TmRechargeLog) PayCallBack(logs *[]dto.TmRechargeCallbackReq) error {
|
func (e *TmRechargeLog) PayCallBack(logs *[]dto.TmRechargeCallbackReq) error {
|
||||||
|
now := time.Now()
|
||||||
|
qmgr := quota_manager.NewQuotaManager(redishelper.DefaultRedis.GetClient())
|
||||||
|
ctx := context.Background()
|
||||||
|
memberService := TmMember{Service: e.Service}
|
||||||
|
platformService := TmPlatform{Service: e.Service}
|
||||||
|
|
||||||
for _, log := range *logs {
|
for _, log := range *logs {
|
||||||
key := fmt.Sprintf(rediskey.TM_RECHARGE_PRE_ORDER, log.PayableAmount.String())
|
amountStr := log.PayableAmount.StringFixed(4)
|
||||||
|
key := fmt.Sprintf(rediskey.TM_RECHARGE_PRE_ORDER, amountStr)
|
||||||
orderNo, err := redishelper.DefaultRedis.GetString(key)
|
orderNo, err := redishelper.DefaultRedis.GetString(key)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -289,7 +374,47 @@ func (e *TmRechargeLog) PayCallBack(logs *[]dto.TmRechargeCallbackReq) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if data.Status == 1 {
|
if data.Status == 1 {
|
||||||
|
data.TxHash = log.TxHash
|
||||||
|
data.Status = 2
|
||||||
|
data.PayTime = &now
|
||||||
|
data.ExpireAt = time.Now().AddDate(0, 0, 30)
|
||||||
|
member := models.TmMember{}
|
||||||
|
err := memberService.GetById(data.MemberId, &member)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
e.Log.Errorf("获取用户信息失败 error:%s \r\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
platform, err := platformService.GetById(data.PlatformId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
e.Log.Errorf("获取平台信息失败 error:%s \r\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
rechargeData := quota_manager.QuotaRecharge{
|
||||||
|
QuotaID: data.OrderNo,
|
||||||
|
Amount: int64(data.TotalChars),
|
||||||
|
ExpireAt: data.ExpireAt.Unix(),
|
||||||
|
}
|
||||||
|
err = e.Orm.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if err1 := e.Orm.Model(&models.TmRechargeLog{}).Where("id =?", data.Id).Updates(map[string]interface{}{"tx_hash": log.TxHash, "status": 2, "pay_time": now}).Error; err1 != nil {
|
||||||
|
e.Log.Errorf("发起充值记录失败 error:%s \r\n", err1)
|
||||||
|
return err1
|
||||||
|
}
|
||||||
|
|
||||||
|
//写入可用字符
|
||||||
|
if err1 := qmgr.AddQuota(ctx, member.ApiKey, platform.Code, rechargeData); err1 != nil {
|
||||||
|
return err1
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
e.Log.Errorf("写入可用字符失败 error:%s \r\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
e.Log.Errorf("订单状态异常:%s 状态:%d\r\n", orderNo, data.Status)
|
e.Log.Errorf("订单状态异常:%s 状态:%d\r\n", orderNo, data.Status)
|
||||||
}
|
}
|
||||||
@ -334,3 +459,28 @@ func (e *TmRechargeLog) GetRemainByOrderNo(orderNo string) (int, error) {
|
|||||||
|
|
||||||
return strconv.Atoi(val)
|
return strconv.Atoi(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *TmRechargeLog) GetPlatforms() ([]models.TmPlatform, error) {
|
||||||
|
key1 := fmt.Sprintf(rediskey.TM_PLATFORM_KEY, "*")
|
||||||
|
scankeys, err := redishelper.DefaultRedis.ScanKeys(key1)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
platforms := make([]models.TmPlatform, 0)
|
||||||
|
for _, key := range scankeys {
|
||||||
|
val, err := redishelper.DefaultRedis.GetString(key)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var platform models.TmPlatform
|
||||||
|
sonic.Unmarshal([]byte(val), &platform)
|
||||||
|
|
||||||
|
if platform.Id > 0 {
|
||||||
|
platforms = append(platforms, platform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return platforms, nil
|
||||||
|
}
|
||||||
|
|||||||
@ -37,6 +37,9 @@ type TranslatorToolService struct {
|
|||||||
service.Service
|
service.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var UnSportPlatformErr = errors.New("平台不支持")
|
||||||
|
var TransUnMarshalConfigErr = errors.New("翻译服务商配置解析失败")
|
||||||
|
|
||||||
// NewTranslatorService 创建翻译服务实例
|
// NewTranslatorService 创建翻译服务实例
|
||||||
func NewTranslatorService(cfg *TranslatorServiceConfig) (*TranslatorService, error) {
|
func NewTranslatorService(cfg *TranslatorServiceConfig) (*TranslatorService, error) {
|
||||||
svc := &TranslatorService{
|
svc := &TranslatorService{
|
||||||
@ -50,30 +53,43 @@ func NewTranslatorService(cfg *TranslatorServiceConfig) (*TranslatorService, err
|
|||||||
var newAdapter Translator
|
var newAdapter Translator
|
||||||
switch providerName {
|
switch providerName {
|
||||||
case "google":
|
case "google":
|
||||||
googleCfgBytes, _ := json.Marshal(providerCfg) // 假设配置是map[string]interface{},需要转换
|
googleCfgBytes, _ := json.Marshal(providerCfg)
|
||||||
var googleCfg GoogleTranslatorConfig
|
var googleCfg GoogleTranslatorConfig
|
||||||
if err := json.Unmarshal(googleCfgBytes, &googleCfg); err != nil {
|
if err := json.Unmarshal(googleCfgBytes, &googleCfg); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to unmarshal config for GoogleTranslate")
|
logger.Error("failed to unmarshal config for GoogleTranslate")
|
||||||
|
return nil, TransUnMarshalConfigErr
|
||||||
}
|
}
|
||||||
newAdapter = NewGoogleTranslator(&googleCfg)
|
newAdapter = NewGoogleTranslator(&googleCfg)
|
||||||
// case "BaiduTranslate":
|
|
||||||
// // newAdapter = adapter.NewBaiduTranslator(...)
|
|
||||||
case "deepseek":
|
case "deepseek":
|
||||||
deepseekCfgBytes, _ := json.Marshal(providerCfg) // 假设配置是map[string]interface{},需要转换
|
deepseekCfgBytes, _ := json.Marshal(providerCfg)
|
||||||
var deepseekCfg DeepseekTranslatorConfig
|
var deepseekCfg DeepseekTranslatorConfig
|
||||||
if err := json.Unmarshal(deepseekCfgBytes, &deepseekCfg); err != nil {
|
if err := json.Unmarshal(deepseekCfgBytes, &deepseekCfg); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to unmarshal config for DeepseekTranslator")
|
logger.Error(err, "failed to unmarshal config for DeepseekTranslator")
|
||||||
|
|
||||||
|
return nil, TransUnMarshalConfigErr
|
||||||
}
|
}
|
||||||
newAdapter = NewDeepseekTranslator(&deepseekCfg)
|
newAdapter = NewDeepseekTranslator(&deepseekCfg)
|
||||||
case "deepl", "deepl_free":
|
case "deepl", "deepl_free":
|
||||||
deeplCfgBytes, _ := json.Marshal(providerCfg) // 假设配置是map[string]interface{},需要转换
|
deeplCfgBytes, _ := json.Marshal(providerCfg)
|
||||||
var deeplCfg DeeplTranslatorConfig
|
var deeplCfg DeeplTranslatorConfig
|
||||||
if err := json.Unmarshal(deeplCfgBytes, &deeplCfg); err != nil {
|
if err := json.Unmarshal(deeplCfgBytes, &deeplCfg); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to unmarshal config for DeepLTranslator")
|
logger.Error("failed to unmarshal config for DeepLTranslator")
|
||||||
|
return nil, TransUnMarshalConfigErr
|
||||||
}
|
}
|
||||||
newAdapter = NewDeeplTranslator(&deeplCfg)
|
newAdapter = NewDeeplTranslator(&deeplCfg)
|
||||||
|
|
||||||
|
//翻译之家
|
||||||
|
case "deepl_trans", "google_trans", "baidu_trans", "youdao_trans", "bing_trans", "huoshan_trans", "chatgpt-4o_trans", "yandex_trans":
|
||||||
|
transCfgBytes, _ := json.Marshal(providerCfg)
|
||||||
|
var transCfg TransTranslatorConfig
|
||||||
|
if err := json.Unmarshal(transCfgBytes, &transCfg); err != nil {
|
||||||
|
logger.Error("failed to unmarshal config for Translator")
|
||||||
|
return nil, TransUnMarshalConfigErr
|
||||||
|
}
|
||||||
|
|
||||||
|
newAdapter = NewTransTranslator(&transCfg)
|
||||||
default:
|
default:
|
||||||
return nil, errors.Errorf("unsupported translation provider: %s", providerName)
|
return nil, UnSportPlatformErr
|
||||||
}
|
}
|
||||||
svc.RegisterProvider(providerName, newAdapter)
|
svc.RegisterProvider(providerName, newAdapter)
|
||||||
}
|
}
|
||||||
@ -149,7 +165,7 @@ func (s *TranslatorService) TranslateJudge(req *dto.TranslateReq, apiKey string)
|
|||||||
platformConfigInterface := Translator.config.ProviderConfigs[req.Platform]
|
platformConfigInterface := Translator.config.ProviderConfigs[req.Platform]
|
||||||
|
|
||||||
// 尝试将 interface{} 断言为 map[string]interface{}
|
// 尝试将 interface{} 断言为 map[string]interface{}
|
||||||
if mapData, ok := platformConfigInterface.(map[string]interface{}); !ok {
|
if mapData, ok := platformConfigInterface.(map[string]interface{}); ok {
|
||||||
tmPlatformAccount.DecrRemainBy(req.Platform, mapData["apiKey"].(string), count)
|
tmPlatformAccount.DecrRemainBy(req.Platform, mapData["apiKey"].(string), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +173,7 @@ func (s *TranslatorService) TranslateJudge(req *dto.TranslateReq, apiKey string)
|
|||||||
redishelper.DefaultRedis.IncrBy(fmt.Sprintf(rediskey.TM_MEMBER_DAILY_COUNT, date, apiKey, req.Platform), int64(count))
|
redishelper.DefaultRedis.IncrBy(fmt.Sprintf(rediskey.TM_MEMBER_DAILY_COUNT, date, apiKey, req.Platform), int64(count))
|
||||||
//每日统计保留三天
|
//每日统计保留三天
|
||||||
redishelper.DefaultRedis.Expire(fmt.Sprintf(rediskey.TM_MEMBER_DAILY_COUNT, date, apiKey, req.Platform), 3*24*time.Hour)
|
redishelper.DefaultRedis.Expire(fmt.Sprintf(rediskey.TM_MEMBER_DAILY_COUNT, date, apiKey, req.Platform), 3*24*time.Hour)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
tmMemberService.RefundQuote(ctx, apiKey, req.Platform, &decyDatas)
|
tmMemberService.RefundQuote(ctx, apiKey, req.Platform, &decyDatas)
|
||||||
|
|
||||||
@ -200,22 +217,20 @@ func (s *TranslatorService) GetTranslator(platform string) (translator *Translat
|
|||||||
ProviderConfigs: configs,
|
ProviderConfigs: configs,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch platform {
|
translator, err = NewTranslatorService(&cfg)
|
||||||
case "deepl", "deepl_free", "deepseek":
|
|
||||||
translator, err = NewTranslatorService(&cfg)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Log.Errorf("failed to create translator service: %s", err)
|
switch err {
|
||||||
|
case UnSportPlatformErr:
|
||||||
|
code = statuscode.PlatformNotSupport
|
||||||
|
default:
|
||||||
code = statuscode.ServerError
|
code = statuscode.ServerError
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
code = statuscode.Success
|
code = statuscode.Success
|
||||||
return
|
|
||||||
default:
|
|
||||||
code = statuscode.PlatformNotSupport
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从 Redis List 顺序取出一个账号,使用后放回队尾,模拟轮询
|
// 从 Redis List 顺序取出一个账号,使用后放回队尾,模拟轮询
|
||||||
|
|||||||
108
app/admin/service/translator_trans.go
Normal file
108
app/admin/service/translator_trans.go
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go-admin/app/admin/service/dto"
|
||||||
|
"go-admin/utils/httphelper"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 翻译之家
|
||||||
|
type TransTranslator struct {
|
||||||
|
config *TransTranslatorConfig
|
||||||
|
client *httphelper.HTTPClient
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransTranslatorConfig struct {
|
||||||
|
ApiKey string `json:"apiKey"`
|
||||||
|
ApiSecret string `json:"apiSecret"`
|
||||||
|
Endpoint string `json:"endpoint"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransTranslatorResponse[T any] struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Data T `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 剩余字符数
|
||||||
|
type TransTranslatorResponseNumData struct {
|
||||||
|
UseNum int `json:"use_num" comment:"总字符"`
|
||||||
|
IsUsed int `json:"is_used" comment:"已用字符"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 翻译内容
|
||||||
|
type TransTranslatorResponseData struct {
|
||||||
|
Text string `json:"text"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 翻译之家
|
||||||
|
func NewTransTranslator(config *TransTranslatorConfig) *TransTranslator {
|
||||||
|
defaultHeaders := map[string]string{
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
|
||||||
|
httpClient := httphelper.NewHTTPClient(
|
||||||
|
15*time.Second,
|
||||||
|
config.Endpoint,
|
||||||
|
defaultHeaders,
|
||||||
|
)
|
||||||
|
|
||||||
|
return &TransTranslator{
|
||||||
|
config: config,
|
||||||
|
client: httpClient,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 翻译
|
||||||
|
func (e *TransTranslator) Translate(text string, sourceLang, targetLang string) (*dto.TranslateResult, error) {
|
||||||
|
result := dto.TranslateResult{}
|
||||||
|
responseData := TransTranslatorResponse[TransTranslatorResponseData]{}
|
||||||
|
route := fmt.Sprintf("/api/index/translate?token=%s", e.config.ApiKey)
|
||||||
|
params := map[string]string{
|
||||||
|
"keywords": text,
|
||||||
|
"sourceLanguage": sourceLang,
|
||||||
|
"targetLanguage": targetLang,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deepl API 翻译通常是 POST 请求到 /v2/translate
|
||||||
|
err := e.client.Post(route, params, nil, &responseData)
|
||||||
|
if err != nil {
|
||||||
|
return &result, fmt.Errorf("翻译请求出错: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if responseData.Code != 1 {
|
||||||
|
return &result, fmt.Errorf("翻译失败,错误代码: %d msg: %s", responseData.Code, responseData.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
if responseData.Data.Text != "" {
|
||||||
|
result.TranslatedText = responseData.Data.Text
|
||||||
|
} else {
|
||||||
|
return &result, fmt.Errorf("翻译失败,返回数据为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *TransTranslator) GetRemainCount() (int, error) {
|
||||||
|
responseData := TransTranslatorResponse[TransTranslatorResponseNumData]{}
|
||||||
|
route := fmt.Sprintf("/api/index/getUserNums?token=%s", e.config.ApiKey)
|
||||||
|
|
||||||
|
// Deepl API 翻译通常是 POST 请求到 /v2/translate
|
||||||
|
err := e.client.Get(route, nil, &responseData)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("翻译请求出错: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if responseData.Code != 1 {
|
||||||
|
return 0, fmt.Errorf("翻译失败,错误代码: %d msg: %s", responseData.Code, responseData.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := responseData.Data.UseNum - responseData.Data.IsUsed
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取服务商
|
||||||
|
func (t *TransTranslator) GetPlatform() string {
|
||||||
|
return "trans"
|
||||||
|
}
|
||||||
@ -10,9 +10,11 @@ import (
|
|||||||
// 字典 key 可以配置到 自动任务 调用目标 中;
|
// 字典 key 可以配置到 自动任务 调用目标 中;
|
||||||
func InitJob() {
|
func InitJob() {
|
||||||
jobList = map[string]JobExec{
|
jobList = map[string]JobExec{
|
||||||
"ExamplesOne": ExamplesOne{},
|
"ExamplesOne": ExamplesOne{},
|
||||||
"DailyJob": DailyJob{},
|
"DailyJob": DailyJob{},
|
||||||
"RemainCharJob": RemainCharJob{},
|
"RemainCharJob": RemainCharJob{},
|
||||||
|
"CleanExpiredOrderJob": CleanExpiredOrderJob{},
|
||||||
|
"TrxPaymentJob": TrxPaymentJob{},
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,18 @@ type DailyJob struct{}
|
|||||||
|
|
||||||
type RemainCharJob struct{}
|
type RemainCharJob struct{}
|
||||||
|
|
||||||
|
type CleanExpiredOrderJob struct{}
|
||||||
|
|
||||||
|
// 清理过期订单
|
||||||
|
func (t CleanExpiredOrderJob) Exec(arg interface{}) error {
|
||||||
|
// expireTime := time.Now().Add(5 * time.Minute)
|
||||||
|
rechargeLogService := service.TmRechargeLog{}
|
||||||
|
rechargeLogService.Orm = GetDb()
|
||||||
|
rechargeLogService.Log = logger.NewHelper(logger.DefaultLogger)
|
||||||
|
|
||||||
|
return rechargeLogService.CleanExpiredOrder()
|
||||||
|
}
|
||||||
|
|
||||||
// 剩余字符统计
|
// 剩余字符统计
|
||||||
func (t RemainCharJob) Exec(arg interface{}) error {
|
func (t RemainCharJob) Exec(arg interface{}) error {
|
||||||
memberService := service.TmMember{}
|
memberService := service.TmMember{}
|
||||||
|
|||||||
@ -36,3 +36,17 @@ func TestRemainTranslate(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClean(t *testing.T) {
|
||||||
|
dsn := "root:123456@tcp(127.0.0.1:3306)/aggregate_translate?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"
|
||||||
|
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||||
|
sdk.Runtime.SetDb("default", db)
|
||||||
|
|
||||||
|
redishelper.InitDefaultRedis("127.0.0.1:6379", "", 1)
|
||||||
|
redishelper.InitLockRedisConn("127.0.0.1:6379", "", "1")
|
||||||
|
|
||||||
|
job := CleanExpiredOrderJob{}
|
||||||
|
if err := job.Exec(nil); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"go-admin/utils/utility"
|
"go-admin/utils/utility"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-admin-team/go-admin-core/logger"
|
"github.com/go-admin-team/go-admin-core/logger"
|
||||||
@ -23,7 +24,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// trx 链上支付定时查询
|
// trx 链上支付定时查询
|
||||||
func (j *TrxPaymentJob) Exec(args interface{}) error {
|
func (j TrxPaymentJob) Exec(arg interface{}) error {
|
||||||
configService := service.SysConfig{}
|
configService := service.SysConfig{}
|
||||||
configService.Orm = GetDb()
|
configService.Orm = GetDb()
|
||||||
req := dto.SysConfigByKeyReq{}
|
req := dto.SysConfigByKeyReq{}
|
||||||
@ -37,39 +38,58 @@ func (j *TrxPaymentJob) Exec(args interface{}) error {
|
|||||||
|
|
||||||
rechargeService := service.TmRechargeLog{}
|
rechargeService := service.TmRechargeLog{}
|
||||||
rechargeService.Orm = GetDb()
|
rechargeService.Orm = GetDb()
|
||||||
|
platforms, err := rechargeService.GetPlatforms()
|
||||||
|
toAddresss := []string{}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("查询平台失败", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, platform := range platforms {
|
||||||
|
if strings.ToLower(platform.BlockChain) == "trx" && !utility.ContainsString(toAddresss, platform.ReceiveAddress) {
|
||||||
|
toAddresss = append(toAddresss, platform.ReceiveAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
startTime := time.Now().UnixMilli()
|
startTime := time.Now().UnixMilli()
|
||||||
endTime := time.Now().Add(-1 * time.Hour).UnixMilli()
|
endTime := time.Now().Add(-1 * time.Hour).UnixMilli()
|
||||||
transfers, err := GetTRC20Transfers(UsdtContractAddress, configData.ConfigValue, endTime, startTime)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("查询失败", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
logs := make([]dto.TmRechargeCallbackReq, 0)
|
|
||||||
item := dto.TmRechargeCallbackReq{}
|
|
||||||
|
|
||||||
for _, transfer := range transfers {
|
|
||||||
if transfer.TransactionID == "" || transfer.ToAddress != configData.ConfigValue {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//实际金额
|
|
||||||
payableAmount := utility.StringToDecimal(transfer.Value).Div(decimal.NewFromInt(10).Pow(decimal.NewFromInt(int64(transfer.TokenInfo.Decimals)))).Truncate(6)
|
|
||||||
item.TxHash = transfer.TransactionID
|
|
||||||
item.PayableAmount = payableAmount
|
|
||||||
item.FromAddress = transfer.FromAddress
|
|
||||||
|
|
||||||
logs = append(logs, item)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(logs) > 0 {
|
|
||||||
err := rechargeService.PayCallBack(&logs)
|
|
||||||
|
|
||||||
|
for _, toAddress := range toAddresss {
|
||||||
|
transfers, err := GetTRC20Transfers(UsdtContractAddress, toAddress, endTime, startTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("执行完毕,err:")
|
logger.Error("查询失败", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logs := make([]dto.TmRechargeCallbackReq, 0)
|
||||||
|
item := dto.TmRechargeCallbackReq{}
|
||||||
|
|
||||||
|
for _, transfer := range transfers {
|
||||||
|
if transfer.TransactionID == "" || transfer.ToAddress != toAddress {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//实际金额
|
||||||
|
payableAmount := utility.StringToDecimal(transfer.Value).Div(decimal.NewFromInt(10).Pow(decimal.NewFromInt(int64(transfer.TokenInfo.Decimals)))).Truncate(6)
|
||||||
|
item.TxHash = transfer.TransactionID
|
||||||
|
item.PayableAmount = payableAmount
|
||||||
|
item.FromAddress = transfer.FromAddress
|
||||||
|
item.ToAddress = transfer.ToAddress
|
||||||
|
|
||||||
|
if utility.ContainsString(toAddresss, item.ToAddress) {
|
||||||
|
logs = append(logs, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(logs) > 0 {
|
||||||
|
err := rechargeService.PayCallBack(&logs)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("执行完毕,err:", err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
app/jobs/trxpayment_job_test.go
Normal file
28
app/jobs/trxpayment_job_test.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package jobs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go-admin/config"
|
||||||
|
"go-admin/utils/redishelper"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-admin-team/go-admin-core/sdk"
|
||||||
|
"gorm.io/driver/mysql"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTrxPaymentJob(t *testing.T) {
|
||||||
|
dsn := "root:123456@tcp(127.0.0.1:3306)/aggregate_translate?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"
|
||||||
|
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||||
|
sdk.Runtime.SetDb("default", db)
|
||||||
|
config.ExtConfig.TrxGridUrl = "https://api.trongrid.io"
|
||||||
|
redishelper.InitDefaultRedis("127.0.0.1:6379", "", 1)
|
||||||
|
redishelper.InitLockRedisConn("127.0.0.1:6379", "", "1")
|
||||||
|
|
||||||
|
trxPaymentJob := TrxPaymentJob{}
|
||||||
|
|
||||||
|
err := trxPaymentJob.Exec(nil)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,7 +23,7 @@ var ErrorMessage = map[int]string{
|
|||||||
NotFindMember: "not find member",
|
NotFindMember: "not find member",
|
||||||
NotFindApiKey: "not find api key",
|
NotFindApiKey: "not find api key",
|
||||||
MemberPlatformNotSupport: "member platform not support",
|
MemberPlatformNotSupport: "member platform not support",
|
||||||
RechargeAmountMustBeGreaterThanZero: "recharge amount must be greater than zero",
|
RechargeNumberMustBeGreaterThanZero: "The recharge quantity must be greater than 0",
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -47,6 +47,6 @@ const (
|
|||||||
MemberPlatformNotSupport = 30003 //用户平台不支持
|
MemberPlatformNotSupport = 30003 //用户平台不支持
|
||||||
|
|
||||||
//================ 充值相关 ===============
|
//================ 充值相关 ===============
|
||||||
RechargeAmountMustBeGreaterThanZero = 40001 //充值金额必须大于0
|
RechargeNumberMustBeGreaterThanZero = 40001 //充值数量必须大于0
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|||||||
@ -12,7 +12,7 @@ var ExtConfig Extend
|
|||||||
type Extend struct {
|
type Extend struct {
|
||||||
AMap AMap // 这里配置对应配置文件的结构即可
|
AMap AMap // 这里配置对应配置文件的结构即可
|
||||||
Mq MqConfig
|
Mq MqConfig
|
||||||
TrxGridUrl string `yaml:"trx_grid_url"`
|
TrxGridUrl string `yaml:"trxGridUrl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AMap struct {
|
type AMap struct {
|
||||||
|
|||||||
@ -54,7 +54,7 @@ settings:
|
|||||||
password: '123456'
|
password: '123456'
|
||||||
pass: "123456"
|
pass: "123456"
|
||||||
#trx api
|
#trx api
|
||||||
trx_grid_url: "https://api.trongrid.io"
|
trxGridUrl: "https://api.trongrid.io"
|
||||||
cache:
|
cache:
|
||||||
redis:
|
redis:
|
||||||
addr: 127.0.0.1:6379
|
addr: 127.0.0.1:6379
|
||||||
|
|||||||
35
utils/chainhelper/chainhelper.go
Normal file
35
utils/chainhelper/chainhelper.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package chainhelper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 比较钱包地址格式
|
||||||
|
func JudgeChainAddress(chain, walletAddress string) error {
|
||||||
|
switch chain {
|
||||||
|
case "trx":
|
||||||
|
return validateTronAddress(walletAddress)
|
||||||
|
default:
|
||||||
|
return errors.New("invalid chain")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateTronAddress(address string) error {
|
||||||
|
// TRON 地址通常以 'T' 开头,并且是 34 个字符的 Base58Check 编码
|
||||||
|
// 这是一个简化的检查,最佳实践是使用专门的 Tron 地址验证库来包含校验和验证
|
||||||
|
if len(address) != 34 {
|
||||||
|
return errors.New("Tron 钱包地址长度不正确")
|
||||||
|
}
|
||||||
|
if address[0] != 'T' {
|
||||||
|
return errors.New("Tron 钱包地址长度不正确,必须以 'T'开头")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查字符集
|
||||||
|
matched, _ := regexp.MatchString("^[T][1-9a-zA-Z]{33}$", address)
|
||||||
|
if !matched {
|
||||||
|
return errors.New("TRON 钱包地址格式不正确")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@ -27,3 +27,13 @@ func ContainsInt(arr []int, v int) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ContainsString(arr []string, v string) bool {
|
||||||
|
for _, a := range arr {
|
||||||
|
if a == v {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user