140 lines
4.4 KiB
Go
140 lines
4.4 KiB
Go
package agent
|
||
|
||
import (
|
||
"context"
|
||
"database/sql"
|
||
|
||
"jnc-server/app/main/api/internal/svc"
|
||
"jnc-server/app/main/api/internal/types"
|
||
"jnc-server/app/main/model"
|
||
"jnc-server/common/ctxdata"
|
||
"jnc-server/common/xerr"
|
||
"jnc-server/pkg/lzkit/crypto"
|
||
|
||
"github.com/google/uuid"
|
||
"github.com/pkg/errors"
|
||
"github.com/zeromicro/go-zero/core/logx"
|
||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||
)
|
||
|
||
type CreateWithdrawLogic struct {
|
||
logx.Logger
|
||
ctx context.Context
|
||
svcCtx *svc.ServiceContext
|
||
}
|
||
|
||
func NewCreateWithdrawLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateWithdrawLogic {
|
||
return &CreateWithdrawLogic{
|
||
Logger: logx.WithContext(ctx),
|
||
ctx: ctx,
|
||
svcCtx: svcCtx,
|
||
}
|
||
}
|
||
|
||
func (l *CreateWithdrawLogic) CreateWithdraw(req *types.CreateWithdrawReq) (resp *types.CreateWithdrawResp, err error) {
|
||
// 1. 获取当前用户ID(代理ID)
|
||
userId, err := ctxdata.GetUidFromCtx(l.ctx)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户信息失败: %v", err)
|
||
}
|
||
|
||
// 2. 查询代理信息
|
||
agent, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userId)
|
||
if err != nil {
|
||
if errors.Is(err, model.ErrNotFound) {
|
||
return nil, errors.Wrap(xerr.NewErrCode(xerr.CUSTOM_ERROR), "您还不是代理,无法申请提现")
|
||
}
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询代理信息失败: %v", err)
|
||
}
|
||
|
||
// 3. 查询钱包信息
|
||
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, agent.Id)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询钱包信息失败: %v", err)
|
||
}
|
||
|
||
// 4. 验证提现金额
|
||
if req.WithdrawAmount <= 0 {
|
||
return nil, errors.Wrap(xerr.NewErrCode(xerr.REUQEST_PARAM_ERROR), "提现金额必须大于0")
|
||
}
|
||
|
||
minWithdraw := 100.00 // 最低提现金额100元
|
||
if req.WithdrawAmount < minWithdraw {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.REUQEST_PARAM_ERROR), "最低提现金额为%.2f元", minWithdraw)
|
||
}
|
||
|
||
if wallet.Balance < req.WithdrawAmount {
|
||
return nil, errors.Wrap(xerr.NewErrCode(xerr.CUSTOM_ERROR), "可用余额不足")
|
||
}
|
||
|
||
// 5. 加密银行卡号
|
||
encryptedCardNumber, err := crypto.AesEncrypt([]byte(req.BankCardNumber), []byte(l.svcCtx.Config.Encrypt.SecretKey))
|
||
if err != nil {
|
||
logx.Errorf("加密银行卡号失败: %v", err)
|
||
return nil, errors.Wrap(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "加密银行卡号失败")
|
||
}
|
||
|
||
// 6. 生成提现记录ID
|
||
withdrawId := uuid.NewString()
|
||
|
||
// 7. 解密代理手机号(用于冗余存储)
|
||
agentMobile, err := crypto.DecryptMobile(agent.Mobile, l.svcCtx.Config.Encrypt.SecretKey)
|
||
if err != nil {
|
||
logx.Errorf("解密代理手机号失败: %v", err)
|
||
agentMobile = ""
|
||
}
|
||
|
||
// 8. 开启事务处理
|
||
err = l.svcCtx.AgentWalletModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||
// 8.1 冻结提现金额
|
||
wallet.Balance -= req.WithdrawAmount
|
||
wallet.FrozenAmount += req.WithdrawAmount
|
||
|
||
// 使用版本号乐观锁更新
|
||
err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet)
|
||
if err != nil {
|
||
return errors.Wrapf(err, "冻结金额失败")
|
||
}
|
||
|
||
// 8.2 创建提现记录
|
||
withdrawRecord := &model.AgentWithdraw{
|
||
Id: withdrawId,
|
||
AgentId: agent.Id,
|
||
WithdrawAmount: req.WithdrawAmount,
|
||
TaxAmount: 0.00,
|
||
ActualAmount: 0.00,
|
||
FrozenAmount: req.WithdrawAmount,
|
||
AccountName: req.AccountName,
|
||
BankCardNumber: req.BankCardNumber,
|
||
BankCardNumberEncrypted: sql.NullString{String: string(encryptedCardNumber), Valid: true},
|
||
BankBranch: sql.NullString{String: req.BankBranch, Valid: req.BankBranch != ""},
|
||
Status: 0,
|
||
}
|
||
|
||
// 冗余存储代理手机号和编码
|
||
if agentMobile != "" {
|
||
withdrawRecord.AgentMobile = sql.NullString{String: agentMobile, Valid: true}
|
||
}
|
||
if agent.AgentCode > 0 {
|
||
withdrawRecord.AgentCode = sql.NullInt64{Int64: agent.AgentCode, Valid: true}
|
||
}
|
||
|
||
_, err = l.svcCtx.AgentWithdrawModel.Insert(ctx, session, withdrawRecord)
|
||
if err != nil {
|
||
return errors.Wrapf(err, "创建提现记录失败")
|
||
}
|
||
|
||
return nil
|
||
})
|
||
|
||
if err != nil {
|
||
return nil, errors.Wrap(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), err.Error())
|
||
}
|
||
|
||
logx.Infof("代理 %s 申请提现成功,提现金额: %.2f", agent.Id, req.WithdrawAmount)
|
||
|
||
return &types.CreateWithdrawResp{
|
||
WithdrawId: withdrawId,
|
||
}, nil
|
||
}
|