完成合并:解决代码冲突
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"qnc-server/app/main/api/internal/logic/agent"
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
"qnc-server/common/result"
|
||||
"qnc-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func CheckFeatureWhitelistStatusHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.CheckFeatureWhitelistStatusReq
|
||||
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 := agent.NewCheckFeatureWhitelistStatusLogic(r.Context(), svcCtx)
|
||||
resp, err := l.CheckFeatureWhitelistStatus(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"qnc-server/app/main/api/internal/logic/agent"
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
"qnc-server/common/result"
|
||||
"qnc-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func CheckOrderAgentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.CheckOrderAgentReq
|
||||
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 := agent.NewCheckOrderAgentLogic(r.Context(), svcCtx)
|
||||
resp, err := l.CheckOrderAgent(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"qnc-server/app/main/api/internal/logic/agent"
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
"qnc-server/common/result"
|
||||
"qnc-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func CreateWhitelistOrderHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.CreateWhitelistOrderReq
|
||||
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 := agent.NewCreateWhitelistOrderLogic(r.Context(), svcCtx)
|
||||
resp, err := l.CreateWhitelistOrder(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"qnc-server/app/main/api/internal/logic/agent"
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
"qnc-server/common/result"
|
||||
"qnc-server/pkg/lzkit/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func GetLastWithdrawalInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GetLastWithdrawalInfoReq
|
||||
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 := agent.NewGetLastWithdrawalInfoLogic(r.Context(), svcCtx)
|
||||
resp, err := l.GetLastWithdrawalInfo(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"qnc-server/app/main/api/internal/logic/agent"
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
"qnc-server/common/result"
|
||||
"qnc-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func GetWhitelistFeaturesHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GetWhitelistFeaturesReq
|
||||
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 := agent.NewGetWhitelistFeaturesLogic(r.Context(), svcCtx)
|
||||
resp, err := l.GetWhitelistFeatures(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"qnc-server/app/main/api/internal/logic/agent"
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
"qnc-server/common/result"
|
||||
"qnc-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func GetWhitelistListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GetWhitelistListReq
|
||||
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 := agent.NewGetWhitelistListLogic(r.Context(), svcCtx)
|
||||
resp, err := l.GetWhitelistList(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
29
app/main/api/internal/handler/agent/offlinefeaturehandler.go
Normal file
29
app/main/api/internal/handler/agent/offlinefeaturehandler.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"qnc-server/app/main/api/internal/logic/agent"
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
"qnc-server/common/result"
|
||||
"qnc-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func OfflineFeatureHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.OfflineFeatureReq
|
||||
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 := agent.NewOfflineFeatureLogic(r.Context(), svcCtx)
|
||||
resp, err := l.OfflineFeature(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/upgrade",
|
||||
Path: "/upgrade/agent",
|
||||
Handler: admin_agent.AdminUpgradeAgentHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
@@ -671,6 +671,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
Path: "/level/privilege",
|
||||
Handler: agent.GetLevelPrivilegeHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/order/agent",
|
||||
Handler: agent.CheckOrderAgentHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/product_config",
|
||||
@@ -736,11 +741,41 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
Path: "/upgrade/subordinate",
|
||||
Handler: agent.UpgradeSubordinateHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/whitelist/check",
|
||||
Handler: agent.CheckFeatureWhitelistStatusHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/whitelist/features",
|
||||
Handler: agent.GetWhitelistFeaturesHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/whitelist/list",
|
||||
Handler: agent.GetWhitelistListHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/whitelist/offline",
|
||||
Handler: agent.OfflineFeatureHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/whitelist/order/create",
|
||||
Handler: agent.CreateWhitelistOrderHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/withdrawal/apply",
|
||||
Handler: agent.ApplyWithdrawalHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/withdrawal/last_info",
|
||||
Handler: agent.GetLastWithdrawalInfoHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/withdrawal/list",
|
||||
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
"qnc-server/common/globalkey"
|
||||
"os"
|
||||
"qnc-server/common/xerr"
|
||||
"qnc-server/pkg/lzkit/lzUtils"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
@@ -32,6 +32,13 @@ func NewAdminAuditWithdrawalLogic(ctx context.Context, svcCtx *svc.ServiceContex
|
||||
}
|
||||
}
|
||||
|
||||
// parseFloat 解析配置中的浮点数
|
||||
func (l *AdminAuditWithdrawalLogic) parseFloat(s string) (float64, error) {
|
||||
var result float64
|
||||
_, err := fmt.Sscanf(s, "%f", &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (l *AdminAuditWithdrawalLogic) AdminAuditWithdrawal(req *types.AdminAuditWithdrawalReq) (resp *types.AdminAuditWithdrawalResp, err error) {
|
||||
// 1. 查询提现记录
|
||||
withdrawal, err := l.svcCtx.AgentWithdrawalModel.FindOne(l.ctx, req.WithdrawalId)
|
||||
@@ -46,39 +53,126 @@ func (l *AdminAuditWithdrawalLogic) AdminAuditWithdrawal(req *types.AdminAuditWi
|
||||
|
||||
// 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, "更新提现记录失败")
|
||||
}
|
||||
switch req.Status {
|
||||
case 2: // 审核通过
|
||||
// 4.1 根据提现方式处理
|
||||
switch withdrawal.WithdrawalType {
|
||||
case 1:
|
||||
// 支付宝提现:审核通过前再次校验月度额度,避免一次性通过多笔超限
|
||||
now := time.Now()
|
||||
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||
nextMonthStart := monthStart.AddDate(0, 1, 0)
|
||||
|
||||
// 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)
|
||||
// 获取支付宝月度额度配置(默认 800 元)
|
||||
alipayQuota := 800.0
|
||||
if cfg, cfgErr := l.svcCtx.AgentConfigModel.FindOneByConfigKey(transCtx, "alipay_month_quota"); cfgErr == nil {
|
||||
if parsed, parseErr := l.parseFloat(cfg.ConfigValue); parseErr == nil && parsed > 0 {
|
||||
alipayQuota = parsed
|
||||
}
|
||||
}
|
||||
|
||||
return errors.Wrapf(err, "支付宝转账失败")
|
||||
}
|
||||
// 统计本月已成功的支付宝提现金额(status=5)
|
||||
withdrawBuilder := l.svcCtx.AgentWithdrawalModel.SelectBuilder().
|
||||
Where("agent_id = ? AND withdrawal_type = ? AND status = ? AND create_time >= ? AND create_time < ?",
|
||||
withdrawal.AgentId, 1, 5, monthStart, nextMonthStart)
|
||||
usedAmount, sumErr := l.svcCtx.AgentWithdrawalModel.FindSum(transCtx, withdrawBuilder, "amount")
|
||||
if sumErr != nil {
|
||||
return errors.Wrapf(sumErr, "查询本月支付宝提现额度使用情况失败")
|
||||
}
|
||||
|
||||
// 4.3 根据转账结果更新状态
|
||||
switch transferResp.Status {
|
||||
case "SUCCESS":
|
||||
// 转账成功
|
||||
if usedAmount+withdrawal.Amount > alipayQuota {
|
||||
// 超出额度,不允许通过,保持待审核状态并提示原因
|
||||
withdrawal.Status = 1
|
||||
withdrawal.Remark = sql.NullString{
|
||||
String: fmt.Sprintf("超过本月支付宝提现额度(限额:%.2f 元,已用:%.2f 元),请使用银行卡提现或调整金额", alipayQuota, usedAmount),
|
||||
Valid: true,
|
||||
}
|
||||
if err := l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal); err != nil {
|
||||
return errors.Wrapf(err, "更新提现记录失败")
|
||||
}
|
||||
return errors.Wrapf(xerr.NewErrMsg("超过本月支付宝提现额度,无法通过该笔提现"), "")
|
||||
}
|
||||
|
||||
// 支付宝提现:开发环境下做模拟,不调用真实支付宝转账
|
||||
mockTransferStatus := "SUCCESS"
|
||||
var transferResp struct {
|
||||
Status string
|
||||
SubCode string
|
||||
}
|
||||
|
||||
if os.Getenv("ENV") == "development" {
|
||||
transferResp.Status = mockTransferStatus
|
||||
logx.Infof("【DEV】模拟支付宝转账成功,withdrawNo=%s, amount=%.2f, payee=%s",
|
||||
withdrawal.WithdrawNo, withdrawal.ActualAmount, withdrawal.PayeeAccount)
|
||||
} else {
|
||||
// 生产环境:同步调用支付宝转账接口
|
||||
outBizNo := withdrawal.WithdrawNo
|
||||
resp, err := l.svcCtx.AlipayService.AliTransfer(transCtx, withdrawal.PayeeAccount, withdrawal.PayeeName, withdrawal.ActualAmount, "代理提现", outBizNo)
|
||||
if err != nil {
|
||||
// 调用失败:保持状态为待审核(1),只记录备注,方便管理员重试
|
||||
withdrawal.Status = 1 // 待审核
|
||||
withdrawal.Remark = sql.NullString{String: fmt.Sprintf("支付宝转账调用失败: %v", err), Valid: true}
|
||||
_ = l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal)
|
||||
|
||||
return errors.Wrapf(err, "支付宝转账失败")
|
||||
}
|
||||
transferResp.Status = resp.Status
|
||||
transferResp.SubCode = resp.SubCode
|
||||
}
|
||||
|
||||
// 4.2 根据转账结果更新状态
|
||||
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 = ?", withdrawal.Id)
|
||||
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 = 1 // 待审核
|
||||
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, "更新提现记录失败")
|
||||
}
|
||||
|
||||
case "DEALING":
|
||||
// 处理中:同样保持待审核状态(1),由管理员后续确认
|
||||
withdrawal.Status = 1
|
||||
withdrawal.Remark = sql.NullString{String: "支付宝处理中,请稍后重试或联系平台", Valid: true}
|
||||
if err := l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal); err != nil {
|
||||
return errors.Wrapf(err, "更新提现记录失败")
|
||||
}
|
||||
}
|
||||
|
||||
case 2:
|
||||
// 银行卡提现:审核通过即视为提现成功(线下已/将立即打款)
|
||||
withdrawal.Status = 5 // 提现成功
|
||||
withdrawal.Remark = sql.NullString{String: req.Remark, Valid: true}
|
||||
if err := l.svcCtx.AgentWithdrawalModel.UpdateWithVersion(transCtx, session, withdrawal); err != nil {
|
||||
return errors.Wrapf(err, "更新提现记录失败")
|
||||
}
|
||||
@@ -96,7 +190,7 @@ func (l *AdminAuditWithdrawalLogic) AdminAuditWithdrawal(req *types.AdminAuditWi
|
||||
|
||||
// 更新扣税记录状态
|
||||
taxBuilder := l.svcCtx.AgentWithdrawalTaxModel.SelectBuilder().
|
||||
Where("withdrawal_id = ? AND del_state = ?", withdrawal.Id, globalkey.DelStateNo)
|
||||
Where("withdrawal_id = ?", withdrawal.Id)
|
||||
taxRecords, err := l.svcCtx.AgentWithdrawalTaxModel.FindAll(transCtx, taxBuilder, "")
|
||||
if err == nil && len(taxRecords) > 0 {
|
||||
taxRecord := taxRecords[0]
|
||||
@@ -104,30 +198,9 @@ func (l *AdminAuditWithdrawalLogic) AdminAuditWithdrawal(req *types.AdminAuditWi
|
||||
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 { // 审核拒绝
|
||||
case 3: // 审核拒绝
|
||||
// 4.1 更新提现记录状态为拒绝
|
||||
withdrawal.Status = 3 // 审核拒绝
|
||||
withdrawal.Remark = sql.NullString{String: req.Remark, Valid: true}
|
||||
|
||||
@@ -49,6 +49,17 @@ func (l *AdminGetAgentWithdrawalListLogic) AdminGetAgentWithdrawalList(req *type
|
||||
item.Remark = v.Remark.String
|
||||
}
|
||||
item.CreateTime = v.CreateTime.Format("2006-01-02 15:04:05")
|
||||
|
||||
// 如果是银行卡提现,填充银行卡信息
|
||||
if v.WithdrawalType == 2 {
|
||||
if v.BankCardNo.Valid {
|
||||
item.BankCardNo = v.BankCardNo.String
|
||||
}
|
||||
if v.BankName.Valid {
|
||||
item.BankName = v.BankName.String
|
||||
}
|
||||
}
|
||||
|
||||
items = append(items, item)
|
||||
}
|
||||
resp = &types.AdminGetAgentWithdrawalListResp{
|
||||
|
||||
@@ -3,12 +3,11 @@ package agent
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
"qnc-server/app/main/model"
|
||||
"qnc-server/common/ctxdata"
|
||||
"qnc-server/common/globalkey"
|
||||
"qnc-server/common/xerr"
|
||||
"qnc-server/pkg/lzkit/lzUtils"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
@@ -62,53 +61,138 @@ func (l *ApplyWithdrawalLogic) ApplyWithdrawal(req *types.ApplyWithdrawalReq) (r
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("请先完成实名认证"), "")
|
||||
}
|
||||
|
||||
// 3. 验证提现金额
|
||||
// 3. 验证提现方式
|
||||
if req.WithdrawalType != 1 && req.WithdrawalType != 2 {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("提现方式无效"), "")
|
||||
}
|
||||
|
||||
// 4. 验证提现信息
|
||||
if req.WithdrawalType == 1 {
|
||||
// 支付宝提现:验证支付宝账号和姓名
|
||||
if req.PayeeAccount == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("请输入支付宝账号"), "")
|
||||
}
|
||||
if req.PayeeName == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("请输入收款人姓名"), "")
|
||||
}
|
||||
} else if req.WithdrawalType == 2 {
|
||||
// 银行卡提现:验证银行卡号、开户行和姓名
|
||||
if req.BankCardNo == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("请输入银行卡号"), "")
|
||||
}
|
||||
if req.BankName == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("请输入开户行名称"), "")
|
||||
}
|
||||
if req.PayeeName == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("请输入收款人姓名"), "")
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 验证提现金额
|
||||
if req.Amount <= 0 {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("提现金额必须大于0"), "")
|
||||
}
|
||||
|
||||
// 4. 获取钱包信息
|
||||
// 6. 获取钱包信息
|
||||
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, agent.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询钱包失败, %v", err)
|
||||
}
|
||||
|
||||
// 5. 验证余额
|
||||
// 7. 验证余额(包括检查是否为负数)
|
||||
if wallet.Balance < 0 {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("账户存在欠款,请先补足欠款后再申请提现,当前余额:%.2f", wallet.Balance)), "")
|
||||
}
|
||||
if wallet.Balance < req.Amount {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("余额不足,当前余额:%.2f", wallet.Balance)), "")
|
||||
}
|
||||
|
||||
// 6. 计算税费
|
||||
// 8. 支付宝月度提现额度校验(仅针对支付宝提现)
|
||||
if req.WithdrawalType == 1 {
|
||||
now := time.Now()
|
||||
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||
nextMonthStart := monthStart.AddDate(0, 1, 0)
|
||||
|
||||
// 8.1 获取支付宝月度额度配置(默认 800 元)
|
||||
alipayQuota := 800.0
|
||||
if cfg, cfgErr := l.svcCtx.AgentConfigModel.FindOneByConfigKey(l.ctx, "alipay_month_quota"); cfgErr == nil {
|
||||
if parsed, parseErr := l.parseFloat(cfg.ConfigValue); parseErr == nil && parsed > 0 {
|
||||
alipayQuota = parsed
|
||||
}
|
||||
}
|
||||
|
||||
// 8.2 统计本月已申请/成功的支付宝提现金额(status IN (1,5)),避免多次申请占用超额
|
||||
withdrawBuilder := l.svcCtx.AgentWithdrawalModel.SelectBuilder().
|
||||
Where("agent_id = ? AND withdrawal_type = ? AND status IN (1,5) AND create_time >= ? AND create_time < ?",
|
||||
agent.Id, 1, monthStart, nextMonthStart)
|
||||
usedAmount, sumErr := l.svcCtx.AgentWithdrawalModel.FindSum(l.ctx, withdrawBuilder, "amount")
|
||||
if sumErr != nil {
|
||||
return nil, errors.Wrapf(sumErr, "查询本月支付宝提现额度使用情况失败")
|
||||
}
|
||||
|
||||
remainQuota := alipayQuota - usedAmount
|
||||
if remainQuota <= 0 {
|
||||
return nil, errors.Wrapf(
|
||||
xerr.NewErrMsg(fmt.Sprintf("本月支付宝提现额度已用完(额度:%.2f 元),请使用银行卡提现", alipayQuota)),
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
if req.Amount > remainQuota {
|
||||
return nil, errors.Wrapf(
|
||||
xerr.NewErrMsg(fmt.Sprintf("本月支付宝最高可提现 %.2f 元,请调整提现金额或使用银行卡提现", remainQuota)),
|
||||
"",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 9. 计算税费
|
||||
yearMonth := int64(time.Now().Year()*100 + int(time.Now().Month()))
|
||||
taxInfo, err := l.calculateTax(l.ctx, agent.Id, req.Amount, yearMonth)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "计算税费失败")
|
||||
}
|
||||
|
||||
// 7. 生成提现单号
|
||||
withdrawNo := fmt.Sprintf("WD%d%d", time.Now().Unix(), agent.Id)
|
||||
// 10. 生成提现单号(WD开头 + GenerateOutTradeNo生成的订单号,确保总长度不超过32个字符)
|
||||
orderNo := l.svcCtx.AlipayService.GenerateOutTradeNo()
|
||||
withdrawNo := "WD" + orderNo
|
||||
// 确保总长度不超过32个字符
|
||||
if len(withdrawNo) > 32 {
|
||||
withdrawNo = withdrawNo[:32]
|
||||
}
|
||||
|
||||
// 8. 使用事务处理提现申请
|
||||
// 11. 使用事务处理提现申请
|
||||
var withdrawalId string
|
||||
err = l.svcCtx.AgentWalletModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
|
||||
// 8.1 冻结余额
|
||||
// 11.1 冻结余额
|
||||
wallet.FrozenBalance += req.Amount
|
||||
wallet.Balance -= req.Amount
|
||||
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(transCtx, session, wallet); err != nil {
|
||||
return errors.Wrapf(err, "冻结余额失败")
|
||||
}
|
||||
|
||||
// 8.2 创建提现记录
|
||||
// 11.2 创建提现记录
|
||||
withdrawal := &model.AgentWithdrawal{
|
||||
Id: uuid.New().String(),
|
||||
AgentId: agent.Id,
|
||||
WithdrawNo: withdrawNo,
|
||||
PayeeAccount: req.PayeeAccount,
|
||||
PayeeName: req.PayeeName,
|
||||
Amount: req.Amount,
|
||||
ActualAmount: taxInfo.ActualAmount,
|
||||
TaxAmount: taxInfo.TaxAmount,
|
||||
Status: 1, // 处理中(待审核)
|
||||
Id: uuid.New().String(),
|
||||
AgentId: agent.Id,
|
||||
WithdrawNo: withdrawNo,
|
||||
WithdrawalType: req.WithdrawalType,
|
||||
PayeeAccount: req.PayeeAccount,
|
||||
PayeeName: req.PayeeName,
|
||||
Amount: req.Amount,
|
||||
ActualAmount: taxInfo.ActualAmount,
|
||||
TaxAmount: taxInfo.TaxAmount,
|
||||
Status: 1, // 待审核
|
||||
}
|
||||
|
||||
// 如果是银行卡提现,设置银行卡相关字段
|
||||
if req.WithdrawalType == 2 {
|
||||
withdrawal.BankCardNo = lzUtils.StringToNullString(req.BankCardNo)
|
||||
withdrawal.BankName = lzUtils.StringToNullString(req.BankName)
|
||||
// 银行卡提现时,payee_account 可以存储银行卡号(便于查询),也可以留空
|
||||
if req.PayeeAccount == "" {
|
||||
withdrawal.PayeeAccount = req.BankCardNo
|
||||
}
|
||||
}
|
||||
|
||||
_, err := l.svcCtx.AgentWithdrawalModel.Insert(transCtx, session, withdrawal)
|
||||
@@ -117,7 +201,7 @@ func (l *ApplyWithdrawalLogic) ApplyWithdrawal(req *types.ApplyWithdrawalReq) (r
|
||||
}
|
||||
withdrawalId = withdrawal.Id
|
||||
|
||||
// 8.3 创建扣税记录
|
||||
// 11.3 创建扣税记录
|
||||
taxRecord := &model.AgentWithdrawalTax{
|
||||
AgentId: agent.Id,
|
||||
WithdrawalId: withdrawalId,
|
||||
@@ -167,8 +251,10 @@ func (l *ApplyWithdrawalLogic) calculateTax(ctx context.Context, agentId string,
|
||||
}
|
||||
|
||||
// 查询本月已提现金额
|
||||
// 注意:FindAll 方法会自动添加 del_state = ? 条件,所以这里不需要手动添加
|
||||
// 这里对 year_month 使用反引号包裹,避免与某些数据库版本/SQL 模式下的关键字冲突
|
||||
builder := l.svcCtx.AgentWithdrawalTaxModel.SelectBuilder().
|
||||
Where("agent_id = ? AND year_month = ? AND del_state = ?", agentId, yearMonth, globalkey.DelStateNo)
|
||||
Where("agent_id = ? AND `year_month` = ?", agentId, yearMonth)
|
||||
taxRecords, err := l.svcCtx.AgentWithdrawalTaxModel.FindAll(ctx, builder, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "查询月度提现记录失败")
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type CheckFeatureWhitelistStatusLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewCheckFeatureWhitelistStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CheckFeatureWhitelistStatusLogic {
|
||||
return &CheckFeatureWhitelistStatusLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CheckFeatureWhitelistStatusLogic) CheckFeatureWhitelistStatus(req *types.CheckFeatureWhitelistStatusReq) (resp *types.CheckFeatureWhitelistStatusResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
||||
30
app/main/api/internal/logic/agent/checkorderagentlogic.go
Normal file
30
app/main/api/internal/logic/agent/checkorderagentlogic.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type CheckOrderAgentLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewCheckOrderAgentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CheckOrderAgentLogic {
|
||||
return &CheckOrderAgentLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CheckOrderAgentLogic) CheckOrderAgent(req *types.CheckOrderAgentReq) (resp *types.CheckOrderAgentResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type CreateWhitelistOrderLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewCreateWhitelistOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateWhitelistOrderLogic {
|
||||
return &CreateWhitelistOrderLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CreateWhitelistOrderLogic) CreateWhitelistOrder(req *types.CreateWhitelistOrderReq) (resp *types.CreateWhitelistOrderResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"qnc-server/app/main/model"
|
||||
"qnc-server/common/ctxdata"
|
||||
"qnc-server/common/xerr"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetLastWithdrawalInfoLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGetLastWithdrawalInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetLastWithdrawalInfoLogic {
|
||||
return &GetLastWithdrawalInfoLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetLastWithdrawalInfoLogic) GetLastWithdrawalInfo(req *types.GetLastWithdrawalInfoReq) (resp *types.GetLastWithdrawalInfoResp, err error) {
|
||||
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户信息失败, %v", err)
|
||||
}
|
||||
|
||||
// 1. 获取代理信息
|
||||
agent, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("您不是代理"), "")
|
||||
}
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败, %v", err)
|
||||
}
|
||||
|
||||
// 2. 验证提现方式
|
||||
if req.WithdrawalType != 1 && req.WithdrawalType != 2 {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("提现方式无效"), "")
|
||||
}
|
||||
|
||||
// 3. 查询该代理最近一次该类型的提现记录
|
||||
// 注意:FindAll 方法会自动添加 del_state = ? 条件,所以这里不需要手动添加
|
||||
builder := l.svcCtx.AgentWithdrawalModel.SelectBuilder().
|
||||
Where("agent_id = ? AND withdrawal_type = ?", agent.Id, req.WithdrawalType).
|
||||
OrderBy("create_time DESC").
|
||||
Limit(1)
|
||||
|
||||
withdrawals, err := l.svcCtx.AgentWithdrawalModel.FindAll(l.ctx, builder, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询上次提现记录失败, %v", err)
|
||||
}
|
||||
|
||||
// 4. 如果没有找到记录,返回空信息
|
||||
if len(withdrawals) == 0 {
|
||||
return &types.GetLastWithdrawalInfoResp{
|
||||
WithdrawalType: req.WithdrawalType,
|
||||
PayeeAccount: "",
|
||||
PayeeName: "",
|
||||
BankCardNo: "",
|
||||
BankName: "",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 5. 组装响应
|
||||
lastWithdrawal := withdrawals[0]
|
||||
resp = &types.GetLastWithdrawalInfoResp{
|
||||
WithdrawalType: lastWithdrawal.WithdrawalType,
|
||||
PayeeAccount: lastWithdrawal.PayeeAccount,
|
||||
PayeeName: lastWithdrawal.PayeeName,
|
||||
BankCardNo: "",
|
||||
BankName: "",
|
||||
}
|
||||
|
||||
// 如果是银行卡提现,填充银行卡信息
|
||||
if lastWithdrawal.WithdrawalType == 2 {
|
||||
if lastWithdrawal.BankCardNo.Valid {
|
||||
resp.BankCardNo = lastWithdrawal.BankCardNo.String
|
||||
}
|
||||
if lastWithdrawal.BankName.Valid {
|
||||
resp.BankName = lastWithdrawal.BankName.String
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetWhitelistFeaturesLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGetWhitelistFeaturesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWhitelistFeaturesLogic {
|
||||
return &GetWhitelistFeaturesLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetWhitelistFeaturesLogic) GetWhitelistFeatures(req *types.GetWhitelistFeaturesReq) (resp *types.GetWhitelistFeaturesResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
||||
30
app/main/api/internal/logic/agent/getwhitelistlistlogic.go
Normal file
30
app/main/api/internal/logic/agent/getwhitelistlistlogic.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetWhitelistListLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGetWhitelistListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetWhitelistListLogic {
|
||||
return &GetWhitelistListLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetWhitelistListLogic) GetWhitelistList(req *types.GetWhitelistListReq) (resp *types.GetWhitelistListResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
||||
@@ -81,18 +81,31 @@ func (l *GetWithdrawalListLogic) GetWithdrawalList(req *types.GetWithdrawalListR
|
||||
remark = withdrawal.Remark.String
|
||||
}
|
||||
|
||||
list = append(list, types.WithdrawalItem{
|
||||
Id: withdrawal.Id,
|
||||
WithdrawalNo: withdrawal.WithdrawNo,
|
||||
Amount: withdrawal.Amount,
|
||||
TaxAmount: withdrawal.TaxAmount,
|
||||
ActualAmount: withdrawal.ActualAmount,
|
||||
Status: withdrawal.Status,
|
||||
PayeeAccount: withdrawal.PayeeAccount,
|
||||
PayeeName: withdrawal.PayeeName,
|
||||
Remark: remark,
|
||||
CreateTime: withdrawal.CreateTime.Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
item := types.WithdrawalItem{
|
||||
Id: withdrawal.Id,
|
||||
WithdrawalNo: withdrawal.WithdrawNo,
|
||||
WithdrawalType: withdrawal.WithdrawalType,
|
||||
Amount: withdrawal.Amount,
|
||||
TaxAmount: withdrawal.TaxAmount,
|
||||
ActualAmount: withdrawal.ActualAmount,
|
||||
Status: withdrawal.Status,
|
||||
PayeeAccount: withdrawal.PayeeAccount,
|
||||
PayeeName: withdrawal.PayeeName,
|
||||
Remark: remark,
|
||||
CreateTime: withdrawal.CreateTime.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
|
||||
// 如果是银行卡提现,填充银行卡信息
|
||||
if withdrawal.WithdrawalType == 2 {
|
||||
if withdrawal.BankCardNo.Valid {
|
||||
item.BankCardNo = withdrawal.BankCardNo.String
|
||||
}
|
||||
if withdrawal.BankName.Valid {
|
||||
item.BankName = withdrawal.BankName.String
|
||||
}
|
||||
}
|
||||
|
||||
list = append(list, item)
|
||||
}
|
||||
|
||||
return &types.GetWithdrawalListResp{
|
||||
|
||||
30
app/main/api/internal/logic/agent/offlinefeaturelogic.go
Normal file
30
app/main/api/internal/logic/agent/offlinefeaturelogic.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"qnc-server/app/main/api/internal/svc"
|
||||
"qnc-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type OfflineFeatureLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewOfflineFeatureLogic(ctx context.Context, svcCtx *svc.ServiceContext) *OfflineFeatureLogic {
|
||||
return &OfflineFeatureLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *OfflineFeatureLogic) OfflineFeature(req *types.OfflineFeatureReq) (resp *types.OfflineFeatureResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
||||
@@ -282,6 +282,7 @@ type AdminGetAgentOrderListReq struct {
|
||||
AgentId *string `form:"agent_id,optional"` // 代理ID(可选)
|
||||
OrderId *string `form:"order_id,optional"` // 订单ID(可选)
|
||||
ProcessStatus *int64 `form:"process_status,optional"` // 处理状态(可选)
|
||||
OrderStatus *string `form:"order_status,optional"` // 订单状态(可选):pending-待支付,paid-已支付,refunded-已退款,closed-已关闭,failed-支付失败
|
||||
}
|
||||
|
||||
type AdminGetAgentOrderListResp struct {
|
||||
@@ -319,6 +320,7 @@ type AdminGetAgentRebateListReq struct {
|
||||
AgentId *string `form:"agent_id,optional"` // 代理ID(可选)
|
||||
SourceAgentId *string `form:"source_agent_id,optional"` // 来源代理ID(可选)
|
||||
RebateType *int64 `form:"rebate_type,optional"` // 返佣类型(可选)
|
||||
Status *int64 `form:"status,optional"` // 状态(可选):1=已发放,2=已冻结,3=已取消(已退款)
|
||||
}
|
||||
|
||||
type AdminGetAgentRebateListResp struct {
|
||||
@@ -898,7 +900,7 @@ type AdminUpgradeAgentReq struct {
|
||||
}
|
||||
|
||||
type AdminUpgradeAgentResp struct {
|
||||
Success bool `json:"success"`
|
||||
Success bool `json:"success"` // 是否成功
|
||||
}
|
||||
|
||||
type AdminUserInfoReq struct {
|
||||
@@ -1008,7 +1010,8 @@ type AgentOrderListItem struct {
|
||||
ActualBasePrice float64 `json:"actual_base_price"` // 实际底价
|
||||
PriceCost float64 `json:"price_cost"` // 提价成本
|
||||
AgentProfit float64 `json:"agent_profit"` // 代理收益
|
||||
ProcessStatus int64 `json:"process_status"` // 处理状态
|
||||
ProcessStatus int64 `json:"process_status"` // 处理状态(保留用于筛选,前端不显示)
|
||||
OrderStatus string `json:"order_status"` // 订单状态:pending-待支付,paid-已支付,refunded-已退款,closed-已关闭,failed-支付失败
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
}
|
||||
|
||||
@@ -1046,6 +1049,7 @@ type AgentRebateListItem struct {
|
||||
OrderId string `json:"order_id"` // 订单ID
|
||||
RebateType int64 `json:"rebate_type"` // 返佣类型
|
||||
Amount float64 `json:"amount"` // 金额
|
||||
Status int64 `json:"status"` // 状态:1=已发放,2=已冻结,3=已取消(已退款)
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
}
|
||||
|
||||
@@ -1062,17 +1066,20 @@ type AgentUpgradeListItem struct {
|
||||
}
|
||||
|
||||
type AgentWithdrawalListItem struct {
|
||||
Id string `json:"id"` // 主键
|
||||
AgentId string `json:"agent_id"` // 代理ID
|
||||
WithdrawNo string `json:"withdraw_no"` // 提现单号
|
||||
Amount float64 `json:"amount"` // 金额
|
||||
TaxAmount float64 `json:"tax_amount"` // 税费金额
|
||||
ActualAmount float64 `json:"actual_amount"` // 实际到账金额
|
||||
Status int64 `json:"status"` // 状态
|
||||
PayeeAccount string `json:"payee_account"` // 收款账户
|
||||
PayeeName string `json:"payee_name"` // 收款人姓名
|
||||
Remark string `json:"remark"` // 备注
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
Id string `json:"id"` // 主键
|
||||
AgentId string `json:"agent_id"` // 代理ID
|
||||
WithdrawNo string `json:"withdraw_no"` // 提现单号
|
||||
Amount float64 `json:"amount"` // 金额
|
||||
TaxAmount float64 `json:"tax_amount"` // 税费金额
|
||||
ActualAmount float64 `json:"actual_amount"` // 实际到账金额
|
||||
Status int64 `json:"status"` // 状态
|
||||
WithdrawalType int64 `json:"withdrawal_type"` // 提现方式:1=支付宝,2=银行卡
|
||||
PayeeAccount string `json:"payee_account"` // 收款账户(支付宝账号或银行卡号)
|
||||
PayeeName string `json:"payee_name"` // 收款人姓名
|
||||
BankCardNo string `json:"bank_card_no"` // 银行卡号(银行卡提现时使用)
|
||||
BankName string `json:"bank_name"` // 开户行名称(银行卡提现时使用)
|
||||
Remark string `json:"remark"` // 备注
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
}
|
||||
|
||||
type ApplyUpgradeReq struct {
|
||||
@@ -1085,9 +1092,12 @@ type ApplyUpgradeResp struct {
|
||||
}
|
||||
|
||||
type ApplyWithdrawalReq struct {
|
||||
Amount float64 `json:"amount"` // 提现金额
|
||||
PayeeAccount string `json:"payee_account"` // 收款账户
|
||||
PayeeName string `json:"payee_name"` // 收款人姓名
|
||||
Amount float64 `json:"amount"` // 提现金额
|
||||
WithdrawalType int64 `json:"withdrawal_type"` // 提现方式:1=支付宝,2=银行卡
|
||||
PayeeAccount string `json:"payee_account"` // 收款账户(支付宝账号或银行卡号)
|
||||
PayeeName string `json:"payee_name"` // 收款人姓名
|
||||
BankCardNo string `json:"bank_card_no,optional"` // 银行卡号(银行卡提现必填)
|
||||
BankName string `json:"bank_name,optional"` // 开户行名称(银行卡提现必填)
|
||||
}
|
||||
|
||||
type ApplyWithdrawalResp struct {
|
||||
@@ -1133,6 +1143,27 @@ type BindMobileResp struct {
|
||||
RefreshAfter int64 `json:"refreshAfter"`
|
||||
}
|
||||
|
||||
type CheckFeatureWhitelistStatusReq struct {
|
||||
IdCard string `form:"id_card"` // 身份证号
|
||||
FeatureApiId string `form:"feature_api_id"` // Feature的API标识
|
||||
QueryId string `form:"query_id,optional"` // 查询记录ID(可选,用于检查报告数据是否已删除)
|
||||
}
|
||||
|
||||
type CheckFeatureWhitelistStatusResp struct {
|
||||
IsWhitelisted bool `json:"is_whitelisted"` // 是否在白名单中
|
||||
WhitelistPrice float64 `json:"whitelist_price"` // 屏蔽价格(单位:元),如果为0表示不支持下架
|
||||
FeatureId string `json:"feature_id"` // Feature的UUID
|
||||
DataDeleted bool `json:"data_deleted"` // 报告数据是否已删除(仅当提供了query_id时有效)
|
||||
}
|
||||
|
||||
type CheckOrderAgentReq struct {
|
||||
OrderId string `form:"order_id"` // 订单ID
|
||||
}
|
||||
|
||||
type CheckOrderAgentResp struct {
|
||||
IsAgentOrder bool `json:"is_agent_order"` // 是否是当前代理推广的订单
|
||||
}
|
||||
|
||||
type CommissionFreezeConfig struct {
|
||||
Ratio float64 `json:"ratio"` // 佣金冻结比例(例如:0.1表示10%)
|
||||
Threshold float64 `json:"threshold"` // 佣金冻结阈值(订单单价达到此金额才触发冻结,单位:元)
|
||||
@@ -1189,6 +1220,18 @@ type CreateRoleResp struct {
|
||||
Id string `json:"id"` // 角色ID
|
||||
}
|
||||
|
||||
type CreateWhitelistOrderReq struct {
|
||||
IdCard string `json:"id_card"` // 身份证号(查询对象标识)
|
||||
FeatureIds []string `json:"feature_ids"` // 要屏蔽的feature ID列表
|
||||
OrderId string `json:"order_id,optional"` // 关联的查询订单ID(可选)
|
||||
}
|
||||
|
||||
type CreateWhitelistOrderResp struct {
|
||||
OrderId string `json:"order_id"` // 订单ID
|
||||
OrderNo string `json:"order_no"` // 订单号
|
||||
TotalAmount float64 `json:"total_amount"` // 总金额
|
||||
}
|
||||
|
||||
type DeleteInviteCodeReq struct {
|
||||
Id string `json:"id"` // 邀请码ID
|
||||
}
|
||||
@@ -1306,6 +1349,18 @@ type GetInviteLinkResp struct {
|
||||
InviteLink string `json:"invite_link"` // 邀请链接
|
||||
}
|
||||
|
||||
type GetLastWithdrawalInfoReq struct {
|
||||
WithdrawalType int64 `form:"withdrawal_type"` // 提现方式:1=支付宝,2=银行卡
|
||||
}
|
||||
|
||||
type GetLastWithdrawalInfoResp struct {
|
||||
WithdrawalType int64 `json:"withdrawal_type"` // 提现方式
|
||||
PayeeAccount string `json:"payee_account"` // 收款账户(支付宝账号或银行卡号)
|
||||
PayeeName string `json:"payee_name"` // 收款人姓名
|
||||
BankCardNo string `json:"bank_card_no"` // 银行卡号
|
||||
BankName string `json:"bank_name"` // 开户行名称
|
||||
}
|
||||
|
||||
type GetLevelPrivilegeResp struct {
|
||||
Levels []LevelPrivilegeItem `json:"levels"`
|
||||
UpgradeToGoldFee float64 `json:"upgrade_to_gold_fee"`
|
||||
@@ -1404,16 +1459,18 @@ type GetRebateListResp struct {
|
||||
}
|
||||
|
||||
type GetRevenueInfoResp struct {
|
||||
Balance float64 `json:"balance"` // 可用余额
|
||||
FrozenBalance float64 `json:"frozen_balance"` // 冻结余额
|
||||
TotalEarnings float64 `json:"total_earnings"` // 累计收益(钱包总收益)
|
||||
WithdrawnAmount float64 `json:"withdrawn_amount"` // 累计提现
|
||||
CommissionTotal float64 `json:"commission_total"` // 佣金累计总收益(推广订单获得的佣金)
|
||||
CommissionToday float64 `json:"commission_today"` // 佣金今日收益
|
||||
CommissionMonth float64 `json:"commission_month"` // 佣金本月收益
|
||||
RebateTotal float64 `json:"rebate_total"` // 返佣累计总收益(包括推广返佣和升级返佣)
|
||||
RebateToday float64 `json:"rebate_today"` // 返佣今日收益
|
||||
RebateMonth float64 `json:"rebate_month"` // 返佣本月收益
|
||||
Balance float64 `json:"balance"` // 可用余额
|
||||
FrozenBalance float64 `json:"frozen_balance"` // 冻结余额
|
||||
TotalEarnings float64 `json:"total_earnings"` // 累计收益(钱包总收益)
|
||||
WithdrawnAmount float64 `json:"withdrawn_amount"` // 累计提现
|
||||
CommissionTotal float64 `json:"commission_total"` // 佣金累计总收益(推广订单获得的佣金)
|
||||
CommissionToday float64 `json:"commission_today"` // 佣金今日收益
|
||||
CommissionMonth float64 `json:"commission_month"` // 佣金本月收益
|
||||
RebateTotal float64 `json:"rebate_total"` // 返佣累计总收益(包括推广返佣和升级返佣)
|
||||
RebateToday float64 `json:"rebate_today"` // 返佣今日收益
|
||||
RebateMonth float64 `json:"rebate_month"` // 返佣本月收益
|
||||
AlipayMonthQuota float64 `json:"alipay_month_quota"` // 支付宝每月提现总额度
|
||||
AlipayMonthUsed float64 `json:"alipay_month_used"` // 本月已使用的支付宝提现额度
|
||||
}
|
||||
|
||||
type GetRoleDetailReq struct {
|
||||
@@ -1518,6 +1575,24 @@ type GetUpgradeRebateListResp struct {
|
||||
List []UpgradeRebateItem `json:"list"` // 列表
|
||||
}
|
||||
|
||||
type GetWhitelistFeaturesReq struct {
|
||||
}
|
||||
|
||||
type GetWhitelistFeaturesResp struct {
|
||||
List []WhitelistFeatureItem `json:"list"` // 可屏蔽的feature列表
|
||||
}
|
||||
|
||||
type GetWhitelistListReq struct {
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"page_size"` // 每页数量
|
||||
IdCard string `form:"id_card,optional"` // 身份证号(可选,用于筛选)
|
||||
}
|
||||
|
||||
type GetWhitelistListResp struct {
|
||||
Total int64 `json:"total"` // 总数
|
||||
List []WhitelistItem `json:"list"` // 列表
|
||||
}
|
||||
|
||||
type GetWithdrawalListReq struct {
|
||||
Page int64 `form:"page"` // 页码
|
||||
PageSize int64 `form:"page_size"` // 每页数量
|
||||
@@ -1650,6 +1725,17 @@ type NotificationListItem struct {
|
||||
UpdateTime string `json:"update_time"` // 更新时间
|
||||
}
|
||||
|
||||
type OfflineFeatureReq struct {
|
||||
FeatureApiId string `json:"feature_api_id"` // Feature的API标识
|
||||
QueryId string `json:"query_id"` // 查询记录ID(Query表的ID,必选)
|
||||
}
|
||||
|
||||
type OfflineFeatureResp struct {
|
||||
Success bool `json:"success"` // 是否已完成下架
|
||||
NeedPay bool `json:"need_pay"` // 是否需要发起支付
|
||||
Amount float64 `json:"amount"` // 需要支付的金额(单位:元),0表示无需支付
|
||||
}
|
||||
|
||||
type OrderItem struct {
|
||||
OrderNo string `json:"order_no"` // 订单号
|
||||
ProductId string `json:"product_id"` // 产品ID
|
||||
@@ -1695,7 +1781,6 @@ type PaymentReq struct {
|
||||
Id string `json:"id"`
|
||||
PayMethod string `json:"pay_method"` // 支付方式: wechat, alipay, appleiap, test(仅开发环境), test_empty(仅开发环境-空报告模式)
|
||||
PayType string `json:"pay_type" validate:"required,oneof=query agent_vip agent_upgrade"`
|
||||
Code string `json:"code,optional"` // 微信小程序/H5授权码,用于自动绑定微信账号(当用户未绑定微信时)
|
||||
}
|
||||
|
||||
type PaymentResp struct {
|
||||
@@ -1767,11 +1852,13 @@ type ProductResponse struct {
|
||||
}
|
||||
|
||||
type PromotionQueryItem struct {
|
||||
Id string `json:"id"` // 查询ID
|
||||
OrderId string `json:"order_id"` // 订单ID
|
||||
ProductName string `json:"product_name"` // 产品名称
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
QueryState string `json:"query_state"` // 查询状态
|
||||
Id string `json:"id"` // 查询ID
|
||||
OrderId string `json:"order_id"` // 订单ID
|
||||
ProductName string `json:"product_name"` // 产品名称
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
QueryState string `json:"query_state"` // 查询状态
|
||||
Params map[string]interface{} `json:"params"` // 查询参数(已脱敏)
|
||||
Price float64 `json:"price"` // 查询价格
|
||||
}
|
||||
|
||||
type Query struct {
|
||||
@@ -1931,6 +2018,7 @@ type RebateItem struct {
|
||||
OrderNo string `json:"order_no"` // 订单号
|
||||
RebateType int64 `json:"rebate_type"` // 返佣类型:1=直接上级,2=钻石上级,3=黄金上级
|
||||
Amount float64 `json:"amount"` // 返佣金额
|
||||
Status int64 `json:"status"` // 状态:1=已发放,2=已冻结,3=已取消(已退款)
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
}
|
||||
|
||||
@@ -1990,14 +2078,14 @@ type TeamMemberItem struct {
|
||||
LevelName string `json:"level_name"` // 等级名称
|
||||
Mobile string `json:"mobile"` // 手机号
|
||||
CreateTime string `json:"create_time"` // 加入团队时间
|
||||
TotalRebateAmount float64 `json:"total_rebate_amount"` // 返佣给我的总金额
|
||||
TodayRebateAmount float64 `json:"today_rebate_amount"` // 返佣给我的今日金额
|
||||
TodayInvites int64 `json:"today_invites"` // 邀请加入团队的今日人数
|
||||
MonthInvites int64 `json:"month_invites"` // 邀请加入团队的本月人数
|
||||
TotalInvites int64 `json:"total_invites"` // 邀请加入团队的总人数
|
||||
TodayQueries int64 `json:"today_queries"` // 当日查询量
|
||||
MonthQueries int64 `json:"month_queries"` // 本月查询量
|
||||
TotalQueries int64 `json:"total_queries"` // 总查询量
|
||||
TotalRebateAmount float64 `json:"total_rebate_amount"` // 返佣给我的总金额
|
||||
TodayRebateAmount float64 `json:"today_rebate_amount"` // 返佣给我的今日金额
|
||||
TotalInvites int64 `json:"total_invites"` // 邀请加入团队的总人数
|
||||
TodayInvites int64 `json:"today_invites"` // 邀请加入团队的今日人数
|
||||
MonthInvites int64 `json:"month_invites"` // 邀请加入团队的本月人数
|
||||
IsDirect bool `json:"is_direct"` // 是否直接下级
|
||||
}
|
||||
|
||||
@@ -2137,17 +2225,39 @@ type WXMiniAuthResp struct {
|
||||
RefreshAfter int64 `json:"refreshAfter"`
|
||||
}
|
||||
|
||||
type WhitelistFeatureItem struct {
|
||||
FeatureId string `json:"feature_id"` // Feature的UUID
|
||||
FeatureApiId string `json:"feature_api_id"` // Feature的API标识
|
||||
FeatureName string `json:"feature_name"` // Feature的名称
|
||||
WhitelistPrice float64 `json:"whitelist_price"` // 屏蔽价格(单位:元)
|
||||
}
|
||||
|
||||
type WhitelistItem struct {
|
||||
Id string `json:"id"` // 白名单记录ID
|
||||
IdCard string `json:"id_card"` // 身份证号
|
||||
FeatureId string `json:"feature_id"` // Feature的UUID
|
||||
FeatureApiId string `json:"feature_api_id"` // Feature的API标识
|
||||
FeatureName string `json:"feature_name"` // Feature的名称
|
||||
Amount float64 `json:"amount"` // 费用
|
||||
Status int64 `json:"status"` // 状态:1=生效,2=已失效
|
||||
StatusText string `json:"status_text"` // 状态文本
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
}
|
||||
|
||||
type WithdrawalItem struct {
|
||||
Id string `json:"id"` // 记录ID
|
||||
WithdrawalNo string `json:"withdrawal_no"` // 提现单号
|
||||
Amount float64 `json:"amount"` // 提现金额
|
||||
TaxAmount float64 `json:"tax_amount"` // 税费金额
|
||||
ActualAmount float64 `json:"actual_amount"` // 实际到账金额
|
||||
Status int64 `json:"status"` // 状态:1=待审核,2=审核通过,3=审核拒绝,4=提现中,5=提现成功,6=提现失败
|
||||
PayeeAccount string `json:"payee_account"` // 收款账户
|
||||
PayeeName string `json:"payee_name"` // 收款人姓名
|
||||
Remark string `json:"remark"` // 备注
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
Id string `json:"id"` // 记录ID
|
||||
WithdrawalNo string `json:"withdrawal_no"` // 提现单号
|
||||
Amount float64 `json:"amount"` // 提现金额
|
||||
TaxAmount float64 `json:"tax_amount"` // 税费金额
|
||||
ActualAmount float64 `json:"actual_amount"` // 实际到账金额
|
||||
Status int64 `json:"status"` // 状态:1=待审核,2=审核通过,3=审核拒绝,4=提现中,5=提现成功,6=提现失败
|
||||
WithdrawalType int64 `json:"withdrawal_type"` // 提现方式:1=支付宝,2=银行卡
|
||||
PayeeAccount string `json:"payee_account"` // 收款账户(支付宝账号或银行卡号)
|
||||
PayeeName string `json:"payee_name"` // 收款人姓名
|
||||
BankCardNo string `json:"bank_card_no"` // 银行卡号(银行卡提现时填写)
|
||||
BankName string `json:"bank_name"` // 开户行名称(银行卡提现时填写)
|
||||
Remark string `json:"remark"` // 备注
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
}
|
||||
|
||||
type GetAppConfigResp struct {
|
||||
|
||||
Reference in New Issue
Block a user