176 lines
6.2 KiB
Go
176 lines
6.2 KiB
Go
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 "系统错误,请联系客服"
|
||
}
|