fix add 修改钱包余额
This commit is contained in:
@@ -50,6 +50,10 @@ service main {
|
||||
@handler AdminGetAgentWallet
|
||||
get /wallet/:agent_id (AdminGetAgentWalletReq) returns (AdminGetAgentWalletResp)
|
||||
|
||||
// 修改代理钱包余额
|
||||
@handler AdminUpdateAgentWalletBalance
|
||||
post /wallet/update-balance (AdminUpdateAgentWalletBalanceReq) returns (AdminUpdateAgentWalletBalanceResp)
|
||||
|
||||
// 平台抽佣分页查询
|
||||
@handler AdminGetAgentPlatformDeductionList
|
||||
get /agent-platform-deduction/list (AdminGetAgentPlatformDeductionListReq) returns (AdminGetAgentPlatformDeductionListResp)
|
||||
@@ -93,6 +97,7 @@ service main {
|
||||
// 获取代理链接产品统计
|
||||
@handler AdminGetAgentLinkProductStatistics
|
||||
get /agent-link/product-statistics (AdminGetAgentLinkProductStatisticsReq) returns (AdminGetAgentLinkProductStatisticsResp)
|
||||
|
||||
}
|
||||
|
||||
type (
|
||||
@@ -163,6 +168,8 @@ type (
|
||||
OrderId *int64 `form:"order_id,optional"` // 订单ID(可选)
|
||||
ProductName *string `form:"product_name,optional"` // 产品名(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选)
|
||||
CreateTimeStart *string `form:"create_time_start,optional"` // 创建时间开始(可选)
|
||||
CreateTimeEnd *string `form:"create_time_end,optional"` // 创建时间结束(可选)
|
||||
}
|
||||
|
||||
// 代理佣金列表项
|
||||
@@ -237,6 +244,7 @@ type (
|
||||
AgentId *int64 `form:"agent_id,optional"` // 代理ID(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选)
|
||||
WithdrawNo *string `form:"withdraw_no,optional"` // 提现单号(可选)
|
||||
WithdrawType *int64 `form:"withdraw_type,optional"` // 提现类型(可选)1-支付宝,2-银行卡
|
||||
}
|
||||
|
||||
// 代理提现列表项
|
||||
@@ -516,4 +524,17 @@ type (
|
||||
FrozenBalance float64 `json:"frozen_balance"` // 冻结余额
|
||||
TotalEarnings float64 `json:"total_earnings"` // 总收益
|
||||
}
|
||||
|
||||
// 修改代理钱包余额请求
|
||||
AdminUpdateAgentWalletBalanceReq {
|
||||
AgentId int64 `json:"agent_id"` // 代理ID
|
||||
Amount float64 `json:"amount"` // 修改金额(正数增加,负数减少)
|
||||
}
|
||||
|
||||
// 修改代理钱包余额响应
|
||||
AdminUpdateAgentWalletBalanceResp {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
Balance float64 `json:"balance"` // 修改后的余额
|
||||
}
|
||||
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"tydata-server/app/main/api/internal/logic/admin_agent"
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/common/result"
|
||||
"tydata-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func AdminUpdateAgentWalletBalanceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminUpdateAgentWalletBalanceReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
result.ParamErrorResult(r, w, err)
|
||||
return
|
||||
}
|
||||
if err := validator.Validate(req); err != nil {
|
||||
result.ParamValidateErrorResult(r, w, err)
|
||||
return
|
||||
}
|
||||
l := admin_agent.NewAdminUpdateAgentWalletBalanceLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminUpdateAgentWalletBalance(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -137,6 +137,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
Path: "/wallet/:agent_id",
|
||||
Handler: admin_agent.AdminGetAgentWalletHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/wallet/update-balance",
|
||||
Handler: admin_agent.AdminUpdateAgentWalletBalanceHandler(serverCtx),
|
||||
},
|
||||
}...,
|
||||
),
|
||||
rest.WithPrefix("/api/v1/admin/agent"),
|
||||
|
||||
@@ -2,6 +2,7 @@ package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
@@ -37,6 +38,20 @@ func (l *AdminGetAgentCommissionListLogic) AdminGetAgentCommissionList(req *type
|
||||
builder = builder.Where(squirrel.Eq{"status": *req.Status})
|
||||
}
|
||||
|
||||
// 时间范围筛选
|
||||
if req.CreateTimeStart != nil && *req.CreateTimeStart != "" {
|
||||
startTime, err := time.Parse("2006-01-02 15:04:05", *req.CreateTimeStart)
|
||||
if err == nil {
|
||||
builder = builder.Where(squirrel.GtOrEq{"create_time": startTime})
|
||||
}
|
||||
}
|
||||
if req.CreateTimeEnd != nil && *req.CreateTimeEnd != "" {
|
||||
endTime, err := time.Parse("2006-01-02 15:04:05", *req.CreateTimeEnd)
|
||||
if err == nil {
|
||||
builder = builder.Where(squirrel.LtOrEq{"create_time": endTime})
|
||||
}
|
||||
}
|
||||
|
||||
// 先查出所有product_id对应的product_name(如有product_name筛选,需反查id)
|
||||
if req.ProductName != nil && *req.ProductName != "" {
|
||||
// 支持模糊匹配产品名称
|
||||
|
||||
@@ -36,6 +36,9 @@ func (l *AdminGetAgentWithdrawalListLogic) AdminGetAgentWithdrawalList(req *type
|
||||
if req.WithdrawNo != nil && *req.WithdrawNo != "" {
|
||||
builder = builder.Where(squirrel.Eq{"withdraw_no": *req.WithdrawNo})
|
||||
}
|
||||
if req.WithdrawType != nil {
|
||||
builder = builder.Where(squirrel.Eq{"withdraw_type": *req.WithdrawType})
|
||||
}
|
||||
list, total, err := l.svcCtx.AgentWithdrawalModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -80,9 +80,9 @@ func (l *AdminReviewBankCardWithdrawalLogic) AdminReviewBankCardWithdrawal(req *
|
||||
return errors.Wrapf(xerr.NewErrMsg("该提现记录已处理,无法重复操作"), "状态验证失败")
|
||||
}
|
||||
|
||||
// 验证提现类型
|
||||
if record.WithdrawType != WithdrawTypeBankCard {
|
||||
return errors.Wrapf(xerr.NewErrMsg("该记录不是银行卡提现,无法审核"), "提现类型验证失败")
|
||||
// 验证提现类型(支持银行卡和支付宝提现)
|
||||
if record.WithdrawType != WithdrawTypeBankCard && record.WithdrawType != WithdrawTypeAlipay {
|
||||
return errors.Wrapf(xerr.NewErrMsg("提现类型不正确"), "提现类型验证失败")
|
||||
}
|
||||
|
||||
if req.Action == ReviewActionApprove {
|
||||
@@ -104,6 +104,49 @@ func (l *AdminReviewBankCardWithdrawalLogic) AdminReviewBankCardWithdrawal(req *
|
||||
|
||||
// 确认提现
|
||||
func (l *AdminReviewBankCardWithdrawalLogic) approveWithdrawal(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal) error {
|
||||
// 根据提现类型执行不同的操作
|
||||
if record.WithdrawType == WithdrawTypeAlipay {
|
||||
// 支付宝提现:先调用支付宝转账接口
|
||||
return l.approveAlipayWithdrawal(ctx, session, record)
|
||||
} else {
|
||||
// 银行卡提现:直接更新状态为成功(线下转账)
|
||||
return l.approveBankCardWithdrawal(ctx, session, record)
|
||||
}
|
||||
}
|
||||
|
||||
// 确认支付宝提现
|
||||
func (l *AdminReviewBankCardWithdrawalLogic) approveAlipayWithdrawal(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal) error {
|
||||
// 同步调用支付宝转账
|
||||
transferResp, err := l.svcCtx.AlipayService.AliTransfer(ctx, record.PayeeAccount, record.PayeeName.String, record.ActualAmount, "公司提现", record.WithdrawNo)
|
||||
if err != nil {
|
||||
l.Logger.Errorf("【支付宝转账失败】withdrawNo:%s error:%v", record.WithdrawNo, err)
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "支付宝接口调用失败: %v", err)
|
||||
}
|
||||
|
||||
switch {
|
||||
case transferResp.Status == "SUCCESS":
|
||||
// 立即处理成功状态
|
||||
return l.completeWithdrawalSuccess(ctx, session, record)
|
||||
case transferResp.Status == "FAIL" || transferResp.SubCode != "":
|
||||
// 处理明确失败
|
||||
errorMsg := l.mapAlipayError(transferResp.SubCode)
|
||||
return l.completeWithdrawalFailure(ctx, session, record, errorMsg)
|
||||
case transferResp.Status == "DEALING":
|
||||
// 处理中状态,更新为处理中但不标记为最终状态
|
||||
record.Remark = sql.NullString{String: "支付宝转账处理中", Valid: true}
|
||||
if _, err := l.svcCtx.AgentWithdrawalModel.Update(ctx, session, record); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新提现记录失败: %v", err)
|
||||
}
|
||||
l.Logger.Infof("支付宝提现审核通过,转账处理中 withdrawalId:%d withdrawNo:%s", record.Id, record.WithdrawNo)
|
||||
return nil
|
||||
default:
|
||||
// 未知状态按失败处理
|
||||
return l.completeWithdrawalFailure(ctx, session, record, "支付宝返回未知状态")
|
||||
}
|
||||
}
|
||||
|
||||
// 确认银行卡提现
|
||||
func (l *AdminReviewBankCardWithdrawalLogic) approveBankCardWithdrawal(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal) error {
|
||||
// 更新提现记录状态为成功
|
||||
record.Status = StatusSuccess
|
||||
record.Remark = sql.NullString{String: "管理员确认提现", Valid: true}
|
||||
@@ -185,3 +228,126 @@ func (l *AdminReviewBankCardWithdrawalLogic) rejectWithdrawal(ctx context.Contex
|
||||
l.Logger.Infof("银行卡提现拒绝 withdrawalId:%d amount:%f reason:%s", record.Id, record.Amount, remark)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 完成提现成功(支付宝转账成功后调用)
|
||||
func (l *AdminReviewBankCardWithdrawalLogic) completeWithdrawalSuccess(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal) error {
|
||||
// 更新提现记录状态为成功
|
||||
record.Status = StatusSuccess
|
||||
record.Remark = sql.NullString{String: "支付宝转账成功", Valid: true}
|
||||
if _, err := l.svcCtx.AgentWithdrawalModel.Update(ctx, session, record); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新提现记录失败: %v", err)
|
||||
}
|
||||
|
||||
// 解冻资金并扣除(FrozenBalance -= amount, Balance不变)
|
||||
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, record.AgentId)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询钱包失败: %v", err)
|
||||
}
|
||||
|
||||
wallet.FrozenBalance -= record.Amount
|
||||
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新钱包失败: %v", err)
|
||||
}
|
||||
|
||||
// 更新扣税记录状态为成功
|
||||
taxModel, err := l.svcCtx.AgentWithdrawalTaxModel.FindOneByWithdrawalId(ctx, record.Id)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询扣税记录失败: %v", err)
|
||||
}
|
||||
if taxModel.TaxStatus == model.TaxStatusPending {
|
||||
taxModel.TaxStatus = model.TaxStatusSuccess // 扣税状态 = 成功
|
||||
taxModel.TaxTime = sql.NullTime{Time: time.Now(), Valid: true}
|
||||
if err := l.svcCtx.AgentWithdrawalTaxModel.UpdateWithVersion(ctx, session, taxModel); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新扣税记录失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 提现成功后,给上级代理发放提现奖励
|
||||
withdrawRewardErr := l.svcCtx.AgentService.GiveWithdrawReward(ctx, record.AgentId, record.Amount, session)
|
||||
if withdrawRewardErr != nil {
|
||||
l.Logger.Errorf("发放提现奖励失败,代理ID:%d,提现金额:%f,错误:%+v", record.AgentId, record.Amount, withdrawRewardErr)
|
||||
// 提现奖励失败不影响主流程,只记录日志
|
||||
} else {
|
||||
l.Logger.Infof("发放提现奖励成功,代理ID:%d,提现金额:%f", record.AgentId, record.Amount)
|
||||
}
|
||||
|
||||
l.Logger.Infof("支付宝提现成功 withdrawalId:%d withdrawNo:%s", record.Id, record.WithdrawNo)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 完成提现失败(支付宝转账失败后调用)
|
||||
func (l *AdminReviewBankCardWithdrawalLogic) completeWithdrawalFailure(ctx context.Context, session sqlx.Session, record *model.AgentWithdrawal, errorMsg string) error {
|
||||
// 更新提现记录状态为失败
|
||||
record.Status = StatusFailed
|
||||
record.Remark = sql.NullString{String: errorMsg, Valid: true}
|
||||
if _, err := l.svcCtx.AgentWithdrawalModel.Update(ctx, session, record); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新提现记录失败: %v", err)
|
||||
}
|
||||
|
||||
// 解冻资金(FrozenBalance -= amount, Balance += amount)
|
||||
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, record.AgentId)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询钱包失败: %v", err)
|
||||
}
|
||||
|
||||
wallet.Balance += record.Amount
|
||||
wallet.FrozenBalance -= record.Amount
|
||||
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新钱包失败: %v", err)
|
||||
}
|
||||
|
||||
// 更新扣税记录状态为失败
|
||||
taxModel, err := l.svcCtx.AgentWithdrawalTaxModel.FindOneByWithdrawalId(ctx, record.Id)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询扣税记录失败: %v", err)
|
||||
}
|
||||
if taxModel.TaxStatus == model.TaxStatusPending {
|
||||
taxModel.TaxStatus = model.TaxStatusFailed // 扣税状态 = 失败
|
||||
taxModel.TaxTime = sql.NullTime{Time: time.Now(), Valid: true}
|
||||
if err := l.svcCtx.AgentWithdrawalTaxModel.UpdateWithVersion(ctx, session, taxModel); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新扣税记录失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
l.Logger.Infof("支付宝提现失败 withdrawalId:%d withdrawNo:%s reason:%s", record.Id, record.WithdrawNo, errorMsg)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 错误类型映射
|
||||
func (l *AdminReviewBankCardWithdrawalLogic) mapAlipayError(code string) string {
|
||||
errorMapping := map[string]string{
|
||||
// 账户存在性错误
|
||||
"PAYEE_ACCOUNT_NOT_EXSIT": "收款账户不存在,请检查账号是否正确",
|
||||
"PAYEE_NOT_EXIST": "收款账户不存在或姓名有误,请核实信息",
|
||||
"PAYEE_ACC_OCUPIED": "收款账号存在多个账户,无法确认唯一性",
|
||||
"PAYEE_MID_CANNOT_SAME": "收款方和中间方不能是同一个人,请修改收款方或者中间方信息",
|
||||
|
||||
// 实名认证问题
|
||||
"PAYEE_CERTIFY_LEVEL_LIMIT": "收款方未完成实名认证",
|
||||
"PAYEE_NOT_RELNAME_CERTIFY": "收款方未完成实名认证",
|
||||
"PAYEE_CERT_INFO_ERROR": "收款方证件信息不匹配",
|
||||
|
||||
// 账户状态异常
|
||||
"PAYEE_ACCOUNT_STATUS_ERROR": "收款账户状态异常,请更换账号",
|
||||
"PAYEE_USERINFO_STATUS_ERROR": "收款账户状态异常,无法收款",
|
||||
"PERMIT_LIMIT_PAYEE": "收款账户异常,请更换账号",
|
||||
"BLOCK_USER_FORBBIDEN_RECIEVE": "账户冻结无法收款",
|
||||
"PAYEE_TRUSTEESHIP_ACC_OVER_LIMIT": "收款方托管子户累计收款金额超限",
|
||||
|
||||
// 账户信息错误
|
||||
"PAYEE_USERINFO_ERROR": "收款方姓名或信息不匹配",
|
||||
"PAYEE_CARD_INFO_ERROR": "收款支付宝账号及户名不一致",
|
||||
"PAYEE_IDENTITY_NOT_MATCH": "收款方身份信息不匹配",
|
||||
"PAYEE_USER_IS_INST": "收款方为金融机构,不能使用提现功能,请更换收款账号",
|
||||
"PAYEE_USER_TYPE_ERROR": "该支付宝账号类型不支持提现,请更换收款账号",
|
||||
|
||||
// 权限与限制
|
||||
"PAYEE_RECEIVE_COUNT_EXCEED_LIMIT": "收款次数超限,请明日再试",
|
||||
"PAYEE_OUT_PERMLIMIT_CHECK_FAILURE": "收款方权限校验不通过",
|
||||
"PERMIT_NON_BANK_LIMIT_PAYEE": "收款方未完善身份信息,无法收款",
|
||||
}
|
||||
if msg, ok := errorMapping[code]; ok {
|
||||
return msg
|
||||
}
|
||||
return "系统错误,请联系客服"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package admin_agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"tydata-server/app/main/api/internal/svc"
|
||||
"tydata-server/app/main/api/internal/types"
|
||||
"tydata-server/app/main/model"
|
||||
"tydata-server/common/xerr"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
type AdminUpdateAgentWalletBalanceLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminUpdateAgentWalletBalanceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateAgentWalletBalanceLogic {
|
||||
return &AdminUpdateAgentWalletBalanceLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminUpdateAgentWalletBalanceLogic) AdminUpdateAgentWalletBalance(req *types.AdminUpdateAgentWalletBalanceReq) (resp *types.AdminUpdateAgentWalletBalanceResp, err error) {
|
||||
// 参数校验
|
||||
if req.AgentId <= 0 {
|
||||
return nil, xerr.NewErrMsg("代理ID无效")
|
||||
}
|
||||
if req.Amount == 0 {
|
||||
return nil, xerr.NewErrMsg("修改金额不能为0")
|
||||
}
|
||||
|
||||
// 查询代理钱包信息
|
||||
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, req.AgentId)
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
return nil, xerr.NewErrMsg("代理钱包不存在")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 计算新余额
|
||||
newBalance := wallet.Balance + req.Amount
|
||||
|
||||
// 校验余额不能为负数
|
||||
if newBalance < 0 {
|
||||
return nil, xerr.NewErrMsg(fmt.Sprintf("操作后余额不能为负数,当前余额: %.2f,操作金额: %.2f", wallet.Balance, req.Amount))
|
||||
}
|
||||
|
||||
// 更新余额
|
||||
updateErr := l.svcCtx.AgentWalletModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
|
||||
// 使用版本号更新
|
||||
wallet.Balance = newBalance
|
||||
err := l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: 这里可以添加记录余额变更日志的逻辑
|
||||
l.Logger.Infof("代理钱包余额变更 - AgentId: %d, 原余额: %.2f, 变更金额: %.2f, 新余额: %.2f",
|
||||
req.AgentId, wallet.Balance-req.Amount, req.Amount, newBalance)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if updateErr != nil {
|
||||
l.Logger.Errorf("更新代理钱包余额失败: %+v", updateErr)
|
||||
return nil, xerr.NewErrMsg("更新余额失败")
|
||||
}
|
||||
|
||||
resp = &types.AdminUpdateAgentWalletBalanceResp{
|
||||
Success: true,
|
||||
Balance: newBalance,
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -53,6 +53,7 @@ func (l *AgentWithdrawalLogic) AgentWithdrawal(req *types.WithdrawalReq) (*types
|
||||
var (
|
||||
outBizNo string
|
||||
withdrawRes = &types.WithdrawalResp{}
|
||||
agentID int64
|
||||
)
|
||||
var finalWithdrawAmount float64 // 实际到账金额
|
||||
// 使用事务处理核心操作
|
||||
@@ -67,6 +68,7 @@ func (l *AgentWithdrawalLogic) AgentWithdrawal(req *types.WithdrawalReq) (*types
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
|
||||
}
|
||||
agentID = agentModel.Id // 保存agentId用于日志
|
||||
agentRealName, err := l.svcCtx.AgentRealNameModel.FindOneByAgentId(l.ctx, agentModel.Id)
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
@@ -116,7 +118,7 @@ func (l *AgentWithdrawalLogic) AgentWithdrawal(req *types.WithdrawalReq) (*types
|
||||
finalWithdrawAmount = req.Amount - taxAmount // 实际到账金额 = 提现金额 - 应缴税费
|
||||
|
||||
// 创建提现记录(初始状态为处理中)
|
||||
withdrawalID, err := l.createWithdrawalRecord(session, agentModel.Id, req.PayeeAccount, req.Amount, finalWithdrawAmount, taxAmount, outBizNo)
|
||||
withdrawalID, err := l.createWithdrawalRecord(session, agentModel.Id, req.PayeeAccount, req.PayeeName, req.Amount, finalWithdrawAmount, taxAmount, outBizNo)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建提现记录失败: %v", err)
|
||||
}
|
||||
@@ -146,34 +148,12 @@ func (l *AgentWithdrawalLogic) AgentWithdrawal(req *types.WithdrawalReq) (*types
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 同步调用支付宝转账
|
||||
transferResp, err := l.svcCtx.AlipayService.AliTransfer(l.ctx, req.PayeeAccount, req.PayeeName, finalWithdrawAmount, "公司提现", outBizNo)
|
||||
if err != nil {
|
||||
l.Logger.Errorf("【支付宝转账失败】outBizNo:%s error:%v", outBizNo, err)
|
||||
l.handleTransferError(outBizNo, err, "支付宝接口调用失败")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "支付宝接口调用失败: %v", err)
|
||||
}
|
||||
|
||||
switch {
|
||||
case transferResp.Status == "SUCCESS":
|
||||
// 立即处理成功状态
|
||||
l.handleTransferSuccess(outBizNo, transferResp)
|
||||
withdrawRes.Status = WithdrawStatusSuccess
|
||||
case transferResp.Status == "FAIL" || transferResp.SubCode != "":
|
||||
// 处理明确失败
|
||||
errorMsg := l.mapAlipayError(transferResp.SubCode)
|
||||
l.handleTransferFailure(outBizNo, transferResp)
|
||||
withdrawRes.Status = WithdrawStatusFailed
|
||||
withdrawRes.FailMsg = errorMsg
|
||||
case transferResp.Status == "DEALING":
|
||||
// 处理中状态,启动异步轮询
|
||||
go l.startAsyncPolling(outBizNo)
|
||||
// 支付宝提现不再直接调用转账接口,改为先申请后审核
|
||||
// 直接返回申请中状态,等待管理员审核
|
||||
withdrawRes.Status = WithdrawStatusProcessing
|
||||
default:
|
||||
// 未知状态按失败处理
|
||||
l.handleTransferError(outBizNo, fmt.Errorf("未知状态:%s", transferResp.Status), "支付宝返回未知状态")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "支付宝接口调用失败: %v", err)
|
||||
}
|
||||
withdrawRes.FailMsg = ""
|
||||
|
||||
l.Logger.Infof("支付宝提现申请成功 outBizNo:%s agentId:%d amount:%f", outBizNo, agentID, req.Amount)
|
||||
return withdrawRes, nil
|
||||
}
|
||||
|
||||
@@ -217,12 +197,13 @@ func (l *AgentWithdrawalLogic) mapAlipayError(code string) string {
|
||||
}
|
||||
|
||||
// 创建提现记录(事务内操作)
|
||||
func (l *AgentWithdrawalLogic) createWithdrawalRecord(session sqlx.Session, agentID int64, payeeAccount string, amount float64, finalWithdrawAmount float64, taxAmount float64, outBizNo string) (int64, error) {
|
||||
func (l *AgentWithdrawalLogic) createWithdrawalRecord(session sqlx.Session, agentID int64, payeeAccount string, payeeName string, amount float64, finalWithdrawAmount float64, taxAmount float64, outBizNo string) (int64, error) {
|
||||
record := &model.AgentWithdrawal{
|
||||
AgentId: agentID,
|
||||
WithdrawType: 1, // 支付宝提现
|
||||
WithdrawNo: outBizNo,
|
||||
PayeeAccount: payeeAccount,
|
||||
PayeeName: sql.NullString{String: payeeName, Valid: true}, // 设置收款人姓名
|
||||
Amount: amount,
|
||||
ActualAmount: finalWithdrawAmount,
|
||||
TaxAmount: taxAmount,
|
||||
|
||||
@@ -35,7 +35,6 @@ func NewUnfreezeCommissionHandler(svcCtx *svc.ServiceContext) *UnfreezeCommissio
|
||||
func (l *UnfreezeCommissionHandler) ProcessTask(ctx context.Context, t *asynq.Task) error {
|
||||
now := time.Now()
|
||||
logx.Infof("%s - 开始执行佣金解冻任务", now.Format("2006-01-02 15:04:05"))
|
||||
|
||||
// 解析任务payload,获取佣金ID
|
||||
var payload types.MsgUnfreezeCommissionPayload
|
||||
if err := json.Unmarshal(t.Payload(), &payload); err != nil {
|
||||
|
||||
@@ -230,6 +230,8 @@ type AdminGetAgentCommissionListReq struct {
|
||||
OrderId *int64 `form:"order_id,optional"` // 订单ID(可选)
|
||||
ProductName *string `form:"product_name,optional"` // 产品名(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选)
|
||||
CreateTimeStart *string `form:"create_time_start,optional"` // 创建时间开始(可选)
|
||||
CreateTimeEnd *string `form:"create_time_end,optional"` // 创建时间结束(可选)
|
||||
}
|
||||
|
||||
type AdminGetAgentCommissionListResp struct {
|
||||
@@ -367,6 +369,7 @@ type AdminGetAgentWithdrawalListReq struct {
|
||||
AgentId *int64 `form:"agent_id,optional"` // 代理ID(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选)
|
||||
WithdrawNo *string `form:"withdraw_no,optional"` // 提现单号(可选)
|
||||
WithdrawType *int64 `form:"withdraw_type,optional"` // 提现类型(可选)1-支付宝,2-银行卡
|
||||
}
|
||||
|
||||
type AdminGetAgentWithdrawalListResp struct {
|
||||
@@ -849,6 +852,16 @@ type AdminUpdateAgentProductionConfigResp struct {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
}
|
||||
|
||||
type AdminUpdateAgentWalletBalanceReq struct {
|
||||
AgentId int64 `json:"agent_id"` // 代理ID
|
||||
Amount float64 `json:"amount"` // 修改金额(正数增加,负数减少)
|
||||
}
|
||||
|
||||
type AdminUpdateAgentWalletBalanceResp struct {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
Balance float64 `json:"balance"` // 修改后的余额
|
||||
}
|
||||
|
||||
type AdminUpdateApiReq struct {
|
||||
Id int64 `path:"id"`
|
||||
ApiName string `json:"api_name"`
|
||||
|
||||
Reference in New Issue
Block a user