package transfercastile import ( "context" "errors" "github.com/zeromicro/go-zero/core/jsonx" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/sqlx" "nova_task/internal/consts" "nova_task/internal/model" "nova_task/internal/pkg/errs" "nova_task/internal/pkg/utils" "nova_task/internal/svc" "nova_task/internal/types" ) type TransferCastileToGameLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } // 提取castile到游戏 func NewTransferCastileToGameLogic(ctx context.Context, svcCtx *svc.ServiceContext) *TransferCastileToGameLogic { return &TransferCastileToGameLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *TransferCastileToGameLogic) TransferCastileToGame(req *types.TransferCastileToGameReq) (resp *types.TransferCastileToGameResp, err error) { //获取JWT中的UID uid := utils.GetUidUint(l.ctx) //验证是否当前用户的角色 r, err := l.svcCtx.RoleModel.FindOneByRoleId(l.ctx, req.RoleID) if err != nil { if errors.Is(err, model.ErrNotFound) { return nil, errs.New(errs.ErrRoleNotFound, "role not exist") } l.Errorw("find role error", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid)) return nil, errs.New(errs.ErrDatabaseOperate, err) } u, err := l.svcCtx.UserModel.FindOneByEmail(l.ctx, r.Account) if err != nil { if errors.Is(err, model.ErrNotFound) { return nil, errs.New(errs.ErrUserNotFound, "user not found") } l.Errorw("find user error", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid)) return nil, errs.New(errs.ErrDatabaseOperate, err) } if u.Id != uid { return nil, errs.New(errs.ErrRoleNotFound, "role not exist.") } cToken, err := l.svcCtx.CastileTokenModel.FindOneByEmail(l.ctx, r.Account) if err != nil { if errors.Is(err, model.ErrNotFound) { return nil, errs.New(errs.ErrPointLevelConfigNotFound, "castile record is not exists") } return nil, errs.New(errs.ErrDatabaseOperate, err) } //判断余额 remain := int(cToken.Total) - int(cToken.Transfer) - int(req.Amount) if remain < 0 { return nil, errs.New(errs.ErrInsufficientCastile, "castile insufficient") } lastId := int64(0) err = l.svcCtx.DBConn.TransactCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error { err := l.svcCtx.CastileTokenModel.WithSession(session).UpdateTransferIncrease(ctx, uint(req.Amount), cToken.Id) if err != nil { logx.Errorw("castile 余额更新失败", logx.Field("err", err), logx.Field("id", cToken.Id), logx.Field("roleId", req.RoleID)) return err } res, err := l.svcCtx.CastileTokenLogModel.WithSession(session).Insert(ctx, &model.NhCastileTokenLog{ Uid: u.Id, RoleId: uint64(req.RoleID), Amount: uint(req.Amount), Action: 1, }) if err != nil { logx.Errorw("castile 日志插入失败", logx.Field("err", err), logx.Field("id", cToken.Id), logx.Field("roleId", req.RoleID)) return err } lastId, err = res.LastInsertId() if err != nil { return err } return nil }) if err != nil { logx.Errorw("castile 更新的事务报错", logx.Field("err", err), logx.Field("id", cToken.Id), logx.Field("roleId", req.RoleID)) return nil, errs.New(errs.ErrDatabaseOperate, err) } itemList := []map[string]any{ { "itemId": 32110, "itemCount": 20, }, } data, _ := jsonx.MarshalToString(itemList) //给多角色发邮件 _, err = l.svcCtx.GameAction(l.ctx, int64(req.RoleID), consts.GameActionSendNoticeAward, map[string]any{ "role_ids": req.RoleID, "item_list": data, "template_id": 120338, "mail_ttl": 24 * 90, }) if err != nil { logx.Errorw("game 发送邮件失败", logx.Field("err", err), logx.Field("roleId", req.RoleID)) return nil, errs.New(errs.ErrInternalServer, err) } res, err := l.svcCtx.CastileTokenLogModel.FindOne(l.ctx, uint(lastId)) if err != nil { logx.Errorw("查询 castile 日志表出错", logx.Field("err", err), logx.Field("Id", lastId)) return nil, errs.New(errs.ErrInternalServer, err) } //更新状态 res.CallbackStatus = 1 err = l.svcCtx.CastileTokenLogModel.Update(l.ctx, res) if err != nil { logx.Errorw("更新 castile 日志表状态出错", logx.Field("err", err), logx.Field("Id", lastId)) return nil, errs.New(errs.ErrInternalServer, err) } return &types.TransferCastileToGameResp{ Id: int(res.Id), RoleID: int64(res.RoleId), Amount: int64(res.Amount), Status: int64(res.CallbackStatus), }, nil }