diff --git a/api/errcode/errcode.go b/api/errcode/errcode.go index 16fdf437..2ca10d49 100644 --- a/api/errcode/errcode.go +++ b/api/errcode/errcode.go @@ -294,6 +294,7 @@ const ( ErrCodeVasInvalidVerifycode ErrCode = -7020 // 提现验证码错误 ErrCodeVasAlipayUniTransferFail ErrCode = -7021 // 支付宝提现失败 ErrCodeVasOverTodayWithdrawCnt ErrCode = -7022 // 今天提现次数到达上限 + ErrCodeVasOverRefundLimit ErrCode = -7023 // 退款次数达上限 // Moment: 8xxx ErrCodeMomentSrvOk ErrCode = ErrCodeOk diff --git a/api/errs/error.go b/api/errs/error.go index 80e88a7a..683cf0e0 100644 --- a/api/errs/error.go +++ b/api/errs/error.go @@ -8,12 +8,9 @@ import ( func DealVasErr(err error) (errcode.ErrCode, error) { var ( ec = errcode.ErrCodeVasSrvOk - ok bool ) if err != nil { - ec, ok = ErrEcMap[err] - err = errors.Wrap(err, "VasError") - if ok { + if ec, ok := ErrEcMap[err]; ok { return ec, err } ec = errcode.ErrCodeVasSrvFail @@ -41,6 +38,7 @@ var ErrEcMap = map[error]errcode.ErrCode{ ErrVasNoEnoughWithdrawDias: errcode.ErrCodeVasNoEnoughWithdrawDias, ErrVasAlipayUniTransferFail: errcode.ErrCodeVasAlipayUniTransferFail, ErrVasOverTodayWithdrawCnt: errcode.ErrCodeVasOverTodayWithdrawCnt, + ErrVasRefundLimit: errcode.ErrCodeVasOverRefundLimit, } var ( @@ -62,4 +60,5 @@ var ( ErrVasNoEnoughWithdrawDias = errors.New("no enough withdraw dias") ErrVasAlipayUniTransferFail = errors.New("alipay uni transfer fail") ErrVasOverTodayWithdrawCnt = errors.New("over today withdraw cnt") + ErrVasRefundLimit = errors.New("账号已受限,解限请联系客服") ) diff --git a/app/mix/controller/init.go b/app/mix/controller/init.go index 2c9b5d88..dd99c786 100644 --- a/app/mix/controller/init.go +++ b/app/mix/controller/init.go @@ -288,6 +288,7 @@ func Init(r *gin.Engine) { vasPayGroup.POST("withdraw_apply", middleware.JSONParamValidator(vasproto.WithdrawApplyReq{}), WithdrawApply) vasPayGroup.POST("deal_one_coin_order", middleware.JSONParamValidator(vasproto.DealOneCoinOrderReq{}), DealOneCoinOrder) vasPayGroup.POST("deal_one_order", middleware.JSONParamValidator(vasproto.DealOneOrderReq{}), DealOneOrder) + vasPayGroup.POST("moment_order_list", middleware.JSONParamValidator(vasproto.ZoneMomentOrderListReq{}), ZoneMomentOrderList) extVasPayGroup := r.Group("/ext/vas") extVasPayGroup.POST("alipay_callback", AlipayCallback) diff --git a/app/mix/controller/vas.go b/app/mix/controller/vas.go index ee9e1e5f..e9109ce4 100644 --- a/app/mix/controller/vas.go +++ b/app/mix/controller/vas.go @@ -50,9 +50,13 @@ func CreateOrder(ctx *gin.Context) { ReplyErrCodeMsg(ctx, errcode.ErrCodeBadParam) return } - data, ec := service.DefaultService.CreateOrder(ctx, req) + data, ec, err := service.DefaultService.CreateOrder(ctx, req) if ec != errcode.ErrCodeVasSrvOk { logger.Error("CreateOrder fail, req: %v, ec: %v", util.ToJson(req), ec) + if ec == errcode.ErrCodeVasSrvFail && err != nil { + ReplyErrorMsg(ctx, err.Error()) + return + } ReplyErrCodeMsg(ctx, ec) return } @@ -241,6 +245,15 @@ func isWithdrawFreeze(mid int64) bool { return WithdrawFreezeMidMap[mid] } +// 任意额度提现 +var WithdrawAnyDiasMap = map[int64]bool{ + 74: true, +} + +func isWithdrawAnyDiasEnable(mid int64) bool { + return WithdrawAnyDiasMap[mid] +} + // 提现发送验证码 func WithdrawSendVerifycode(ctx *gin.Context) { req := ctx.MustGet("client_req").(*vasproto.WithdrawSendVerifycodeReq) diff --git a/app/mix/controller/zone_vas_api.go b/app/mix/controller/zone_vas_api.go index e0ad9ad2..b0dec7e4 100644 --- a/app/mix/controller/zone_vas_api.go +++ b/app/mix/controller/zone_vas_api.go @@ -155,3 +155,31 @@ func ZoneExit(ctx *gin.Context) { } ReplyOk(ctx, nil) } + +func ZoneMomentOrderList(ctx *gin.Context) { + req := ctx.MustGet("client_req").(*vasproto.ZoneMomentOrderListReq) + if req.Mid <= 0 || req.MomentId <= 0 { + logger.Error("ZoneExit, invalid param, req: %v", util.ToJson(req)) + ReplyErrCodeMsg(ctx, errcode.ErrCodeBadParam) + return + } + list, ec, err := service.DefaultService.ZoneMomentOrderList(ctx, req) + if ec != errcode.ErrCodeVasSrvOk { + logger.Error("ZoneExit fail, req: %v, ec: %v", util.ToJson(req), ec) + if ec == errcode.ErrCodeVasSrvFail && err != nil { + ReplyErrorMsg(ctx, err.Error()) + return + } + ReplyErrCodeMsg(ctx, ec) + return + } + + data := &vasproto.ZoneMomentOrderListData{ + List: list, + Offset: req.Offset + len(list), + } + if len(list) >= req.Limit { + data.More = 1 + } + ReplyOk(ctx, data) +} diff --git a/app/mix/dao/mysql.go b/app/mix/dao/mysql.go index a2497d7f..fc2d1f26 100644 --- a/app/mix/dao/mysql.go +++ b/app/mix/dao/mysql.go @@ -270,6 +270,32 @@ func (m *Mysql) GetOrders(ctx *gin.Context, tx *sqlx.Tx, mid, st, et int64, offs return } +// 获取订单数 +func (m *Mysql) GetOrderCnt(ctx *gin.Context, tx *sqlx.Tx, mid, st, et int64, orderStatus int32) (int, error) { + type S struct { + Cnt int `json:"cnt"` + } + var ( + err error + s = S{} + ) + sqlStr := fmt.Sprintf("select count(1) as cnt from %s where mid=? and order_status=? and ct>=? and ct= 8 { + err = fmt.Errorf("账号已受限,解限请联系客服") + return + } + var ( productId = req.ProductId order *dbstruct.Order @@ -2970,6 +2986,9 @@ func (v *Vas) refundZoneMoment(ctx *gin.Context, order *dbstruct.Order, req *vas return err } + // 减购买人数 + _ = v.store.DecZoneMomentBuyerCnt(ctx, zid, momentId) + return nil } diff --git a/app/mix/service/logic/vas_zone.go b/app/mix/service/logic/vas_zone.go index 9fd108c2..2c2d7db9 100644 --- a/app/mix/service/logic/vas_zone.go +++ b/app/mix/service/logic/vas_zone.go @@ -14,6 +14,7 @@ import ( "service/bizcommon/util" "service/dbstruct" "service/library/logger" + "service/library/redis" "time" ) @@ -911,7 +912,20 @@ func (v *Vas) ZoneGetRefundPage(ctx *gin.Context, req *vasproto.ZoneRefundPageRe } // 空间退款 +func getCheckZoneRefundFreqKey(mid int64) string { + return fmt.Sprintf("zone_refund_freq_%d", mid) +} + func (v *Vas) ZoneRefund(ctx *gin.Context, req *vasproto.ZoneRefundReq) error { + redisKey := getCheckZoneRefundFreqKey(req.Mid) + redisCli := redis.GetRedisClient() + // 获取上次退款时间 + t, _ := redisCli.GetInt64(redisKey) + logger.Info("ZoneRefund check freq, key: %v, t: %v", redisKey, t) + if time.Now().Unix()-t < 3600*12 { + return fmt.Errorf("12小时内您最多只能进行1次退款") + } + // 获取解锁信息 zv, err := v.store.GetZoneUnlock(ctx, nil, req.Mid, req.Zid) if err == sql.ErrNoRows || zv == nil { @@ -951,6 +965,9 @@ func (v *Vas) ZoneRefund(ctx *gin.Context, req *vasproto.ZoneRefundReq) error { return err } + // redis记录退款时间 + _ = redisCli.Set(redisKey, time.Now().Unix(), 86400) + return nil } @@ -1184,3 +1201,8 @@ func (v *Vas) ZoneExit(ctx *gin.Context, mid, zid int64) error { return nil } + +// 获取动态解锁记录 +func (v *Vas) GetZoneMomentUnlockList(ctx *gin.Context, momentId int64, offset, limit int) (list []*dbstruct.ZoneMomentUnlock, err error) { + return v.store.GetZoneMomentUnlockList(ctx, nil, momentId, offset, limit) +} diff --git a/app/mix/service/service.go b/app/mix/service/service.go index a2131b30..71f07397 100644 --- a/app/mix/service/service.go +++ b/app/mix/service/service.go @@ -1015,7 +1015,7 @@ func (s *Service) GetMembershipProductList(ctx *gin.Context, req *vasproto.GetMe return } -func (s *Service) CreateOrder(ctx *gin.Context, req *vasproto.CreateOrderReq) (data *vasproto.CreateOrderData, ec errcode.ErrCode) { +func (s *Service) CreateOrder(ctx *gin.Context, req *vasproto.CreateOrderReq) (data *vasproto.CreateOrderData, ec errcode.ErrCode, err error) { switch req.ProductId { case dbstruct.ProductIdMembership: req.ReturnUrl = "https://tiefen.fun/vip" @@ -1023,7 +1023,7 @@ func (s *Service) CreateOrder(ctx *gin.Context, req *vasproto.CreateOrderReq) (d req.ReturnUrl = "https://tiefen.fun/pay" } - data, err := _DefaultVas.CreateOrder(ctx, req) + data, err = _DefaultVas.CreateOrder(ctx, req) ec, err = errs.DealVasErr(err) if err != nil { logger.Error("CreateOrder fail, err: %v", err) diff --git a/app/mix/service/vasservice.go b/app/mix/service/vasservice.go index 051660fe..32c9c4bf 100644 --- a/app/mix/service/vasservice.go +++ b/app/mix/service/vasservice.go @@ -1040,3 +1040,33 @@ func (s *Service) OpZoneRefundList(ctx *gin.Context, req *zoneproto.OpZoneRefund } return } + +func (s *Service) ZoneMomentOrderList(ctx *gin.Context, req *vasproto.ZoneMomentOrderListReq) (list []*vasproto.ZoneMomentOrderVO, ec errcode.ErrCode, err error) { + list = make([]*vasproto.ZoneMomentOrderVO, 0) + // 空间动态解锁历史 + zmuList, err := _DefaultVas.GetZoneMomentUnlockList(ctx, req.MomentId, req.Offset, req.Limit) + logger.Info("ZoneMomentOrderList, id: %v, zmuList: %v, err: %v", req.MomentId, len(zmuList), err) + ec, err = errs.DealVasErr(err) + if err != nil { + return + } + + // 获取账号 + mids := make([]int64, 0) + for _, zmu := range zmuList { + mids = append(mids, zmu.GetMid()) + } + acntMap, _ := _DefaultAccount.GetAccountMapByMids(ctx, mids) + logger.Info("ZoneMomentOrderList, id: %v, acntMap: %v, err: %v", req.MomentId, len(acntMap), err) + + // 组装 + for _, zmu := range zmuList { + item := &vasproto.ZoneMomentOrderVO{ + Account: acntMap[zmu.GetMid()], + BuyTime: zmu.GetCt(), + OrderId: zmu.GetOrderId(), + } + list = append(list, item) + } + return +} diff --git a/dbstruct/media.go b/dbstruct/media.go index e278a9b0..6b4f5e71 100644 --- a/dbstruct/media.go +++ b/dbstruct/media.go @@ -141,10 +141,10 @@ func NewVideoFromJson(item any) (vid *Video, err error) { err = errors.New("invalid video object with null md5") return } - if vid.Dur == 0 { - err = errors.New("invalid video object with zero dur") - return - } + //if vid.Dur == 0 { + // err = errors.New("invalid video object with zero dur") + // return + //} if vid.Fmt == "" { err = errors.New("invalid video object with null fmt") return diff --git a/etc/mix/mix-test.yaml b/etc/mix/mix-test.yaml index 9e6c47ed..0dc7953d 100644 --- a/etc/mix/mix-test.yaml +++ b/etc/mix/mix-test.yaml @@ -59,7 +59,7 @@ crypto: alipay: appid: "2021004115647165" private_key: "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtj6Nu2olEB8c8SDSANExaPbmk8LoYPEGB/APZDskhezO/w4OwPmG1Ak79XDpUUIihdmTZ8i2nBLhhRpFZGU4MMdil4X7a5nYHBm5dkGo3isIInn/qV7AYDqek4pGpMUPI6fbR05NWnUTZ+3AvMjTNBa979MgLyqS3jzpvuK6yXM5RinKVv8IF9KgthRKjH4LHyyRXBGu2cJSA5utjzFCL9KIu/T4XXZ09HOgz+JKPxXDj25Ob5eTtcBDsoJfXChcOvwCA7nxb1jzvGDrkqF36H1CC8KT1aoLRLisBsM+7sjEfNcB4RG5pGHSDGQJwZ0stGAhXf/fuWiLmI/zMOXODAgMBAAECggEAEL7CAuj8w16Iv20r+46QK0i3R42eNsZhf5wD9wYxK5TKal7/rppmLOObIWCrlATtGb7lfg2aj/mpnGEFlvYVDKImh+KYrZ/8lTLupQJQ7SjrDY/VQZPSPo/zZrohWZSSOKkyEg56samcwfc7XKJYa8t3odr9Df4wJDGibrL/z99xrJrz85le+NHBISXUyddS5ojuDNfGwE39wgLu52P74QYxv6s0xZKj2aALXaLXyTzF4ys34nVhhv75gXFtENiUet5/PVRYe7OE4cndcOP9WI3nXP5ojak8N4fY15S0YOm/0NZP8w6nWUemFjUNRXYRY42J+W+/myW8RIppaGuwkQKBgQDYH263Lh8C9EkjGA2po68LUTBhM2fT2L3batzHjXo0jvLT0IR88/9V7xhC3ZQZNcxQCK0xaCYfzFx3UV9veC1zeVRW0i/hyJ8B40w3WXCoGDiHgzQ/kcu/Iaw2qmJyhEFzOwAfrxIgco9EiZBaY7fXyy7YkZLGqXNFcLsuWR5qWwKBgQDNlc19CESIukT31Ap2QBe6t9YNXHZuKTePBRaIUCan3vZwPfZePLJQCgtoVhnCGoHZJ+ZlNhYri9x6DNLZpxCSHZNjccmqFGj3N7xWBqU38gu2dcPdMAxT1ERwf2gdlhgWAhVzD56hsWyrbP9YZACXy7TlevSj7s/5GaNaVuHT+QKBgQC2VZZ3zt51BJnrlLB6LVFRz/ZsGw1+qj5LLpYDeXXff7aYQzRzovsJigVC7GO0/TFZWGid5Us8ypI8TBejGJXn9TXVZdDlwPd9hUFY9QlZl82hbm0XMK7fms4K9KbIDJKXX/CTyoUVgPEkFpcF21lQIuhr6C0XlABfVmNlD+TcPwKBgHJuot2ov3UXsZH8/gHKNSsibswrHmS9HobGPz+K1al1Stk5NCxKPrqcjLL70gSf+ozkT7MggwCkLgnln2u1OV0Lh2HAEY9RIwgQhw2fT1GvseNS873no8T5j0rLMCnfxPJjIItWM2cvOhzFY/BQYaAcrElbwlaJdEvkgG+lkrgJAoGBAInYRdHo9V1exDUS0ucQuraoEtuvgOrqatnCbuNZ9EpgjFJxDbHXOIJYPvgfpyws4amdksNQL0Ux9+p+esJOS+JYYkE1nmCTCrfb6SNKr+PdeUteKtTiHJb4zJhGVC2Lk4uBg9AGa/d7j5apWw4RsZ/R1ky1S6KQUkqItbVrhC8l" - notify_url: "" + notify_url: "https://api.wishpal.cn/ext/vas/alipay_callback" app_cert_path: "/app/wishpal-ironfan/etc/mix/alipaycert/appCertPublicKey_2021004115647165.crt" alipay_root_cert_path: "/app/wishpal-ironfan/etc/mix/alipaycert/alipayRootCert.crt" alipay_public_cert_path: "/app/wishpal-ironfan/etc/mix/alipaycert/alipayCertPublicKey_RSA2.crt" @@ -67,7 +67,7 @@ alipay: alipay_myts: appid: "2021004135664261" private_key: "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCT2MbUzyyMFUJ8EXGVotZmNMDhkw4Zv9diPgLEmnExoBGj41waqtumFMo2o63J4akBP//87r2ap+e7KKqt+WkRZZ8UB/Mj5SwQBzxqJakI+pO7YM6kM6kiAAKOLG7lloMDiQwlMxHUC52o+xJQj7RA0M/pUcVar5rr+BOnhLSH5RTrA5u5xzT5vPdmwqOxnY1OiDe7WB6VbPusLKDVbtvdT7icLnS200FYg4AQ27Sa5L8Ss9MwNcNCh4Z2eA/iriVgCvdtgNiz2RRgmAReSn4u2BBb6dZEDG6SAVsNARYs+avcYaVHpflqDfDRqPgdJ+4mQSCetQ2HDPA8GDbkn05HAgMBAAECggEAHUeaIP0ikl+HejCuMPc9xKH/7OyFp13R1vf27l6zuiM8OxvE2tcphtupLGb//PI+2SuGk93oGN/VycAFBU1WnIZmmb31Tg+NyWLVeSQaNNgDN+G1Ktm8Tip4VxW/pKJJMgMLL7bMehUO1S9b8i5zgT6ZXli+X/ZVFRRdOBjU8/CCDntTI44JmSLDnGAmR0dz3rP5/Sp2x8Yo/2O77bEBPHmT//7RVk+x1pn6olHwAsztmMddurZuLGoCP4hhZGwjuplrlyEXpe6IEpI2G0UNS97PJfL6JU56TKwMYrbo9ZV6ru5AfEeAKANPL/Urb6Gx9pcpEgktLga5B6z1glh/gQKBgQDRcZeJmpBjLO3mYlz7jqGmMtNPK06JiFr9m3NGsiE3fQmqKvEY9W0nfPX5DFYx5NFb/UWTpeuYe3NHMVo8Jwh4gNip3/AkUQylYLNxirFf6/2FltlPCsnlmeFclz9xDKzQncO60m40g2oEQ4eXUmVEOfLzpLzlsL3aXUP/K3sWBwKBgQC0tgHdFgTqE7rVn/xvZsgBas26P1tM707EYYoMGccf6zbhEMCs5e1n5nvPenX2H11TOzQDLsQz6bsZvnJ8FSoo1+pTYWi6Zr1nWDZMEQQcVGf2yLsUzFSrWHNyII/ZEeSW1UV25zlMjbv7y/VnuBlH1EJZDlv5ssSUyaAugYn1wQKBgQDQMoW70Ly1CYWXXbImkjtYVe++JEOW7cfdkDiATzQ7z3za/oLaF6Yg+dQddMj+IgKH2fXe9rGCyzzlyUZ0wyxldVdrTmOOBk922fCm7oKx4ooK0NBGBWh7Z4Mhomv7OelUG2/k96d7ZiLuCB7yKoLl1mEPF3R7Mz0Wo12jexqI4wKBgGdr3scr6eYZIo1OAYe0F/UPrevQhK0ULE0h0YK5Yge3cvH9x3dsI6GZ+/OzDz2rl5qhwFOt+SYIt0a1gwnWhwlXAMl1bx123SD/EBwahPK9r75CBSeTBUYG2hNP5WOC5QMZzaaOEHHqj9I8WRdh+j3skYgsOqE+GVlZxy22f0FBAoGAXFiGFH/X2hbwRGE5KChzQsuClC7GJ/JJgjIhHuUqUa/rHiQwWyx+uJI0c91KwsGssdpMVTnlFzeDHxdICId7YLhOgSNX92gdZDpJc6RvrU834xBszLtuukHWXpShbBDcsN/sSChI1jg6CPbjKuI2FoNm66s6puSHDXEPMTZTQYA=" - notify_url: "" + notify_url: "https://api.wishpal.cn/ext/vas/alipay_callback" app_cert_path: "/app/wishpal-ironfan/etc/mix/alipaycert_myts/appCertPublicKey_2021004135664261.crt" alipay_root_cert_path: "/app/wishpal-ironfan/etc/mix/alipaycert_myts/alipayRootCert.crt" alipay_public_cert_path: "/app/wishpal-ironfan/etc/mix/alipaycert_myts/alipayCertPublicKey_RSA2.crt"