修复逻辑问题
This commit is contained in:
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"platform/pkg/u"
|
||||
"platform/web/core"
|
||||
m "platform/web/models"
|
||||
q "platform/web/queries"
|
||||
@@ -50,9 +49,8 @@ func authUser(loginType PwdLoginType, username, password string) (user *m.User,
|
||||
}
|
||||
if user == nil {
|
||||
user = &m.User{
|
||||
Phone: username,
|
||||
Username: u.P(username),
|
||||
Status: m.UserStatusEnabled,
|
||||
Phone: username,
|
||||
Status: m.UserStatusEnabled,
|
||||
}
|
||||
}
|
||||
case PwdLoginByEmail:
|
||||
@@ -79,7 +77,7 @@ func authUser(loginType PwdLoginType, username, password string) (user *m.User,
|
||||
|
||||
func authUserBySms(tx *q.Query, username, code string) (*m.User, error) {
|
||||
// 验证验证码
|
||||
err := s.Verifier.VerifySms(context.Background(), username, code)
|
||||
err := s.Verifier.VerifySms(context.Background(), username, code, s.VerifierSmsPurposeLogin)
|
||||
if err != nil {
|
||||
return nil, core.NewBizErr("短信认证失败", err)
|
||||
}
|
||||
|
||||
@@ -537,10 +537,10 @@ func introspectUser(ctx *fiber.Ctx, authCtx *AuthCtx) error {
|
||||
|
||||
// 掩码敏感信息
|
||||
if profile.Phone != "" {
|
||||
profile.Phone = maskPhone(profile.Phone)
|
||||
profile.Phone = u.MaskPhone(profile.Phone)
|
||||
}
|
||||
if profile.IDNo != nil && *profile.IDNo != "" {
|
||||
profile.IDNo = u.P(maskIdNo(*profile.IDNo))
|
||||
profile.IDNo = u.P(u.MaskIdNo(*profile.IDNo))
|
||||
}
|
||||
|
||||
return ctx.JSON(struct {
|
||||
@@ -579,20 +579,6 @@ func introspectAdmin(ctx *fiber.Ctx, authCtx *AuthCtx) error {
|
||||
}{profile, list})
|
||||
}
|
||||
|
||||
func maskPhone(phone string) string {
|
||||
if len(phone) < 11 {
|
||||
return phone
|
||||
}
|
||||
return phone[:3] + "****" + phone[7:]
|
||||
}
|
||||
|
||||
func maskIdNo(idNo string) string {
|
||||
if len(idNo) < 18 {
|
||||
return idNo
|
||||
}
|
||||
return idNo[:3] + "*********" + idNo[14:]
|
||||
}
|
||||
|
||||
type CodeContext struct {
|
||||
UserID int32 `json:"user_id"`
|
||||
ClientID int32 `json:"client_id"`
|
||||
|
||||
@@ -12,9 +12,9 @@ type IModel interface {
|
||||
}
|
||||
|
||||
type Model struct {
|
||||
ID int32 `json:"id" gorm:"column:id;primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
|
||||
ID int32 `json:"id,omitzero" gorm:"column:id;primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at,omitzero" gorm:"column:created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at,omitzero" gorm:"column:updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"column:deleted_at"`
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,6 @@ type AllProductsByAdminReq struct {
|
||||
}
|
||||
|
||||
func AllProduct(c *fiber.Ctx) error {
|
||||
_, err := auth.GetAuthCtx(c).PermitUser()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
infos, err := s.Product.AllProductSaleInfos()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -817,11 +817,13 @@ func ResourcePrice(c *fiber.Ctx) error {
|
||||
// 计算折扣
|
||||
return c.JSON(ResourcePriceResp{
|
||||
Price: detail.Amount.StringFixed(2),
|
||||
Discounted: detail.Actual.StringFixed(2),
|
||||
Discounted: detail.Discounted.StringFixed(2),
|
||||
Actual: detail.Actual.StringFixed(2),
|
||||
})
|
||||
}
|
||||
|
||||
type ResourcePriceResp struct {
|
||||
Price string `json:"price"`
|
||||
Discounted string `json:"discounted_price"`
|
||||
Discounted string `json:"discounted"`
|
||||
Actual string `json:"actual"`
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/shopspring/decimal"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gen/field"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -305,14 +306,26 @@ func UpdateUser(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// 更新用户信息
|
||||
do := make([]field.AssignExpr, 0)
|
||||
if req.Username != nil && *req.Username != "" {
|
||||
do = append(do, q.User.Username.Value(*req.Username))
|
||||
}
|
||||
if req.Email != nil {
|
||||
if *req.Email == "" {
|
||||
do = append(do, q.User.Email.Null())
|
||||
} else {
|
||||
do = append(do, q.User.Email.Value(*req.Email))
|
||||
}
|
||||
}
|
||||
if req.ContactQQ != nil {
|
||||
do = append(do, q.User.ContactQQ.Value(*req.ContactQQ))
|
||||
}
|
||||
if req.ContactWechat != nil {
|
||||
do = append(do, q.User.ContactWechat.Value(*req.ContactWechat))
|
||||
}
|
||||
_, err = q.User.
|
||||
Where(q.User.ID.Eq(authCtx.User.ID)).
|
||||
Updates(m.User{
|
||||
Username: &req.Username,
|
||||
Email: &req.Email,
|
||||
ContactQQ: &req.ContactQQ,
|
||||
ContactWechat: &req.ContactWechat,
|
||||
})
|
||||
UpdateSimple(do...)
|
||||
if errors.Is(err, gorm.ErrDuplicatedKey) {
|
||||
return core.NewBizErr("用户名或邮箱已被占用")
|
||||
}
|
||||
@@ -325,10 +338,10 @@ func UpdateUser(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
type UpdateUserReq struct {
|
||||
Username string `json:"username" validate:"omitempty,min=3,max=20"`
|
||||
Email string `json:"email" validate:"omitempty,email"`
|
||||
ContactQQ string `json:"contact_qq" validate:"omitempty,qq"`
|
||||
ContactWechat string `json:"contact_wechat" validate:"omitempty,wechat"`
|
||||
Username *string `json:"username" validate:"omitempty,min=3,max=20"`
|
||||
Email *string `json:"email" validate:"omitempty,email"`
|
||||
ContactQQ *string `json:"contact_qq" validate:"omitempty,qq"`
|
||||
ContactWechat *string `json:"contact_wechat" validate:"omitempty,wechat"`
|
||||
}
|
||||
|
||||
// 更新账号信息
|
||||
@@ -379,16 +392,14 @@ func UpdatePassword(c *fiber.Ctx) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 验证手机号
|
||||
if req.Phone != authCtx.User.Phone {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "手机号码不正确")
|
||||
}
|
||||
|
||||
// 验证手机令牌
|
||||
if req.Code == "" {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "手机号码和验证码不能为空")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "验证码不能为空")
|
||||
}
|
||||
err = s.Verifier.VerifySms(c.Context(), authCtx.User.Phone, req.Code, s.VerifierSmsPurposePassword)
|
||||
if errors.Is(err, s.ErrVerifierServiceInvalid) {
|
||||
return core.NewBizErr(s.ErrVerifierServiceInvalid.Error())
|
||||
}
|
||||
err = s.Verifier.VerifySms(c.Context(), req.Phone, req.Code)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -411,7 +422,6 @@ func UpdatePassword(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
type UpdatePasswordReq struct {
|
||||
Phone string `json:"phone"`
|
||||
Code string `json:"code"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"platform/pkg/env"
|
||||
"platform/web/auth"
|
||||
"platform/web/services"
|
||||
s "platform/web/services"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
@@ -13,12 +14,11 @@ import (
|
||||
)
|
||||
|
||||
type VerifierReq struct {
|
||||
Purpose services.VerifierSmsPurpose `json:"purpose"`
|
||||
Phone string `json:"phone"`
|
||||
Purpose s.VerifierSmsPurpose `json:"purpose"`
|
||||
Phone string `json:"phone"`
|
||||
}
|
||||
|
||||
func SmsCode(c *fiber.Ctx) error {
|
||||
|
||||
func SendSmsCode(c *fiber.Ctx) error {
|
||||
_, err := auth.GetAuthCtx(c).PermitOfficialClient()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -38,9 +38,9 @@ func SmsCode(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// 发送身份验证码
|
||||
err = services.Verifier.SendSms(c.Context(), req.Phone, req.Purpose)
|
||||
err = s.Verifier.SendSms(c.Context(), req.Phone, req.Purpose)
|
||||
if err != nil {
|
||||
var sErr services.VerifierServiceSendLimitErr
|
||||
var sErr s.VerifierServiceSendLimitErr
|
||||
if errors.As(err, &sErr) {
|
||||
return fiber.NewError(fiber.StatusTooManyRequests, strconv.Itoa(int(sErr)))
|
||||
}
|
||||
@@ -51,6 +51,23 @@ func SmsCode(c *fiber.Ctx) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SendSmsCodeForPassword(c *fiber.Ctx) error {
|
||||
ac, err := auth.GetAuthCtx(c).PermitUser()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.Verifier.SendSms(c.Context(), ac.User.Phone, s.VerifierSmsPurposePassword); err != nil {
|
||||
var sErr s.VerifierServiceSendLimitErr
|
||||
if errors.As(err, &sErr) {
|
||||
return fiber.NewError(fiber.StatusTooManyRequests, strconv.Itoa(int(sErr)))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DebugGetSmsCode(c *fiber.Ctx) error {
|
||||
if env.RunMode != env.RunModeDev {
|
||||
return fiber.NewError(fiber.StatusForbidden, "not allowed")
|
||||
|
||||
@@ -13,7 +13,7 @@ type Product struct {
|
||||
Sort int32 `json:"sort" gorm:"column:sort"` // 排序
|
||||
Status ProductStatus `json:"status" gorm:"column:status"` // 产品状态:0-禁用,1-正常
|
||||
|
||||
Skus []ProductSku `json:"skus"`
|
||||
Skus []*ProductSku `json:"skus,omitempty" gorm:"foreignKey:ProductID"` // 产品包含的SKU列表
|
||||
}
|
||||
|
||||
// ProductStatus 产品状态枚举
|
||||
|
||||
@@ -16,6 +16,7 @@ type ProductSku struct {
|
||||
Price decimal.Decimal `json:"price" gorm:"column:price"` // 定价
|
||||
PriceMin decimal.Decimal `json:"price_min" gorm:"column:price_min"` // 最低价格
|
||||
Status SkuStatus `json:"status" gorm:"column:status"` // SKU 状态:0-禁用,1-正常
|
||||
Sort int32 `json:"sort" gorm:"column:sort"` // 排序
|
||||
|
||||
Product *Product `json:"product,omitempty" gorm:"foreignKey:ProductID"`
|
||||
Discount *ProductDiscount `json:"discount,omitempty" gorm:"foreignKey:DiscountId"`
|
||||
|
||||
@@ -38,6 +38,7 @@ func newProductSku(db *gorm.DB, opts ...gen.DOOption) productSku {
|
||||
_productSku.Price = field.NewField(tableName, "price")
|
||||
_productSku.PriceMin = field.NewField(tableName, "price_min")
|
||||
_productSku.Status = field.NewInt32(tableName, "status")
|
||||
_productSku.Sort = field.NewInt32(tableName, "sort")
|
||||
_productSku.Product = productSkuBelongsToProduct{
|
||||
db: db.Session(&gorm.Session{}),
|
||||
|
||||
@@ -91,6 +92,7 @@ type productSku struct {
|
||||
Price field.Field
|
||||
PriceMin field.Field
|
||||
Status field.Int32
|
||||
Sort field.Int32
|
||||
Product productSkuBelongsToProduct
|
||||
|
||||
Discount productSkuBelongsToDiscount
|
||||
@@ -121,6 +123,7 @@ func (p *productSku) updateTableName(table string) *productSku {
|
||||
p.Price = field.NewField(table, "price")
|
||||
p.PriceMin = field.NewField(table, "price_min")
|
||||
p.Status = field.NewInt32(table, "status")
|
||||
p.Sort = field.NewInt32(table, "sort")
|
||||
|
||||
p.fillFieldMap()
|
||||
|
||||
@@ -137,7 +140,7 @@ func (p *productSku) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
}
|
||||
|
||||
func (p *productSku) fillFieldMap() {
|
||||
p.fieldMap = make(map[string]field.Expr, 13)
|
||||
p.fieldMap = make(map[string]field.Expr, 14)
|
||||
p.fieldMap["id"] = p.ID
|
||||
p.fieldMap["created_at"] = p.CreatedAt
|
||||
p.fieldMap["updated_at"] = p.UpdatedAt
|
||||
@@ -149,6 +152,7 @@ func (p *productSku) fillFieldMap() {
|
||||
p.fieldMap["price"] = p.Price
|
||||
p.fieldMap["price_min"] = p.PriceMin
|
||||
p.fieldMap["status"] = p.Status
|
||||
p.fieldMap["sort"] = p.Sort
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -113,6 +113,10 @@ func userRouter(api fiber.Router) {
|
||||
// 产品
|
||||
product := api.Group("/product")
|
||||
product.Post("/list", handlers.AllProduct)
|
||||
|
||||
// 认证
|
||||
verify := api.Group("/verify")
|
||||
verify.Post("/sms/password", handlers.SendSmsCodeForPassword)
|
||||
}
|
||||
|
||||
// 客户端接口路由
|
||||
@@ -120,7 +124,7 @@ func clientRouter(api fiber.Router) {
|
||||
client := api
|
||||
|
||||
// 验证短信令牌
|
||||
client.Post("/verify/sms", handlers.SmsCode)
|
||||
client.Post("/verify/sms", handlers.SendSmsCode)
|
||||
|
||||
// 套餐定价查询
|
||||
resource := client.Group("/resource")
|
||||
|
||||
@@ -16,7 +16,7 @@ func (s *billService) CreateForBalance(q *q.Query, uid, tradeId int32, detail *T
|
||||
TradeID: &tradeId,
|
||||
Type: m.BillTypeRecharge,
|
||||
Info: &detail.Subject,
|
||||
Amount: detail.Amount,
|
||||
Amount: detail.Discounted,
|
||||
Actual: detail.Actual,
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func (s *billService) CreateForResource(q *q.Query, uid, resourceId int32, trade
|
||||
CouponUserID: detail.CouponUserId,
|
||||
Type: m.BillTypeConsume,
|
||||
Info: &detail.Subject,
|
||||
Amount: detail.Amount,
|
||||
Amount: detail.Discounted,
|
||||
Actual: detail.Actual,
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ func findResource(resourceId int32, now time.Time) (*ResourceView, error) {
|
||||
var sub = resource.Short
|
||||
info.ShortId = &sub.ID
|
||||
info.ExpireAt = sub.ExpireAt
|
||||
info.Live = time.Duration(sub.Live) * time.Second
|
||||
info.Live = time.Duration(sub.Live) * time.Minute
|
||||
info.Mode = sub.Type
|
||||
info.Quota = sub.Quota
|
||||
info.Used = sub.Used
|
||||
|
||||
@@ -21,24 +21,58 @@ func (s *productService) AllProducts() ([]*m.Product, error) {
|
||||
}
|
||||
|
||||
func (s *productService) AllProductSaleInfos() ([]*m.Product, error) {
|
||||
return q.Product.
|
||||
Joins(q.Product.Skus).
|
||||
products, err := q.Product.
|
||||
Select(
|
||||
q.Product.ID,
|
||||
q.Product.Code,
|
||||
q.Product.Name,
|
||||
q.Product.Description,
|
||||
q.Product.Sort,
|
||||
).
|
||||
Where(
|
||||
q.Product.Status.Eq(int(m.ProductStatusEnabled)),
|
||||
).
|
||||
Order(q.Product.Sort).
|
||||
Find()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pids := make([]int32, len(products))
|
||||
for i, p := range products {
|
||||
pids[i] = p.ID
|
||||
}
|
||||
|
||||
skus, err := q.ProductSku.
|
||||
Select(
|
||||
q.ProductSku.ID,
|
||||
q.ProductSku.Code,
|
||||
q.ProductSku.ProductID,
|
||||
q.ProductSku.Name,
|
||||
q.ProductSku.Code,
|
||||
q.ProductSku.Price,
|
||||
).
|
||||
Where(
|
||||
q.Product.Status.Eq(int(m.ProxyStatusOnline)),
|
||||
q.ProductSku.Status.Eq(int32(m.ProductStatusEnabled)),
|
||||
q.ProductSku.ProductID.In(pids...),
|
||||
q.ProductSku.Status.Eq(int32(m.SkuStatusEnabled)),
|
||||
).
|
||||
Order(q.ProductSku.Sort).
|
||||
Find()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pmap := make(map[int32]*m.Product, len(products))
|
||||
for _, p := range products {
|
||||
pmap[p.ID] = p
|
||||
p.Skus = make([]*m.ProductSku, 0)
|
||||
}
|
||||
for _, s := range skus {
|
||||
if p, ok := pmap[s.ProductID]; ok {
|
||||
p.Skus = append(p.Skus, s)
|
||||
}
|
||||
}
|
||||
|
||||
return products, nil
|
||||
}
|
||||
|
||||
// 新增产品
|
||||
|
||||
@@ -20,7 +20,7 @@ func (s *productSkuService) All(product_code string) (result []*m.ProductSku, er
|
||||
Joins(q.ProductSku.Product).
|
||||
Where(q.Product.As("Product").Code.Eq(product_code)).
|
||||
Select(q.ProductSku.ALL).
|
||||
Order(q.ProductSku.CreatedAt.Desc()).
|
||||
Order(q.ProductSku.Sort).
|
||||
Find()
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func (s *productSkuService) Page(req *core.PageReq, productId *int32) (result []
|
||||
return q.ProductSku.
|
||||
Joins(q.ProductSku.Discount, q.ProductSku.Product).
|
||||
Where(do...).
|
||||
Order(q.ProductSku.ID).
|
||||
Order(q.ProductSku.Sort).
|
||||
FindByPage(req.GetOffset(), req.GetLimit())
|
||||
}
|
||||
|
||||
|
||||
@@ -144,31 +144,31 @@ type UpdateResourceData struct {
|
||||
Active *bool `json:"active"`
|
||||
}
|
||||
|
||||
func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, cuid *int32) (*m.ProductSku, *m.ProductDiscount, *m.CouponUser, decimal.Decimal, decimal.Decimal, error) {
|
||||
func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, cuid *int32) (*m.ProductSku, *m.ProductDiscount, *m.CouponUser, decimal.Decimal, decimal.Decimal, decimal.Decimal, error) {
|
||||
|
||||
sku, err := q.ProductSku.
|
||||
Joins(q.ProductSku.Discount).
|
||||
Where(q.ProductSku.Code.Eq(skuCode), q.ProductSku.Status.Eq(int32(m.SkuStatusEnabled))).
|
||||
Take()
|
||||
if err != nil {
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, core.NewServErr(fmt.Sprintf("产品不可用 %s", skuCode), err)
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, core.NewServErr(fmt.Sprintf("产品不可用 %s", skuCode), err)
|
||||
}
|
||||
|
||||
// 原价
|
||||
price := sku.Price
|
||||
amount := price.Mul(decimal.NewFromInt32(count))
|
||||
amountMin := sku.PriceMin.Mul(decimal.NewFromInt32(count))
|
||||
amount := sku.Price.Mul(decimal.NewFromInt32(count))
|
||||
|
||||
// 折扣价
|
||||
discount := sku.Discount
|
||||
if discount == nil {
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, core.NewServErr("价格查询失败", err)
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, core.NewServErr("价格查询失败", err)
|
||||
}
|
||||
|
||||
discountRate := discount.Rate()
|
||||
if user != nil && user.DiscountID != nil { // 用户特殊优惠
|
||||
uDiscount, err := q.ProductDiscount.Where(q.ProductDiscount.ID.Eq(*user.DiscountID)).Take()
|
||||
if err != nil {
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, core.NewServErr("客户特殊价查询失败", err)
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, core.NewServErr("客户特殊价查询失败", err)
|
||||
}
|
||||
|
||||
uDiscountRate := uDiscount.Rate()
|
||||
@@ -186,20 +186,20 @@ func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, c
|
||||
var err error
|
||||
coupon, err = Coupon.GetUserCoupon(user.ID, *cuid, discounted)
|
||||
if err != nil {
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, err
|
||||
return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, err
|
||||
}
|
||||
couponApplied = discounted.Sub(coupon.Coupon.Amount)
|
||||
}
|
||||
|
||||
// 约束到最低价格
|
||||
if discounted.Cmp(sku.PriceMin) < 0 {
|
||||
discounted = sku.PriceMin.Copy()
|
||||
if discounted.Cmp(amountMin) < 0 {
|
||||
discounted = amountMin.Copy()
|
||||
}
|
||||
if couponApplied.Cmp(sku.PriceMin) < 0 {
|
||||
couponApplied = sku.PriceMin.Copy()
|
||||
if couponApplied.Cmp(amountMin) < 0 {
|
||||
couponApplied = amountMin.Copy()
|
||||
}
|
||||
|
||||
return sku, discount, coupon, discounted, couponApplied, nil
|
||||
return sku, discount, coupon, amount, discounted, couponApplied, nil
|
||||
}
|
||||
|
||||
type CreateResourceData struct {
|
||||
@@ -260,7 +260,7 @@ func (data *CreateResourceData) Code() string {
|
||||
}
|
||||
|
||||
func (data *CreateResourceData) TradeDetail(user *m.User) (*TradeDetail, error) {
|
||||
sku, discount, coupon, amount, actual, err := Resource.CalcPrice(data.Code(), data.Count(), user, data.CouponId)
|
||||
sku, discount, coupon, amount, discounted, actual, err := Resource.CalcPrice(data.Code(), data.Count(), user, data.CouponId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -277,7 +277,7 @@ func (data *CreateResourceData) TradeDetail(user *m.User) (*TradeDetail, error)
|
||||
data,
|
||||
m.TradeTypePurchase,
|
||||
sku.Name,
|
||||
amount, actual,
|
||||
amount, discounted, actual,
|
||||
discountId, couponUserId,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -619,6 +619,7 @@ type TradeDetail struct {
|
||||
Type m.TradeType `json:"type"`
|
||||
Subject string `json:"subject"`
|
||||
Amount decimal.Decimal `json:"amount"`
|
||||
Discounted decimal.Decimal `json:"discounted"`
|
||||
Actual decimal.Decimal `json:"actual"`
|
||||
DiscountId *int32 `json:"discount_id,omitempty"`
|
||||
CouponUserId *int32 `json:"coupon_id,omitempty"`
|
||||
|
||||
@@ -93,7 +93,7 @@ func (data *UpdateBalanceData) TradeDetail(user *m.User) (*TradeDetail, error) {
|
||||
data,
|
||||
m.TradeTypeRecharge,
|
||||
fmt.Sprintf("账户充值 - %s元", amount.StringFixed(2)),
|
||||
amount, amount,
|
||||
amount, amount, amount,
|
||||
nil, nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -89,8 +89,8 @@ func (s *verifierService) SendSms(ctx context.Context, phone string, purpose Ver
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *verifierService) VerifySms(ctx context.Context, phone, code string) error {
|
||||
key := smsKey(phone, VerifierSmsPurposeLogin)
|
||||
func (s *verifierService) VerifySms(ctx context.Context, phone, code string, purpose VerifierSmsPurpose) error {
|
||||
key := smsKey(phone, purpose)
|
||||
keyLock := key + ":lock"
|
||||
|
||||
err := g.Redis.Watch(ctx, func(tx *redis.Tx) error {
|
||||
@@ -146,7 +146,8 @@ func smsKey(phone string, purpose VerifierSmsPurpose) string {
|
||||
type VerifierSmsPurpose int
|
||||
|
||||
const (
|
||||
VerifierSmsPurposeLogin VerifierSmsPurpose = iota // 登录
|
||||
VerifierSmsPurposeLogin VerifierSmsPurpose = iota // 登录
|
||||
VerifierSmsPurposePassword // 修改密码
|
||||
)
|
||||
|
||||
// region 服务异常
|
||||
|
||||
Reference in New Issue
Block a user