重构支付接口,以动态支持多种产品类型,整合长短效套餐的购买支付逻辑;引入 decimal 类型的金额计算;

This commit is contained in:
2025-05-20 17:14:07 +08:00
parent 689964e3ef
commit 6f1bc72912
45 changed files with 891 additions and 754 deletions

View File

@@ -6,6 +6,7 @@ import (
"gorm.io/gen/field"
"gorm.io/gorm"
"gorm.io/gorm/schema"
"strings"
)
var g *gen.Generator
@@ -23,9 +24,10 @@ func main() {
)
g = gen.NewGenerator(gen.Config{
OutPath: "web/queries",
ModelPkgPath: "models",
Mode: gen.WithDefaultQuery | gen.WithoutContext,
OutPath: "web/queries",
ModelPkgPath: "models",
FieldWithTypeTag: true,
Mode: gen.WithDefaultQuery | gen.WithoutContext,
})
g.UseDB(db)
@@ -35,6 +37,9 @@ func main() {
if field.Type == "time.Time" {
field.Type = "orm.LocalDateTime"
}
if strings.Contains(field.Tags(), "numeric") {
field.Type = "decimal.Decimal"
}
return field
}),
gen.FieldRename("contact_qq", "ContactQQ"),

1
go.mod
View File

@@ -57,6 +57,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/smartwalle/ncrypto v1.0.4 // indirect
github.com/smartwalle/ngx v1.0.9 // indirect
github.com/smartwalle/nsign v1.0.9 // indirect

2
go.sum
View File

@@ -176,6 +176,8 @@ github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRl
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/smartwalle/alipay/v3 v3.2.25 h1:cRDN+fpDWTVHnuHIF/vsJETskRXS/S+fDOdAkzXmV/Q=
github.com/smartwalle/alipay/v3 v3.2.25/go.mod h1:lVqFiupPf8YsAXaq5JXcwqnOUC2MCF+2/5vub+RlagE=
github.com/smartwalle/ncrypto v1.0.4 h1:P2rqQxDepJwgeO5ShoC+wGcK2wNJDmcdBOWAksuIgx8=

View File

@@ -792,7 +792,7 @@ comment on table resource_long is '长效动态套餐表';
comment on column resource_long.id is 'ID';
comment on column resource_long.resource_id is '套餐ID';
comment on column resource_long.type is '套餐类型1-包时2-包量';
comment on column resource_long.live is '可用时长()';
comment on column resource_long.live is '可用时长()';
comment on column resource_long.quota is '配额数量';
comment on column resource_long.used is '已用数量';
comment on column resource_long.expire is '过期时间';

View File

@@ -6,6 +6,7 @@ import (
"platform/web/core"
resource2 "platform/web/domains/resource"
trade2 "platform/web/domains/trade"
g "platform/web/globals"
"platform/web/globals/orm"
q "platform/web/queries"
s "platform/web/services"
@@ -143,163 +144,92 @@ func AllResource(c *fiber.Ctx) error {
// endregion
// region CompleteResource
// region CreateResource
type CreateResourceReq struct {
s.CreateResourceData
s.CreateResourceSerializer
}
type CreateResourceResp struct {
TradeNo string `json:"trade_no"`
PayURL string `json:"pay_url"`
}
type PaidCreateResourceReq struct {
TradeNo string `json:"trade_no" validate:"required"`
}
func PrepareResourceByAlipay(c *fiber.Ctx) error {
func CreateResource(c *fiber.Ctx) error {
// 检查权限
authContext, err := auth.Protect(c, []auth.PayloadType{auth.PayloadUser}, []string{})
authCtx, err := auth.NewProtect(c).Payload(auth.PayloadUser).Do()
if err != nil {
return err
}
// 解析请求参数
req := new(CreateResourceReq)
if err := c.BodyParser(req); err != nil {
return err
}
// 保存交易信息
result, err := s.Resource.PrepareResource(
c.Context(),
&req.CreateResourceData,
authContext.Payload.Id,
trade2.MethodAlipay,
)
if err != nil {
return err
}
// 返回结果
return c.JSON(CreateResourceResp{
TradeNo: result.TradeNo,
PayURL: result.PayURL,
})
}
func PrepareResourceByWechat(c *fiber.Ctx) error {
// 检查权限
authContext, err := auth.Protect(c, []auth.PayloadType{auth.PayloadUser}, []string{})
if err != nil {
return err
}
// 解析请求参数
req := new(CreateResourceReq)
if err := c.BodyParser(req); err != nil {
return err
}
// 保存交易信息
result, err := s.Resource.PrepareResource(
c.Context(),
&req.CreateResourceData,
authContext.Payload.Id,
trade2.MethodWeChat,
)
if err != nil {
return err
}
// 返回结果
return c.JSON(CreateResourceResp{
TradeNo: result.TradeNo,
PayURL: result.PayURL,
})
}
func CreateResourceByAlipay(c *fiber.Ctx) error {
// 检查权限
_, err := auth.Protect(c, []auth.PayloadType{auth.PayloadUser}, []string{})
if err != nil {
return err
}
// 解析请求参数
req := new(PaidCreateResourceReq)
if err := c.BodyParser(req); err != nil {
return err
}
// 验证支付结果
result, err := s.Transaction.VerifyTransaction(c.Context(), &s.TransactionVerifyData{
TradeNo: req.TradeNo,
Method: trade2.MethodAlipay,
})
if err != nil {
return err
}
// 完成套餐创建
err = s.Resource.CompleteResource(c.Context(), req.TradeNo, result)
if err != nil {
return err
}
return nil
}
func CreateResourceByWechat(c *fiber.Ctx) error {
// 检查权限
_, err := auth.Protect(c, []auth.PayloadType{auth.PayloadUser}, []string{})
if err != nil {
return err
}
// 解析请求参数
req := new(PaidCreateResourceReq)
if err := c.BodyParser(req); err != nil {
return err
}
// 验证支付结果
result, err := s.Transaction.VerifyTransaction(c.Context(), &s.TransactionVerifyData{
TradeNo: req.TradeNo,
Method: trade2.MethodWeChat,
})
if err != nil {
return err
}
// 完成套餐创建
err = s.Resource.CompleteResource(c.Context(), req.TradeNo, result)
if err != nil {
return err
}
return nil
}
func CreateResourceByBalance(c *fiber.Ctx) error {
// 检查权限
authCtx, err := auth.Protect(c, []auth.PayloadType{auth.PayloadUser}, []string{})
if err != nil {
return err
}
// 解析请求参数
req := new(CreateResourceReq)
if err := c.BodyParser(req); err != nil {
var req = new(CreateResourceReq)
if err := g.Validator.Validate(c, req); err != nil {
return err
}
// 创建套餐
err = s.Resource.CreateResource(&req.CreateResourceData, authCtx.Payload.Id)
err = s.Resource.CreateResource(authCtx.Payload.Id, time.Now(), &req.CreateResourceSerializer)
if err != nil {
return err
}
return nil
}
type PrepareResourceReq struct {
Method trade2.Method `json:"method" validate:"required"`
s.CreateResourceSerializer
}
type PrepareResourceResp struct {
TradeNo string `json:"trade_no"`
PayURL string `json:"pay_url"`
}
func PrepareCreateResource(c *fiber.Ctx) error {
// 检查权限
authCtx, err := auth.NewProtect(c).Payload(auth.PayloadUser).Do()
if err != nil {
return err
}
// 解析请求参数
var req = new(PrepareResourceReq)
if err := g.Validator.Validate(c, req); err != nil {
return err
}
// 准备创建套餐
result, err := s.Resource.PrepareResource(authCtx.Payload.Id, time.Now(), req.Method, &req.CreateResourceSerializer)
if err != nil {
return err
}
return c.JSON(PrepareResourceResp{
TradeNo: result.TradeNo,
PayURL: result.PayURL,
})
}
type CompleteResourceReq struct {
TradeNo string `json:"trade_no" validate:"required"`
}
func CompleteCreateResource(c *fiber.Ctx) error {
// 检查权限
_, err := auth.NewProtect(c).Payload(auth.PayloadUser).Do()
if err != nil {
return err
}
// 解析请求参数
var req = new(CompleteResourceReq)
if err := g.Validator.Validate(c, req); err != nil {
return err
}
// 完成创建套餐
var now = time.Now()
err = s.Resource.CompleteResource(req.TradeNo, now, nil)
if err != nil {
return err
}
@@ -308,3 +238,26 @@ func CreateResourceByBalance(c *fiber.Ctx) error {
}
// endregion
func ResourcePrice(c *fiber.Ctx) error {
// 检查权限
_, err := auth.NewProtect(c).Payload(auth.PayloadInternalServer).Do()
if err != nil {
return err
}
// 解析请求参数
var req = new(s.CreateResourceSerializer)
if err := g.Validator.Validate(c, req); err != nil {
return err
}
data, err := req.ToData()
if err != nil {
return err
}
return c.JSON(fiber.Map{
"price": data.GetPrice().StringFixed(2),
})
}

View File

@@ -2,13 +2,13 @@ package handlers
import (
"fmt"
"github.com/shopspring/decimal"
"log/slog"
"net/http"
trade2 "platform/web/domains/trade"
g "platform/web/globals"
q "platform/web/queries"
s "platform/web/services"
"strconv"
"time"
"github.com/gofiber/fiber/v2"
@@ -53,7 +53,7 @@ func AlipayCallback(c *fiber.Ctx) error {
case string(alipay.TradeStatusSuccess):
// 收集交易状态
payment, err := strconv.ParseFloat(notification.TotalAmount, 64)
payment, err := decimal.NewFromString(notification.TotalAmount)
if err != nil {
return err
}
@@ -70,14 +70,14 @@ func AlipayCallback(c *fiber.Ctx) error {
// 余额充值
case trade2.TypeRecharge:
err := s.User.RechargeConfirm(c.Context(), notification.OutTradeNo, verified)
err := s.User.RechargeConfirm(notification.OutTradeNo, verified)
if err != nil {
return err
}
// 购买产品
case trade2.TypePurchase:
err = s.Resource.CompleteResource(c.Context(), notification.OutTradeNo, verified)
err = s.Resource.CompleteResource(notification.OutTradeNo, time.Now(), verified)
if err != nil {
return err
}
@@ -89,13 +89,7 @@ func AlipayCallback(c *fiber.Ctx) error {
// 购买产品
case trade2.TypePurchase:
cancelAt, err := time.Parse("2006-01-02 15:04:05", notification.GmtClose)
if err != nil {
return err
}
err = s.Resource.CancelResource(c.Context(), notification.OutTradeNo, cancelAt, trade2.MethodAlipay)
err = s.Resource.CancelResource(notification.OutTradeNo, time.Now(), true)
if err != nil {
return err
}
@@ -163,7 +157,7 @@ func WechatPayCallback(c *fiber.Ctx) error {
case "SUCCESS":
// 收集交易状态
payment := float64(*content.Amount.PayerTotal) / 100
payment := decimal.NewFromInt(*content.Amount.PayerTotal).Div(decimal.NewFromInt(100))
paidAt, err := time.Parse(time.RFC3339, *content.SuccessTime)
if err != nil {
return err
@@ -178,14 +172,14 @@ func WechatPayCallback(c *fiber.Ctx) error {
// 余额充值
case trade.Type == int32(trade2.TypeRecharge):
err := s.User.RechargeConfirm(c.Context(), *content.OutTradeNo, verified)
err := s.User.RechargeConfirm(*content.OutTradeNo, verified)
if err != nil {
return err
}
// 购买产品
case trade.Type == int32(trade2.TypePurchase):
err = s.Resource.CompleteResource(c.Context(), *content.OutTradeNo, verified)
err = s.Resource.CompleteResource(*content.OutTradeNo, time.Now(), verified)
if err != nil {
return err
}

View File

@@ -1,12 +1,12 @@
package handlers
import (
"github.com/shopspring/decimal"
"platform/web/auth"
trade2 "platform/web/domains/trade"
m "platform/web/models"
q "platform/web/queries"
s "platform/web/services"
"strconv"
"time"
"github.com/gofiber/fiber/v2"
@@ -143,7 +143,7 @@ func UpdatePassword(c *fiber.Ctx) error {
// region /recharge
type RechargePrepareReq struct {
Amount float64 `json:"amount" validate:"required,min=0.01"`
Amount string `json:"amount" validate:"required,numeric"`
}
type RechargePrepareResp struct {
@@ -174,11 +174,16 @@ func RechargePrepareAlipay(c *fiber.Ctx) error {
}
// 保存交易信息
var now = time.Now()
amount, err := decimal.NewFromString(req.Amount)
if err != nil {
return err
}
var result *s.TransactionPrepareResult
err = q.Q.Transaction(func(tx *q.Query) error {
result, err = s.Transaction.PrepareTransaction(c.Context(), tx, authContext.Payload.Id, &s.TransactionPrepareData{
Subject: "账户充值 - " + strconv.FormatFloat(req.Amount, 'f', 2, 64) + "元",
Amount: req.Amount,
result, err = s.Transaction.PrepareTransaction(tx, authContext.Payload.Id, now, &s.TransactionPrepareData{
Subject: "账户充值 - " + amount.StringFixed(2) + "元",
Amount: amount,
ExpireAt: time.Now().Add(30 * time.Minute),
Type: trade2.TypeRecharge,
Method: trade2.MethodAlipay,
@@ -210,7 +215,7 @@ func RechargeConfirmAlipay(c *fiber.Ctx) error {
}
// 验证支付结果
result, err := s.Transaction.VerifyTransaction(c.Context(), &s.TransactionVerifyData{
result, err := s.Transaction.VerifyTransaction(&s.TransactionVerifyData{
TradeNo: req.TradeNo,
Method: trade2.MethodAlipay,
})
@@ -219,7 +224,7 @@ func RechargeConfirmAlipay(c *fiber.Ctx) error {
}
// 更新数据库
err = s.User.RechargeConfirm(c.Context(), req.TradeNo, result)
err = s.User.RechargeConfirm(req.TradeNo, result)
if err != nil {
return err
}
@@ -241,12 +246,17 @@ func RechargePrepareWechat(c *fiber.Ctx) error {
}
// 保存交易信息
var now = time.Now()
amount, err := decimal.NewFromString(req.Amount)
if err != nil {
return err
}
var result *s.TransactionPrepareResult
err = q.Q.Transaction(func(tx *q.Query) error {
result, err = s.Transaction.PrepareTransaction(c.Context(), tx, authContext.Payload.Id, &s.TransactionPrepareData{
Subject: "账户充值 - " + strconv.FormatFloat(req.Amount, 'f', 2, 64) + "元",
Amount: req.Amount,
ExpireAt: time.Now().Add(30 * time.Minute),
result, err = s.Transaction.PrepareTransaction(tx, authContext.Payload.Id, now, &s.TransactionPrepareData{
Subject: "账户充值 - " + amount.StringFixed(2) + "元",
Amount: amount,
ExpireAt: now.Add(30 * time.Minute),
Type: trade2.TypeRecharge,
Method: trade2.MethodWeChat,
})
@@ -279,7 +289,7 @@ func RechargeConfirmWechat(c *fiber.Ctx) error {
}
// 验证支付结果
result, err := s.Transaction.VerifyTransaction(c.Context(), &s.TransactionVerifyData{
result, err := s.Transaction.VerifyTransaction(&s.TransactionVerifyData{
TradeNo: req.TradeNo,
Method: trade2.MethodWeChat,
})
@@ -288,7 +298,7 @@ func RechargeConfirmWechat(c *fiber.Ctx) error {
}
// 更新数据库
err = s.User.RechargeConfirm(c.Context(), req.TradeNo, result)
err = s.User.RechargeConfirm(req.TradeNo, result)
if err != nil {
return err
}

View File

@@ -14,20 +14,20 @@ const TableNameAdmin = "admin"
// Admin mapped from table <admin>
type Admin struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:管理员ID" json:"id"` // 管理员ID
Username string `gorm:"column:username;not null;comment:用户名" json:"username"` // 用户名
Password string `gorm:"column:password;not null;comment:密码" json:"password"` // 密码
Name string `gorm:"column:name;comment:真实姓名" json:"name"` // 真实姓名
Avatar string `gorm:"column:avatar;comment:头像URL" json:"avatar"` // 头像URL
Phone string `gorm:"column:phone;comment:手机号码" json:"phone"` // 手机号码
Email string `gorm:"column:email;comment:邮箱" json:"email"` // 邮箱
Status int32 `gorm:"column:status;not null;default:1;comment:状态0-禁用1-正常" json:"status"` // 状态0-禁用1-正常
LastLogin orm.LocalDateTime `gorm:"column:last_login;comment:最后登录时间" json:"last_login"` // 最后登录时间
LastLoginHost string `gorm:"column:last_login_host;comment:最后登录地址" json:"last_login_host"` // 最后登录地址
LastLoginAgent string `gorm:"column:last_login_agent;comment:最后登录代理" json:"last_login_agent"` // 最后登录代理
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:管理员ID" json:"id"` // 管理员ID
Username string `gorm:"column:username;type:character varying(255);not null;comment:用户名" json:"username"` // 用户名
Password string `gorm:"column:password;type:character varying(255);not null;comment:密码" json:"password"` // 密码
Name string `gorm:"column:name;type:character varying(255);comment:真实姓名" json:"name"` // 真实姓名
Avatar string `gorm:"column:avatar;type:character varying(255);comment:头像URL" json:"avatar"` // 头像URL
Phone string `gorm:"column:phone;type:character varying(255);comment:手机号码" json:"phone"` // 手机号码
Email string `gorm:"column:email;type:character varying(255);comment:邮箱" json:"email"` // 邮箱
Status int32 `gorm:"column:status;type:integer;not null;default:1;comment:状态0-禁用1-正常" json:"status"` // 状态0-禁用1-正常
LastLogin orm.LocalDateTime `gorm:"column:last_login;type:timestamp without time zone;comment:最后登录时间" json:"last_login"` // 最后登录时间
LastLoginHost string `gorm:"column:last_login_host;type:character varying(45);comment:最后登录地址" json:"last_login_host"` // 最后登录地址
LastLoginAgent string `gorm:"column:last_login_agent;type:character varying(255);comment:最后登录代理" json:"last_login_agent"` // 最后登录代理
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName Admin's table name

View File

@@ -14,14 +14,14 @@ const TableNameAdminRole = "admin_role"
// AdminRole mapped from table <admin_role>
type AdminRole struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:管理员角色ID" json:"id"` // 管理员角色ID
Name string `gorm:"column:name;not null;comment:角色名称" json:"name"` // 角色名称
Description string `gorm:"column:description;comment:角色描述" json:"description"` // 角色描述
Active bool `gorm:"column:active;default:true;comment:是否激活" json:"active"` // 是否激活
Sort int32 `gorm:"column:sort;comment:排序" json:"sort"` // 排序
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:管理员角色ID" json:"id"` // 管理员角色ID
Name string `gorm:"column:name;type:character varying(255);not null;comment:角色名称" json:"name"` // 角色名称
Description string `gorm:"column:description;type:character varying(255);comment:角色描述" json:"description"` // 角色描述
Active bool `gorm:"column:active;type:boolean;default:true;comment:是否激活" json:"active"` // 是否激活
Sort int32 `gorm:"column:sort;type:integer;comment:排序" json:"sort"` // 排序
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName AdminRole's table name

View File

@@ -14,12 +14,12 @@ const TableNameAdminRoleLink = "admin_role_link"
// AdminRoleLink mapped from table <admin_role_link>
type AdminRoleLink struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
AdminID int32 `gorm:"column:admin_id;not null;comment:管理员ID" json:"admin_id"` // 管理员ID
RoleID int32 `gorm:"column:role_id;not null;comment:角色ID" json:"role_id"` // 角色ID
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
AdminID int32 `gorm:"column:admin_id;type:integer;not null;comment:管理员ID" json:"admin_id"` // 管理员ID
RoleID int32 `gorm:"column:role_id;type:integer;not null;comment:角色ID" json:"role_id"` // 角色ID
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName AdminRoleLink's table name

View File

@@ -14,12 +14,12 @@ const TableNameAdminRolePermissionLink = "admin_role_permission_link"
// AdminRolePermissionLink mapped from table <admin_role_permission_link>
type AdminRolePermissionLink struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
RoleID int32 `gorm:"column:role_id;not null;comment:角色ID" json:"role_id"` // 角色ID
PermissionID int32 `gorm:"column:permission_id;not null;comment:权限ID" json:"permission_id"` // 权限ID
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
RoleID int32 `gorm:"column:role_id;type:integer;not null;comment:角色ID" json:"role_id"` // 角色ID
PermissionID int32 `gorm:"column:permission_id;type:integer;not null;comment:权限ID" json:"permission_id"` // 权限ID
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName AdminRolePermissionLink's table name

View File

@@ -14,16 +14,16 @@ const TableNameAnnouncement = "announcement"
// Announcement mapped from table <announcement>
type Announcement struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:公告ID" json:"id"` // 公告ID
Title string `gorm:"column:title;not null;comment:公告标题" json:"title"` // 公告标题
Content string `gorm:"column:content;comment:公告内容" json:"content"` // 公告内容
Type int32 `gorm:"column:type;not null;default:1;comment:公告类型1-普通公告" json:"type"` // 公告类型1-普通公告
Pin bool `gorm:"column:pin;not null;comment:是否置顶" json:"pin"` // 是否置顶
Status int32 `gorm:"column:status;not null;default:1;comment:公告状态0-禁用1-正常" json:"status"` // 公告状态0-禁用1-正常
Sort int32 `gorm:"column:sort;not null;comment:公告排序" json:"sort"` // 公告排序
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:公告ID" json:"id"` // 公告ID
Title string `gorm:"column:title;type:character varying(255);not null;comment:公告标题" json:"title"` // 公告标题
Content string `gorm:"column:content;type:text;comment:公告内容" json:"content"` // 公告内容
Type int32 `gorm:"column:type;type:integer;not null;default:1;comment:公告类型1-普通公告" json:"type"` // 公告类型1-普通公告
Pin bool `gorm:"column:pin;type:boolean;not null;comment:是否置顶" json:"pin"` // 是否置顶
Status int32 `gorm:"column:status;type:integer;not null;default:1;comment:公告状态0-禁用1-正常" json:"status"` // 公告状态0-禁用1-正常
Sort int32 `gorm:"column:sort;type:integer;not null;comment:公告排序" json:"sort"` // 公告排序
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName Announcement's table name

View File

@@ -7,6 +7,7 @@ package models
import (
"platform/web/globals/orm"
"github.com/shopspring/decimal"
"gorm.io/gorm"
)
@@ -14,18 +15,18 @@ const TableNameBill = "bill"
// Bill mapped from table <bill>
type Bill struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:账单ID" json:"id"` // 账单ID
UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID
TradeID int32 `gorm:"column:trade_id;comment:订单ID" json:"trade_id"` // 订单ID
ResourceID int32 `gorm:"column:resource_id;comment:套餐ID" json:"resource_id"` // 套餐ID
RefundID int32 `gorm:"column:refund_id;comment:退款ID" json:"refund_id"` // 退款ID
BillNo string `gorm:"column:bill_no;not null;comment:易读账单号" json:"bill_no"` // 易读账单号
Info string `gorm:"column:info;comment:产品可读信息" json:"info"` // 产品可读信息
Type int32 `gorm:"column:type;not null;comment:账单类型1-消费2-退款3-充值" json:"type"` // 账单类型1-消费2-退款3-充值
Amount float64 `gorm:"column:amount;not null;comment:账单金额" json:"amount"` // 账单金额
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:账单ID" json:"id"` // 账单ID
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
TradeID int32 `gorm:"column:trade_id;type:integer;comment:订单ID" json:"trade_id"` // 订单ID
ResourceID int32 `gorm:"column:resource_id;type:integer;comment:套餐ID" json:"resource_id"` // 套餐ID
RefundID int32 `gorm:"column:refund_id;type:integer;comment:退款ID" json:"refund_id"` // 退款ID
BillNo string `gorm:"column:bill_no;type:character varying(255);not null;comment:易读账单号" json:"bill_no"` // 易读账单号
Info string `gorm:"column:info;type:character varying(255);comment:产品可读信息" json:"info"` // 产品可读信息
Type int32 `gorm:"column:type;type:integer;not null;comment:账单类型1-消费2-退款3-充值" json:"type"` // 账单类型1-消费2-退款3-充值
Amount decimal.Decimal `gorm:"column:amount;type:numeric(12,2);not null;comment:账单金额" json:"amount"` // 账单金额
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
Trade *Trade `gorm:"foreignKey:TradeID" json:"trade"`
Refund *Refund `gorm:"foreignKey:RefundID" json:"refund"`
Resource *Resource `gorm:"foreignKey:ResourceID" json:"resource"`

View File

@@ -14,22 +14,22 @@ const TableNameChannel = "channel"
// Channel mapped from table <channel>
type Channel struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:通道ID" json:"id"` // 通道ID
UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID
ProxyID int32 `gorm:"column:proxy_id;not null;comment:代理ID" json:"proxy_id"` // 代理ID
ProxyHost string `gorm:"column:proxy_host;not null;comment:代理地址" json:"proxy_host"` // 代理地址
ProxyPort int32 `gorm:"column:proxy_port;not null;comment:转发端口" json:"proxy_port"` // 转发端口
Protocol int32 `gorm:"column:protocol;comment:协议类型1-http2-https3-socks5" json:"protocol"` // 协议类型1-http2-https3-socks5
AuthIP bool `gorm:"column:auth_ip;not null;comment:IP认证" json:"auth_ip"` // IP认证
AuthPass bool `gorm:"column:auth_pass;not null;comment:密码认证" json:"auth_pass"` // 密码认证
Username string `gorm:"column:username;comment:用户名" json:"username"` // 用户名
Password string `gorm:"column:password;comment:密码" json:"password"` // 密码
Expiration orm.LocalDateTime `gorm:"column:expiration;not null;comment:过期时间" json:"expiration"` // 过期时间
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
EdgeHost string `gorm:"column:edge_host;comment:节点地址" json:"edge_host"` // 节点地址
EdgeID int32 `gorm:"column:edge_id;comment:节点ID" json:"edge_id"` // 节点ID
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:通道ID" json:"id"` // 通道ID
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
ProxyID int32 `gorm:"column:proxy_id;type:integer;not null;comment:代理ID" json:"proxy_id"` // 代理ID
ProxyHost string `gorm:"column:proxy_host;type:character varying(255);not null;comment:代理地址" json:"proxy_host"` // 代理地址
ProxyPort int32 `gorm:"column:proxy_port;type:integer;not null;comment:转发端口" json:"proxy_port"` // 转发端口
Protocol int32 `gorm:"column:protocol;type:integer;comment:协议类型1-http2-https3-socks5" json:"protocol"` // 协议类型1-http2-https3-socks5
AuthIP bool `gorm:"column:auth_ip;type:boolean;not null;comment:IP认证" json:"auth_ip"` // IP认证
AuthPass bool `gorm:"column:auth_pass;type:boolean;not null;comment:密码认证" json:"auth_pass"` // 密码认证
Username string `gorm:"column:username;type:character varying(255);comment:用户名" json:"username"` // 用户名
Password string `gorm:"column:password;type:character varying(255);comment:密码" json:"password"` // 密码
Expiration orm.LocalDateTime `gorm:"column:expiration;type:timestamp without time zone;not null;comment:过期时间" json:"expiration"` // 过期时间
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
EdgeHost string `gorm:"column:edge_host;type:character varying(255);comment:节点地址" json:"edge_host"` // 节点地址
EdgeID int32 `gorm:"column:edge_id;type:integer;comment:节点ID" json:"edge_id"` // 节点ID
}
// TableName Channel's table name

View File

@@ -14,21 +14,21 @@ const TableNameClient = "client"
// Client mapped from table <client>
type Client struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:客户端ID" json:"id"` // 客户端ID
ClientID string `gorm:"column:client_id;not null;comment:OAuth2客户端标识符" json:"client_id"` // OAuth2客户端标识符
ClientSecret string `gorm:"column:client_secret;not null;comment:OAuth2客户端密钥" json:"client_secret"` // OAuth2客户端密钥
RedirectURI string `gorm:"column:redirect_uri;comment:OAuth2 重定向URI" json:"redirect_uri"` // OAuth2 重定向URI
GrantCode bool `gorm:"column:grant_code;not null;comment:允许授权码授予" json:"grant_code"` // 允许授权码授予
GrantClient bool `gorm:"column:grant_client;not null;comment:允许客户端凭证授予" json:"grant_client"` // 允许客户端凭证授予
GrantRefresh bool `gorm:"column:grant_refresh;not null;comment:允许刷新令牌授予" json:"grant_refresh"` // 允许刷新令牌授予
GrantPassword bool `gorm:"column:grant_password;not null;comment:允许密码授予" json:"grant_password"` // 允许密码授予
Spec int32 `gorm:"column:spec;not null;comment:安全规范1-native2-browser3-web4-trusted" json:"spec"` // 安全规范1-native2-browser3-web4-trusted
Name string `gorm:"column:name;not null;comment:名称" json:"name"` // 名称
Icon string `gorm:"column:icon;comment:图标URL" json:"icon"` // 图标URL
Status int32 `gorm:"column:status;not null;default:1;comment:状态0-禁用1-正常" json:"status"` // 状态0-禁用1-正常
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:客户端ID" json:"id"` // 客户端ID
ClientID string `gorm:"column:client_id;type:character varying(255);not null;comment:OAuth2客户端标识符" json:"client_id"` // OAuth2客户端标识符
ClientSecret string `gorm:"column:client_secret;type:character varying(255);not null;comment:OAuth2客户端密钥" json:"client_secret"` // OAuth2客户端密钥
RedirectURI string `gorm:"column:redirect_uri;type:character varying(255);comment:OAuth2 重定向URI" json:"redirect_uri"` // OAuth2 重定向URI
GrantCode bool `gorm:"column:grant_code;type:boolean;not null;comment:允许授权码授予" json:"grant_code"` // 允许授权码授予
GrantClient bool `gorm:"column:grant_client;type:boolean;not null;comment:允许客户端凭证授予" json:"grant_client"` // 允许客户端凭证授予
GrantRefresh bool `gorm:"column:grant_refresh;type:boolean;not null;comment:允许刷新令牌授予" json:"grant_refresh"` // 允许刷新令牌授予
GrantPassword bool `gorm:"column:grant_password;type:boolean;not null;comment:允许密码授予" json:"grant_password"` // 允许密码授予
Spec int32 `gorm:"column:spec;type:integer;not null;comment:安全规范1-native2-browser3-web4-trusted" json:"spec"` // 安全规范1-native2-browser3-web4-trusted
Name string `gorm:"column:name;type:character varying(255);not null;comment:名称" json:"name"` // 名称
Icon string `gorm:"column:icon;type:character varying(255);comment:图标URL" json:"icon"` // 图标URL
Status int32 `gorm:"column:status;type:integer;not null;default:1;comment:状态0-禁用1-正常" json:"status"` // 状态0-禁用1-正常
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName Client's table name

View File

@@ -14,12 +14,12 @@ const TableNameClientPermissionLink = "client_permission_link"
// ClientPermissionLink mapped from table <client_permission_link>
type ClientPermissionLink struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
ClientID int32 `gorm:"column:client_id;not null;comment:客户端ID" json:"client_id"` // 客户端ID
PermissionID int32 `gorm:"column:permission_id;not null;comment:权限ID" json:"permission_id"` // 权限ID
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
ClientID int32 `gorm:"column:client_id;type:integer;not null;comment:客户端ID" json:"client_id"` // 客户端ID
PermissionID int32 `gorm:"column:permission_id;type:integer;not null;comment:权限ID" json:"permission_id"` // 权限ID
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName ClientPermissionLink's table name

View File

@@ -7,6 +7,7 @@ package models
import (
"platform/web/globals/orm"
"github.com/shopspring/decimal"
"gorm.io/gorm"
)
@@ -14,17 +15,17 @@ const TableNameCoupon = "coupon"
// Coupon mapped from table <coupon>
type Coupon struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:优惠券ID" json:"id"` // 优惠券ID
UserID int32 `gorm:"column:user_id;comment:用户ID" json:"user_id"` // 用户ID
Code string `gorm:"column:code;not null;comment:优惠券代码" json:"code"` // 优惠券代码
Remark string `gorm:"column:remark;comment:优惠券备注" json:"remark"` // 优惠券备注
Amount float64 `gorm:"column:amount;not null;comment:优惠券金额" json:"amount"` // 优惠券金额
MinAmount float64 `gorm:"column:min_amount;not null;comment:最低消费金额" json:"min_amount"` // 最低消费金额
Status int32 `gorm:"column:status;not null;comment:优惠券状态0-未使用1-已使用2-已过期" json:"status"` // 优惠券状态0-未使用1-已使用2-已过期
ExpireAt orm.LocalDateTime `gorm:"column:expire_at;comment:过期时间" json:"expire_at"` // 过期时间
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:优惠券ID" json:"id"` // 优惠券ID
UserID int32 `gorm:"column:user_id;type:integer;comment:用户ID" json:"user_id"` // 用户ID
Code string `gorm:"column:code;type:character varying(255);not null;comment:优惠券代码" json:"code"` // 优惠券代码
Remark string `gorm:"column:remark;type:character varying(255);comment:优惠券备注" json:"remark"` // 优惠券备注
Amount decimal.Decimal `gorm:"column:amount;type:numeric(12,2);not null;comment:优惠券金额" json:"amount"` // 优惠券金额
MinAmount decimal.Decimal `gorm:"column:min_amount;type:numeric(12,2);not null;comment:最低消费金额" json:"min_amount"` // 最低消费金额
Status int32 `gorm:"column:status;type:integer;not null;comment:优惠券状态0-未使用1-已使用2-已过期" json:"status"` // 优惠券状态0-未使用1-已使用2-已过期
ExpireAt orm.LocalDateTime `gorm:"column:expire_at;type:timestamp without time zone;comment:过期时间" json:"expire_at"` // 过期时间
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName Coupon's table name

View File

@@ -14,22 +14,22 @@ const TableNameEdge = "edge"
// Edge mapped from table <edge>
type Edge struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:节点ID" json:"id"` // 节点ID
ProxyID int32 `gorm:"column:proxy_id;comment:代理ID" json:"proxy_id"` // 代理ID
Type int32 `gorm:"column:type;not null;comment:节点类型1-自建" json:"type"` // 节点类型1-自建
Version int32 `gorm:"column:version;not null;comment:节点版本" json:"version"` // 节点版本
Name string `gorm:"column:name;not null;comment:节点名称" json:"name"` // 节点名称
Host string `gorm:"column:host;not null;comment:节点地址" json:"host"` // 节点地址
Isp int32 `gorm:"column:isp;not null;comment:运营商0-未知1-电信2-联通3-移动" json:"isp"` // 运营商0-未知1-电信2-联通3-移动
Prov string `gorm:"column:prov;not null;comment:省份" json:"prov"` // 省份
City string `gorm:"column:city;not null;comment:城市" json:"city"` // 城市
ProxyPort int32 `gorm:"column:proxy_port;comment:代理端口" json:"proxy_port"` // 代理端口
Status int32 `gorm:"column:status;not null;comment:节点状态0-离线1-正常" json:"status"` // 节点状态0-离线1-正常
Rtt int32 `gorm:"column:rtt;comment:最近平均延迟" json:"rtt"` // 最近平均延迟
Loss int32 `gorm:"column:loss;comment:最近丢包率" json:"loss"` // 最近丢包率
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:节点ID" json:"id"` // 节点ID
ProxyID int32 `gorm:"column:proxy_id;type:integer;comment:代理ID" json:"proxy_id"` // 代理ID
Type int32 `gorm:"column:type;type:integer;not null;comment:节点类型1-自建" json:"type"` // 节点类型1-自建
Version int32 `gorm:"column:version;type:integer;not null;comment:节点版本" json:"version"` // 节点版本
Name string `gorm:"column:name;type:character varying(255);not null;comment:节点名称" json:"name"` // 节点名称
Host string `gorm:"column:host;type:character varying(255);not null;comment:节点地址" json:"host"` // 节点地址
Isp int32 `gorm:"column:isp;type:integer;not null;comment:运营商0-未知1-电信2-联通3-移动" json:"isp"` // 运营商0-未知1-电信2-联通3-移动
Prov string `gorm:"column:prov;type:character varying(255);not null;comment:省份" json:"prov"` // 省份
City string `gorm:"column:city;type:character varying(255);not null;comment:城市" json:"city"` // 城市
ProxyPort int32 `gorm:"column:proxy_port;type:integer;comment:代理端口" json:"proxy_port"` // 代理端口
Status int32 `gorm:"column:status;type:integer;not null;comment:节点状态0-离线1-正常" json:"status"` // 节点状态0-离线1-正常
Rtt int32 `gorm:"column:rtt;type:integer;comment:最近平均延迟" json:"rtt"` // 最近平均延迟
Loss int32 `gorm:"column:loss;type:integer;comment:最近丢包率" json:"loss"` // 最近丢包率
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName Edge's table name

View File

@@ -10,17 +10,17 @@ const TableNameLogsRequest = "logs_request"
// LogsRequest mapped from table <logs_request>
type LogsRequest struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:访问日志ID" json:"id"` // 访问日志ID
Identity int32 `gorm:"column:identity;comment:访客身份0-游客1-用户2-管理员3-公共服务4-安全服务5-内部服务" json:"identity"` // 访客身份0-游客1-用户2-管理员3-公共服务4-安全服务5-内部服务
Visitor int32 `gorm:"column:visitor;comment:访客ID" json:"visitor"` // 访客ID
IP string `gorm:"column:ip;not null;comment:IP地址" json:"ip"` // IP地址
Ua string `gorm:"column:ua;comment:用户代理" json:"ua"` // 用户代理
Method string `gorm:"column:method;not null;comment:请求方法" json:"method"` // 请求方法
Path string `gorm:"column:path;not null;comment:请求路径" json:"path"` // 请求路径
Latency string `gorm:"column:latency;comment:请求延迟" json:"latency"` // 请求延迟
Status int32 `gorm:"column:status;not null;comment:响应状态码" json:"status"` // 响应状态码
Error string `gorm:"column:error;comment:错误信息" json:"error"` // 错误信息
Time orm.LocalDateTime `gorm:"column:time;default:CURRENT_TIMESTAMP;comment:请求时间" json:"time"` // 请求时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:访问日志ID" json:"id"` // 访问日志ID
Identity int32 `gorm:"column:identity;type:integer;comment:访客身份0-游客1-用户2-管理员3-公共服务4-安全服务5-内部服务" json:"identity"` // 访客身份0-游客1-用户2-管理员3-公共服务4-安全服务5-内部服务
Visitor int32 `gorm:"column:visitor;type:integer;comment:访客ID" json:"visitor"` // 访客ID
IP string `gorm:"column:ip;type:character varying(45);not null;comment:IP地址" json:"ip"` // IP地址
Ua string `gorm:"column:ua;type:character varying(255);comment:用户代理" json:"ua"` // 用户代理
Method string `gorm:"column:method;type:character varying(10);not null;comment:请求方法" json:"method"` // 请求方法
Path string `gorm:"column:path;type:character varying(255);not null;comment:请求路径" json:"path"` // 请求路径
Latency string `gorm:"column:latency;type:character varying(255);comment:请求延迟" json:"latency"` // 请求延迟
Status int32 `gorm:"column:status;type:integer;not null;comment:响应状态码" json:"status"` // 响应状态码
Error string `gorm:"column:error;type:character varying(255);comment:错误信息" json:"error"` // 错误信息
Time orm.LocalDateTime `gorm:"column:time;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:请求时间" json:"time"` // 请求时间
}
// TableName LogsRequest's table name

View File

@@ -14,13 +14,13 @@ const TableNamePermission = "permission"
// Permission mapped from table <permission>
type Permission struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:权限ID" json:"id"` // 权限ID
ParentID int32 `gorm:"column:parent_id;comment:父权限ID" json:"parent_id"` // 父权限ID
Name string `gorm:"column:name;not null;comment:权限名称" json:"name"` // 权限名称
Description string `gorm:"column:description;comment:权限描述" json:"description"` // 权限描述
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:权限ID" json:"id"` // 权限ID
ParentID int32 `gorm:"column:parent_id;type:integer;comment:父权限ID" json:"parent_id"` // 父权限ID
Name string `gorm:"column:name;type:character varying(255);not null;comment:权限名称" json:"name"` // 权限名称
Description string `gorm:"column:description;type:character varying(255);comment:权限描述" json:"description"` // 权限描述
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName Permission's table name

View File

@@ -14,15 +14,15 @@ const TableNameProduct = "product"
// Product mapped from table <product>
type Product struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:产品ID" json:"id"` // 产品ID
Code string `gorm:"column:code;not null;comment:产品代码" json:"code"` // 产品代码
Name string `gorm:"column:name;not null;comment:产品名称" json:"name"` // 产品名称
Description string `gorm:"column:description;comment:产品描述" json:"description"` // 产品描述
Sort int32 `gorm:"column:sort;not null;comment:排序" json:"sort"` // 排序
Status int32 `gorm:"column:status;not null;default:1;comment:产品状态0-禁用1-正常" json:"status"` // 产品状态0-禁用1-正常
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:产品ID" json:"id"` // 产品ID
Code string `gorm:"column:code;type:character varying(255);not null;comment:产品代码" json:"code"` // 产品代码
Name string `gorm:"column:name;type:character varying(255);not null;comment:产品名称" json:"name"` // 产品名称
Description string `gorm:"column:description;type:character varying(255);comment:产品描述" json:"description"` // 产品描述
Sort int32 `gorm:"column:sort;type:integer;not null;comment:排序" json:"sort"` // 排序
Status int32 `gorm:"column:status;type:integer;not null;default:1;comment:产品状态0-禁用1-正常" json:"status"` // 产品状态0-禁用1-正常
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName Product's table name

View File

@@ -14,16 +14,16 @@ const TableNameProxy = "proxy"
// Proxy mapped from table <proxy>
type Proxy struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:代理服务ID" json:"id"` // 代理服务ID
Version int32 `gorm:"column:version;not null;comment:代理服务版本" json:"version"` // 代理服务版本
Name string `gorm:"column:name;not null;comment:代理服务名称" json:"name"` // 代理服务名称
Host string `gorm:"column:host;not null;comment:代理服务地址" json:"host"` // 代理服务地址
Type int32 `gorm:"column:type;not null;comment:代理服务类型1-三方2-自有" json:"type"` // 代理服务类型1-三方2-自有
Secret string `gorm:"column:secret;comment:代理服务密钥" json:"secret"` // 代理服务密钥
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
Status int32 `gorm:"column:status;not null;comment:代理服务状态0-离线1-在线" json:"status"` // 代理服务状态0-离线1-在线
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:代理服务ID" json:"id"` // 代理服务ID
Version int32 `gorm:"column:version;type:integer;not null;comment:代理服务版本" json:"version"` // 代理服务版本
Name string `gorm:"column:name;type:character varying(255);not null;comment:代理服务名称" json:"name"` // 代理服务名称
Host string `gorm:"column:host;type:character varying(255);not null;comment:代理服务地址" json:"host"` // 代理服务地址
Type int32 `gorm:"column:type;type:integer;not null;comment:代理服务类型1-三方2-自有" json:"type"` // 代理服务类型1-三方2-自有
Secret string `gorm:"column:secret;type:character varying(255);comment:代理服务密钥" json:"secret"` // 代理服务密钥
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
Status int32 `gorm:"column:status;type:integer;not null;comment:代理服务状态0-离线1-在线" json:"status"` // 代理服务状态0-离线1-在线
Edges []Edge `gorm:"foreignKey:ProxyID;references:ID" json:"edges"`
}

View File

@@ -7,6 +7,7 @@ package models
import (
"platform/web/globals/orm"
"github.com/shopspring/decimal"
"gorm.io/gorm"
)
@@ -14,15 +15,15 @@ const TableNameRefund = "refund"
// Refund mapped from table <refund>
type Refund struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:退款ID" json:"id"` // 退款ID
TradeID int32 `gorm:"column:trade_id;not null;comment:订单ID" json:"trade_id"` // 订单ID
ProductID int32 `gorm:"column:product_id;comment:产品ID" json:"product_id"` // 产品ID
Amount float64 `gorm:"column:amount;not null;comment:退款金额" json:"amount"` // 退款金额
Reason string `gorm:"column:reason;comment:退款原因" json:"reason"` // 退款原因
Status int32 `gorm:"column:status;not null;comment:退款状态0-待处理1-已退款2-已拒绝" json:"status"` // 退款状态0-待处理1-已退款2-已拒绝
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:退款ID" json:"id"` // 退款ID
TradeID int32 `gorm:"column:trade_id;type:integer;not null;comment:订单ID" json:"trade_id"` // 订单ID
ProductID int32 `gorm:"column:product_id;type:integer;comment:产品ID" json:"product_id"` // 产品ID
Amount decimal.Decimal `gorm:"column:amount;type:numeric(12,2);not null;comment:退款金额" json:"amount"` // 退款金额
Reason string `gorm:"column:reason;type:character varying(255);comment:退款原因" json:"reason"` // 退款原因
Status int32 `gorm:"column:status;type:integer;not null;comment:退款状态0-待处理1-已退款2-已拒绝" json:"status"` // 退款状态0-待处理1-已退款2-已拒绝
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName Refund's table name

View File

@@ -14,14 +14,14 @@ const TableNameResource = "resource"
// Resource mapped from table <resource>
type Resource struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:套餐ID" json:"id"` // 套餐ID
UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID
ResourceNo string `gorm:"column:resource_no;comment:套餐编号" json:"resource_no"` // 套餐编号
Active bool `gorm:"column:active;not null;default:true;comment:套餐状态" json:"active"` // 套餐状态
Type int32 `gorm:"column:type;not null;comment:套餐类型1-短效动态2-长效动态" json:"type"` // 套餐类型1-短效动态2-长效动态
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:套餐ID" json:"id"` // 套餐ID
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
ResourceNo string `gorm:"column:resource_no;type:character varying(255);comment:套餐编号" json:"resource_no"` // 套餐编号
Active bool `gorm:"column:active;type:boolean;not null;default:true;comment:套餐状态" json:"active"` // 套餐状态
Type int32 `gorm:"column:type;type:integer;not null;comment:套餐类型1-短效动态2-长效动态" json:"type"` // 套餐类型1-短效动态2-长效动态
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
Short *ResourceShort `gorm:"foreignKey:ResourceID;references:ID" json:"short"`
Long *ResourceLong `gorm:"foreignKey:ResourceID;references:ID" json:"long"`
}

View File

@@ -10,16 +10,16 @@ const TableNameResourceLong = "resource_long"
// ResourceLong mapped from table <resource_long>
type ResourceLong struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:ID" json:"id"` // ID
ResourceID int32 `gorm:"column:resource_id;not null;comment:套餐ID" json:"resource_id"` // 套餐ID
Type int32 `gorm:"column:type;comment:套餐类型1-包时2-包量" json:"type"` // 套餐类型1-包时2-包量
Live int32 `gorm:"column:live;comment:可用时长()" json:"live"` // 可用时长()
Expire orm.LocalDateTime `gorm:"column:expire;comment:过期时间" json:"expire"` // 过期时间
Quota int32 `gorm:"column:quota;comment:配额数量" json:"quota"` // 配额数量
Used int32 `gorm:"column:used;not null;comment:已用数量" json:"used"` // 已用数量
DailyLimit int32 `gorm:"column:daily_limit;not null;comment:每日限制" json:"daily_limit"` // 每日限制
DailyUsed int32 `gorm:"column:daily_used;not null;comment:今日已用数量" json:"daily_used"` // 今日已用数量
DailyLast orm.LocalDateTime `gorm:"column:daily_last;comment:今日最后使用时间" json:"daily_last"` // 今日最后使用时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:ID" json:"id"` // ID
ResourceID int32 `gorm:"column:resource_id;type:integer;not null;comment:套餐ID" json:"resource_id"` // 套餐ID
Type int32 `gorm:"column:type;type:integer;comment:套餐类型1-包时2-包量" json:"type"` // 套餐类型1-包时2-包量
Live int32 `gorm:"column:live;type:integer;comment:可用时长()" json:"live"` // 可用时长()
Expire orm.LocalDateTime `gorm:"column:expire;type:timestamp without time zone;comment:过期时间" json:"expire"` // 过期时间
Quota int32 `gorm:"column:quota;type:integer;comment:配额数量" json:"quota"` // 配额数量
Used int32 `gorm:"column:used;type:integer;not null;comment:已用数量" json:"used"` // 已用数量
DailyLimit int32 `gorm:"column:daily_limit;type:integer;not null;comment:每日限制" json:"daily_limit"` // 每日限制
DailyUsed int32 `gorm:"column:daily_used;type:integer;not null;comment:今日已用数量" json:"daily_used"` // 今日已用数量
DailyLast orm.LocalDateTime `gorm:"column:daily_last;type:timestamp without time zone;comment:今日最后使用时间" json:"daily_last"` // 今日最后使用时间
}
// TableName ResourceLong's table name

View File

@@ -10,16 +10,16 @@ const TableNameResourceShort = "resource_short"
// ResourceShort mapped from table <resource_short>
type ResourceShort struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:ID" json:"id"` // ID
ResourceID int32 `gorm:"column:resource_id;not null;comment:套餐ID" json:"resource_id"` // 套餐ID
Type int32 `gorm:"column:type;comment:套餐类型1-包时2-包量" json:"type"` // 套餐类型1-包时2-包量
Live int32 `gorm:"column:live;comment:可用时长(秒)" json:"live"` // 可用时长(秒)
Expire orm.LocalDateTime `gorm:"column:expire;comment:过期时间" json:"expire"` // 过期时间
Quota int32 `gorm:"column:quota;comment:配额数量" json:"quota"` // 配额数量
Used int32 `gorm:"column:used;not null;comment:已用数量" json:"used"` // 已用数量
DailyLimit int32 `gorm:"column:daily_limit;not null;comment:每日限制" json:"daily_limit"` // 每日限制
DailyUsed int32 `gorm:"column:daily_used;not null;comment:今日已用数量" json:"daily_used"` // 今日已用数量
DailyLast orm.LocalDateTime `gorm:"column:daily_last;comment:今日最后使用时间" json:"daily_last"` // 今日最后使用时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:ID" json:"id"` // ID
ResourceID int32 `gorm:"column:resource_id;type:integer;not null;comment:套餐ID" json:"resource_id"` // 套餐ID
Type int32 `gorm:"column:type;type:integer;comment:套餐类型1-包时2-包量" json:"type"` // 套餐类型1-包时2-包量
Live int32 `gorm:"column:live;type:integer;comment:可用时长(秒)" json:"live"` // 可用时长(秒)
Expire orm.LocalDateTime `gorm:"column:expire;type:timestamp without time zone;comment:过期时间" json:"expire"` // 过期时间
Quota int32 `gorm:"column:quota;type:integer;comment:配额数量" json:"quota"` // 配额数量
Used int32 `gorm:"column:used;type:integer;not null;comment:已用数量" json:"used"` // 已用数量
DailyLimit int32 `gorm:"column:daily_limit;type:integer;not null;comment:每日限制" json:"daily_limit"` // 每日限制
DailyUsed int32 `gorm:"column:daily_used;type:integer;not null;comment:今日已用数量" json:"daily_used"` // 今日已用数量
DailyLast orm.LocalDateTime `gorm:"column:daily_last;type:timestamp without time zone;comment:今日最后使用时间" json:"daily_last"` // 今日最后使用时间
}
// TableName ResourceShort's table name

View File

@@ -14,20 +14,20 @@ const TableNameSession = "session"
// Session mapped from table <session>
type Session struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:会话ID" json:"id"` // 会话ID
UserID int32 `gorm:"column:user_id;comment:用户ID" json:"user_id"` // 用户ID
ClientID int32 `gorm:"column:client_id;comment:客户端ID" json:"client_id"` // 客户端ID
IP string `gorm:"column:ip;comment:IP地址" json:"ip"` // IP地址
Ua string `gorm:"column:ua;comment:用户代理" json:"ua"` // 用户代理
GrantType string `gorm:"column:grant_type;not null;default:0;comment:授权类型authorization_code-授权码模式client_credentials-客户端凭证模式refresh_token-刷新令牌模式password-密码模式" json:"grant_type"` // 授权类型authorization_code-授权码模式client_credentials-客户端凭证模式refresh_token-刷新令牌模式password-密码模式
AccessToken string `gorm:"column:access_token;not null;comment:访问令牌" json:"access_token"` // 访问令牌
AccessTokenExpires orm.LocalDateTime `gorm:"column:access_token_expires;not null;comment:访问令牌过期时间" json:"access_token_expires"` // 访问令牌过期时间
RefreshToken string `gorm:"column:refresh_token;comment:刷新令牌" json:"refresh_token"` // 刷新令牌
RefreshTokenExpires orm.LocalDateTime `gorm:"column:refresh_token_expires;comment:刷新令牌过期时间" json:"refresh_token_expires"` // 刷新令牌过期时间
Scopes_ string `gorm:"column:scopes;comment:权限范围" json:"scopes"` // 权限范围
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:会话ID" json:"id"` // 会话ID
UserID int32 `gorm:"column:user_id;type:integer;comment:用户ID" json:"user_id"` // 用户ID
ClientID int32 `gorm:"column:client_id;type:integer;comment:客户端ID" json:"client_id"` // 客户端ID
IP string `gorm:"column:ip;type:character varying(45);comment:IP地址" json:"ip"` // IP地址
Ua string `gorm:"column:ua;type:character varying(255);comment:用户代理" json:"ua"` // 用户代理
GrantType string `gorm:"column:grant_type;type:character varying(255);not null;default:0;comment:授权类型authorization_code-授权码模式client_credentials-客户端凭证模式refresh_token-刷新令牌模式password-密码模式" json:"grant_type"` // 授权类型authorization_code-授权码模式client_credentials-客户端凭证模式refresh_token-刷新令牌模式password-密码模式
AccessToken string `gorm:"column:access_token;type:character varying(255);not null;comment:访问令牌" json:"access_token"` // 访问令牌
AccessTokenExpires orm.LocalDateTime `gorm:"column:access_token_expires;type:timestamp without time zone;not null;comment:访问令牌过期时间" json:"access_token_expires"` // 访问令牌过期时间
RefreshToken string `gorm:"column:refresh_token;type:character varying(255);comment:刷新令牌" json:"refresh_token"` // 刷新令牌
RefreshTokenExpires orm.LocalDateTime `gorm:"column:refresh_token_expires;type:timestamp without time zone;comment:刷新令牌过期时间" json:"refresh_token_expires"` // 刷新令牌过期时间
Scopes_ string `gorm:"column:scopes;type:character varying(255);comment:权限范围" json:"scopes"` // 权限范围
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName Session's table name

View File

@@ -7,6 +7,7 @@ package models
import (
"platform/web/globals/orm"
"github.com/shopspring/decimal"
"gorm.io/gorm"
)
@@ -14,23 +15,23 @@ const TableNameTrade = "trade"
// Trade mapped from table <trade>
type Trade struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:订单ID" json:"id"` // 订单ID
UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID
InnerNo string `gorm:"column:inner_no;not null;comment:内部订单号" json:"inner_no"` // 内部订单号
OuterNo string `gorm:"column:outer_no;comment:外部订单号" json:"outer_no"` // 外部订单号
Type int32 `gorm:"column:type;not null;comment:订单类型1-购买产品2-充值余额" json:"type"` // 订单类型1-购买产品2-充值余额
Subject string `gorm:"column:subject;not null;comment:订单主题" json:"subject"` // 订单主题
Remark string `gorm:"column:remark;comment:订单备注" json:"remark"` // 订单备注
Amount float64 `gorm:"column:amount;not null;comment:订单总金额" json:"amount"` // 订单总金额
Payment float64 `gorm:"column:payment;not null;comment:支付金额" json:"payment"` // 支付金额
Method int32 `gorm:"column:method;not null;comment:支付方式1-支付宝2-微信" json:"method"` // 支付方式1-支付宝2-微信
Status int32 `gorm:"column:status;not null;comment:订单状态0-待支付1-已支付2-已取消3-已退款" json:"status"` // 订单状态0-待支付1-已支付2-已取消3-已退款
PayURL string `gorm:"column:pay_url;comment:支付链接" json:"pay_url"` // 支付链接
PaidAt orm.LocalDateTime `gorm:"column:paid_at;comment:支付时间" json:"paid_at"` // 支付时间
CancelAt orm.LocalDateTime `gorm:"column:cancel_at;comment:取消时间" json:"cancel_at"` // 取消时间
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:订单ID" json:"id"` // 订单ID
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
InnerNo string `gorm:"column:inner_no;type:character varying(255);not null;comment:内部订单号" json:"inner_no"` // 内部订单号
OuterNo string `gorm:"column:outer_no;type:character varying(255);comment:外部订单号" json:"outer_no"` // 外部订单号
Type int32 `gorm:"column:type;type:integer;not null;comment:订单类型1-购买产品2-充值余额" json:"type"` // 订单类型1-购买产品2-充值余额
Subject string `gorm:"column:subject;type:character varying(255);not null;comment:订单主题" json:"subject"` // 订单主题
Remark string `gorm:"column:remark;type:character varying(255);comment:订单备注" json:"remark"` // 订单备注
Amount decimal.Decimal `gorm:"column:amount;type:numeric(12,2);not null;comment:订单总金额" json:"amount"` // 订单总金额
Payment decimal.Decimal `gorm:"column:payment;type:numeric(12,2);not null;comment:支付金额" json:"payment"` // 支付金额
Method int32 `gorm:"column:method;type:integer;not null;comment:支付方式1-支付宝2-微信" json:"method"` // 支付方式1-支付宝2-微信
Status int32 `gorm:"column:status;type:integer;not null;comment:订单状态0-待支付1-已支付2-已取消3-已退款" json:"status"` // 订单状态0-待支付1-已支付2-已取消3-已退款
PayURL string `gorm:"column:pay_url;type:text;comment:支付链接" json:"pay_url"` // 支付链接
PaidAt orm.LocalDateTime `gorm:"column:paid_at;type:timestamp without time zone;comment:支付时间" json:"paid_at"` // 支付时间
CancelAt orm.LocalDateTime `gorm:"column:cancel_at;type:timestamp without time zone;comment:取消时间" json:"cancel_at"` // 取消时间
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName Trade's table name

View File

@@ -7,6 +7,7 @@ package models
import (
"platform/web/globals/orm"
"github.com/shopspring/decimal"
"gorm.io/gorm"
)
@@ -14,27 +15,27 @@ const TableNameUser = "user"
// User mapped from table <user>
type User struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:用户ID" json:"id"` // 用户ID
AdminID int32 `gorm:"column:admin_id;comment:管理员ID" json:"admin_id"` // 管理员ID
Phone string `gorm:"column:phone;not null;comment:手机号码" json:"phone"` // 手机号码
Username string `gorm:"column:username;comment:用户名" json:"username"` // 用户名
Email string `gorm:"column:email" json:"email"`
Password string `gorm:"column:password;comment:用户密码" json:"password"` // 用户密码
Name string `gorm:"column:name;comment:真实姓名" json:"name"` // 真实姓名
Avatar string `gorm:"column:avatar;comment:头像URL" json:"avatar"` // 头像URL
Status int32 `gorm:"column:status;not null;default:1;comment:用户状态0-禁用1-正常" json:"status"` // 用户状态0-禁用1-正常
Balance float64 `gorm:"column:balance;not null;comment:账户余额" json:"balance"` // 账户余额
IDType int32 `gorm:"column:id_type;not null;comment:认证类型0-未认证1-个人认证2-企业认证" json:"id_type"` // 认证类型0-未认证1-个人认证2-企业认证
IDNo string `gorm:"column:id_no;comment:身份证号或营业执照号" json:"id_no"` // 身份证号或营业执照号
IDToken string `gorm:"column:id_token;comment:身份验证标识" json:"id_token"` // 身份验证标识
ContactQQ string `gorm:"column:contact_qq;comment:QQ联系方式" json:"contact_qq"` // QQ联系方式
ContactWechat string `gorm:"column:contact_wechat;comment:微信联系方式" json:"contact_wechat"` // 微信联系方式
LastLogin orm.LocalDateTime `gorm:"column:last_login;comment:最后登录时间" json:"last_login"` // 最后登录时间
LastLoginHost string `gorm:"column:last_login_host;comment:最后登录地址" json:"last_login_host"` // 最后登录地址
LastLoginAgent string `gorm:"column:last_login_agent;comment:最后登录代理" json:"last_login_agent"` // 最后登录代理
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:用户ID" json:"id"` // 用户ID
AdminID int32 `gorm:"column:admin_id;type:integer;comment:管理员ID" json:"admin_id"` // 管理员ID
Phone string `gorm:"column:phone;type:character varying(255);not null;comment:手机号码" json:"phone"` // 手机号码
Username string `gorm:"column:username;type:character varying(255);comment:用户名" json:"username"` // 用户名
Email string `gorm:"column:email;type:character varying(255)" json:"email"`
Password string `gorm:"column:password;type:character varying(255);comment:用户密码" json:"password"` // 用户密码
Name string `gorm:"column:name;type:character varying(255);comment:真实姓名" json:"name"` // 真实姓名
Avatar string `gorm:"column:avatar;type:character varying(255);comment:头像URL" json:"avatar"` // 头像URL
Status int32 `gorm:"column:status;type:integer;not null;default:1;comment:用户状态0-禁用1-正常" json:"status"` // 用户状态0-禁用1-正常
Balance decimal.Decimal `gorm:"column:balance;type:numeric(12,2);not null;comment:账户余额" json:"balance"` // 账户余额
IDType int32 `gorm:"column:id_type;type:integer;not null;comment:认证类型0-未认证1-个人认证2-企业认证" json:"id_type"` // 认证类型0-未认证1-个人认证2-企业认证
IDNo string `gorm:"column:id_no;type:character varying(255);comment:身份证号或营业执照号" json:"id_no"` // 身份证号或营业执照号
IDToken string `gorm:"column:id_token;type:character varying(255);comment:身份验证标识" json:"id_token"` // 身份验证标识
ContactQQ string `gorm:"column:contact_qq;type:character varying(255);comment:QQ联系方式" json:"contact_qq"` // QQ联系方式
ContactWechat string `gorm:"column:contact_wechat;type:character varying(255);comment:微信联系方式" json:"contact_wechat"` // 微信联系方式
LastLogin orm.LocalDateTime `gorm:"column:last_login;type:timestamp without time zone;comment:最后登录时间" json:"last_login"` // 最后登录时间
LastLoginHost string `gorm:"column:last_login_host;type:character varying(45);comment:最后登录地址" json:"last_login_host"` // 最后登录地址
LastLoginAgent string `gorm:"column:last_login_agent;type:character varying(255);comment:最后登录代理" json:"last_login_agent"` // 最后登录代理
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName User's table name

View File

@@ -14,14 +14,14 @@ const TableNameUserRole = "user_role"
// UserRole mapped from table <user_role>
type UserRole struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:角色ID" json:"id"` // 角色ID
Name string `gorm:"column:name;not null;comment:角色名称" json:"name"` // 角色名称
Description string `gorm:"column:description;comment:角色描述" json:"description"` // 角色描述
Active bool `gorm:"column:active;default:true;comment:是否激活" json:"active"` // 是否激活
Sort int32 `gorm:"column:sort;comment:排序" json:"sort"` // 排序
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:角色ID" json:"id"` // 角色ID
Name string `gorm:"column:name;type:character varying(255);not null;comment:角色名称" json:"name"` // 角色名称
Description string `gorm:"column:description;type:character varying(255);comment:角色描述" json:"description"` // 角色描述
Active bool `gorm:"column:active;type:boolean;default:true;comment:是否激活" json:"active"` // 是否激活
Sort int32 `gorm:"column:sort;type:integer;comment:排序" json:"sort"` // 排序
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName UserRole's table name

View File

@@ -14,12 +14,12 @@ const TableNameUserRoleLink = "user_role_link"
// UserRoleLink mapped from table <user_role_link>
type UserRoleLink struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID
RoleID int32 `gorm:"column:role_id;not null;comment:角色ID" json:"role_id"` // 角色ID
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
RoleID int32 `gorm:"column:role_id;type:integer;not null;comment:角色ID" json:"role_id"` // 角色ID
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName UserRoleLink's table name

View File

@@ -14,12 +14,12 @@ const TableNameUserRolePermissionLink = "user_role_permission_link"
// UserRolePermissionLink mapped from table <user_role_permission_link>
type UserRolePermissionLink struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
RoleID int32 `gorm:"column:role_id;not null;comment:角色ID" json:"role_id"` // 角色ID
PermissionID int32 `gorm:"column:permission_id;not null;comment:权限ID" json:"permission_id"` // 权限ID
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
RoleID int32 `gorm:"column:role_id;type:integer;not null;comment:角色ID" json:"role_id"` // 角色ID
PermissionID int32 `gorm:"column:permission_id;type:integer;not null;comment:权限ID" json:"permission_id"` // 权限ID
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName UserRolePermissionLink's table name

View File

@@ -14,13 +14,13 @@ const TableNameWhitelist = "whitelist"
// Whitelist mapped from table <whitelist>
type Whitelist struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:白名单ID" json:"id"` // 白名单ID
UserID int32 `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID
Host string `gorm:"column:host;not null;comment:IP地址" json:"host"` // IP地址
Remark string `gorm:"column:remark;comment:备注" json:"remark"` // 备注
CreatedAt orm.LocalDateTime `gorm:"column:created_at;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间" json:"deleted_at"` // 删除时间
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:白名单ID" json:"id"` // 白名单ID
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
Host string `gorm:"column:host;type:character varying(45);not null;comment:IP地址" json:"host"` // IP地址
Remark string `gorm:"column:remark;type:character varying(255);comment:备注" json:"remark"` // 备注
CreatedAt orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
UpdatedAt orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
}
// TableName Whitelist's table name

View File

@@ -35,7 +35,7 @@ func newBill(db *gorm.DB, opts ...gen.DOOption) bill {
_bill.BillNo = field.NewString(tableName, "bill_no")
_bill.Info = field.NewString(tableName, "info")
_bill.Type = field.NewInt32(tableName, "type")
_bill.Amount = field.NewFloat64(tableName, "amount")
_bill.Amount = field.NewField(tableName, "amount")
_bill.CreatedAt = field.NewField(tableName, "created_at")
_bill.UpdatedAt = field.NewField(tableName, "updated_at")
_bill.DeletedAt = field.NewField(tableName, "deleted_at")
@@ -76,18 +76,18 @@ type bill struct {
billDo
ALL field.Asterisk
ID field.Int32 // 账单ID
UserID field.Int32 // 用户ID
TradeID field.Int32 // 订单ID
ResourceID field.Int32 // 套餐ID
RefundID field.Int32 // 退款ID
BillNo field.String // 易读账单号
Info field.String // 产品可读信息
Type field.Int32 // 账单类型1-消费2-退款3-充值
Amount field.Float64 // 账单金额
CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间
ID field.Int32 // 账单ID
UserID field.Int32 // 用户ID
TradeID field.Int32 // 订单ID
ResourceID field.Int32 // 套餐ID
RefundID field.Int32 // 退款ID
BillNo field.String // 易读账单号
Info field.String // 产品可读信息
Type field.Int32 // 账单类型1-消费2-退款3-充值
Amount field.Field // 账单金额
CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间
Trade billBelongsToTrade
Refund billBelongsToRefund
@@ -117,7 +117,7 @@ func (b *bill) updateTableName(table string) *bill {
b.BillNo = field.NewString(table, "bill_no")
b.Info = field.NewString(table, "info")
b.Type = field.NewInt32(table, "type")
b.Amount = field.NewFloat64(table, "amount")
b.Amount = field.NewField(table, "amount")
b.CreatedAt = field.NewField(table, "created_at")
b.UpdatedAt = field.NewField(table, "updated_at")
b.DeletedAt = field.NewField(table, "deleted_at")

View File

@@ -31,8 +31,8 @@ func newCoupon(db *gorm.DB, opts ...gen.DOOption) coupon {
_coupon.UserID = field.NewInt32(tableName, "user_id")
_coupon.Code = field.NewString(tableName, "code")
_coupon.Remark = field.NewString(tableName, "remark")
_coupon.Amount = field.NewFloat64(tableName, "amount")
_coupon.MinAmount = field.NewFloat64(tableName, "min_amount")
_coupon.Amount = field.NewField(tableName, "amount")
_coupon.MinAmount = field.NewField(tableName, "min_amount")
_coupon.Status = field.NewInt32(tableName, "status")
_coupon.ExpireAt = field.NewField(tableName, "expire_at")
_coupon.CreatedAt = field.NewField(tableName, "created_at")
@@ -48,17 +48,17 @@ type coupon struct {
couponDo
ALL field.Asterisk
ID field.Int32 // 优惠券ID
UserID field.Int32 // 用户ID
Code field.String // 优惠券代码
Remark field.String // 优惠券备注
Amount field.Float64 // 优惠券金额
MinAmount field.Float64 // 最低消费金额
Status field.Int32 // 优惠券状态0-未使用1-已使用2-已过期
ExpireAt field.Field // 过期时间
CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间
ID field.Int32 // 优惠券ID
UserID field.Int32 // 用户ID
Code field.String // 优惠券代码
Remark field.String // 优惠券备注
Amount field.Field // 优惠券金额
MinAmount field.Field // 最低消费金额
Status field.Int32 // 优惠券状态0-未使用1-已使用2-已过期
ExpireAt field.Field // 过期时间
CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间
fieldMap map[string]field.Expr
}
@@ -79,8 +79,8 @@ func (c *coupon) updateTableName(table string) *coupon {
c.UserID = field.NewInt32(table, "user_id")
c.Code = field.NewString(table, "code")
c.Remark = field.NewString(table, "remark")
c.Amount = field.NewFloat64(table, "amount")
c.MinAmount = field.NewFloat64(table, "min_amount")
c.Amount = field.NewField(table, "amount")
c.MinAmount = field.NewField(table, "min_amount")
c.Status = field.NewInt32(table, "status")
c.ExpireAt = field.NewField(table, "expire_at")
c.CreatedAt = field.NewField(table, "created_at")

View File

@@ -30,7 +30,7 @@ func newRefund(db *gorm.DB, opts ...gen.DOOption) refund {
_refund.ID = field.NewInt32(tableName, "id")
_refund.TradeID = field.NewInt32(tableName, "trade_id")
_refund.ProductID = field.NewInt32(tableName, "product_id")
_refund.Amount = field.NewFloat64(tableName, "amount")
_refund.Amount = field.NewField(tableName, "amount")
_refund.Reason = field.NewString(tableName, "reason")
_refund.Status = field.NewInt32(tableName, "status")
_refund.CreatedAt = field.NewField(tableName, "created_at")
@@ -46,15 +46,15 @@ type refund struct {
refundDo
ALL field.Asterisk
ID field.Int32 // 退款ID
TradeID field.Int32 // 订单ID
ProductID field.Int32 // 产品ID
Amount field.Float64 // 退款金额
Reason field.String // 退款原因
Status field.Int32 // 退款状态0-待处理1-已退款2-已拒绝
CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间
ID field.Int32 // 退款ID
TradeID field.Int32 // 订单ID
ProductID field.Int32 // 产品ID
Amount field.Field // 退款金额
Reason field.String // 退款原因
Status field.Int32 // 退款状态0-待处理1-已退款2-已拒绝
CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间
fieldMap map[string]field.Expr
}
@@ -74,7 +74,7 @@ func (r *refund) updateTableName(table string) *refund {
r.ID = field.NewInt32(table, "id")
r.TradeID = field.NewInt32(table, "trade_id")
r.ProductID = field.NewInt32(table, "product_id")
r.Amount = field.NewFloat64(table, "amount")
r.Amount = field.NewField(table, "amount")
r.Reason = field.NewString(table, "reason")
r.Status = field.NewInt32(table, "status")
r.CreatedAt = field.NewField(table, "created_at")

View File

@@ -50,7 +50,7 @@ type resourceLong struct {
ID field.Int32 // ID
ResourceID field.Int32 // 套餐ID
Type field.Int32 // 套餐类型1-包时2-包量
Live field.Int32 // 可用时长()
Live field.Int32 // 可用时长()
Expire field.Field // 过期时间
Quota field.Int32 // 配额数量
Used field.Int32 // 已用数量

View File

@@ -34,8 +34,8 @@ func newTrade(db *gorm.DB, opts ...gen.DOOption) trade {
_trade.Type = field.NewInt32(tableName, "type")
_trade.Subject = field.NewString(tableName, "subject")
_trade.Remark = field.NewString(tableName, "remark")
_trade.Amount = field.NewFloat64(tableName, "amount")
_trade.Payment = field.NewFloat64(tableName, "payment")
_trade.Amount = field.NewField(tableName, "amount")
_trade.Payment = field.NewField(tableName, "payment")
_trade.Method = field.NewInt32(tableName, "method")
_trade.Status = field.NewInt32(tableName, "status")
_trade.PayURL = field.NewString(tableName, "pay_url")
@@ -54,23 +54,23 @@ type trade struct {
tradeDo
ALL field.Asterisk
ID field.Int32 // 订单ID
UserID field.Int32 // 用户ID
InnerNo field.String // 内部订单号
OuterNo field.String // 外部订单号
Type field.Int32 // 订单类型1-购买产品2-充值余额
Subject field.String // 订单主题
Remark field.String // 订单备注
Amount field.Float64 // 订单总金额
Payment field.Float64 // 支付金额
Method field.Int32 // 支付方式1-支付宝2-微信
Status field.Int32 // 订单状态0-待支付1-已支付2-已取消3-已退款
PayURL field.String // 支付链接
PaidAt field.Field // 支付时间
CancelAt field.Field // 取消时间
CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间
ID field.Int32 // 订单ID
UserID field.Int32 // 用户ID
InnerNo field.String // 内部订单号
OuterNo field.String // 外部订单号
Type field.Int32 // 订单类型1-购买产品2-充值余额
Subject field.String // 订单主题
Remark field.String // 订单备注
Amount field.Field // 订单总金额
Payment field.Field // 支付金额
Method field.Int32 // 支付方式1-支付宝2-微信
Status field.Int32 // 订单状态0-待支付1-已支付2-已取消3-已退款
PayURL field.String // 支付链接
PaidAt field.Field // 支付时间
CancelAt field.Field // 取消时间
CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间
fieldMap map[string]field.Expr
}
@@ -94,8 +94,8 @@ func (t *trade) updateTableName(table string) *trade {
t.Type = field.NewInt32(table, "type")
t.Subject = field.NewString(table, "subject")
t.Remark = field.NewString(table, "remark")
t.Amount = field.NewFloat64(table, "amount")
t.Payment = field.NewFloat64(table, "payment")
t.Amount = field.NewField(table, "amount")
t.Payment = field.NewField(table, "payment")
t.Method = field.NewInt32(table, "method")
t.Status = field.NewInt32(table, "status")
t.PayURL = field.NewString(table, "pay_url")

View File

@@ -36,7 +36,7 @@ func newUser(db *gorm.DB, opts ...gen.DOOption) user {
_user.Name = field.NewString(tableName, "name")
_user.Avatar = field.NewString(tableName, "avatar")
_user.Status = field.NewInt32(tableName, "status")
_user.Balance = field.NewFloat64(tableName, "balance")
_user.Balance = field.NewField(tableName, "balance")
_user.IDType = field.NewInt32(tableName, "id_type")
_user.IDNo = field.NewString(tableName, "id_no")
_user.IDToken = field.NewString(tableName, "id_token")
@@ -63,22 +63,22 @@ type user struct {
Phone field.String // 手机号码
Username field.String // 用户名
Email field.String
Password field.String // 用户密码
Name field.String // 真实姓名
Avatar field.String // 头像URL
Status field.Int32 // 用户状态0-禁用1-正常
Balance field.Float64 // 账户余额
IDType field.Int32 // 认证类型0-未认证1-个人认证2-企业认证
IDNo field.String // 身份证号或营业执照号
IDToken field.String // 身份验证标识
ContactQQ field.String // QQ联系方式
ContactWechat field.String // 微信联系方式
LastLogin field.Field // 最后登录时间
LastLoginHost field.String // 最后登录地址
LastLoginAgent field.String // 最后登录代理
CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间
Password field.String // 用户密码
Name field.String // 真实姓名
Avatar field.String // 头像URL
Status field.Int32 // 用户状态0-禁用1-正常
Balance field.Field // 账户余额
IDType field.Int32 // 认证类型0-未认证1-个人认证2-企业认证
IDNo field.String // 身份证号或营业执照号
IDToken field.String // 身份验证标识
ContactQQ field.String // QQ联系方式
ContactWechat field.String // 微信联系方式
LastLogin field.Field // 最后登录时间
LastLoginHost field.String // 最后登录地址
LastLoginAgent field.String // 最后登录代理
CreatedAt field.Field // 创建时间
UpdatedAt field.Field // 更新时间
DeletedAt field.Field // 删除时间
fieldMap map[string]field.Expr
}
@@ -104,7 +104,7 @@ func (u *user) updateTableName(table string) *user {
u.Name = field.NewString(table, "name")
u.Avatar = field.NewString(table, "avatar")
u.Status = field.NewInt32(table, "status")
u.Balance = field.NewFloat64(table, "balance")
u.Balance = field.NewField(table, "balance")
u.IDType = field.NewInt32(table, "id_type")
u.IDNo = field.NewString(table, "id_no")
u.IDToken = field.NewString(table, "id_token")

View File

@@ -28,12 +28,6 @@ func ApplyRouters(app *fiber.App) {
user.Post("/recharge/prepare/wechat", handlers.RechargePrepareWechat)
user.Post("/recharge/confirm/wechat", handlers.RechargeConfirmWechat)
// 通道
channel := api.Group("/channel")
channel.Post("/list", handlers.ListChannels)
channel.Post("/create", handlers.CreateChannel)
channel.Post("/remove", handlers.RemoveChannels)
// 白名单
whitelist := api.Group("/whitelist")
whitelist.Post("/list", handlers.ListWhitelist)
@@ -45,20 +39,25 @@ func ApplyRouters(app *fiber.App) {
resource := api.Group("/resource")
resource.Post("/list/short", handlers.ListResourceShort)
resource.Post("/all", handlers.AllResource)
resource.Post("/create/balance", handlers.CreateResourceByBalance)
resource.Post("/prepare/alipay", handlers.PrepareResourceByAlipay)
resource.Post("/create/alipay", handlers.CreateResourceByAlipay)
resource.Post("/prepare/wechat", handlers.PrepareResourceByWechat)
resource.Post("/create/wechat", handlers.CreateResourceByWechat)
resource.Post("/create", handlers.CreateResource)
resource.Post("/create/prepare", handlers.PrepareCreateResource)
resource.Post("/create/complete", handlers.CompleteCreateResource)
resource.Post("/price", handlers.ResourcePrice)
// 账单
bill := api.Group("/bill")
bill.Post("/list", handlers.ListBill)
// 通道
channel := api.Group("/channel")
channel.Post("/list", handlers.ListChannels)
channel.Post("/create", handlers.CreateChannel)
channel.Post("/remove", handlers.RemoveChannels)
// 交易
trade := api.Group("/trade")
trade.Post("/callback/alipay", handlers.AlipayCallback)
// 账单
bill := api.Group("/bill")
bill.Post("/list", handlers.ListBill)
// 公告
announcement := api.Group("/announcement")
announcement.Post("/list", handlers.ListAnnouncements)

View File

@@ -305,28 +305,33 @@ func findResource(q *q.Query, resourceId int32, userId int32, count int, now tim
return nil, ErrResourceInvalid
}
// 检查每日限额
used := 0
if now.Format("2006-01-02") == info.DailyLast.Format("2006-01-02") {
used = int(info.DailyUsed)
}
excess := used+count > int(info.DailyLimit)
if excess {
return nil, ErrResourceDailyLimit
}
// 检查时间或配额
// 检查套餐使用情况
switch info.Mode {
default:
return nil, ChannelServiceErr("不支持的套餐模式")
// 包时
case resource2.ModeTime:
// 检查过期时间
if info.Expire.Before(now) {
return nil, ErrResourceExpired
}
// 检查每日限额
used := 0
if now.Format("2006-01-02") == info.DailyLast.Format("2006-01-02") {
used = int(info.DailyUsed)
}
excess := used+count > int(info.DailyLimit)
if excess {
return nil, ErrResourceDailyLimit
}
// 包量
case resource2.ModeCount:
// 检查可用配额
if int(info.Quota)-int(info.Used) < count {
return nil, ErrResourceExhausted
}
default:
return nil, ChannelServiceErr("不支持的套餐模式")
}
return info, nil

View File

@@ -5,6 +5,8 @@ import (
"database/sql"
"encoding/json"
"fmt"
"github.com/gofiber/fiber/v2"
"github.com/shopspring/decimal"
bill2 "platform/web/domains/bill"
resource2 "platform/web/domains/resource"
trade2 "platform/web/domains/trade"
@@ -12,27 +14,97 @@ import (
"platform/web/globals/orm"
m "platform/web/models"
q "platform/web/queries"
"strings"
"time"
"github.com/gofiber/fiber/v2"
)
var Resource = &resourceService{}
type resourceService struct{}
func (s *resourceService) PrepareResource(ctx context.Context, data *CreateResourceData, uid int32, method trade2.Method) (*TransactionPrepareResult, error) {
func (s *resourceService) CreateResource(uid int32, now time.Time, ser *CreateResourceSerializer) error {
data, err := ser.ToData()
if err != nil {
return err
}
var name = data.GetName()
var amount = data.GetPrice()
// 保存交易信息
err = q.Q.Transaction(func(q *q.Query) error {
// 检查用户
user, err := q.User.
Where(q.User.ID.Eq(uid)).
Take()
if err != nil {
return err
}
// 检查余额
if user.Balance.Cmp(amount) < 0 {
return fiber.NewError(fiber.StatusBadRequest, "余额不足")
}
// 保存套餐
resource, err := createResource(q, uid, now, data)
if err != nil {
return err
}
// 生成账单
bill := m.Bill{
UserID: uid,
ResourceID: resource.ID,
BillNo: ID.GenReadable("bil"),
Info: "购买套餐 - " + name,
Type: int32(bill2.TypeConsume),
Amount: amount,
}
err = q.Bill.
Omit(q.Bill.TradeID, q.Bill.RefundID).
Create(&bill)
if err != nil {
return err
}
// 更新用户余额
_, err = q.User.UpdateSimple(q.User.Balance.Value(user.Balance.Sub(amount)))
if err != nil {
return err
}
if err != nil {
return err
}
return nil
}, &sql.TxOptions{Isolation: sql.LevelRepeatableRead})
if err != nil {
return err
}
return nil
}
func (s *resourceService) PrepareResource(uid int32, now time.Time, method trade2.Method, ser *CreateResourceSerializer) (*TransactionPrepareResult, error) {
data, err := ser.ToData()
if err != nil {
return nil, err
}
name := data.GetName()
amount := data.GetPrice()
// 保存到数据库
var result *TransactionPrepareResult
err := q.Q.Transaction(func(q *q.Query) error {
err = q.Q.Transaction(func(q *q.Query) error {
var err error
// 生成交易订单
result, err = Transaction.PrepareTransaction(ctx, q, uid, &TransactionPrepareData{
Subject: "购买套餐 - " + data.GetName(),
result, err = Transaction.PrepareTransaction(q, uid, now, &TransactionPrepareData{
Subject: "购买套餐 - " + name,
Amount: amount,
ExpireAt: time.Now().Add(30 * time.Minute),
Type: trade2.TypeRecharge,
@@ -43,16 +115,18 @@ func (s *resourceService) PrepareResource(ctx context.Context, data *CreateResou
}
// 保存请求缓存
reqStr, err := json.Marshal(&CreateResourceCache{
CreateResourceData: *data,
Uid: uid,
TradeId: result.Trade.ID,
BillId: result.Bill.ID,
})
if err != nil {
resourceSerializer := CreateResourceSerializer{}
if err := resourceSerializer.ByData(data); err != nil {
return err
}
err = g.Redis.Set(ctx, result.TradeNo, reqStr, 30*time.Minute).Err()
err = g.Redis.Set(context.Background(), result.TradeNo, &CreateResourceCache{
Uid: uid,
TradeId: result.Trade.ID,
BillId: result.Bill.ID,
Method: method,
CreateResourceSerializer: resourceSerializer,
}, 30*time.Minute).Err()
if err != nil {
return err
}
@@ -66,10 +140,10 @@ func (s *resourceService) PrepareResource(ctx context.Context, data *CreateResou
return result, nil
}
func (s *resourceService) CompleteResource(ctx context.Context, tradeNo string, rs *TransactionVerifyResult) error {
func (s *resourceService) CompleteResource(tradeNo string, now time.Time, opResult ...*TransactionVerifyResult) error {
// 获取请求缓存
reqStr, err := g.Redis.Get(ctx, tradeNo).Result()
reqStr, err := g.Redis.Get(context.Background(), tradeNo).Result()
if err != nil {
return err
}
@@ -78,11 +152,31 @@ func (s *resourceService) CompleteResource(ctx context.Context, tradeNo string,
return err
}
// 检查交易结果
var rs *TransactionVerifyResult
if len(opResult) > 0 {
rs = opResult[0]
} else {
var err error
rs, err = Transaction.VerifyTransaction(&TransactionVerifyData{
TradeNo: tradeNo,
Method: cache.Method,
})
if err != nil {
return err
}
}
data, err := cache.ToData()
if err != nil {
return err
}
// 保存交易信息
err = q.Q.Transaction(func(q *q.Query) error {
// 保存套餐
resource, err := createResource(q, &cache.CreateResourceData, cache.Uid)
resource, err := createResource(q, cache.Uid, now, data)
if err != nil {
return err
}
@@ -99,7 +193,7 @@ func (s *resourceService) CompleteResource(ctx context.Context, tradeNo string,
}
// 完成交易
_, err = Transaction.CompleteTransaction(ctx, q, &TransactionCompleteData{
_, err = Transaction.CompleteTransaction(q, &TransactionCompleteData{
TradeNo: tradeNo,
TransactionVerifyResult: *rs,
})
@@ -108,7 +202,7 @@ func (s *resourceService) CompleteResource(ctx context.Context, tradeNo string,
}
// 删除缓存
err = g.Redis.Del(ctx, tradeNo).Err()
err = g.Redis.Del(context.Background(), tradeNo).Err()
if err != nil {
return err
}
@@ -122,57 +216,27 @@ func (s *resourceService) CompleteResource(ctx context.Context, tradeNo string,
return nil
}
func (s *resourceService) CreateResource(data *CreateResourceData, uid int32) error {
func (s *resourceService) CancelResource(tradeNo string, now time.Time, opRevoked ...bool) error {
// 删除请求缓存
cacheStr, err := g.Redis.GetDel(context.Background(), tradeNo).Result()
if err != nil {
return err
}
cache := new(CreateResourceCache)
if err := json.Unmarshal([]byte(cacheStr), cache); err != nil {
return err
}
// 保存交易信息
err := q.Q.Transaction(func(q *q.Query) error {
amount := data.GetPrice()
// 检查用户
user, err := q.User.
Where(q.User.ID.Eq(uid)).
Take()
// 取消交易
if len(opRevoked) <= 0 {
err = Transaction.RevokeTransaction(tradeNo, cache.Method)
if err != nil {
return err
}
}
// 检查余额
if user.Balance < amount {
return fiber.NewError(fiber.StatusBadRequest, "余额不足")
}
// 保存套餐
resource, err := createResource(q, data, uid)
if err != nil {
return err
}
// 生成账单
bill := m.Bill{
UserID: uid,
ResourceID: resource.ID,
BillNo: ID.GenReadable("bil"),
Info: "购买套餐 - " + data.GetName(),
Type: int32(bill2.TypeConsume),
Amount: data.GetPrice(),
}
err = q.Bill.
Omit(q.Bill.TradeID, q.Bill.RefundID).
Create(&bill)
if err != nil {
return err
}
// 更新用户余额
_, err = q.User.
Where(q.User.ID.Eq(uid)).
UpdateSimple(q.User.Balance.Sub(amount))
if err != nil {
return err
}
return nil
}, &sql.TxOptions{Isolation: sql.LevelRepeatableRead})
// 更新订单状态
err = Transaction.FinishTransaction(q.Q, tradeNo, now)
if err != nil {
return err
}
@@ -180,81 +244,44 @@ func (s *resourceService) CreateResource(data *CreateResourceData, uid int32) er
return nil
}
type CreateResourceData struct {
Type int32 `json:"type" validate:"required"`
Live int32 `json:"live" validate:"required"`
Expire int32 `json:"expire" validate:"required"`
Quota int32 `json:"quota" validate:"required"`
DailyLimit int32 `json:"daily_limit" validate:"required"`
func createResource(q *q.Query, uid int32, now time.Time, data CreateResourceData) (*m.Resource, error) {
name string
price float64
}
func (data *CreateResourceData) GetName() string {
if data.name == "" {
sb := strings.Builder{}
sb.WriteString("短效动态")
switch data.Type {
case 1:
sb.WriteString("包时 ")
case 2:
sb.WriteString("包量 ")
}
sb.WriteString(fmt.Sprintf("%d 分钟", data.Live/60))
data.name = sb.String()
}
return data.name
}
func (data *CreateResourceData) GetPrice() float64 {
if data.price == 0 {
var count int
switch data.Type {
case 1:
count = int(data.DailyLimit)
case 2:
count = int(data.Quota)
}
seconds := int(data.Live)
if seconds == 180 {
seconds = 150
}
times := int(data.Expire)
if data.Type == 2 {
times = 1
}
data.price = float64(count*seconds*times) / 30000
}
return data.price
}
type CreateResourceCache struct {
CreateResourceData `json:"data"`
Uid int32 `json:"uid"`
TradeId int32 `json:"trade_id"`
BillId int32 `json:"bill_id"`
}
func createResource(q *q.Query, data *CreateResourceData, uid int32) (*m.Resource, error) {
// 创建套餐
resource := m.Resource{
// 套餐基本信息
var resource = m.Resource{
UserID: uid,
ResourceNo: ID.GenReadable("res"),
Active: true,
Type: int32(resource2.TypeShort),
Short: &m.ResourceShort{
Type: data.Type,
}
switch data := data.(type) {
// 短效套餐
case *CreateShortResourceData:
var duration = time.Duration(data.Expire) * 24 * time.Hour
resource.Type = int32(resource2.TypeShort)
resource.Short = &m.ResourceShort{
Type: data.Mode,
Live: data.Live,
Quota: data.Quota,
Expire: orm.LocalDateTime(time.Now().Add(time.Duration(data.Expire) * 24 * time.Hour)),
Expire: orm.LocalDateTime(now.Add(duration)),
DailyLimit: data.DailyLimit,
},
}
// 长效套餐
case *CreateLongResourceData:
var duration = time.Duration(data.Expire) * 24 * time.Hour
resource.Type = int32(resource2.TypeLong)
resource.Long = &m.ResourceLong{
Type: data.Mode,
Live: data.Live,
Quota: data.Quota,
Expire: orm.LocalDateTime(now.Add(duration)),
DailyLimit: data.DailyLimit,
}
default:
return nil, fmt.Errorf("不支持的套餐类型")
}
err := q.Resource.Create(&resource)
if err != nil {
return nil, err
@@ -263,24 +290,154 @@ func createResource(q *q.Query, data *CreateResourceData, uid int32) (*m.Resourc
return &resource, nil
}
func (s *resourceService) CancelResource(ctx context.Context, tradeNo string, at time.Time, method trade2.Method) error {
// 删除请求缓存
_, err := g.Redis.Del(ctx, tradeNo).Result()
if err != nil {
return err
}
type CreateResourceData interface {
GetName() string
GetPrice() decimal.Decimal
}
// 取消交易
err = Transaction.RevokeTransaction(ctx, tradeNo, method)
if err != nil {
return err
}
type CreateShortResourceData struct {
Live int32 `json:"live" validate:"required min=180"`
Mode int32 `json:"mode" validate:"required"`
Expire int32 `json:"expire"`
DailyLimit int32 `json:"daily_limit" validate:"min=2000"`
Quota int32 `json:"quota" validate:"min=10000"`
// 更新订单状态
err = Transaction.FinishTransaction(ctx, q.Q, tradeNo, at)
if err != nil {
return err
}
name string
price *decimal.Decimal
}
func (data *CreateShortResourceData) GetName() string {
if data.name == "" {
var mode string
switch data.Mode {
case 1:
mode = "包时"
case 2:
mode = "包量"
}
data.name = fmt.Sprintf("短效动态%s %d 天", mode, data.Live)
}
return data.name
}
func (data *CreateShortResourceData) GetPrice() decimal.Decimal {
if data.price == nil {
var factor int32
switch data.Mode {
case 1:
factor = data.DailyLimit * data.Expire
case 2:
factor = data.Quota
}
var base = data.Live
if base == 180 {
base = 150
}
var dec = decimal.Decimal{}.
Add(decimal.NewFromInt32(base * factor)).
Div(decimal.NewFromInt(30000))
data.price = &dec
}
return *data.price
}
type CreateLongResourceData struct {
Live int32 `json:"live" validate:"required oneof=1,4,8,12,24"`
Mode int32 `json:"mode" validate:"required oneof=1,2"`
Expire int32 `json:"expire"`
DailyLimit int32 `json:"daily_limit" validate:"min=100"`
Quota int32 `json:"quota" validate:"min=500"`
name string
price *decimal.Decimal
}
func (data *CreateLongResourceData) GetName() string {
if data.name == "" {
var mode string
switch data.Mode {
case 1:
mode = "包时"
case 2:
mode = "包量"
}
data.name = fmt.Sprintf("长效动态%s %d 天", mode, data.Live)
}
return data.name
}
func (data *CreateLongResourceData) GetPrice() decimal.Decimal {
if data.price == nil {
var factor int32 = 0
switch resource2.Mode(data.Mode) {
case resource2.ModeTime:
factor = data.Expire * data.DailyLimit
case resource2.ModeCount:
factor = data.Quota
}
var base int32
switch data.Live {
case 1:
base = 30
case 4:
base = 80
case 8:
base = 120
case 12:
base = 180
case 24:
base = 350
}
// data.price = big.NewRat(int64(base*factor), 100)
var dec = decimal.Decimal{}.
Add(decimal.NewFromInt32(base * factor)).
Div(decimal.NewFromInt(100))
data.price = &dec
}
return *data.price
}
type CreateResourceCache struct {
Uid int32 `json:"uid"`
TradeId int32 `json:"trade_id"`
BillId int32 `json:"bill_id"`
Method trade2.Method `json:"method"`
CreateResourceSerializer
}
type CreateResourceSerializer struct {
Type resource2.Type `json:"type" validate:"required"`
Short *CreateShortResourceData `json:"short,omitempty"`
Long *CreateLongResourceData `json:"long,omitempty"`
}
func (s *CreateResourceSerializer) ToData() (CreateResourceData, error) {
switch s.Type {
case resource2.TypeShort:
return s.Short, nil
case resource2.TypeLong:
return s.Long, nil
}
return nil, fmt.Errorf("不支持的套餐类型")
}
func (s *CreateResourceSerializer) ByData(data CreateResourceData) error {
switch data := data.(type) {
case *CreateShortResourceData:
s.Type = resource2.TypeShort
s.Short = data
case *CreateLongResourceData:
s.Type = resource2.TypeLong
s.Long = data
default:
return fmt.Errorf("不支持的套餐类型")
}
return nil
}

View File

@@ -3,6 +3,7 @@ package services
import (
"context"
"errors"
"github.com/shopspring/decimal"
"io"
"log/slog"
"net/http"
@@ -15,7 +16,6 @@ import (
"platform/web/globals/orm"
m "platform/web/models"
q "platform/web/queries"
"strconv"
"time"
"github.com/smartwalle/alipay/v3"
@@ -28,7 +28,7 @@ var Transaction = &transactionService{}
type transactionService struct {
}
func (s *transactionService) PrepareTransaction(ctx context.Context, q *q.Query, uid int32, data *TransactionPrepareData) (*TransactionPrepareResult, error) {
func (s *transactionService) PrepareTransaction(q *q.Query, uid int32, now time.Time, data *TransactionPrepareData) (*TransactionPrepareResult, error) {
var subject = data.Subject
var expire = data.ExpireAt
var tType = data.Type
@@ -38,12 +38,12 @@ func (s *transactionService) PrepareTransaction(ctx context.Context, q *q.Query,
// 实际支付金额,只在创建真实订单时使用
var amountReal = data.Amount
if env.RunMode == "debug" {
amountReal = 0.01
amountReal = decimal.NewFromFloat(0.01)
}
// 附加优惠券
if data.CouponCode != "" {
coupon, err := q.Coupon.WithContext(ctx).
coupon, err := q.Coupon.
Where(
q.Coupon.Code.Eq(data.CouponCode),
q.Coupon.Status.Eq(int32(coupon2.StatusUnused)),
@@ -57,7 +57,7 @@ func (s *transactionService) PrepareTransaction(ctx context.Context, q *q.Query,
}
var expireAt = time.Time(coupon.ExpireAt)
if !expireAt.IsZero() && expireAt.Before(time.Now()) {
if !expireAt.IsZero() && expireAt.Before(now) {
_, err = q.Coupon.
Where(q.Coupon.ID.Eq(coupon.ID)).
Update(q.Coupon.Status, coupon2.StatusExpired)
@@ -67,7 +67,7 @@ func (s *transactionService) PrepareTransaction(ctx context.Context, q *q.Query,
return nil, errors.New("优惠券已过期")
}
if data.Amount < coupon.MinAmount {
if amount.Cmp(coupon.MinAmount) < 0 {
return nil, errors.New("订单金额未达到使用优惠券的条件")
}
@@ -78,11 +78,11 @@ func (s *transactionService) PrepareTransaction(ctx context.Context, q *q.Query,
// 公开优惠券
case coupon.UserID == 0:
amount = amount - coupon.Amount
amount = amount.Sub(coupon.Amount)
// 指定用户的优惠券
case coupon.UserID == uid:
amount = amount - coupon.Amount
amount = amount.Sub(coupon.Amount)
if time.Time(coupon.ExpireAt).IsZero() {
_, err = q.Coupon.
Where(q.Coupon.ID.Eq(coupon.ID)).
@@ -95,7 +95,7 @@ func (s *transactionService) PrepareTransaction(ctx context.Context, q *q.Query,
}
// 生成订单号
tradeNo, err := ID.GenSerial(ctx)
tradeNo, err := ID.GenSerial(context.Background())
if err != nil {
return nil, err
}
@@ -113,7 +113,7 @@ func (s *transactionService) PrepareTransaction(ctx context.Context, q *q.Query,
ProductCode: "FAST_INSTANT_TRADE_PAY",
OutTradeNo: tradeNo,
Subject: subject,
TotalAmount: strconv.FormatFloat(amountReal, 'f', 2, 64),
TotalAmount: amountReal.StringFixed(2),
TimeExpire: expire.Format("2006-01-02 15:04:05"),
},
})
@@ -124,7 +124,7 @@ func (s *transactionService) PrepareTransaction(ctx context.Context, q *q.Query,
// 调用微信支付接口
case trade2.MethodWeChat:
resp, _, err := g.WechatPay.Native.Prepay(ctx, native.PrepayRequest{
resp, _, err := g.WechatPay.Native.Prepay(context.Background(), native.PrepayRequest{
Appid: &env.WechatPayAppId,
Mchid: &env.WechatPayMchId,
OutTradeNo: &tradeNo,
@@ -132,7 +132,7 @@ func (s *transactionService) PrepareTransaction(ctx context.Context, q *q.Query,
TimeExpire: &expire,
NotifyUrl: &env.WechatPayCallbackUrl,
Amount: &native.Amount{
Total: u.P(int64(amountReal * 100)),
Total: u.P(amountReal.Mul(decimal.NewFromInt(100)).Round(0).IntPart()),
},
})
if err != nil {
@@ -192,19 +192,19 @@ func (s *transactionService) PrepareTransaction(ctx context.Context, q *q.Query,
}, nil
}
func (s *transactionService) VerifyTransaction(ctx context.Context, data *TransactionVerifyData) (*TransactionVerifyResult, error) {
func (s *transactionService) VerifyTransaction(data *TransactionVerifyData) (*TransactionVerifyResult, error) {
var tradeNo = data.TradeNo
var method = data.Method
// 检查交易号是否存在
var transId string
var paidAt time.Time
var payment float64
var payment decimal.Decimal
switch method {
// 检查支付宝交易
case trade2.MethodAlipay:
resp, err := g.Alipay.TradeQuery(ctx, alipay.TradeQuery{
resp, err := g.Alipay.TradeQuery(context.Background(), alipay.TradeQuery{
OutTradeNo: tradeNo,
})
if err != nil {
@@ -219,7 +219,7 @@ func (s *transactionService) VerifyTransaction(ctx context.Context, data *Transa
}
transId = resp.TradeNo
payment, err = strconv.ParseFloat(resp.TotalAmount, 64)
payment, err = decimal.NewFromString(resp.TotalAmount)
if err != nil {
return nil, err
}
@@ -230,7 +230,7 @@ func (s *transactionService) VerifyTransaction(ctx context.Context, data *Transa
// 检查微信交易
case trade2.MethodWeChat:
resp, _, err := g.WechatPay.Native.QueryOrderByOutTradeNo(ctx, native.QueryOrderByOutTradeNoRequest{
resp, _, err := g.WechatPay.Native.QueryOrderByOutTradeNo(context.Background(), native.QueryOrderByOutTradeNoRequest{
OutTradeNo: &tradeNo,
Mchid: &env.WechatPayMchId,
})
@@ -242,7 +242,7 @@ func (s *transactionService) VerifyTransaction(ctx context.Context, data *Transa
}
transId = *resp.TransactionId
payment = float64(*resp.Amount.PayerTotal) / 100
payment = decimal.NewFromInt(*resp.Amount.PayerTotal).Div(decimal.NewFromInt(100))
paidAt, err = time.Parse(time.RFC3339, *resp.SuccessTime)
if err != nil {
return nil, err
@@ -260,14 +260,14 @@ func (s *transactionService) VerifyTransaction(ctx context.Context, data *Transa
}, nil
}
func (s *transactionService) CompleteTransaction(ctx context.Context, q *q.Query, data *TransactionCompleteData) (*TransactionCompleteResult, error) {
func (s *transactionService) CompleteTransaction(q *q.Query, data *TransactionCompleteData) (*TransactionCompleteResult, error) {
var transId = data.TransId
var tradeNo = data.TradeNo
var payment = data.Payment
var paidAt = data.Time
// 获取交易信息
trade, err := q.Trade.WithContext(ctx).
trade, err := q.Trade.
Where(q.Trade.InnerNo.Eq(tradeNo)).
First()
if err != nil {
@@ -275,19 +275,24 @@ func (s *transactionService) CompleteTransaction(ctx context.Context, q *q.Query
}
// 检查交易状态
if trade.Status != int32(trade2.StatusPending) {
return nil, nil
}
switch trade2.Status(trade.Status) {
// 更新交易状态
trade.Status = int32(trade2.StatusSuccess)
trade.OuterNo = transId
trade.Payment = payment
trade.PaidAt = orm.LocalDateTime(paidAt)
trade.PayURL = ""
_, err = q.Trade.WithContext(ctx).Updates(trade)
if err != nil {
return nil, err
// 如果已退款或取消,则返回错误
case trade2.StatusCanceled, trade2.StatusRefunded:
return nil, errors.New("交易已取消或已退款")
// 如果是未支付,则更新支付状态
case trade2.StatusPending:
trade.Status = int32(trade2.StatusSuccess)
trade.OuterNo = transId
trade.Payment = payment
trade.PaidAt = orm.LocalDateTime(paidAt)
trade.PayURL = ""
_, err = q.Trade.Updates(trade)
if err != nil {
return nil, err
}
case trade2.StatusSuccess:
}
return &TransactionCompleteResult{
@@ -295,12 +300,12 @@ func (s *transactionService) CompleteTransaction(ctx context.Context, q *q.Query
}, nil
}
func (s *transactionService) RevokeTransaction(ctx context.Context, tradeNo string, method trade2.Method) error {
func (s *transactionService) RevokeTransaction(tradeNo string, method trade2.Method) error {
switch method {
case trade2.MethodAlipay:
resp, err := g.Alipay.TradeCancel(ctx, alipay.TradeCancel{
resp, err := g.Alipay.TradeCancel(context.Background(), alipay.TradeCancel{
OutTradeNo: tradeNo,
})
if err != nil {
@@ -312,7 +317,7 @@ func (s *transactionService) RevokeTransaction(ctx context.Context, tradeNo stri
}
case trade2.MethodWeChat:
resp, err := g.WechatPay.Native.CloseOrder(ctx, native.CloseOrderRequest{
resp, err := g.WechatPay.Native.CloseOrder(context.Background(), native.CloseOrderRequest{
Mchid: &env.WechatPayMchId,
OutTradeNo: &tradeNo,
})
@@ -329,13 +334,13 @@ func (s *transactionService) RevokeTransaction(ctx context.Context, tradeNo stri
return nil
}
func (s *transactionService) FinishTransaction(ctx context.Context, q *q.Query, tradeNo string, time time.Time) error {
func (s *transactionService) FinishTransaction(q *q.Query, tradeNo string, now time.Time) error {
_, err := q.Trade.
Where(q.Trade.InnerNo.Eq(tradeNo)).
Select(q.Trade.Status, q.Trade.CancelAt, q.Trade.PayURL).
Updates(m.Trade{
Status: int32(trade2.StatusCanceled),
CancelAt: orm.LocalDateTime(time),
CancelAt: orm.LocalDateTime(now),
PayURL: "",
})
if err != nil {
@@ -347,7 +352,7 @@ func (s *transactionService) FinishTransaction(ctx context.Context, q *q.Query,
type TransactionPrepareData struct {
Subject string
Amount float64
Amount decimal.Decimal
ExpireAt time.Time
Type trade2.Type
Method trade2.Method
@@ -368,7 +373,7 @@ type TransactionVerifyData struct {
type TransactionVerifyResult struct {
TransId string
Payment float64
Payment decimal.Decimal
Time time.Time
}

View File

@@ -1,7 +1,6 @@
package services
import (
"context"
q "platform/web/queries"
)
@@ -9,12 +8,12 @@ var User = &userService{}
type userService struct{}
func (s *userService) RechargeConfirm(ctx context.Context, tradeNo string, verified *TransactionVerifyResult) error {
func (s *userService) RechargeConfirm(tradeNo string, verified *TransactionVerifyResult) error {
err := q.Q.Transaction(func(tx *q.Query) error {
// 更新交易状态
result, err := Transaction.CompleteTransaction(ctx, tx, &TransactionCompleteData{
result, err := Transaction.CompleteTransaction(tx, &TransactionCompleteData{
TradeNo: tradeNo,
TransactionVerifyResult: *verified,
})
@@ -31,7 +30,7 @@ func (s *userService) RechargeConfirm(ctx context.Context, tradeNo string, verif
_, err = tx.User.
Where(tx.User.ID.Eq(user.ID)).
UpdateSimple(tx.User.Balance.Add(result.Trade.Amount))
UpdateSimple(tx.User.Balance.Value(user.Balance.Add(result.Trade.Amount)))
if err != nil {
return err
}

View File

@@ -3,6 +3,7 @@ package web
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/gofiber/fiber/v2/middleware/recover"
"github.com/gofiber/fiber/v2/middleware/requestid"
"github.com/google/uuid"
"github.com/jxskiss/base62"
@@ -55,8 +56,9 @@ func (s *Server) Run() error {
})
// middlewares
s.fiber.Use(useRequestId())
s.fiber.Use(useLogger())
s.fiber.Use(newRecover())
s.fiber.Use(newRequestId())
s.fiber.Use(newLogger())
// routes
ApplyRouters(s.fiber)
@@ -100,9 +102,9 @@ func (s *Server) Stop() {
// endregion
// region requestid
// region middlewares
func useRequestId() fiber.Handler {
func newRequestId() fiber.Handler {
return requestid.New(requestid.Config{
Generator: func() string {
binary, _ := uuid.New().MarshalBinary()
@@ -111,11 +113,7 @@ func useRequestId() fiber.Handler {
})
}
// endregion
// region logger
func useLogger() fiber.Handler {
func newLogger() fiber.Handler {
return logger.New(logger.Config{
DisableColors: true,
Format: "🚀 ${time} | ${locals:authtype} ${locals:authid} | ${method} ${path} | ${status} | ${latency} | ${error}\n",
@@ -175,4 +173,8 @@ func useLogger() fiber.Handler {
})
}
func newRecover() fiber.Handler {
return recover.New()
}
// endregion