package admin_agent import ( "context" "database/sql" "fmt" "time" "ycc-server/common/globalkey" "ycc-server/common/xerr" "ycc-server/pkg/lzkit/lzUtils" "github.com/pkg/errors" "github.com/zeromicro/go-zero/core/stores/sqlx" "ycc-server/app/main/api/internal/svc" "ycc-server/app/main/api/internal/types" "github.com/zeromicro/go-zero/core/logx" ) type AdminAuditWithdrawalLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewAdminAuditWithdrawalLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminAuditWithdrawalLogic { return &AdminAuditWithdrawalLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *AdminAuditWithdrawalLogic) AdminAuditWithdrawal(req *types.AdminAuditWithdrawalReq) (resp *types.AdminAuditWithdrawalResp, err error) { // 1. 查询提现记录 withdrawal, err := l.svcCtx.AgentWithdrawalModel.FindOne(l.ctx, req.WithdrawalId) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询提现记录失败, %v", err) } // 3. 检查状态(必须是待审核状态) if withdrawal.Status != 1 { return nil, errors.Wrapf(xerr.NewErrMsg("该提现记录已处理"), "") } // 4. 使用事务处理审核 err = l.svcCtx.AgentWithdrawalModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error { if req.Status == 2 { // 审核通过 // 4.1 更新提现记录状态为提现中 withdrawal.Status = 4 // 提现中 withdrawal.Remark = sql.NullString{String: req.Remark, Valid: true} if err := l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal); err != nil { return errors.Wrapf(err, "更新提现记录失败") } // 4.2 调用支付宝转账接口 outBizNo := withdrawal.WithdrawNo transferResp, err := l.svcCtx.AlipayService.AliTransfer(transCtx, withdrawal.PayeeAccount, withdrawal.PayeeName, withdrawal.ActualAmount, "代理提现", outBizNo) if err != nil { // 转账失败,更新状态为失败 withdrawal.Status = 6 // 提现失败 withdrawal.Remark = sql.NullString{String: fmt.Sprintf("转账失败: %v", err), Valid: true} l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal) // 解冻余额 wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(transCtx, withdrawal.AgentId) if err == nil { wallet.FrozenBalance -= withdrawal.Amount wallet.Balance += withdrawal.Amount l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet) } return errors.Wrapf(err, "支付宝转账失败") } // 4.3 根据转账结果更新状态 switch transferResp.Status { case "SUCCESS": // 转账成功 withdrawal.Status = 5 // 提现成功 if err := l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal); err != nil { return errors.Wrapf(err, "更新提现记录失败") } // 更新钱包(解冻并扣除) wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(transCtx, withdrawal.AgentId) if err != nil { return errors.Wrapf(err, "查询钱包失败") } wallet.FrozenBalance -= withdrawal.Amount wallet.WithdrawnAmount += withdrawal.Amount if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet); err != nil { return errors.Wrapf(err, "更新钱包失败") } // 更新扣税记录状态 taxBuilder := l.svcCtx.AgentWithdrawalTaxModel.SelectBuilder(). Where("withdrawal_id = ? AND del_state = ?", withdrawal.Id, globalkey.DelStateNo) taxRecords, err := l.svcCtx.AgentWithdrawalTaxModel.FindAll(transCtx, taxBuilder, "") if err == nil && len(taxRecords) > 0 { taxRecord := taxRecords[0] taxRecord.TaxStatus = 2 // 已扣税 taxRecord.TaxTime = lzUtils.TimeToNullTime(time.Now()) l.svcCtx.AgentWithdrawalTaxModel.UpdateWithVersion(transCtx, session, taxRecord) } case "FAIL": // 转账失败 withdrawal.Status = 6 // 提现失败 errorMsg := l.mapAlipayError(transferResp.SubCode) withdrawal.Remark = sql.NullString{String: errorMsg, Valid: true} if err := l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal); err != nil { return errors.Wrapf(err, "更新提现记录失败") } // 解冻余额 wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(transCtx, withdrawal.AgentId) if err == nil { wallet.FrozenBalance -= withdrawal.Amount wallet.Balance += withdrawal.Amount l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet) } case "DEALING": // 处理中,保持提现中状态,后续通过轮询更新 // 状态已经是4(提现中),无需更新 } } else if req.Status == 3 { // 审核拒绝 // 4.1 更新提现记录状态为拒绝 withdrawal.Status = 3 // 审核拒绝 withdrawal.Remark = sql.NullString{String: req.Remark, Valid: true} if err := l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal); err != nil { return errors.Wrapf(err, "更新提现记录失败") } // 4.2 解冻余额 wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(transCtx, withdrawal.AgentId) if err != nil { return errors.Wrapf(err, "查询钱包失败") } wallet.FrozenBalance -= withdrawal.Amount wallet.Balance += withdrawal.Amount if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet); err != nil { return errors.Wrapf(err, "更新钱包失败") } } return nil }) if err != nil { return nil, err } return &types.AdminAuditWithdrawalResp{ Success: true, }, nil } // mapAlipayError 映射支付宝错误码 func (l *AdminAuditWithdrawalLogic) mapAlipayError(code string) string { errorMapping := map[string]string{ "PAYEE_USERINFO_ERROR": "收款方姓名或信息不匹配", "PAYEE_CARD_INFO_ERROR": "收款支付宝账号及户名不一致", "PAYEE_IDENTITY_NOT_MATCH": "收款方身份信息不匹配", "PAYEE_USER_IS_INST": "收款方为金融机构,不能使用提现功能", "PAYEE_USER_TYPE_ERROR": "该支付宝账号类型不支持提现", } if msg, ok := errorMapping[code]; ok { return msg } return "系统错误,请联系客服" }