新版本,代理功能上线

This commit is contained in:
2025-03-07 03:48:59 +08:00
parent 8ead7a7a67
commit b2d9d828e3
130 changed files with 11004 additions and 2209 deletions

View File

@@ -40,12 +40,15 @@ type Encrypt struct {
}
type AlipayConfig struct {
AppID string
PrivateKey string
AlipayPublicKey string
IsProduction bool
NotifyUrl string
ReturnURL string
AppID string
PrivateKey string
AlipayPublicKey string
AppCertPath string // 应用公钥证书路径
AlipayCertPath string // 支付宝公钥证书路径
AlipayRootCertPath string // 根证书路径
IsProduction bool
NotifyUrl string
ReturnURL string
}
type WxpayConfig struct {
AppID string

View File

@@ -0,0 +1,29 @@
package agent
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"tydata-server/app/user/cmd/api/internal/logic/agent"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
)
func ActivateAgentMembershipHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.AgentActivateMembershipReq
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.NewActivateAgentMembershipLogic(r.Context(), svcCtx)
resp, err := l.ActivateAgentMembership(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -1,19 +1,19 @@
package query
package agent
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"tydata-server/app/user/cmd/api/internal/logic/query"
"tydata-server/app/user/cmd/api/internal/logic/agent"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
)
func RentalInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
func ApplyForAgentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.QueryReq
var req types.AgentApplyReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
@@ -22,8 +22,8 @@ func RentalInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
result.ParamValidateErrorResult(r, w, err)
return
}
l := query.NewRentalInfoLogic(r.Context(), svcCtx)
resp, err := l.RentalInfo(&req)
l := agent.NewApplyForAgentLogic(r.Context(), svcCtx)
resp, err := l.ApplyForAgent(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -1,19 +1,19 @@
package query
package agent
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"tydata-server/app/user/cmd/api/internal/logic/query"
"tydata-server/app/user/cmd/api/internal/logic/agent"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
)
func RiskAssessmentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
func GeneratingLinkHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.QueryReq
var req types.AgentGeneratingLinkReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
@@ -22,8 +22,8 @@ func RiskAssessmentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
result.ParamValidateErrorResult(r, w, err)
return
}
l := query.NewRiskAssessmentLogic(r.Context(), svcCtx)
resp, err := l.RiskAssessment(&req)
l := agent.NewGeneratingLinkLogic(r.Context(), svcCtx)
resp, err := l.GeneratingLink(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -0,0 +1,17 @@
package agent
import (
"net/http"
"tydata-server/app/user/cmd/api/internal/logic/agent"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/common/result"
)
func GetAgentAuditStatusHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := agent.NewGetAgentAuditStatusLogic(r.Context(), svcCtx)
resp, err := l.GetAgentAuditStatus()
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -0,0 +1,17 @@
package agent
import (
"net/http"
"tydata-server/app/user/cmd/api/internal/logic/agent"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/common/result"
)
func GetAgentInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := agent.NewGetAgentInfoLogic(r.Context(), svcCtx)
resp, err := l.GetAgentInfo()
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -0,0 +1,29 @@
package agent
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"tydata-server/app/user/cmd/api/internal/logic/agent"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
)
func GetAgentMembershipProductConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.AgentMembershipProductConfigReq
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.NewGetAgentMembershipProductConfigLogic(r.Context(), svcCtx)
resp, err := l.GetAgentMembershipProductConfig(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -0,0 +1,17 @@
package agent
import (
"net/http"
"tydata-server/app/user/cmd/api/internal/logic/agent"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/common/result"
)
func GetAgentProductConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := agent.NewGetAgentProductConfigLogic(r.Context(), svcCtx)
resp, err := l.GetAgentProductConfig()
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -0,0 +1,29 @@
package agent
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"tydata-server/app/user/cmd/api/internal/logic/agent"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
)
func GetAgentRevenueInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GetAgentRevenueInfoReq
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.NewGetAgentRevenueInfoLogic(r.Context(), svcCtx)
resp, err := l.GetAgentRevenueInfo(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -1,19 +1,19 @@
package query
package agent
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"tydata-server/app/user/cmd/api/internal/logic/query"
"tydata-server/app/user/cmd/api/internal/logic/agent"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
)
func CompanyInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
func GetLinkDataHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.QueryReq
var req types.GetLinkDataReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
@@ -22,8 +22,8 @@ func CompanyInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
result.ParamValidateErrorResult(r, w, err)
return
}
l := query.NewCompanyInfoLogic(r.Context(), svcCtx)
resp, err := l.CompanyInfo(&req)
l := agent.NewGetLinkDataLogic(r.Context(), svcCtx)
resp, err := l.GetLinkData(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -0,0 +1,29 @@
package agent
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"tydata-server/app/user/cmd/api/internal/logic/agent"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
)
func SaveAgentMembershipUserConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.SaveAgentMembershipUserConfigReq
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.NewSaveAgentMembershipUserConfigLogic(r.Context(), svcCtx)
err := l.SaveAgentMembershipUserConfig(&req)
result.HttpResult(r, w, nil, err)
}
}

View File

@@ -11,9 +11,9 @@ import (
"tydata-server/pkg/lzkit/validator"
)
func BackgroundCheckHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
func QueryServiceAgentHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.QueryReq
var req types.QueryServiceReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
@@ -22,8 +22,8 @@ func BackgroundCheckHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
result.ParamValidateErrorResult(r, w, err)
return
}
l := query.NewBackgroundCheckLogic(r.Context(), svcCtx)
resp, err := l.BackgroundCheck(&req)
l := query.NewQueryServiceLogic(r.Context(), svcCtx)
resp, err := l.QueryService(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -4,6 +4,7 @@ package handler
import (
"net/http"
agent "tydata-server/app/user/cmd/api/internal/handler/agent"
auth "tydata-server/app/user/cmd/api/internal/handler/auth"
notification "tydata-server/app/user/cmd/api/internal/handler/notification"
pay "tydata-server/app/user/cmd/api/internal/handler/pay"
@@ -16,6 +17,89 @@ import (
)
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodGet,
Path: "/audit/status",
Handler: agent.GetAgentAuditStatusHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/commission",
Handler: agent.GetAgentCommissionHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/generating_link",
Handler: agent.GeneratingLinkHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/info",
Handler: agent.GetAgentInfoHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/membership/save_user_config",
Handler: agent.SaveAgentMembershipUserConfigHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/membership/user_config",
Handler: agent.GetAgentMembershipProductConfigHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/product_config",
Handler: agent.GetAgentProductConfigHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/revenue",
Handler: agent.GetAgentRevenueInfoHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/rewards",
Handler: agent.GetAgentRewardsHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/withdrawal",
Handler: agent.GetAgentWithdrawalHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/withdrawal",
Handler: agent.AgentWithdrawalHandler(serverCtx),
},
},
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/api/v1/agent"),
)
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodPost,
Path: "/apply",
Handler: agent.ApplyForAgentHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/link",
Handler: agent.GetLinkDataHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/membership/activate",
Handler: agent.ActivateAgentMembershipHandler(serverCtx),
},
},
rest.WithPrefix("/api/v1/agent"),
)
server.AddRoutes(
[]rest.Route{
{
@@ -101,47 +185,17 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
// query general background check
// query service agent
Method: http.MethodPost,
Path: "/query/backgroundCheck",
Handler: query.BackgroundCheckHandler(serverCtx),
},
{
// query company info
Method: http.MethodPost,
Path: "/query/companyInfo",
Handler: query.CompanyInfoHandler(serverCtx),
},
{
// query home service
Method: http.MethodPost,
Path: "/query/homeService",
Handler: query.HomeServiceHandler(serverCtx),
},
{
// query marriage
Method: http.MethodPost,
Path: "/query/marriage",
Handler: query.MarriageHandler(serverCtx),
},
{
// query pre-loan background check
Method: http.MethodPost,
Path: "/query/preLoanBackgroundCheck",
Handler: query.PreLoanBackgroundCheckHandler(serverCtx),
},
{
// query rental info
Method: http.MethodPost,
Path: "/query/rentalInfo",
Handler: query.RentalInfoHandler(serverCtx),
},
{
// query risk assessment
Method: http.MethodPost,
Path: "/query/riskAssessment",
Handler: query.RiskAssessmentHandler(serverCtx),
Path: "/query/service_agent/:product",
Handler: query.QueryServiceAgentHandler(serverCtx),
},
},
rest.WithPrefix("/api/v1"),
)
server.AddRoutes(
[]rest.Route{
{
// query service
Method: http.MethodPost,
@@ -204,6 +258,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
// agent mobile code login
Method: http.MethodPost,
Path: "/user/agent_mobile_code_login",
Handler: user.AgentMobileCodeLoginHandler(serverCtx),
},
{
// mobile code login
Method: http.MethodPost,

View File

@@ -1,19 +1,19 @@
package query
package user
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"tydata-server/app/user/cmd/api/internal/logic/query"
"tydata-server/app/user/cmd/api/internal/logic/user"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
)
func PreLoanBackgroundCheckHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
func AgentMobileCodeLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.QueryReq
var req types.MobileCodeLoginReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
@@ -22,8 +22,8 @@ func PreLoanBackgroundCheckHandler(svcCtx *svc.ServiceContext) http.HandlerFunc
result.ParamValidateErrorResult(r, w, err)
return
}
l := query.NewPreLoanBackgroundCheckLogic(r.Context(), svcCtx)
resp, err := l.PreLoanBackgroundCheck(&req)
l := user.NewAgentMobileCodeLoginLogic(r.Context(), svcCtx)
resp, err := l.AgentMobileCodeLogin(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -0,0 +1,121 @@
package agent
import (
"context"
"database/sql"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"time"
"tydata-server/app/user/model"
"tydata-server/common/xerr"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type ActivateAgentMembershipLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewActivateAgentMembershipLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ActivateAgentMembershipLogic {
return &ActivateAgentMembershipLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *ActivateAgentMembershipLogic) ActivateAgentMembership(req *types.AgentActivateMembershipReq) (resp *types.AgentActivateMembershipResp, err error) {
//userID, err := ctxdata.GetUidFromCtx(l.ctx)
//if err != nil {
// return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户ID失败: %v", err)
//}
userModel, err := l.svcCtx.UserModel.FindOneByMobile(l.ctx, req.Mobile)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
}
// 查询用户代理信息
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userModel.Id)
if err != nil && err != sql.ErrNoRows {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
}
// 定义等级顺序映射
levelOrder := map[string]int{
"": 1,
model.AgentLeveNameNormal: 1,
model.AgentLeveNameVIP: 2,
model.AgentLeveNameSVIP: 3,
}
// 验证请求等级合法性
if _, valid := levelOrder[req.Type]; !valid {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "无效的代理等级: %s", req.Type)
}
// 如果存在代理记录,进行等级验证
if agentModel != nil {
currentLevel, exists := levelOrder[agentModel.LevelName]
if !exists {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR),
"非法的当前代理等级: %s", agentModel.LevelName)
}
requestedLevel := levelOrder[req.Type]
if requestedLevel < currentLevel {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR),
"禁止降级操作(当前等级:%s请求等级%s", agentModel.LevelName, req.Type)
}
}
err = l.svcCtx.AgentModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
agentModel.LevelName = req.Type
agentModel.MembershipExpiryTime = RenewMembership(agentModel.MembershipExpiryTime)
transErr := l.svcCtx.AgentModel.UpdateWithVersion(transCtx, session, agentModel)
if transErr != nil {
return transErr
}
agentMembershipRechargeOrder := model.AgentMembershipRechargeOrder{
AgentId: agentModel.Id,
UserId: userModel.Id,
LevelName: req.Type,
Amount: req.Amount,
PaymentMethod: req.PaymentMethod,
TransactionId: req.TransactionId,
}
_, transErr = l.svcCtx.AgentMembershipRechargeOrderModel.Insert(transCtx, session, &agentMembershipRechargeOrder)
if transErr != nil {
return transErr
}
return nil
})
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "升级代理等级失败: %s", req.Type)
}
return &types.AgentActivateMembershipResp{
MembershipType: req.Type,
ExpireTime: agentModel.MembershipExpiryTime.Time.Format("2006-01-02 15:04:05"),
}, nil
}
func RenewMembership(expiry sql.NullTime) sql.NullTime {
// 确定基准时间
var baseTime time.Time
if expiry.Valid {
baseTime = expiry.Time
} else {
baseTime = time.Now()
}
// 增加一年(自动处理闰年)
newTime := baseTime.AddDate(1, 0, 0)
// 返回始终有效的 NullTime
return sql.NullTime{
Time: newTime,
Valid: true,
}
}

View File

@@ -0,0 +1,305 @@
package agent
import (
"context"
"fmt"
"github.com/cenkalti/backoff/v4"
"github.com/pkg/errors"
"github.com/smartwalle/alipay/v3"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"time"
"tydata-server/app/user/model"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/lzUtils"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
// 状态常量
const (
StatusProcessing = 1 // 处理中
StatusSuccess = 2 // 成功
StatusFailed = 3 // 失败
)
// 前端响应状态
const (
WithdrawStatusProcessing = 1
WithdrawStatusSuccess = 2
WithdrawStatusFailed = 3
)
type AgentWithdrawalLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAgentWithdrawalLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AgentWithdrawalLogic {
return &AgentWithdrawalLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AgentWithdrawalLogic) AgentWithdrawal(req *types.WithdrawalReq) (*types.WithdrawalResp, error) {
var (
outBizNo string
withdrawRes = &types.WithdrawalResp{}
)
// 使用事务处理核心操作
err := l.svcCtx.AgentModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户ID失败: %v", err)
}
// 查询代理信息
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
}
// 查询钱包
agentWallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, agentModel.Id)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理钱包失败: %v", err)
}
// 校验可提现金额
withdrawableAmount := agentWallet.Balance - agentWallet.FrozenBalance
if req.Amount > withdrawableAmount {
return errors.Wrapf(xerr.NewErrMsg("您可提现的余额不足"), "获取用户ID失败")
}
// 生成交易号
outBizNo = l.svcCtx.AlipayService.GenerateOutTradeNo()
// 创建提现记录(初始状态为处理中)
if err = l.createWithdrawalRecord(session, agentModel.Id, req, outBizNo); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建提现记录失败: %v", err)
}
// 冻结资金(事务内操作)
if err = l.freezeFunds(session, agentWallet, req.Amount); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "资金冻结失败: %v", err)
}
return nil
})
if err != nil {
return nil, err
}
// 同步调用支付宝转账
transferResp, err := l.svcCtx.AlipayService.AliTransfer(l.ctx, req.PayeeAccount, req.PayeeName, req.Amount, "代理提现", outBizNo)
if err != nil {
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)
}
return withdrawRes, nil
}
// 错误类型映射
func (l *AgentWithdrawalLogic) 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 "系统错误,请联系客服"
}
// 创建提现记录(事务内操作)
func (l *AgentWithdrawalLogic) createWithdrawalRecord(session sqlx.Session, agentID int64, req *types.WithdrawalReq, outBizNo string) error {
record := &model.AgentWithdrawal{
AgentId: agentID,
WithdrawNo: outBizNo,
PayeeAccount: req.PayeeAccount,
Amount: req.Amount,
Status: StatusProcessing,
}
_, err := l.svcCtx.AgentWithdrawalModel.Insert(l.ctx, session, record)
return err
}
// 冻结资金(事务内操作)
func (l *AgentWithdrawalLogic) freezeFunds(session sqlx.Session, wallet *model.AgentWallet, amount float64) error {
wallet.Balance -= amount
wallet.FrozenBalance += amount
err := l.svcCtx.AgentWalletModel.UpdateWithVersion(l.ctx, session, wallet)
if err != nil {
return err
}
return nil
}
// 处理异步轮询
func (l *AgentWithdrawalLogic) startAsyncPolling(outBizNo string) {
go func() {
detachedCtx := context.WithoutCancel(l.ctx)
retryConfig := &backoff.ExponentialBackOff{
InitialInterval: 10 * time.Second,
RandomizationFactor: 0.5, // 增加随机因子防止惊群
Multiplier: 2,
MaxInterval: 30 * time.Second,
MaxElapsedTime: 5 * time.Minute, // 缩短总超时
Clock: backoff.SystemClock,
}
retryConfig.Reset()
operation := func() error {
statusRsp, err := l.svcCtx.AlipayService.QueryTransferStatus(detachedCtx, outBizNo)
if err != nil {
return err // 触发重试
}
switch statusRsp.Status {
case "SUCCESS":
l.handleTransferSuccess(outBizNo, statusRsp)
return nil
case "FAIL":
l.handleTransferFailure(outBizNo, statusRsp)
return nil
default:
return fmt.Errorf("转账处理中")
}
}
err := backoff.RetryNotify(operation,
backoff.WithContext(retryConfig, detachedCtx),
func(err error, duration time.Duration) {
l.Logger.Infof("轮询延迟 outBizNo:%s 等待:%v", outBizNo, duration)
})
if err != nil {
l.handleTransferTimeout(outBizNo)
}
}()
}
// 统一状态更新
func (l *AgentWithdrawalLogic) updateWithdrawalStatus(outBizNo string, status int64, errorMsg string) {
detachedCtx := context.WithoutCancel(l.ctx)
err := l.svcCtx.AgentModel.Trans(detachedCtx, func(ctx context.Context, session sqlx.Session) error {
// 获取提现记录
record, err := l.svcCtx.AgentWithdrawalModel.FindOneByWithdrawNo(l.ctx, outBizNo)
if err != nil {
return err
}
// 更新状态
record.Status = status
record.Remark = lzUtils.StringToNullString(errorMsg)
if _, err = l.svcCtx.AgentWithdrawalModel.Update(ctx, session, record); err != nil {
return err
}
// 失败时解冻资金
if status == StatusFailed {
wallet, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(ctx, record.AgentId)
if err != nil {
return err
}
wallet.Balance += record.Amount
wallet.FrozenBalance -= record.Amount
if err := l.svcCtx.AgentWalletModel.UpdateWithVersion(ctx, session, wallet); err != nil {
return err
}
}
return nil
})
if err != nil {
l.Logger.Errorf("状态更新失败 outBizNo:%s error:%v", outBizNo, err)
}
}
// 成功处理
func (l *AgentWithdrawalLogic) handleTransferSuccess(outBizNo string, rsp interface{}) {
l.updateWithdrawalStatus(outBizNo, StatusSuccess, "")
l.Logger.Infof("提现成功 outBizNo:%s", outBizNo)
}
// 失败处理
func (l *AgentWithdrawalLogic) handleTransferFailure(outBizNo string, rsp interface{}) {
var errorMsg string
if resp, ok := rsp.(*alipay.FundTransUniTransferRsp); ok {
errorMsg = l.mapAlipayError(resp.SubCode)
}
l.updateWithdrawalStatus(outBizNo, StatusFailed, errorMsg)
l.Logger.Errorf("提现失败 outBizNo:%s reason:%s", outBizNo, errorMsg)
}
// 超时处理
func (l *AgentWithdrawalLogic) handleTransferTimeout(outBizNo string) {
l.updateWithdrawalStatus(outBizNo, StatusFailed, "系统处理超时")
l.Logger.Errorf("轮询超时 outBizNo:%s", outBizNo)
}
// 错误处理
func (l *AgentWithdrawalLogic) handleTransferError(outBizNo string, err error, contextMsg string) {
l.updateWithdrawalStatus(outBizNo, StatusFailed, "系统处理异常")
l.Logger.Errorf("%s outBizNo:%s error:%v", contextMsg, outBizNo, err)
}

View File

@@ -0,0 +1,169 @@
package agent
import (
"context"
"fmt"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"time"
"tydata-server/app/user/model"
jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/lzUtils"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type ApplyForAgentLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewApplyForAgentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ApplyForAgentLogic {
return &ApplyForAgentLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *types.AgentApplyResp, err error) {
// 校验验证码
redisKey := fmt.Sprintf("%s:%s", "agentApply", req.Mobile)
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
if err != nil {
if errors.Is(err, redis.Nil) {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "代理申请, 验证码过期: %s", req.Mobile)
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 读取验证码redis缓存失败, mobile: %s, err: %+v", req.Mobile, err)
}
if cacheCode != req.Code {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "代理申请, 验证码不正确: %s", req.Mobile)
}
if req.Ancestor == req.Mobile {
return nil, errors.Wrapf(xerr.NewErrMsg("不能成为自己的代理"), "")
}
var userID int64
transErr := l.svcCtx.AgentAuditModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
// 两种情况1. 已注册账号然后申请代理 2. 未注册账号申请代理
user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, req.Mobile)
if findUserErr != nil && !errors.Is(findUserErr, model.ErrNotFound) {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取数据库获取用户失败, mobile: %s, err: %+v", req.Mobile, err)
}
if user == nil {
user = &model.User{Mobile: req.Mobile}
if len(user.Nickname) == 0 {
user.Nickname = req.Mobile
}
insertResult, userInsertErr := l.svcCtx.UserModel.Insert(transCtx, session, user)
if userInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 数据库插入新用户失败, mobile%s, err: %+v", req.Mobile, err)
}
lastId, lastInsertIdErr := insertResult.LastInsertId()
if lastInsertIdErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 获取新用户ID失败, err:%+v, user:%+v", lastInsertIdErr, user)
}
user.Id = lastId
userID = lastId
userAuth := new(model.UserAuth)
userAuth.UserId = lastId
userAuth.AuthKey = req.Mobile
userAuth.AuthType = model.UserAuthTypeAgentDirect
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(transCtx, session, userAuth); userAuthInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 数据库插入用户认证失败, err:%+v", userAuthInsertErr)
}
}
userID = user.Id
agentAuditModel, findAgentAuditErr := l.svcCtx.AgentAuditModel.FindOneByUserId(transCtx, user.Id)
if findAgentAuditErr != nil && !errors.Is(findAgentAuditErr, model.ErrNotFound) {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 查找审核列表失败%+v", findAgentAuditErr)
}
if agentAuditModel != nil {
if agentAuditModel.Status == 0 {
return errors.Wrapf(xerr.NewErrMsg("您的代理申请中"), "代理申请, 代理申请中")
} else {
return errors.Wrapf(xerr.NewErrMsg("您已申请过代理"), "代理申请, 代理已申请过")
}
}
var agentAudit model.AgentAudit
agentAudit.UserId = user.Id
agentAudit.Mobile = req.Mobile
agentAudit.Region = req.Region
agentAudit.WechatId = lzUtils.StringToNullString(req.WechatID)
agentAudit.Status = 1
_, insetAgentAuditErr := l.svcCtx.AgentAuditModel.Insert(transCtx, session, &agentAudit)
if insetAgentAuditErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 保存代理审核信息失败: %v", insetAgentAuditErr)
}
//agentAuditID, _ := agentAuditInsert.LastInsertId()
//agentAuditRow, findAgentAuditModelErr := l.svcCtx.AgentAuditModel.FindOne(l.ctx, agentAuditID)
//if findAgentAuditModelErr != nil {
// return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 查找代理审核信息失败: %v", insetAgentAuditErr)
//}
//agentAuditRow.Status = 1
//updateAgentAuditErr := l.svcCtx.AgentAuditModel.UpdateWithVersion(transCtx, session, agentAuditRow)
//if updateAgentAuditErr != nil {
// return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 通过代理审核失败: %+v", updateAgentAuditErr)
//}
// 新增代理
var agentModel model.Agent
agentModel.Mobile = agentAudit.Mobile
agentModel.Region = agentAudit.Region
agentModel.UserId = agentAudit.UserId
agentModel.WechatId = lzUtils.StringToNullString(req.WechatID)
agentModelInsert, insertAgentModelErr := l.svcCtx.AgentModel.Insert(transCtx, session, &agentModel)
if insertAgentModelErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 新增代理失败: %+v", insertAgentModelErr)
}
agentID, _ := agentModelInsert.LastInsertId()
// 关联上级
if req.Ancestor != "" {
ancestorAgentModel, findAgentModelErr := l.svcCtx.AgentModel.FindOneByMobile(transCtx, req.Ancestor)
if findAgentModelErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 查找上级代理失败: %+v", findAgentModelErr)
}
agentClosureModel := model.AgentClosure{
AncestorId: ancestorAgentModel.Id,
DescendantId: agentID,
Depth: 1,
}
_, insertAgentClosureModelErr := l.svcCtx.AgentClosureModel.Insert(transCtx, session, &agentClosureModel)
if insertAgentClosureModelErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 添加代理上下级关联失败: %+v", insertAgentClosureModelErr)
}
}
// 新增代理钱包
var agentWallet model.AgentWallet
agentWallet.AgentId = agentID
_, insertAgentWalletModelErr := l.svcCtx.AgentWalletModel.Insert(transCtx, session, &agentWallet)
if insertAgentWalletModelErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 新增代理钱包失败: %+v", insertAgentWalletModelErr)
}
return nil
})
if transErr != nil {
return nil, transErr
}
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 生成token失败 : %d", userID)
}
// 获取当前时间戳
now := time.Now().Unix()
return &types.AgentApplyResp{
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}

View File

@@ -0,0 +1,110 @@
package agent
import (
"context"
"encoding/hex"
"encoding/json"
"github.com/Masterminds/squirrel"
"github.com/pkg/errors"
"strconv"
"tydata-server/app/user/model"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GeneratingLinkLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGeneratingLinkLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GeneratingLinkLogic {
return &GeneratingLinkLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GeneratingLinkLogic) GeneratingLink(req *types.AgentGeneratingLinkReq) (resp *types.AgentGeneratingLinkResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成代理链接, %v", err)
}
productModel, err := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, req.Product)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成代理链接, %v", err)
}
agentProductConfig, err := l.svcCtx.AgentProductConfigModel.FindOneByProductId(l.ctx, productModel.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成代理链接, %v", err)
}
price, err := strconv.ParseFloat(req.Price, 64)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成代理链接, %v", err)
}
if price < agentProductConfig.PriceRangeMin || price > agentProductConfig.PriceRangeMax {
return nil, errors.Wrapf(xerr.NewErrMsg("请设定范围区间内的价格"), "")
}
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
return nil, err
}
build := l.svcCtx.AgentLinkModel.SelectBuilder().Where(squirrel.And{
squirrel.Eq{"user_id": userID},
squirrel.Eq{"product_id": productModel.Id}, // 添加 product_id 的匹配条件
squirrel.Eq{"price": price}, // 添加 price 的匹配条件
squirrel.Eq{"agent_id": agentModel.Id}, // 添加 agent_id 的匹配条件
})
agentLinkModel, err := l.svcCtx.AgentLinkModel.FindAll(l.ctx, build, "")
if err != nil && !errors.Is(err, model.ErrNotFound) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成代理链接, %v", err)
}
if len(agentLinkModel) > 0 {
return &types.AgentGeneratingLinkResp{
LinkIdentifier: agentLinkModel[0].LinkIdentifier,
}, nil
}
var agentIdentifier types.AgentIdentifier
agentIdentifier.AgentID = agentModel.Id
agentIdentifier.Product = req.Product
agentIdentifier.Price = req.Price
agentIdentifierByte, err := json.Marshal(agentIdentifier)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单,序列化标识失败, %v", err)
}
key, decodeErr := hex.DecodeString("8e3e7a2f60edb49221e953b9c029ed10")
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取AES密钥失败: %+v", decodeErr)
}
// Encrypt the params
encrypted, err := crypto.AesEncryptURL(agentIdentifierByte, key)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成代理链接, %v", err)
}
var agentLink model.AgentLink
agentLink.AgentId = agentModel.Id
agentLink.UserId = userID
agentLink.LinkIdentifier = encrypted
agentLink.ProductId = productModel.Id
agentLink.Price = price
_, err = l.svcCtx.AgentLinkModel.Insert(l.ctx, nil, &agentLink)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成代理链接, %v", err)
}
return &types.AgentGeneratingLinkResp{
LinkIdentifier: encrypted,
}, nil
}

View File

@@ -0,0 +1,43 @@
package agent
import (
"context"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetAgentAuditStatusLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAgentAuditStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentAuditStatusLogic {
return &GetAgentAuditStatusLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetAgentAuditStatusLogic) GetAgentAuditStatus() (resp *types.AgentAuditStatusResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理审核信息, %v", err)
}
agentAuditModel, err := l.svcCtx.AgentAuditModel.FindOneByUserId(l.ctx, userID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理审核信息, %v", err)
}
var agentAuditStautsResp types.AgentAuditStatusResp
copier.Copy(&agentAuditStautsResp, agentAuditModel)
return &agentAuditStautsResp, nil
}

View File

@@ -0,0 +1,70 @@
package agent
import (
"context"
"github.com/Masterminds/squirrel"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetAgentCommissionLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAgentCommissionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentCommissionLogic {
return &GetAgentCommissionLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetAgentCommissionLogic) GetAgentCommission(req *types.GetCommissionReq) (resp *types.GetCommissionResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理佣金列表, %v", err)
}
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理佣金列表, %v", err)
}
builder := l.svcCtx.AgentCommissionModel.SelectBuilder().Where(squirrel.Eq{
"agent_id": agentModel.Id,
})
agentCommissionModelList, total, err := l.svcCtx.AgentCommissionModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理佣金列表, 查找列表错误, %v", err)
}
var list = make([]types.Commission, 0)
if len(agentCommissionModelList) > 0 {
for _, agentCommissionModel := range agentCommissionModelList {
var commission types.Commission
copyErr := copier.Copy(&commission, agentCommissionModel)
if copyErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理佣金列表, %v", err)
}
product, findProductErr := l.svcCtx.ProductModel.FindOne(l.ctx, agentCommissionModel.ProductId)
if findProductErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理佣金列表, %v", err)
}
commission.CreateTime = agentCommissionModel.CreateTime.Format("2006-01-02 15:04:05")
commission.ProductName = product.ProductName
list = append(list, commission)
}
}
return &types.GetCommissionResp{
Total: total,
List: list,
}, nil
}

View File

@@ -0,0 +1,66 @@
package agent
import (
"context"
"database/sql"
"github.com/pkg/errors"
"tydata-server/app/user/model"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/lzUtils"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetAgentInfoLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAgentInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentInfoLogic {
return &GetAgentInfoLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetAgentInfoLogic) GetAgentInfo() (resp *types.AgentInfoResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理信息, %v", err)
}
agent, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
agentAuditModel, findAgentAuditErr := l.svcCtx.AgentAuditModel.FindOneByUserId(l.ctx, userID)
if findAgentAuditErr != nil && !errors.Is(findAgentAuditErr, model.ErrNotFound) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理信息, %v", err)
}
if errors.Is(findAgentAuditErr, model.ErrNotFound) {
return &types.AgentInfoResp{
IsAgent: false,
Status: 3,
}, nil
}
return &types.AgentInfoResp{
IsAgent: false,
Status: agentAuditModel.Status,
}, nil
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理信息, %v", err)
}
return &types.AgentInfoResp{
AgentID: agent.Id,
Level: agent.LevelName,
IsAgent: true,
Status: 1,
Region: agent.Region,
Mobile: agent.Mobile,
WechatID: lzUtils.NullStringToString(agent.WechatId),
}, nil
}

View File

@@ -0,0 +1,77 @@
package agent
import (
"context"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"tydata-server/app/user/model"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/lzUtils"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetAgentMembershipProductConfigLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAgentMembershipProductConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentMembershipProductConfigLogic {
return &GetAgentMembershipProductConfigLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetAgentMembershipProductConfigLogic) GetAgentMembershipProductConfig(req *types.AgentMembershipProductConfigReq) (resp *types.AgentMembershipProductConfigResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取会员用户报告配置获取用户ID失败: %v", err)
}
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取会员用户报告配置,获取代理信息失败: %v", err)
}
agentMembershipConfigModel, err := l.svcCtx.AgentMembershipConfigModel.FindOneByLevelName(l.ctx, agentModel.LevelName)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取会员用户报告配置,获取平台配置会员信息失败: %v", err)
}
agentMembershipUserConfigModel, err := l.svcCtx.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(l.ctx, agentModel.Id, req.ProductID)
if err != nil && !errors.Is(err, model.ErrNotFound) {
return nil, err
}
var agentMembershipUserConfig types.AgentMembershipUserConfig
if agentMembershipUserConfigModel != nil {
err = copier.Copy(&agentMembershipUserConfig, agentMembershipUserConfigModel)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取会员用户报告配置,复制平台配置会员信息失败: %v", err)
}
} else {
agentMembershipUserConfig.ProductID = req.ProductID
}
agentProductConfigModelAll, err := l.svcCtx.AgentProductConfigModel.FindOneByProductId(l.ctx, req.ProductID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取会员用户报告配置, 获取产品配置%v", err)
}
var productConfig types.ProductConfig
err = copier.Copy(&productConfig, agentProductConfigModelAll)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取会员用户报告配置,复制平台产品配置失败: %v", err)
}
return &types.AgentMembershipProductConfigResp{
AgentMembershipUserConfig: agentMembershipUserConfig,
ProductConfig: productConfig,
PriceIncreaseAmount: lzUtils.NullFloat64ToFloat64(agentMembershipConfigModel.PriceIncreaseAmount),
PriceIncreaseMax: lzUtils.NullFloat64ToFloat64(agentMembershipConfigModel.PriceIncreaseMax),
PriceRatio: lzUtils.NullFloat64ToFloat64(agentMembershipConfigModel.PriceRatio),
}, nil
}

View File

@@ -0,0 +1,136 @@
package agent
import (
"context"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/mr"
"tydata-server/app/user/model"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetAgentProductConfigLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAgentProductConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentProductConfigLogic {
return &GetAgentProductConfigLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
type AgentProductConfigResp struct {
}
func (l *GetAgentProductConfigLogic) GetAgentProductConfig() (resp *types.AgentProductConfigResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取推广项目配置失败, %v", err)
}
agentModel, 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.SERVER_COMMON_ERROR), "获取推广项目配置失败, %v", err)
}
// 1. 查询推广项目配置数据
builder := l.svcCtx.AgentProductConfigModel.SelectBuilder()
agentProductConfigModelAll, err := l.svcCtx.AgentProductConfigModel.FindAll(l.ctx, builder, "")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取推广项目配置失败, %v", err)
}
// 用于存放最终组装好的响应数据
var respList []types.AgentProductConfig
// 2. 使用 mr.MapReduceVoid 并行处理每个推广项目配置项
mrMapErr := mr.MapReduceVoid(
// source 函数:遍历所有推广项目配置,将每个配置项发送到 channel 中
func(source chan<- interface{}) {
for _, config := range agentProductConfigModelAll {
source <- config
}
},
// map 函数:处理每个推广项目配置项,根据 ProductId 查询会员用户配置,并组装响应数据
func(item interface{}, writer mr.Writer[*types.AgentProductConfig], cancel func(error)) {
// 将 item 转换为推广项目配置模型
config := item.(*model.AgentProductConfig)
var agentProductConfig types.AgentProductConfig
// 配置平台成本价和定价成本
agentProductConfigModel, findAgentProductConfigErr := l.svcCtx.AgentProductConfigModel.FindOneByProductId(l.ctx, config.ProductId)
if findAgentProductConfigErr != nil {
cancel(findAgentProductConfigErr)
return
}
agentProductConfig.ProductID = config.ProductId
agentProductConfig.CostPrice = agentProductConfigModel.CostPrice
agentProductConfig.PriceRangeMin = agentProductConfigModel.PriceRangeMin
agentProductConfig.PriceRangeMax = agentProductConfigModel.PriceRangeMax
agentProductConfig.PPricingStandard = agentProductConfigModel.PricingStandard
agentProductConfig.POverpricingRatio = agentProductConfigModel.OverpricingRatio
// 看推广人是否有上级,上级是否有这个配置权限,上级是否有相关配置
agentClosureModel, findAgentClosureErr := l.svcCtx.AgentClosureModel.FindOneByDescendantIdDepth(l.ctx, agentModel.Id, 1)
if findAgentClosureErr != nil && !errors.Is(findAgentClosureErr, model.ErrNotFound) {
cancel(findAgentClosureErr)
return
}
if agentClosureModel != nil {
ancestorAgentModel, findAncestorAgentErr := l.svcCtx.AgentModel.FindOne(l.ctx, agentClosureModel.AncestorId)
if findAncestorAgentErr != nil {
cancel(findAncestorAgentErr)
return
}
agentMembershipConfigModel, findAgentMembershipErr := l.svcCtx.AgentMembershipConfigModel.FindOneByLevelName(l.ctx, ancestorAgentModel.LevelName)
if findAgentMembershipErr != nil {
cancel(findAgentMembershipErr)
return
}
// 是否有提成本价
if agentMembershipConfigModel.PriceIncreaseAmount.Valid {
// 根据产品ID查询会员用户配置数据
membershipUserConfigModel, membershipConfigErr := l.svcCtx.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(l.ctx, agentClosureModel.AncestorId, config.ProductId)
if membershipConfigErr != nil {
if errors.Is(membershipConfigErr, model.ErrNotFound) {
writer.Write(&agentProductConfig)
return
}
cancel(membershipConfigErr)
return
}
agentProductConfig.CostPrice += membershipUserConfigModel.PriceIncreaseAmount
agentProductConfig.PriceRangeMin += membershipUserConfigModel.PriceIncreaseAmount
agentProductConfig.APricingStandard = membershipUserConfigModel.PriceRangeFrom
agentProductConfig.APricingEnd = membershipUserConfigModel.PriceRangeTo
agentProductConfig.AOverpricingRatio = membershipUserConfigModel.PriceRatio
}
}
writer.Write(&agentProductConfig)
},
// reduce 函数:收集 map 阶段写入的响应数据,并汇总到 respList 中
func(pipe <-chan *types.AgentProductConfig, cancel func(error)) {
for item := range pipe {
respList = append(respList, *item)
}
},
)
if mrMapErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取推广项目配置失败, %+v", mrMapErr)
}
// 3. 组装最终响应返回
return &types.AgentProductConfigResp{
AgentProductConfig: respList,
}, nil
}

View File

@@ -0,0 +1,198 @@
package agent
import (
"context"
"github.com/Masterminds/squirrel"
"github.com/pkg/errors"
"time"
"tydata-server/app/user/model"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetAgentRevenueInfoLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAgentRevenueInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentRevenueInfoLogic {
return &GetAgentRevenueInfoLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetAgentRevenueInfoLogic) GetAgentRevenueInfo(req *types.GetAgentRevenueInfoReq) (resp *types.GetAgentRevenueInfoResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理奖励, %v", err)
}
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励, %v", err)
}
agentWalletModel, err := l.svcCtx.AgentWalletModel.FindOneByAgentId(l.ctx, agentModel.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励, %v", err)
}
resp = &types.GetAgentRevenueInfoResp{}
resp.Balance = agentWalletModel.Balance
resp.TotalEarnings = agentWalletModel.TotalEarnings
resp.FrozenBalance = agentWalletModel.FrozenBalance
// 直推报告统计
//now := time.Now()
//startTime := now.AddDate(0, 0, -30).Format("2006-01-02 15:04:05")
//endTime := now.Format("2006-01-02 15:04:05")
// 直推报告佣金
agentCommissionModelBuild := l.svcCtx.AgentCommissionModel.SelectBuilder().
Where(squirrel.Eq{"agent_id": agentModel.Id})
//.Where(squirrel.Expr("create_time BETWEEN ? AND ?", startTime, endTime))
agentCommissionsModel, err := l.svcCtx.AgentCommissionModel.FindAll(l.ctx, agentCommissionModelBuild, "")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励, %v", err)
}
// 筛选分类
directPush, err := calculateDirectPushReport(agentCommissionsModel, nil)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励, %v", err)
}
// 绑定到响应体
resp.DirectPush = directPush
// 活跃下级统计
agentRewardsModelBuilder := l.svcCtx.AgentRewardsModel.SelectBuilder().Where("agent_id = ?", agentModel.Id)
agentRewardsModel, err := l.svcCtx.AgentRewardsModel.FindAll(l.ctx, agentRewardsModelBuilder, "")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励, %v", err)
}
activeReward := calculateActiveReward(agentRewardsModel)
resp.ActiveReward = activeReward
return resp, nil
}
// 统计直推报告的独立函数
func calculateDirectPushReport(commissions []*model.AgentCommission, loc *time.Location) (types.DirectPushReport, error) {
// 初始化报告结构
report := types.DirectPushReport{
Today: types.TimeRangeReport{},
Last7D: types.TimeRangeReport{},
Last30D: types.TimeRangeReport{},
}
// 获取当前中国时间
now := time.Now()
// 计算时间分界点
todayStart := now.Add(-24 * time.Hour)
last7dStart := now.AddDate(0, 0, -7)
last30dStart := now.AddDate(0, 0, -30)
// 遍历所有佣金记录
for _, c := range commissions {
// 转换时区
createTime := c.CreateTime
// 统计总量
report.TotalCommission += c.Amount
report.TotalReport++
// 近24小时滚动周期
if createTime.After(todayStart) {
report.Today.Commission += c.Amount
report.Today.Report++
}
// 近7天滚动周期
if createTime.After(last7dStart) {
report.Last7D.Commission += c.Amount
report.Last7D.Report++
}
// 近30天滚动周期
if createTime.After(last30dStart) {
report.Last30D.Commission += c.Amount
report.Last30D.Report++
}
}
return report, nil
}
func calculateActiveReward(rewards []*model.AgentRewards) types.ActiveReward {
result := types.ActiveReward{
Today: types.ActiveRewardData{},
Last7D: types.ActiveRewardData{},
Last30D: types.ActiveRewardData{},
}
now := time.Now()
todayStart := now.Add(-24 * time.Hour) // 近24小时
last7dStart := now.AddDate(0, 0, -7) // 近7天
last30dStart := now.AddDate(0, 0, -30) // 近30天
for _, r := range rewards {
createTime := r.CreateTime
amount := r.Amount
// 总奖励累加
result.TotalReward += amount
// 时间范围判断
isToday := createTime.After(todayStart)
isLast7d := createTime.After(last7dStart)
isLast30d := createTime.After(last30dStart)
// 类型分类统计
switch r.Type {
case model.AgentRewardsTypeDescendantWithdraw:
addToPeriods(&result, amount, isToday, isLast7d, isLast30d, "withdraw")
case model.AgentRewardsTypeDescendantNewActive:
addToPeriods(&result, amount, isToday, isLast7d, isLast30d, "new_active")
case model.AgentRewardsTypeDescendantUpgradeSvip, model.AgentRewardsTypeDescendantUpgradeVip:
addToPeriods(&result, amount, isToday, isLast7d, isLast30d, "upgrade")
case model.AgentRewardsTypeDescendantPromotion:
addToPeriods(&result, amount, isToday, isLast7d, isLast30d, "promotion")
}
}
return result
}
// 统一处理时间段累加
func addToPeriods(res *types.ActiveReward, amount float64, today, last7d, last30d bool, t string) {
if today {
addToData(&res.Today, amount, t)
}
if last7d {
addToData(&res.Last7D, amount, t)
}
if last30d {
addToData(&res.Last30D, amount, t)
}
}
// 分类添加具体字段
func addToData(data *types.ActiveRewardData, amount float64, t string) {
switch t {
case "withdraw":
data.SubWithdrawReward += amount
case "new_active":
data.NewActiveReward += amount
case "upgrade":
data.SubUpgradeReward += amount
case "promotion":
data.SubPromoteReward += amount
}
}

View File

@@ -0,0 +1,67 @@
package agent
import (
"context"
"github.com/Masterminds/squirrel"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetAgentRewardsLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAgentRewardsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentRewardsLogic {
return &GetAgentRewardsLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetAgentRewardsLogic) GetAgentRewards(req *types.GetRewardsReq) (resp *types.GetRewardsResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理奖励列表, %v", err)
}
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励列表, %v", err)
}
builder := l.svcCtx.AgentRewardsModel.SelectBuilder().Where(squirrel.Eq{
"agent_id": agentModel.Id,
})
agentRewardsModelList, total, err := l.svcCtx.AgentRewardsModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理奖励列表, 查找列表错误, %v", err)
}
var list = make([]types.Rewards, 0)
if len(agentRewardsModelList) > 0 {
for _, agentRewardsModel := range agentRewardsModelList {
var rewards types.Rewards
copyErr := copier.Copy(&rewards, agentRewardsModel)
if copyErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理奖励列表, %v", err)
}
rewards.CreateTime = agentRewardsModel.CreateTime.Format("2006-01-02 15:04:05")
list = append(list, rewards)
}
}
return &types.GetRewardsResp{
Total: total,
List: list,
}, nil
return
}

View File

@@ -0,0 +1,65 @@
package agent
import (
"context"
"github.com/Masterminds/squirrel"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetAgentWithdrawalLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAgentWithdrawalLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentWithdrawalLogic {
return &GetAgentWithdrawalLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetAgentWithdrawalLogic) GetAgentWithdrawal(req *types.GetWithdrawalReq) (resp *types.GetWithdrawalResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理提现列表, %v", err)
}
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理提现列表, %v", err)
}
builder := l.svcCtx.AgentWithdrawalModel.SelectBuilder().Where(squirrel.Eq{
"agent_id": agentModel.Id,
})
agentWithdrawalModelList, total, err := l.svcCtx.AgentWithdrawalModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理提现列表, 查找列表错误, %v", err)
}
var list = make([]types.Withdrawal, 0)
if len(agentWithdrawalModelList) > 0 {
for _, agentWithdrawalModel := range agentWithdrawalModelList {
var withdrawal types.Withdrawal
copyErr := copier.Copy(&withdrawal, agentWithdrawalModel)
if copyErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理提现列表, %v", err)
}
withdrawal.CreateTime = agentWithdrawalModel.CreateTime.Format("2006-01-02 15:04:05")
list = append(list, withdrawal)
}
}
return &types.GetWithdrawalResp{
Total: total,
List: list,
}, nil
}

View File

@@ -0,0 +1,45 @@
package agent
import (
"context"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"tydata-server/common/xerr"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetLinkDataLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetLinkDataLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetLinkDataLogic {
return &GetLinkDataLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetLinkDataLogic) GetLinkData(req *types.GetLinkDataReq) (resp *types.GetLinkDataResp, err error) {
agentLinkModel, err := l.svcCtx.AgentLinkModel.FindOneByLinkIdentifier(l.ctx, req.LinkIdentifier)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理链接数据, %v", err)
}
productModel, err := l.svcCtx.ProductModel.FindOne(l.ctx, agentLinkModel.ProductId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取代理链接数据, %v", err)
}
var product types.Product
copier.Copy(&product, productModel)
product.SellPrice = agentLinkModel.Price
return &types.GetLinkDataResp{
Product: product,
}, nil
}

View File

@@ -0,0 +1,63 @@
package agent
import (
"context"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"tydata-server/app/user/model"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type SaveAgentMembershipUserConfigLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewSaveAgentMembershipUserConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SaveAgentMembershipUserConfigLogic {
return &SaveAgentMembershipUserConfigLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *SaveAgentMembershipUserConfigLogic) SaveAgentMembershipUserConfig(req *types.SaveAgentMembershipUserConfigReq) error {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "保存会员代理报告配置获取用户ID失败: %v", err)
}
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "保存会员代理报告配置: %v", err)
}
agentMembershipUserConfigModel, err := l.svcCtx.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(l.ctx, agentModel.Id, req.ProductID)
if err != nil && !errors.Is(err, model.ErrNotFound) {
return err
}
err = copier.Copy(&agentMembershipUserConfigModel, &req)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "保存会员代理报告配置: %v", err)
}
if agentMembershipUserConfigModel == nil {
agentMembershipUserConfigModel.UserId = userID
agentMembershipUserConfigModel.AgentId = agentModel.Id
_, err = l.svcCtx.AgentMembershipUserConfigModel.Insert(l.ctx, nil, agentMembershipUserConfigModel)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "保存会员代理报告配置: %v", err)
}
} else {
_, err = l.svcCtx.AgentMembershipUserConfigModel.Update(l.ctx, nil, agentMembershipUserConfigModel)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "保存会员代理报告配置: %v", err)
}
}
return nil
}

View File

@@ -50,7 +50,7 @@ func (l *SendSmsLogic) SendSms(req *types.SendSmsReq) error {
// 发送短信
smsResp, err := l.sendSmsRequest(req.Mobile, code)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 调用阿里客户端失败: %+v", err)
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 调用阿里客户端失败: %v", err)
}
if *smsResp.Body.Code != "OK" {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 阿里客户端响应失败: %s", *smsResp.Body.Message)
@@ -59,12 +59,12 @@ func (l *SendSmsLogic) SendSms(req *types.SendSmsReq) error {
// 将验证码保存到 Redis设置过期时间
err = l.svcCtx.Redis.Setex(codeKey, code, l.svcCtx.Config.VerifyCode.ValidTime) // 验证码有效期5分钟
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 验证码设置过期时间失败: %+v", err)
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 验证码设置过期时间失败: %v", err)
}
// 在 Redis 中设置 1 分钟的标记,限制重复请求
err = l.svcCtx.Redis.Setex(limitCodeKey, code, 60) // 标记 1 分钟内不能重复请求
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 验证码设置限制重复请求失败: %+v", err)
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "短信发送, 验证码设置限制重复请求失败: %v", err)
}
return nil
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"github.com/smartwalle/alipay/v3"
"net/http"
"os"
"time"
"tydata-server/pkg/lzkit/lzUtils"
@@ -26,9 +27,13 @@ func NewAlipayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Al
}
func (l *AlipayCallbackLogic) AlipayCallback(w http.ResponseWriter, r *http.Request) error {
env := os.Getenv("ENV")
if env == "development" {
return nil
}
notification, err := l.svcCtx.AlipayService.HandleAliPaymentNotification(r)
if err != nil {
logx.Errorf("支付宝支付回调,%+v", err)
logx.Errorf("支付宝支付回调,%v", err)
return nil
}
order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, notification.OutTradeNo)

View File

@@ -8,6 +8,7 @@ import (
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"os"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/app/user/model"
@@ -48,12 +49,12 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
var data types.QueryCacheLoad
err = json.Unmarshal([]byte(cache), &data)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 解析缓存内容失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 解析缓存内容失败, %v", err)
}
product, err := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, data.Product)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 查找产品错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 查找产品错误: %v", err)
}
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
@@ -71,16 +72,28 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
var prepayData interface{}
var outTradeNo string
var amount float64
var orderAmount float64
user, err := l.svcCtx.UserModel.FindOne(l.ctx, userID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取用户信息失败: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取用户信息失败: %v", err)
}
if data.AgentIdentifier != "" {
agentLinkModel, findAgentLinkErr := l.svcCtx.AgentLinkModel.FindOneByLinkIdentifier(l.ctx, data.AgentIdentifier)
if findAgentLinkErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取代理订单失败: %+v", findAgentLinkErr)
}
amount = agentLinkModel.Price
orderAmount = agentLinkModel.Price
} else {
amount = product.SellPrice
orderAmount = product.SellPrice
}
if user.Inside == 1 {
amount = 0.01
} else {
amount = product.SellPrice
}
var createOrderErr error
if req.PayMethod == "wechat" {
outTradeNo = l.svcCtx.WechatPayService.GenerateOutTradeNo()
@@ -103,16 +116,16 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
ProductId: product.Id,
PaymentPlatform: req.PayMethod,
PaymentScene: "app",
Amount: amount,
Amount: orderAmount,
Status: "pending",
}
orderInsertResult, insertOrderErr := l.svcCtx.OrderModel.Insert(ctx, session, &order)
if insertOrderErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 保存订单失败: %+v", insertOrderErr)
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存订单失败: %+v", insertOrderErr)
}
insertedOrderID, lastInsertIdErr := orderInsertResult.LastInsertId()
if lastInsertIdErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取保存订单ID失败: %+v", lastInsertIdErr)
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取保存订单ID失败: %+v", lastInsertIdErr)
}
orderID = insertedOrderID
query := model.Query{
@@ -124,14 +137,32 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
}
_, insertQueryErr := l.svcCtx.QueryModel.Insert(l.ctx, session, &query)
if insertQueryErr != nil {
return insertQueryErr
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存查询失败: %+v", lastInsertIdErr)
}
if data.AgentIdentifier != "" {
agent, parsingErr := l.agentParsing(data.AgentIdentifier)
if parsingErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 解析代理标识符失败: %+v", parsingErr)
}
var agentOrder model.AgentOrder
agentOrder.OrderId = orderID
agentOrder.AgentId = agent.AgentID
_, agentOrderInsert := l.svcCtx.AgentOrderModel.Insert(ctx, session, &agentOrder)
if agentOrderInsert != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存代理订单失败: %+v", agentOrderInsert)
}
}
return nil
})
if transErr != nil {
return nil, transErr
}
env := os.Getenv("ENV")
if env == "development" {
if asyncErr := l.svcCtx.AsynqService.SendQueryTask(orderID); asyncErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 异步订单调用失败: %+v", asyncErr)
}
}
switch v := prepayData.(type) {
case string:
// 如果 prepayData 是字符串类型,直接返回
@@ -140,3 +171,21 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
return &types.PaymentResp{PrepayData: prepayData, OrderID: orderID}, nil
}
}
func (l *PaymentLogic) agentParsing(agentIdentifier string) (*types.AgentIdentifier, error) {
key, decodeErr := hex.DecodeString("8e3e7a2f60edb49221e953b9c029ed10")
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取AES密钥失败: %+v", decodeErr)
}
// Encrypt the params
encrypted, err := crypto.AesDecryptURL(agentIdentifier, key)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, %v", err)
}
var agentIdentifierStruct types.AgentIdentifier
err = json.Unmarshal(encrypted, &agentIdentifierStruct)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务,反序列化失败 %v", err)
}
return &agentIdentifierStruct, nil
}

View File

@@ -28,7 +28,7 @@ func NewWechatPayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext)
func (l *WechatPayCallbackLogic) WechatPayCallback(w http.ResponseWriter, r *http.Request) error {
notification, err := l.svcCtx.WechatPayService.HandleWechatPayNotification(l.ctx, r)
if err != nil {
logx.Errorf("微信支付回调,%+v", err)
logx.Errorf("微信支付回调,%v", err)
return nil
}
order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, *notification.OutTradeNo)

View File

@@ -25,7 +25,7 @@ func NewWechatPayRefundCallbackLogic(ctx context.Context, svcCtx *svc.ServiceCon
func (l *WechatPayRefundCallbackLogic) WechatPayRefundCallback(w http.ResponseWriter, r *http.Request) error {
notification, err := l.svcCtx.WechatPayService.HandleRefundNotification(l.ctx, r)
if err != nil {
logx.Errorf("微信退款回调,%+v", err)
logx.Errorf("微信退款回调,%v", err)
return nil
}
order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, *notification.OutTradeNo)

View File

@@ -32,7 +32,7 @@ func NewGetProductByEnLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Ge
func (l *GetProductByEnLogic) GetProductByEn(req *types.GetProductByEnRequest) (resp *types.ProductResponse, err error) {
productModel, err := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, req.ProductEn)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "产品查询, 查找产品错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "产品查询, 查找产品错误: %v", err)
}
build := l.svcCtx.ProductFeatureModel.SelectBuilder().Where(squirrel.Eq{
@@ -40,12 +40,12 @@ func (l *GetProductByEnLogic) GetProductByEn(req *types.GetProductByEnRequest) (
})
productFeatureAll, err := l.svcCtx.ProductFeatureModel.FindAll(l.ctx, build, "")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "产品查询, 查找产品关联错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "产品查询, 查找产品关联错误: %v", err)
}
var product types.Product
err = copier.Copy(&product, productModel)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 用户信息结构体复制失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 用户信息结构体复制失败, %v", err)
}
mr.MapReduceVoid(func(source chan<- interface{}) {
for _, productFeature := range productFeatureAll {

View File

@@ -1,140 +0,0 @@
package query
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"time"
"tydata-server/app/user/cmd/api/internal/service"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"tydata-server/pkg/lzkit/validator"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type BackgroundCheckLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewBackgroundCheckLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BackgroundCheckLogic {
return &BackgroundCheckLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *BackgroundCheckLogic) BackgroundCheck(req *types.QueryReq) (resp *types.QueryResp, err error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 获取用户信息失败, %+v", getUidErr)
}
// 1、AES解密
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 密钥获取失败: %+v", decodeErr)
}
decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key)
if aesDecryptErr != nil || len(decryptData) == 0 {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 解密失败: %+v", decodeErr)
}
// 2、校验
var data types.BackgroundCheckReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "人事背调, 参数不正确: %+v", validatorErr)
}
if data.Name == "刘福思" && data.IDCard == "45262419980929047X" && data.Mobile == "17776203797" {
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: "backgroundcheck",
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}
// 校验验证码
codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile)
cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey)
if err != nil {
if errors.Is(err, redis.Nil) {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "人事背调, 验证码过期: %s", data.Mobile)
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "人事背调, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err)
}
if cacheCode != data.Code {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "人事背调, 验证码不正确: %s", data.Mobile)
}
// 3、二要素三要素核验
//twoVerification := service.TwoFactorVerificationRequest{
// Name: data.Name,
// IDCard: data.IDCard,
//}
//verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification)
//if err != nil {
// return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 二要素验证失败: %+v", err)
//}
//if !verification.Passed {
// return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "人事背调, 二要素验证不通过: %+v", err)
//}
// 3、二要素三要素核验
threeVerification := service.ThreeFactorVerificationRequest{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
}
verification, err := l.svcCtx.VerificationService.ThreeFactorVerification(threeVerification)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 三要素验证失败: %+v", err)
}
if !verification.Passed {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "人事背调, 三要素验证不通过: %+v", err)
}
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: "backgroundcheck",
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "人事背调, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}

View File

@@ -1,140 +0,0 @@
package query
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"time"
"tydata-server/app/user/cmd/api/internal/service"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"tydata-server/pkg/lzkit/validator"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type CompanyInfoLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewCompanyInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CompanyInfoLogic {
return &CompanyInfoLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *CompanyInfoLogic) CompanyInfo(req *types.QueryReq) (resp *types.QueryResp, err error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 获取用户信息失败, %+v", getUidErr)
}
// 1、AES解密
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 密钥获取失败: %+v", decodeErr)
}
decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key)
if aesDecryptErr != nil || len(decryptData) == 0 {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 解密失败: %+v", decodeErr)
}
// 2、校验
var data types.CompanyInfoReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "企业报告, 参数不正确: %+v", validatorErr)
}
if data.Name == "刘福思" && data.IDCard == "45262419980929047X" && data.Mobile == "17776203797" {
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: "companyinfo",
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}
// 校验验证码
codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile)
cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey)
if err != nil {
if errors.Is(err, redis.Nil) {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "企业报告, 验证码过期: %s", data.Mobile)
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "企业报告, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err)
}
if cacheCode != data.Code {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "企业报告, 验证码不正确: %s", data.Mobile)
}
// 3、二要素三要素核验
//twoVerification := service.TwoFactorVerificationRequest{
// Name: data.Name,
// IDCard: data.IDCard,
//}
//verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification)
//if err != nil {
// return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 二要素验证失败: %+v", err)
//}
//if !verification.Passed {
// return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "企业报告, 二要素验证不通过: %+v", err)
//}
// 3、二要素三要素核验
threeVerification := service.ThreeFactorVerificationRequest{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
}
verification, err := l.svcCtx.VerificationService.ThreeFactorVerification(threeVerification)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 三要素验证失败: %+v", err)
}
if !verification.Passed {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "企业报告, 三要素验证不通过: %+v", err)
}
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: "companyinfo",
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "企业报告, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}

View File

@@ -1,141 +0,0 @@
package query
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"time"
"tydata-server/app/user/cmd/api/internal/service"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"tydata-server/pkg/lzkit/validator"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type HomeServiceLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewHomeServiceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *HomeServiceLogic {
return &HomeServiceLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *HomeServiceLogic) HomeService(req *types.QueryReq) (resp *types.QueryResp, err error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 获取用户信息失败, %+v", getUidErr)
}
// 1、AES解密
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 密钥获取失败: %+v", decodeErr)
}
decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key)
if aesDecryptErr != nil || len(decryptData) == 0 {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 解密失败: %+v", decodeErr)
}
// 2、校验
var data types.HomeServiceReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "家政服务, 参数不正确: %+v", validatorErr)
}
if data.Name == "刘福思" && data.IDCard == "45262419980929047X" && data.Mobile == "17776203797" {
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: "homeservice",
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}
// 校验验证码
codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile)
cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey)
if err != nil {
if errors.Is(err, redis.Nil) {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "家政服务, 验证码过期: %s", data.Mobile)
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "家政服务, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err)
}
if cacheCode != data.Code {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "家政服务, 验证码不正确: %s", data.Mobile)
}
// 3、二要素三要素核验
//twoVerification := service.TwoFactorVerificationRequest{
// Name: data.Name,
// IDCard: data.IDCard,
//}
//verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification)
//if err != nil {
// return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 二要素验证失败: %+v", err)
//}
//if !verification.Passed {
// return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "家政服务, 二要素验证不通过: %+v", err)
//}
// 3、二要素三要素核验
threeVerification := service.ThreeFactorVerificationRequest{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
}
verification, err := l.svcCtx.VerificationService.ThreeFactorVerification(threeVerification)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 三要素验证失败: %+v", err)
}
if !verification.Passed {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "家政服务, 三要素验证不通过: %+v", err)
}
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: "homeservice",
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "家政服务, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}

View File

@@ -1,142 +0,0 @@
package query
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/redis"
"time"
"tydata-server/app/user/cmd/api/internal/service"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"tydata-server/pkg/lzkit/validator"
)
type MarriageLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewMarriageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MarriageLogic {
return &MarriageLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
const MERRIAGE = "marriage"
func (l *MarriageLogic) Marriage(req *types.QueryReq) (resp *types.QueryResp, err error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 获取用户信息失败, %+v", getUidErr)
}
// 1、AES解密
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 密钥获取失败: %+v", decodeErr)
}
decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key)
if aesDecryptErr != nil || len(decryptData) == 0 {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 解密失败: %+v", decodeErr)
}
// 2、校验
var data types.MarriageReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "婚恋评估, 参数不正确: %+v", validatorErr)
}
if data.Name == "刘福思" && data.IDCard == "45262419980929047X" && data.Mobile == "17776203797" {
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: MERRIAGE,
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}
// 校验验证码
codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile)
cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey)
if err != nil {
if errors.Is(err, redis.Nil) {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "婚恋评估, 验证码过期: %s", data.Mobile)
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "婚恋评估, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err)
}
if cacheCode != data.Code {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "婚恋评估, 验证码不正确: %s", data.Mobile)
}
//// 3、二要素核验
//twoVerification := service.TwoFactorVerificationRequest{
// Name: data.Name,
// IDCard: data.IDCard,
//}
//verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification)
//if err != nil {
// return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 二要素验证失败: %+v", err)
//}
//if !verification.Passed {
// return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "婚恋评估, 二要素验证不通过: %+v", err)
//}
// 3、三要素核验
threeVerification := service.ThreeFactorVerificationRequest{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
}
verification, err := l.svcCtx.VerificationService.ThreeFactorVerification(threeVerification)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 三要素验证失败: %+v", err)
}
if !verification.Passed {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "婚恋评估, 三要素验证不通过: %+v", err)
}
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: MERRIAGE,
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}

View File

@@ -1,140 +0,0 @@
package query
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"time"
"tydata-server/app/user/cmd/api/internal/service"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"tydata-server/pkg/lzkit/validator"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type PreLoanBackgroundCheckLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewPreLoanBackgroundCheckLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PreLoanBackgroundCheckLogic {
return &PreLoanBackgroundCheckLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *PreLoanBackgroundCheckLogic) PreLoanBackgroundCheck(req *types.QueryReq) (resp *types.QueryResp, err error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 获取用户信息失败, %+v", getUidErr)
}
// 1、AES解密
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 密钥获取失败: %+v", decodeErr)
}
decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key)
if aesDecryptErr != nil || len(decryptData) == 0 {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 解密失败: %+v", decodeErr)
}
// 2、校验
var data types.PreLoanBackgroundCheckReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "贷前背调, 参数不正确: %+v", validatorErr)
}
if data.Name == "刘福思" && data.IDCard == "45262419980929047X" && data.Mobile == "17776203797" {
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: "preloanbackgroundcheck",
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}
// 校验验证码
codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile)
cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey)
if err != nil {
if errors.Is(err, redis.Nil) {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "贷前背调, 验证码过期: %s", data.Mobile)
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "贷前背调, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err)
}
if cacheCode != data.Code {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "贷前背调, 验证码不正确: %s", data.Mobile)
}
// 3、二要素三要素核验
//twoVerification := service.TwoFactorVerificationRequest{
// Name: data.Name,
// IDCard: data.IDCard,
//}
//verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification)
//if err != nil {
// return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 二要素验证失败: %+v", err)
//}
//if !verification.Passed {
// return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "贷前背调, 二要素验证不通过: %+v", err)
//}
// 3、二要素三要素核验
threeVerification := service.ThreeFactorVerificationRequest{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
}
verification, err := l.svcCtx.VerificationService.ThreeFactorVerification(threeVerification)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 三要素验证失败: %+v", err)
}
if !verification.Passed {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "贷前背调, 三要素验证不通过: %+v", err)
}
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: "preloanbackgroundcheck",
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "贷前背调, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}

View File

@@ -38,13 +38,13 @@ func (l *QueryDetailByOrderIdLogic) QueryDetailByOrderId(req *types.QueryDetailB
// 获取订单信息
order, err := l.svcCtx.OrderModel.FindOne(l.ctx, req.OrderId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err)
}
// 创建渐进式延迟策略实例
progressiveDelayOrder, err := delay.New(200*time.Millisecond, 3*time.Second, 10*time.Second, 1.5)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %v", err)
}
// 等待订单状态变为 "paid"
@@ -63,7 +63,7 @@ func (l *QueryDetailByOrderIdLogic) QueryDetailByOrderId(req *types.QueryDetailB
// 再次查找订单
order, err = l.svcCtx.OrderModel.FindOne(l.ctx, req.OrderId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找订单错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找订单错误: %v", err)
}
}
if order.Status != "paid" {
@@ -72,13 +72,13 @@ func (l *QueryDetailByOrderIdLogic) QueryDetailByOrderId(req *types.QueryDetailB
// 获取报告信息
queryModel, err := l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, req.OrderId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err)
}
// 创建渐进式延迟实例
progressiveDelayQuery, err := delay.New(200*time.Millisecond, 3*time.Second, 10*time.Second, 1.5)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %v", err)
}
// 等待 queryModel.QueryState 不再是 "pending"
@@ -97,7 +97,7 @@ func (l *QueryDetailByOrderIdLogic) QueryDetailByOrderId(req *types.QueryDetailB
// 再次查询 report 状态
queryModel, err = l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, req.OrderId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err)
}
}
@@ -114,7 +114,7 @@ func (l *QueryDetailByOrderIdLogic) QueryDetailByOrderId(req *types.QueryDetailB
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取AES解密解药失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取AES解密解药失败, %v", err)
}
processParamsErr := ProcessQueryParams(queryModel.QueryParams, &query.QueryParams, key)
if processParamsErr != nil {
@@ -131,11 +131,11 @@ func (l *QueryDetailByOrderIdLogic) QueryDetailByOrderId(req *types.QueryDetailB
// 复制报告数据
err = copier.Copy(&query, queryModel)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体复制失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体复制失败, %v", err)
}
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取商品信息失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取商品信息失败, %v", err)
}
query.ProductName = product.ProductName
return &types.QueryDetailByOrderIdResp{

View File

@@ -34,13 +34,13 @@ func (l *QueryDetailByOrderNoLogic) QueryDetailByOrderNo(req *types.QueryDetailB
// 获取订单信息
order, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err)
}
// 创建渐进式延迟策略实例
progressiveDelayOrder, err := delay.New(200*time.Millisecond, 3*time.Second, 10*time.Second, 1.5)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %v", err)
}
// 等待订单状态变为 "paid"
@@ -59,7 +59,7 @@ func (l *QueryDetailByOrderNoLogic) QueryDetailByOrderNo(req *types.QueryDetailB
// 再次查找订单
order, err = l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找订单错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找订单错误: %v", err)
}
}
if order.Status != "paid" {
@@ -68,13 +68,13 @@ func (l *QueryDetailByOrderNoLogic) QueryDetailByOrderNo(req *types.QueryDetailB
// 获取报告信息
queryModel, err := l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, order.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err)
}
// 创建渐进式延迟实例
progressiveDelayQuery, err := delay.New(200*time.Millisecond, 3*time.Second, 10*time.Second, 1.5)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %v", err)
}
// 等待 queryModel.QueryState 不再是 "pending"
@@ -93,7 +93,7 @@ func (l *QueryDetailByOrderNoLogic) QueryDetailByOrderNo(req *types.QueryDetailB
// 再次查询 report 状态
queryModel, err = l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, order.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err)
}
}
@@ -110,7 +110,7 @@ func (l *QueryDetailByOrderNoLogic) QueryDetailByOrderNo(req *types.QueryDetailB
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取AES解密解药失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取AES解密解药失败, %v", err)
}
processParamsErr := ProcessQueryParams(queryModel.QueryParams, &query.QueryParams, key)
if processParamsErr != nil {
@@ -127,11 +127,11 @@ func (l *QueryDetailByOrderNoLogic) QueryDetailByOrderNo(req *types.QueryDetailB
// 复制报告数据
err = copier.Copy(&query, queryModel)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体复制失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体复制失败, %v", err)
}
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取商品信息失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取商品信息失败, %v", err)
}
query.ProductName = product.ProductName
return &types.QueryDetailByOrderNoResp{

View File

@@ -33,7 +33,7 @@ func NewQueryDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Query
func (l *QueryDetailLogic) QueryDetail(req *types.QueryDetailReq) (resp *types.QueryDetailResp, err error) {
queryModel, err := l.svcCtx.QueryModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err)
}
var query types.Query
@@ -42,7 +42,7 @@ func (l *QueryDetailLogic) QueryDetail(req *types.QueryDetailReq) (resp *types.Q
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取AES解密解药失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取AES解密解药失败, %v", err)
}
if lzUtils.NullStringToString(queryModel.QueryData) != "" {
queryData, decryptErr := crypto.AesDecrypt(lzUtils.NullStringToString(queryModel.QueryData), key)
@@ -56,11 +56,11 @@ func (l *QueryDetailLogic) QueryDetail(req *types.QueryDetailReq) (resp *types.Q
}
err = copier.Copy(&query, queryModel)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体复制失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体复制失败, %v", err)
}
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取商品信息失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取商品信息失败, %v", err)
}
query.ProductName = product.ProductName
return &types.QueryDetailResp{

View File

@@ -60,7 +60,7 @@ func (l *QueryExampleLogic) QueryExample(req *types.QueryExampleReq) (resp *type
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 获取AES解密解药失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 获取AES解密解药失败, %v", err)
}
processParamsErr := ProcessQueryParams(queryModel.QueryParams, &query.QueryParams, key)
if processParamsErr != nil {
@@ -77,11 +77,11 @@ func (l *QueryExampleLogic) QueryExample(req *types.QueryExampleReq) (resp *type
// 复制报告数据
err = copier.Copy(&query, queryModel)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 报告结构体复制失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 报告结构体复制失败, %v", err)
}
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 获取商品信息失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 获取商品信息失败, %v", err)
}
query.ProductName = product.ProductName
return &types.QueryExampleResp{

View File

@@ -38,7 +38,7 @@ func (l *QueryListLogic) QueryList(req *types.QueryListReq) (resp *types.QueryLi
})
orderList, total, err := l.svcCtx.OrderModel.FindPageListByPageWithTotal(l.ctx, build, req.Page, req.PageSize, "create_time DESC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告列表查询, 查找订单列表错误, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告列表查询, 查找订单列表错误, %v", err)
}
var list []types.Query
@@ -54,11 +54,11 @@ func (l *QueryListLogic) QueryList(req *types.QueryListReq) (resp *types.QueryLi
query.UpdateTime = queryModel.UpdateTime.Format("2006-01-02 15:04:05")
copyErr := copier.Copy(&query, queryModel)
if copyErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告列表查询, 报告结构体复制失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告列表查询, 报告结构体复制失败, %v", err)
}
product, findProductErr := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId)
if findProductErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告列表查询, 获取商品信息失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告列表查询, 获取商品信息失败, %v", err)
}
query.ProductName = product.ProductName
list = append(list, query)

View File

@@ -41,17 +41,17 @@ func (l *QueryProvisionalOrderLogic) QueryProvisionalOrder(req *types.QueryProvi
var data types.QueryCache
err = json.Unmarshal([]byte(cache), &data)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取临时订单, 解析缓存内容失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取临时订单, 解析缓存内容失败, %v", err)
}
productModel, err := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, data.Product)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取临时订单, 查找产品错误: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取临时订单, 查找产品错误: %v", err)
}
var product types.Product
err = copier.Copy(&product, productModel)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取临时订单, 用户信息结构体复制失败: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取临时订单, 用户信息结构体复制失败: %v", err)
}
return &types.QueryProvisionalOrderResp{
Name: data.Name,

View File

@@ -29,7 +29,7 @@ func (l *QueryRetryLogic) QueryRetry(req *types.QueryRetryReq) (resp *types.Quer
query, err := l.svcCtx.QueryModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询重试, 查找报告失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询重试, 查找报告失败, %v", err)
}
if query.QueryState == "success" {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIN_FAILED, "该报告不能重试"), "报告查询重试, 该报告不能重试, %d", query.Id)

View File

@@ -0,0 +1,27 @@
package query
import (
"context"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type QueryServiceAgentLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewQueryServiceAgentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryServiceAgentLogic {
return &QueryServiceAgentLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *QueryServiceAgentLogic) QueryServiceAgent(req *types.QueryServiceReq) (resp *types.QueryServiceResp, err error) {
return &types.QueryServiceResp{}, nil
}

View File

@@ -7,9 +7,12 @@ import (
"fmt"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"time"
"tydata-server/app/user/cmd/api/internal/service"
"tydata-server/app/user/model"
"tydata-server/common/ctxdata"
jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"tydata-server/pkg/lzkit/validator"
@@ -35,9 +38,32 @@ func NewQueryServiceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Quer
}
func (l *QueryServiceLogic) QueryService(req *types.QueryServiceReq) (resp *types.QueryServiceResp, err error) {
if req.AgentIdentifier != "" {
l.ctx = context.WithValue(l.ctx, "agentIdentifier", req.AgentIdentifier)
return l.PreprocessLogic(req, req.Product)
}
return l.PreprocessLogic(req, req.Product)
}
//func (l *QueryServiceLogic) agentParsing(req *types.QueryServiceReq) (*types.AgentIdentifier, error) {
// key, decodeErr := hex.DecodeString("8e3e7a2f60edb49221e953b9c029ed10")
// if decodeErr != nil {
// return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取AES密钥失败: %+v", decodeErr)
// }
//
// encrypted, err := crypto.AesDecryptURL(req.Product, key)
// if err != nil {
// return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, %v", err)
// }
// var agentIdentifier types.AgentIdentifier
// err = json.Unmarshal(encrypted, &agentIdentifier)
// if err != nil {
// return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务,反序列化失败 %v", err)
// }
// l.ctx = context.WithValue(l.ctx, "agent", req.Agent)
// return &agentIdentifier, nil
//}
var productProcessors = map[string]func(*QueryServiceLogic, *types.QueryServiceReq) (*types.QueryServiceResp, error){
"marriage": (*QueryServiceLogic).ProcessMarriageLogic,
"homeservice": (*QueryServiceLogic).ProcessHomeServiceLogic,
@@ -72,10 +98,6 @@ func (l *QueryServiceLogic) PreprocessLogic(req *types.QueryServiceReq, product
return nil, errors.New("未找到相应的处理程序")
}
func (l *QueryServiceLogic) ProcessMarriageLogic(req *types.QueryServiceReq) (*types.QueryServiceResp, error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取用户信息失败, %+v", getUidErr)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
@@ -111,21 +133,31 @@ func (l *QueryServiceLogic) ProcessMarriageLogic(req *types.QueryServiceReq) (*t
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %v", err)
}
cacheNo, cacheDataErr := l.CacheData(params, "marriage", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
}
return &types.QueryServiceResp{Id: cacheNo}, nil
// 获取当前时间戳
now := time.Now().Unix()
return &types.QueryServiceResp{
Id: cacheNo,
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}
// 处理家政服务相关逻辑
func (l *QueryServiceLogic) ProcessHomeServiceLogic(req *types.QueryServiceReq) (*types.QueryServiceResp, error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取用户信息失败, %+v", getUidErr)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
@@ -161,20 +193,32 @@ func (l *QueryServiceLogic) ProcessHomeServiceLogic(req *types.QueryServiceReq)
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %v", err)
}
cacheNo, cacheDataErr := l.CacheData(params, "homeservice", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
}
// 获取当前时间戳
now := time.Now().Unix()
return &types.QueryServiceResp{
Id: cacheNo,
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}
// 处理风险评估相关逻辑
func (l *QueryServiceLogic) ProcessRiskAssessmentLogic(req *types.QueryServiceReq) (*types.QueryServiceResp, error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取用户信息失败, %+v", getUidErr)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
@@ -210,21 +254,32 @@ func (l *QueryServiceLogic) ProcessRiskAssessmentLogic(req *types.QueryServiceRe
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %v", err)
}
cacheNo, cacheDataErr := l.CacheData(params, "riskassessment", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
}
// 获取当前时间戳
now := time.Now().Unix()
return &types.QueryServiceResp{
Id: cacheNo,
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}
// 处理公司信息查询相关逻辑
func (l *QueryServiceLogic) ProcessCompanyInfoLogic(req *types.QueryServiceReq) (*types.QueryServiceResp, error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取用户信息失败, %+v", getUidErr)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
@@ -259,20 +314,32 @@ func (l *QueryServiceLogic) ProcessCompanyInfoLogic(req *types.QueryServiceReq)
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %v", err)
}
cacheNo, cacheDataErr := l.CacheData(params, "companyinfo", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
}
// 获取当前时间戳
now := time.Now().Unix()
return &types.QueryServiceResp{
Id: cacheNo,
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}
// 处理租赁信息查询相关逻辑
func (l *QueryServiceLogic) ProcessRentalInfoLogic(req *types.QueryServiceReq) (*types.QueryServiceResp, error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取用户信息失败, %+v", getUidErr)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
@@ -308,20 +375,32 @@ func (l *QueryServiceLogic) ProcessRentalInfoLogic(req *types.QueryServiceReq) (
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %v", err)
}
cacheNo, cacheDataErr := l.CacheData(params, "rentalinfo", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
}
// 获取当前时间戳
now := time.Now().Unix()
return &types.QueryServiceResp{
Id: cacheNo,
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}
// 处理贷前背景检查相关逻辑
func (l *QueryServiceLogic) ProcessPreLoanBackgroundCheckLogic(req *types.QueryServiceReq) (*types.QueryServiceResp, error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取用户信息失败, %+v", getUidErr)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
@@ -357,21 +436,32 @@ func (l *QueryServiceLogic) ProcessPreLoanBackgroundCheckLogic(req *types.QueryS
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %v", err)
}
cacheNo, cacheDataErr := l.CacheData(params, "preloanbackgroundcheck", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
}
// 获取当前时间戳
now := time.Now().Unix()
return &types.QueryServiceResp{
Id: cacheNo,
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}
// 处理人事背调相关逻辑
func (l *QueryServiceLogic) ProcessBackgroundCheckLogic(req *types.QueryServiceReq) (*types.QueryServiceResp, error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取用户信息失败, %+v", getUidErr)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
@@ -389,16 +479,16 @@ func (l *QueryServiceLogic) ProcessBackgroundCheckLogic(req *types.QueryServiceR
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
if verifyErr != nil {
return nil, verifyErr
}
//verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
//if verifyCodeErr != nil {
// return nil, verifyCodeErr
//}
//
//// 校验三要素
//verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
//if verifyErr != nil {
// return nil, verifyErr
//}
// 缓存
params := map[string]interface{}{
@@ -406,12 +496,28 @@ func (l *QueryServiceLogic) ProcessBackgroundCheckLogic(req *types.QueryServiceR
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %v", err)
}
cacheNo, cacheDataErr := l.CacheData(params, "backgroundcheck", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
}
// 获取当前时间戳
now := time.Now().Unix()
return &types.QueryServiceResp{
Id: cacheNo,
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}
func (l *QueryServiceLogic) ProcessTocMarriageLogic(req *types.QueryServiceReq) (*types.QueryServiceResp, error) {
@@ -652,7 +758,7 @@ func (l *QueryServiceLogic) ProcessTocPhoneThreeElementsLogic(req *types.QuerySe
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后失败: %+v", DecryptDataErr)
}
// 校验参数
@@ -1096,7 +1202,23 @@ func (l *QueryServiceLogic) VerifyCode(mobile string, code string) error {
// 二、三要素验证
func (l *QueryServiceLogic) Verify(Name string, IDCard string, Mobile string) error {
if l.svcCtx.Config.SystemConfig.ThreeVerify {
agent, ok := l.ctx.Value("agent").(bool)
if !ok {
agent = false
}
if !l.svcCtx.Config.SystemConfig.ThreeVerify || agent {
twoVerification := service.TwoFactorVerificationRequest{
Name: Name,
IDCard: IDCard,
}
verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "二要素验证失败: %v", err)
}
if !verification.Passed {
return errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "二要素验证不通过: %v", err)
}
} else {
// 三要素验证
threeVerification := service.ThreeFactorVerificationRequest{
Name: Name,
@@ -1105,22 +1227,10 @@ func (l *QueryServiceLogic) Verify(Name string, IDCard string, Mobile string) er
}
verification, err := l.svcCtx.VerificationService.ThreeFactorVerification(threeVerification)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "三要素验证失败: %+v", err)
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "三要素验证失败: %v", err)
}
if !verification.Passed {
return errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "三要素验证不通过: %+v", err)
}
} else {
twoVerification := service.TwoFactorVerificationRequest{
Name: Name,
IDCard: IDCard,
}
verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "二要素验证失败: %+v", err)
}
if !verification.Passed {
return errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "二要素验证不通过: %+v", err)
return errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "三要素验证不通过: %v", err)
}
}
return nil
@@ -1128,9 +1238,11 @@ func (l *QueryServiceLogic) Verify(Name string, IDCard string, Mobile string) er
// 缓存
func (l *QueryServiceLogic) CacheData(params map[string]interface{}, Product string, userID int64) (string, error) {
agentIdentifier, _ := l.ctx.Value("agentIdentifier").(string)
queryCache := types.QueryCacheLoad{
Params: params,
Product: Product,
Params: params,
Product: Product,
AgentIdentifier: agentIdentifier,
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
@@ -1144,3 +1256,51 @@ func (l *QueryServiceLogic) CacheData(params map[string]interface{}, Product str
}
return outTradeNo, nil
}
func (l *QueryServiceLogic) GetOrCreateUser(mobile string) (int64, error) {
agentIdentifier, ok := l.ctx.Value("agentIdentifier").(string)
if !ok || agentIdentifier == "" {
// 不是代理查询
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return 0, getUidErr
}
return userID, nil
}
userModel, err := l.svcCtx.UserModel.FindOneByMobile(l.ctx, mobile)
if err != nil && !errors.Is(err, model.ErrNotFound) {
return 0, err
}
// 没有则创建账号
if userModel == nil {
userModel = &model.User{Mobile: mobile}
if len(userModel.Nickname) == 0 {
userModel.Nickname = mobile
}
if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
insertResult, userInsertErr := l.svcCtx.UserModel.Insert(ctx, session, userModel)
if userInsertErr != nil {
return userInsertErr
}
lastId, lastInsertIdErr := insertResult.LastInsertId()
if lastInsertIdErr != nil {
return lastInsertIdErr
}
userModel.Id = lastId
userAuth := new(model.UserAuth)
userAuth.UserId = lastId
userAuth.AuthKey = mobile
userAuth.AuthType = model.UserAuthTypeAgentPromote
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(ctx, session, userAuth); userAuthInsertErr != nil {
return userAuthInsertErr
}
return nil
}); transErr != nil {
return 0, transErr
}
}
return userModel.Id, nil
}

View File

@@ -1,140 +0,0 @@
package query
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"time"
"tydata-server/app/user/cmd/api/internal/service"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"tydata-server/pkg/lzkit/validator"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type RentalInfoLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewRentalInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RentalInfoLogic {
return &RentalInfoLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *RentalInfoLogic) RentalInfo(req *types.QueryReq) (resp *types.QueryResp, err error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 获取用户信息失败, %+v", getUidErr)
}
// 1、AES解密
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 密钥获取失败: %+v", decodeErr)
}
decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key)
if aesDecryptErr != nil || len(decryptData) == 0 {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 解密失败: %+v", decodeErr)
}
// 2、校验
var data types.RentalInfoReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "租赁服务, 参数不正确: %+v", validatorErr)
}
if data.Name == "刘福思" && data.IDCard == "45262419980929047X" && data.Mobile == "17776203797" {
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: "rentalinfo",
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}
// 校验验证码
codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile)
cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey)
if err != nil {
if errors.Is(err, redis.Nil) {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "租赁服务, 验证码过期: %s", data.Mobile)
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "租赁服务, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err)
}
if cacheCode != data.Code {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "租赁服务, 验证码不正确: %s", data.Mobile)
}
// 3、二要素三要素核验
//twoVerification := service.TwoFactorVerificationRequest{
// Name: data.Name,
// IDCard: data.IDCard,
//}
//verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification)
//if err != nil {
// return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 二要素验证失败: %+v", err)
//}
//if !verification.Passed {
// return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "租赁服务, 二要素验证不通过: %+v", err)
//}
// 3、二要素三要素核验
threeVerification := service.ThreeFactorVerificationRequest{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
}
verification, err := l.svcCtx.VerificationService.ThreeFactorVerification(threeVerification)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 三要素验证失败: %+v", err)
}
if !verification.Passed {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "租赁服务, 三要素验证不通过: %+v", err)
}
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: "rentalinfo",
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "租赁服务, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}

View File

@@ -1,140 +0,0 @@
package query
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"time"
"tydata-server/app/user/cmd/api/internal/service"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"tydata-server/pkg/lzkit/validator"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type RiskAssessmentLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewRiskAssessmentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RiskAssessmentLogic {
return &RiskAssessmentLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *RiskAssessmentLogic) RiskAssessment(req *types.QueryReq) (resp *types.QueryResp, err error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 获取用户信息失败, %+v", getUidErr)
}
// 1、AES解密
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 密钥获取失败: %+v", decodeErr)
}
decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key)
if aesDecryptErr != nil || len(decryptData) == 0 {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 解密失败: %+v", decodeErr)
}
// 2、校验
var data types.RiskAssessmentReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "个人风险, 参数不正确: %+v", validatorErr)
}
if data.Name == "刘福思" && data.IDCard == "45262419980929047X" && data.Mobile == "17776203797" {
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: "riskassessment",
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "婚恋评估, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}
// 校验验证码
codeRedisKey := fmt.Sprintf("%s:%s", "query", data.Mobile)
cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey)
if err != nil {
if errors.Is(err, redis.Nil) {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "个人风险, 验证码过期: %s", data.Mobile)
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "个人风险, 读取验证码redis缓存失败, mobile: %s, err: %+v", data.Mobile, err)
}
if cacheCode != data.Code {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "个人风险, 验证码不正确: %s", data.Mobile)
}
// 3、二要素三要素核验
//twoVerification := service.TwoFactorVerificationRequest{
// Name: data.Name,
// IDCard: data.IDCard,
//}
//verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification)
//if err != nil {
// return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 二要素验证失败: %+v", err)
//}
//if !verification.Passed {
// return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "个人风险, 二要素验证不通过: %+v", err)
//}
// 3、二要素三要素核验
threeVerification := service.ThreeFactorVerificationRequest{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
}
verification, err := l.svcCtx.VerificationService.ThreeFactorVerification(threeVerification)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 三要素验证失败: %+v", err)
}
if !verification.Passed {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "个人风险, 三要素验证不通过: %+v", err)
}
// 缓存
queryCache := types.QueryCache{
Name: data.Name,
IDCard: data.IDCard,
Mobile: data.Mobile,
Product: "riskassessment",
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "个人风险, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return nil, cacheErr
}
return &types.QueryResp{Id: outTradeNo}, nil
}

View File

@@ -0,0 +1,91 @@
package user
import (
"context"
"fmt"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"time"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types"
"tydata-server/app/user/model"
jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr"
"github.com/zeromicro/go-zero/core/logx"
)
type AgentMobileCodeLoginLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAgentMobileCodeLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AgentMobileCodeLoginLogic {
return &AgentMobileCodeLoginLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AgentMobileCodeLoginLogic) AgentMobileCodeLogin(req *types.MobileCodeLoginReq) (resp *types.MobileCodeLoginResp, err error) {
// 检查手机号是否在一分钟内已发送过验证码
redisKey := fmt.Sprintf("%s:%s", "query", req.Mobile)
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
if err != nil {
if errors.Is(err, redis.Nil) {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "手机登录, 验证码过期: %s", req.Mobile)
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取验证码redis缓存失败, mobile: %s, err: %+v", req.Mobile, err)
}
if cacheCode != req.Code {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机登录, 验证码不正确: %s", req.Mobile)
}
user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, req.Mobile)
if findUserErr != nil && findUserErr != model.ErrNotFound {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取数据库获取用户失败, mobile: %s, err: %+v", req.Mobile, err)
}
if user == nil {
user = &model.User{Mobile: req.Mobile}
if len(user.Nickname) == 0 {
user.Nickname = req.Mobile
}
if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
insertResult, userInsertErr := l.svcCtx.UserModel.Insert(ctx, session, user)
if userInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 数据库插入新用户失败, mobile%s, err: %+v", req.Mobile, err)
}
lastId, lastInsertIdErr := insertResult.LastInsertId()
if lastInsertIdErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 获取新用户ID失败, err:%+v, user:%+v", lastInsertIdErr, user)
}
user.Id = lastId
userAuth := new(model.UserAuth)
userAuth.UserId = lastId
userAuth.AuthKey = req.Mobile
userAuth.AuthType = model.UserAuthTypeH5Mobile
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(ctx, session, userAuth); userAuthInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 数据库插入用户认证失败, err:%+v", userAuthInsertErr)
}
return nil
}); transErr != nil {
return nil, transErr
}
}
token, generaErr := jwtx.GenerateJwtToken(user.Id, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 生成token失败 : %d", user.Id)
}
// 获取当前时间戳
now := time.Now().Unix()
return &types.MobileCodeLoginResp{
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}

View File

@@ -29,16 +29,16 @@ func NewDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DetailLogi
func (l *DetailLogic) Detail() (resp *types.UserInfoResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, %v", err)
}
user, err := l.svcCtx.UserModel.FindOne(l.ctx, userID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "用户信息, 数据库查询用户信息失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "用户信息, 数据库查询用户信息失败, %v", err)
}
var userInfo types.User
err = copier.Copy(&userInfo, user)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 用户信息结构体复制失败, %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 用户信息结构体复制失败, %v", err)
}
return &types.UserInfoResp{
UserInfo: userInfo,

View File

@@ -31,7 +31,7 @@ func NewGetTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetToken
func (l *GetTokenLogic) GetToken() (resp *types.MobileCodeLoginResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, %+v", err)
return nil, errors.Wrapf(xerr.NewErrMsg(""), "用户信息, %v", err)
}
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
@@ -44,5 +44,4 @@ func (l *GetTokenLogic) GetToken() (resp *types.MobileCodeLoginResp, err error)
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}

View File

@@ -37,7 +37,7 @@ func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthRe
// Step 1: 使用code获取access_token
accessTokenResp, err := GetAccessToken(req.Code)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取access_token失败: %+v", err)
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取access_token失败: %v", err)
}
// Step 2: 查找用户授权信息

View File

@@ -7,6 +7,7 @@ import (
"fmt"
"github.com/hibiken/asynq"
"github.com/zeromicro/go-zero/core/logx"
"os"
"tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/model"
"tydata-server/pkg/lzkit/crypto"
@@ -37,7 +38,9 @@ func (l *PaySuccessNotifyUserHandler) ProcessTask(ctx context.Context, t *asynq.
if err != nil {
return fmt.Errorf("无效的订单ID: %d, %v", payload.OrderID, err)
}
if order.Status != "paid" {
//
env := os.Getenv("ENV")
if order.Status != "paid" && env != "development" {
err = fmt.Errorf("无效的订单: %d", payload.OrderID)
logx.Errorf("处理任务失败,原因: %v", err)
return asynq.SkipRetry
@@ -58,6 +61,7 @@ func (l *PaySuccessNotifyUserHandler) ProcessTask(ctx context.Context, t *asynq.
logx.Errorf("处理任务失败,原因: %v", err)
return asynq.SkipRetry
}
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
@@ -95,6 +99,11 @@ func (l *PaySuccessNotifyUserHandler) ProcessTask(ctx context.Context, t *asynq.
return l.handleError(ctx, updateQueryErr, order, query)
}
err = l.svcCtx.AgentService.AgentProcess(ctx, order)
if err != nil {
return l.handleError(ctx, err, order, query)
}
return nil
}

View File

@@ -0,0 +1,335 @@
package service
import (
"context"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"tydata-server/app/user/cmd/api/internal/config"
"tydata-server/app/user/model"
"tydata-server/pkg/lzkit/lzUtils"
)
type AgentService struct {
config config.Config
AgentModel model.AgentModel
AgentAuditModel model.AgentAuditModel
AgentClosureModel model.AgentClosureModel
AgentCommissionModel model.AgentCommissionModel
AgentCommissionDeductionModel model.AgentCommissionDeductionModel
AgentWalletModel model.AgentWalletModel
AgentLinkModel model.AgentLinkModel
AgentOrderModel model.AgentOrderModel
AgentRewardsModel model.AgentRewardsModel
AgentMembershipConfigModel model.AgentMembershipConfigModel
AgentMembershipRechargeOrderModel model.AgentMembershipRechargeOrderModel
AgentMembershipUserConfigModel model.AgentMembershipUserConfigModel
AgentProductConfigModel model.AgentProductConfigModel
AgentPlatformDeductionModel model.AgentPlatformDeductionModel
AgentActiveStatModel model.AgentActiveStatModel
AgentWithdrawalModel model.AgentWithdrawalModel
}
func NewAgentService(c config.Config, agentModel model.AgentModel, agentAuditModel model.AgentAuditModel,
agentClosureModel model.AgentClosureModel, agentCommissionModel model.AgentCommissionModel,
agentCommissionDeductionModel model.AgentCommissionDeductionModel, agentWalletModel model.AgentWalletModel, agentLinkModel model.AgentLinkModel, agentOrderModel model.AgentOrderModel, agentRewardsModel model.AgentRewardsModel,
agentMembershipConfigModel model.AgentMembershipConfigModel,
agentMembershipRechargeOrderModel model.AgentMembershipRechargeOrderModel,
agentMembershipUserConfigModel model.AgentMembershipUserConfigModel,
agentProductConfigModel model.AgentProductConfigModel, agentPlatformDeductionModel model.AgentPlatformDeductionModel,
agentActiveStatModel model.AgentActiveStatModel, agentWithdrawalModel model.AgentWithdrawalModel) *AgentService {
return &AgentService{
config: c,
AgentModel: agentModel,
AgentAuditModel: agentAuditModel,
AgentClosureModel: agentClosureModel,
AgentCommissionModel: agentCommissionModel,
AgentCommissionDeductionModel: agentCommissionDeductionModel,
AgentWalletModel: agentWalletModel,
AgentLinkModel: agentLinkModel,
AgentOrderModel: agentOrderModel,
AgentRewardsModel: agentRewardsModel,
AgentMembershipConfigModel: agentMembershipConfigModel,
AgentMembershipRechargeOrderModel: agentMembershipRechargeOrderModel,
AgentMembershipUserConfigModel: agentMembershipUserConfigModel,
AgentProductConfigModel: agentProductConfigModel,
AgentPlatformDeductionModel: agentPlatformDeductionModel,
AgentActiveStatModel: agentActiveStatModel,
AgentWithdrawalModel: agentWithdrawalModel,
}
}
// AgentProcess 推广单成功
func (l *AgentService) AgentProcess(ctx context.Context, order *model.Order) error {
// 获取是否该订单是代理推广订单
agentOrderModel, err := l.AgentOrderModel.FindOneByOrderId(ctx, order.Id)
if err != nil {
return err
}
// 事务
transErr := l.AgentWalletModel.Trans(ctx, func(transCtx context.Context, session sqlx.Session) error {
agentID := agentOrderModel.AgentId
agentProductConfigModel, findAgentProductConfigModelErr := l.AgentProductConfigModel.FindOneByProductId(transCtx, order.ProductId)
if findAgentProductConfigModelErr != nil {
return findAgentProductConfigModelErr
}
// 平台底价成本
PlatformCostAmount, platformCostErr := l.PlatformCost(transCtx, agentID, agentProductConfigModel, session)
if platformCostErr != nil {
return platformCostErr
}
// 平台提价成本
PlatformPricingAmount, platformPricingErr := l.PlatformPricing(transCtx, agentID, order.Amount, agentProductConfigModel, session)
if platformPricingErr != nil {
return platformPricingErr
}
// 查找上级
AgentClosureModel, findAgentClosureModelErr := l.AgentClosureModel.FindOneByDescendantIdDepth(transCtx, agentID, 1)
if findAgentClosureModelErr != nil && !errors.Is(findAgentClosureModelErr, model.ErrNotFound) {
return findAgentClosureModelErr
}
var descendantDeductedAmount = 0.00
if AgentClosureModel != nil {
AncestorId := AgentClosureModel.AncestorId
AncestorModel, findAgentModelErr := l.AgentModel.FindOne(transCtx, AncestorId)
if findAgentModelErr != nil != errors.Is(findAgentModelErr, model.ErrNotFound) {
return findAgentModelErr
}
if AgentClosureModel != nil {
AgentMembershipConfigModel, findAgentMembersipConfigModelErr := l.AgentMembershipConfigModel.FindOneByLevelName(ctx, AncestorModel.LevelName)
if findAgentMembersipConfigModelErr != nil {
return findAgentMembersipConfigModelErr
}
// 定价
commissionCost, commissionCostErr := l.CommissionCost(transCtx, agentID, AncestorId, AgentMembershipConfigModel, order.ProductId, session)
if commissionCostErr != nil {
return commissionCostErr
}
// 提价
commissionPricing, commissionPricingErr := l.CommissionPricing(transCtx, agentID, AncestorId, AgentMembershipConfigModel, order.ProductId, order.Amount, session)
if commissionPricingErr != nil {
return commissionPricingErr
}
// 上级克扣的成本
descendantDeductedAmount = commissionCost + commissionPricing
// 佣金
ancestorCommissionReward, ancestorCommissionErr := l.AncestorCommission(transCtx, agentID, AncestorId, session)
if ancestorCommissionErr != nil {
return ancestorCommissionErr
}
// 给上级成本以及佣金
ancestorCommissionAmount := commissionCost + commissionPricing + ancestorCommissionReward
ancestorWallet, findAgentWalletModelErr := l.AgentWalletModel.FindOneByAgentId(transCtx, AncestorId)
if findAgentWalletModelErr != nil {
return findAgentWalletModelErr
}
ancestorWallet.Balance += ancestorCommissionAmount
ancestorWallet.TotalEarnings += ancestorCommissionAmount
updateErr := l.AgentWalletModel.UpdateWithVersion(transCtx, session, ancestorWallet)
if updateErr != nil {
return updateErr
}
}
}
// 推广人扣除金额 = 平台成本价 + 平台提价成本 + 上级佣金
deductedAmount := PlatformCostAmount + PlatformPricingAmount + descendantDeductedAmount
agentCommissionErr := l.AgentCommission(transCtx, agentID, order, deductedAmount, session)
if agentCommissionErr != nil {
return agentCommissionErr
}
return nil
})
if transErr != nil {
return transErr
}
return nil
}
// AgentCommission 直推报告推广人佣金
func (l *AgentService) AgentCommission(ctx context.Context, agentID int64, order *model.Order, deductedAmount float64, session sqlx.Session) error {
agentWalletModel, findAgentWalletModelErr := l.AgentWalletModel.FindOneByAgentId(ctx, agentID)
if findAgentWalletModelErr != nil {
return findAgentWalletModelErr
}
// 推广人最终获得代理佣金
finalCommission := order.Amount - deductedAmount
agentWalletModel.Balance += finalCommission
agentWalletModel.TotalEarnings += finalCommission
agentCommission := model.AgentCommission{
AgentId: agentID,
OrderId: order.Id,
Amount: finalCommission,
ProductId: order.ProductId,
}
_, insertAgentCommissionErr := l.AgentCommissionModel.Insert(ctx, session, &agentCommission)
if insertAgentCommissionErr != nil {
return insertAgentCommissionErr
}
updateAgentWalletErr := l.AgentWalletModel.UpdateWithVersion(ctx, session, agentWalletModel)
if updateAgentWalletErr != nil {
return updateAgentWalletErr
}
return nil
}
// AncestorCommission 直推报告上级佣金(奖励型)
func (l *AgentService) AncestorCommission(ctx context.Context, descendantId int64, ancestorId int64, session sqlx.Session) (float64, error) {
agentModel, err := l.AgentModel.FindOneByUserId(ctx, ancestorId)
if err != nil {
return 0, err
}
agentMembershipConfigModel, err := l.AgentMembershipConfigModel.FindOneByLevelName(ctx, agentModel.LevelName)
if err != nil {
return 0, err
}
if agentMembershipConfigModel.ReportCommission.Valid {
reportCommissionAmount := agentMembershipConfigModel.ReportCommission.Float64
agentRewards := model.AgentRewards{
AgentId: ancestorId,
Amount: reportCommissionAmount,
RelationAgentId: lzUtils.Int64ToNullInt64(descendantId),
Type: model.AgentRewardsTypeDescendantPromotion,
}
_, agentRewardsModelInsetErr := l.AgentRewardsModel.Insert(ctx, session, &agentRewards)
if agentRewardsModelInsetErr != nil {
return 0, agentRewardsModelInsetErr
}
return reportCommissionAmount, nil
}
return 0, nil
}
// PlatformCost 平台底价成本
func (l *AgentService) PlatformCost(ctx context.Context, agentID int64, agentProductConfigModel *model.AgentProductConfig, session sqlx.Session) (float64, error) {
costAgentPlatformDeductionModel := model.AgentPlatformDeduction{
AgentId: agentID,
Amount: agentProductConfigModel.CostPrice,
Type: model.AgentDeductionTypeCost,
}
_, err := l.AgentPlatformDeductionModel.Insert(ctx, session, &costAgentPlatformDeductionModel)
if err != nil {
return 0, err
}
return agentProductConfigModel.CostPrice, nil
}
// PlatformPricing 平台提价成本
func (l *AgentService) PlatformPricing(ctx context.Context, agentID int64, pricing float64, agentProductConfigModel *model.AgentProductConfig, session sqlx.Session) (float64, error) {
// 2. 计算平台提价成本
if pricing > agentProductConfigModel.PricingStandard {
// 超出部分
overpricing := pricing - agentProductConfigModel.PricingStandard
// 收取成本
overpricingCost := overpricing * agentProductConfigModel.OverpricingRatio
pricingAgentPlatformDeductionModel := model.AgentPlatformDeduction{
AgentId: agentID,
Amount: overpricingCost,
Type: model.AgentDeductionTypePricing,
}
_, err := l.AgentPlatformDeductionModel.Insert(ctx, session, &pricingAgentPlatformDeductionModel)
if err != nil {
return 0, err
}
return overpricingCost, nil
}
return 0, nil
}
// CommissionCost 上级底价成本
func (l *AgentService) CommissionCost(ctx context.Context, descendantId int64, AncestorId int64, agentMembershipConfigModel *model.AgentMembershipConfig, productID int64, session sqlx.Session) (float64, error) {
if agentMembershipConfigModel.PriceIncreaseAmount.Valid {
// 拥有则查看该上级设定的成本
agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID)
if findAgentMembershipUserConfigModelErr != nil {
return 0, findAgentMembershipUserConfigModelErr
}
deductCostAmount := agentMembershipUserConfigModel.PriceIncreaseAmount
agentCommissionDeductionModel := model.AgentCommissionDeduction{
AgentId: AncestorId,
DeductedAgentId: descendantId,
Amount: deductCostAmount,
Type: model.AgentDeductionTypeCost,
ProductId: productID,
}
_, insertAgentCommissionDeductionModelErr := l.AgentCommissionDeductionModel.Insert(ctx, session, &agentCommissionDeductionModel)
if insertAgentCommissionDeductionModelErr != nil {
return 0, insertAgentCommissionDeductionModelErr
}
return deductCostAmount, nil
}
return 0, nil
}
// CommissionPricing 上级提价成本
func (l *AgentService) CommissionPricing(ctx context.Context, descendantId int64, AncestorId int64, agentMembershipConfigModel *model.AgentMembershipConfig, productID int64, pricing float64, session sqlx.Session) (float64, error) {
//看上级代理等级否有拥有定价标准收益功能
if agentMembershipConfigModel.PriceIncreaseMax.Valid && agentMembershipConfigModel.PriceRatio.Valid {
// 拥有则查看该上级设定的成本
agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID)
if findAgentMembershipUserConfigModelErr != nil {
return 0, findAgentMembershipUserConfigModelErr
}
// 计算是否在范围内
var pricingRange float64
if pricing > agentMembershipUserConfigModel.PriceRangeFrom {
if pricing > agentMembershipUserConfigModel.PriceRangeTo {
pricingRange = agentMembershipUserConfigModel.PriceRangeTo - agentMembershipUserConfigModel.PriceRangeFrom
} else {
pricingRange = pricing - agentMembershipUserConfigModel.PriceRangeFrom
}
}
deductCostAmount := pricingRange * agentMembershipUserConfigModel.PriceRatio
agentCommissionDeductionModel := model.AgentCommissionDeduction{
AgentId: AncestorId,
DeductedAgentId: descendantId,
Amount: deductCostAmount,
Type: model.AgentDeductionTypePricing,
ProductId: productID,
}
_, insertAgentCommissionDeductionModelErr := l.AgentCommissionDeductionModel.Insert(ctx, session, &agentCommissionDeductionModel)
if insertAgentCommissionDeductionModelErr != nil {
return 0, insertAgentCommissionDeductionModelErr
}
return deductCostAmount, nil
}
return 0, nil
}
//func (l *AgentService) UpgradeVip(ctx context.Context, agentID int64, leve string, session sqlx.Session) error {
// agentModel, err := l.AgentModel.FindOne(ctx, agentID)
// if err != nil {
// return err
// }
// if agentModel.LevelName != model.AgentLeveNameNormal {
// return fmt.Errorf("已经是会员")
// }
// return nil
//}

View File

@@ -24,11 +24,23 @@ func NewAliPayService(c config.Config) *AliPayService {
panic(fmt.Sprintf("创建支付宝客户端失败: %v", err))
}
// 加载支付宝公钥
err = client.LoadAliPayPublicKey(c.Alipay.AlipayPublicKey)
if err != nil {
panic(fmt.Sprintf("加载支付宝公钥失败: %v", err))
//// 加载支付宝公钥
//err = client.LoadAliPayPublicKey(c.Alipay.AlipayPublicKey)
//if err != nil {
// panic(fmt.Sprintf("加载支付宝公钥失败: %v", err))
//}
// 加载证书
if err = client.LoadAppCertPublicKeyFromFile(c.Alipay.AppCertPath); err != nil {
panic(fmt.Sprintf("加载应用公钥证书失败: %v", err))
}
if err = client.LoadAlipayCertPublicKeyFromFile(c.Alipay.AlipayCertPath); err != nil {
panic(fmt.Sprintf("加载支付宝公钥证书失败: %v", err))
}
if err = client.LoadAliPayRootCertFromFile(c.Alipay.AlipayRootCertPath); err != nil {
panic(fmt.Sprintf("加载根证书失败: %v", err))
}
return &AliPayService{
config: c.Alipay,
AlipayClient: client,
@@ -186,3 +198,62 @@ func (a *AliPayService) GenerateOutTradeNo() string {
return combined
}
// AliTransfer 支付宝单笔转账到支付宝账户(提现功能)
func (a *AliPayService) AliTransfer(
ctx context.Context,
payeeAccount string, // 收款方支付宝账户
payeeName string, // 收款方姓名
amount float64, // 转账金额
remark string, // 转账备注
outBizNo string, // 商户转账唯一订单号可使用GenerateOutTradeNo生成
) (*alipay.FundTransUniTransferRsp, error) {
// 参数校验
if payeeAccount == "" {
return nil, fmt.Errorf("收款账户不能为空")
}
if amount <= 0 {
return nil, fmt.Errorf("转账金额必须大于0")
}
// 构造转账请求
req := alipay.FundTransUniTransfer{
OutBizNo: outBizNo,
TransAmount: lzUtils.ToAlipayAmount(amount), // 金额格式转换
ProductCode: "TRANS_ACCOUNT_NO_PWD", // 单笔无密转账到支付宝账户
BizScene: "DIRECT_TRANSFER", // 单笔转账
OrderTitle: "账户提现", // 转账标题
Remark: remark,
PayeeInfo: &alipay.PayeeInfo{
Identity: payeeAccount,
IdentityType: "ALIPAY_LOGON_ID", // 根据账户类型选择:
Name: payeeName,
// ALIPAY_USER_ID/ALIPAY_LOGON_ID
},
}
// 执行转账请求
transferRsp, err := a.AlipayClient.FundTransUniTransfer(ctx, req)
if err != nil {
return nil, fmt.Errorf("支付宝转账请求失败: %v", err)
}
return transferRsp, nil
}
func (a *AliPayService) QueryTransferStatus(
ctx context.Context,
outBizNo string,
) (*alipay.FundTransOrderQueryRsp, error) {
req := alipay.FundTransOrderQuery{
OutBizNo: outBizNo,
}
response, err := a.AlipayClient.FundTransOrderQuery(ctx, req)
if err != nil {
return nil, fmt.Errorf("支付宝接口调用失败: %v", err)
}
// 处理响应
if response.Code.IsFailure() {
return nil, fmt.Errorf("支付宝返回错误: %s-%s", response.Code, response.Msg)
}
return response, nil
}

View File

@@ -158,7 +158,7 @@ func (a *ApiRequestService) ProcessRequests(params []byte, productID int64) ([]b
combinedResponse, err := json.Marshal(responseData)
if err != nil {
return nil, fmt.Errorf("响应数据转 JSON 失败: %+v", err)
return nil, fmt.Errorf("响应数据转 JSON 失败: %v", err)
}
return combinedResponse, nil
@@ -670,14 +670,14 @@ func (a *ApiRequestService) ProcessKZEYSRequest(params []byte) ([]byte, error) {
req, err := http.NewRequest(http.MethodPost, requestUrl, strings.NewReader(data.Encode()))
if err != nil {
return nil, fmt.Errorf("KZEYS 创建请求失败: %+v", err)
return nil, fmt.Errorf("KZEYS 创建请求失败: %v", err)
}
req.Header.Set("Authorization", "APPCODE "+appCode)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("KZEYS 请求失败: %+v", err)
return nil, fmt.Errorf("KZEYS 请求失败: %v", err)
}
defer resp.Body.Close()
@@ -725,7 +725,7 @@ func (a *ApiRequestService) ProcessP_C_B332Request(params []byte) ([]byte, error
}
resp, err := a.yushanService.request("P_C_B332", request)
if err != nil {
return nil, fmt.Errorf("人车核验查询失败: %+v", err)
return nil, fmt.Errorf("人车核验查询失败: %v", err)
}
return resp, nil
}
@@ -748,7 +748,7 @@ func (a *ApiRequestService) ProcessFIN019Request(params []byte) ([]byte, error)
}
resp, err := a.yushanService.request("FIN019", request)
if err != nil {
return nil, fmt.Errorf("银行卡黑名单查询失败: %+v", err)
return nil, fmt.Errorf("银行卡黑名单查询失败: %v", err)
}
return resp, nil
}
@@ -765,7 +765,7 @@ func (a *ApiRequestService) ProcessCAR061Request(params []byte) ([]byte, error)
}
resp, err := a.yushanService.request("CAR061", request)
if err != nil {
return nil, fmt.Errorf("名下车辆查询失败: %+v", err)
return nil, fmt.Errorf("名下车辆查询失败: %v", err)
}
return resp, nil
}

View File

@@ -77,14 +77,14 @@ func (r *VerificationService) TwoFactorVerification(request TwoFactorVerificatio
req, err := http.NewRequest(http.MethodPost, requestUrl, strings.NewReader(data.Encode()))
if err != nil {
return nil, fmt.Errorf("创建请求失败: %+v", err)
return nil, fmt.Errorf("创建请求失败: %v", err)
}
req.Header.Set("Authorization", "APPCODE "+appCode)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("请求失败: %+v", err)
return nil, fmt.Errorf("请求失败: %v", err)
}
defer resp.Body.Close()

View File

@@ -13,35 +13,54 @@ import (
)
type ServiceContext struct {
Config config.Config
Redis *redis.Redis
SourceInterceptor rest.Middleware
UserModel model.UserModel
UserAuthModel model.UserAuthModel
ProductModel model.ProductModel
FeatureModel model.FeatureModel
ProductFeatureModel model.ProductFeatureModel
OrderModel model.OrderModel
QueryModel model.QueryModel
GlobalNotificationsModel model.GlobalNotificationsModel
AlipayService *service.AliPayService
WechatPayService *service.WechatPayService
ApplePayService *service.ApplePayService
WestDexService *service.WestDexService
YushanService *service.YushanService
ApiRequestService *service.ApiRequestService
AsynqServer *asynq.Server // 服务端
AsynqService *service.AsynqService // 客户端
VerificationService *service.VerificationService
Config config.Config
Redis *redis.Redis
SourceInterceptor rest.Middleware
UserModel model.UserModel
UserAuthModel model.UserAuthModel
ProductModel model.ProductModel
FeatureModel model.FeatureModel
ProductFeatureModel model.ProductFeatureModel
OrderModel model.OrderModel
QueryModel model.QueryModel
AgentModel model.AgentModel
AgentAuditModel model.AgentAuditModel
AgentClosureModel model.AgentClosureModel
AgentCommissionModel model.AgentCommissionModel
AgentCommissionDeductionModel model.AgentCommissionDeductionModel
AgentWalletModel model.AgentWalletModel
AgentLinkModel model.AgentLinkModel
AgentOrderModel model.AgentOrderModel
AgentRewardsModel model.AgentRewardsModel
AgentMembershipConfigModel model.AgentMembershipConfigModel
AgentMembershipRechargeOrderModel model.AgentMembershipRechargeOrderModel
AgentMembershipUserConfigModel model.AgentMembershipUserConfigModel
AgentProductConfigModel model.AgentProductConfigModel
AgentPlatformDeductionModel model.AgentPlatformDeductionModel
AgentActiveStatModel model.AgentActiveStatModel
AgentWithdrawalModel model.AgentWithdrawalModel
GlobalNotificationsModel model.GlobalNotificationsModel
AlipayService *service.AliPayService
WechatPayService *service.WechatPayService
ApplePayService *service.ApplePayService
WestDexService *service.WestDexService
YushanService *service.YushanService
ApiRequestService *service.ApiRequestService
AsynqServer *asynq.Server // 服务端
AsynqService *service.AsynqService // 客户端
VerificationService *service.VerificationService
AgentService *service.AgentService
}
func NewServiceContext(c config.Config) *ServiceContext {
db := sqlx.NewMysql(c.DataSource)
redisConf := redis.RedisConf{
Host: c.CacheRedis[0].Host,
Pass: c.CacheRedis[0].Pass,
Type: c.CacheRedis[0].Type,
}
asynqServer := asynq.NewServer(
asynq.RedisClientOpt{Addr: c.CacheRedis[0].Host, Password: c.CacheRedis[0].Pass},
asynq.Config{
@@ -52,34 +71,87 @@ func NewServiceContext(c config.Config) *ServiceContext {
Concurrency: 10,
},
)
westDexService := service.NewWestDexService(c)
yushanService := service.NewYushanService(c)
productFeatureModel := model.NewProductFeatureModel(db, c.CacheRedis)
featureModel := model.NewFeatureModel(db, c.CacheRedis)
userAuthModel := model.NewUserAuthModel(db, c.CacheRedis)
userModel := model.NewUserModel(db, c.CacheRedis)
productModel := model.NewProductModel(db, c.CacheRedis)
orderModel := model.NewOrderModel(db, c.CacheRedis)
queryModel := model.NewQueryModel(db, c.CacheRedis)
globalNotificationsModel := model.NewGlobalNotificationsModel(db, c.CacheRedis)
agentModel := model.NewAgentModel(db, c.CacheRedis)
agentAuditModel := model.NewAgentAuditModel(db, c.CacheRedis)
agentCommissionModel := model.NewAgentCommissionModel(db, c.CacheRedis)
agentCommissionDeductionModel := model.NewAgentCommissionDeductionModel(db, c.CacheRedis)
agentWalletModel := model.NewAgentWalletModel(db, c.CacheRedis)
agentClosureModel := model.NewAgentClosureModel(db, c.CacheRedis)
agentLinkModel := model.NewAgentLinkModel(db, c.CacheRedis)
agentOrderModel := model.NewAgentOrderModel(db, c.CacheRedis)
agentRewardsModel := model.NewAgentRewardsModel(db, c.CacheRedis)
agentMembershipConfigModel := model.NewAgentMembershipConfigModel(db, c.CacheRedis)
agentMembershipRechargeOrderModel := model.NewAgentMembershipRechargeOrderModel(db, c.CacheRedis)
agentMembershipUserConfigModel := model.NewAgentMembershipUserConfigModel(db, c.CacheRedis)
agentProductConfigModel := model.NewAgentProductConfigModel(db, c.CacheRedis)
agentPlatformDeductionModel := model.NewAgentPlatformDeductionModel(db, c.CacheRedis)
agentActiveStatModel := model.NewAgentActiveStatModel(db, c.CacheRedis)
agentWithdrawalModel := model.NewAgentWithdrawalModel(db, c.CacheRedis)
alipayService := service.NewAliPayService(c)
wechatPayService := service.NewWechatPayService(c, userAuthModel)
applePayService := service.NewApplePayService(c)
verificationService := service.NewVerificationService(c, westDexService)
apiRequestService := service.NewApiRequestService(c, westDexService, yushanService, featureModel, productFeatureModel)
asynqService := service.NewAsynqService(c)
agentService := service.NewAgentService(c, agentModel, agentAuditModel, agentClosureModel, agentCommissionModel,
agentCommissionDeductionModel, agentWalletModel, agentLinkModel, agentOrderModel, agentRewardsModel,
agentMembershipConfigModel, agentMembershipRechargeOrderModel, agentMembershipUserConfigModel,
agentProductConfigModel, agentPlatformDeductionModel, agentActiveStatModel, agentWithdrawalModel)
return &ServiceContext{
Config: c,
Redis: redis.MustNewRedis(redisConf),
SourceInterceptor: middleware.NewSourceInterceptorMiddleware().Handle,
AlipayService: service.NewAliPayService(c),
WechatPayService: service.NewWechatPayService(c, userAuthModel),
ApplePayService: service.NewApplePayService(c),
WestDexService: westDexService,
YushanService: yushanService,
VerificationService: service.NewVerificationService(c, westDexService),
AsynqServer: asynqServer,
ApiRequestService: service.NewApiRequestService(c, westDexService, yushanService, featureModel, productFeatureModel),
AsynqService: service.NewAsynqService(c),
UserModel: model.NewUserModel(db, c.CacheRedis),
UserAuthModel: userAuthModel,
ProductModel: model.NewProductModel(db, c.CacheRedis),
OrderModel: model.NewOrderModel(db, c.CacheRedis),
QueryModel: model.NewQueryModel(db, c.CacheRedis),
GlobalNotificationsModel: model.NewGlobalNotificationsModel(db, c.CacheRedis),
FeatureModel: featureModel,
ProductFeatureModel: productFeatureModel,
Config: c,
Redis: redis.MustNewRedis(redisConf),
SourceInterceptor: middleware.NewSourceInterceptorMiddleware().Handle,
AlipayService: alipayService,
WechatPayService: wechatPayService,
ApplePayService: applePayService,
WestDexService: westDexService,
YushanService: yushanService,
VerificationService: verificationService,
AsynqServer: asynqServer,
ApiRequestService: apiRequestService,
AsynqService: asynqService,
AgentService: agentService,
UserModel: userModel,
UserAuthModel: userAuthModel,
ProductModel: productModel,
OrderModel: orderModel,
QueryModel: queryModel,
GlobalNotificationsModel: globalNotificationsModel,
FeatureModel: featureModel,
ProductFeatureModel: productFeatureModel,
AgentModel: agentModel,
AgentAuditModel: agentAuditModel,
AgentCommissionModel: agentCommissionModel,
AgentCommissionDeductionModel: agentCommissionDeductionModel,
AgentWalletModel: agentWalletModel,
AgentClosureModel: agentClosureModel,
AgentLinkModel: agentLinkModel,
AgentOrderModel: agentOrderModel,
AgentRewardsModel: agentRewardsModel,
AgentMembershipConfigModel: agentMembershipConfigModel,
AgentMembershipRechargeOrderModel: agentMembershipRechargeOrderModel,
AgentMembershipUserConfigModel: agentMembershipUserConfigModel,
AgentProductConfigModel: agentProductConfigModel,
AgentPlatformDeductionModel: agentPlatformDeductionModel,
AgentActiveStatModel: agentActiveStatModel,
AgentWithdrawalModel: agentWithdrawalModel,
}
}
func (s *ServiceContext) Close() {
if s.AsynqService != nil {
s.AsynqService.Close()

View File

@@ -7,6 +7,7 @@ type QueryCache struct {
Product string `json:"product_id"`
}
type QueryCacheLoad struct {
Product string `json:"product_en"`
Params map[string]interface{} `json:"params"`
Product string `json:"product_en"`
Params map[string]interface{} `json:"params"`
AgentIdentifier string `json:"agent_dentifier"`
}

View File

@@ -101,3 +101,13 @@ type TocPhoneSecondaryCard struct {
Mobile string `json:"mobile" validate:"required,mobile"`
StartDate string `json:"start_date" validate:"required"`
}
type AgentQueryData struct {
Mobile string `json:"mobile"`
Code string `json:"code"`
}
type AgentIdentifier struct {
Product string `json:"product"`
AgentID int64 `json:"agent_id"`
Price string `json:"price"`
}

View File

@@ -1,12 +1,156 @@
// Code generated by goctl. DO NOT EDIT.
package types
type ActiveReward struct {
TotalReward float64 `json:"total_reward"`
Today ActiveRewardData `json:"today"` // 今日数据
Last7D ActiveRewardData `json:"last7d"` // 近7天数据
Last30D ActiveRewardData `json:"last30d"` // 近30天数据
}
type ActiveRewardData struct {
NewActiveReward float64 `json:"active_reward"`
SubPromoteReward float64 `json:"sub_promote_reward"`
SubUpgradeReward float64 `json:"sub_upgrade_reward"`
SubWithdrawReward float64 `json:"sub_withdraw_reward"`
}
type AgentActivateMembershipReq struct {
Mobile string `json:"mobile"`
Type string `json:"type,oneof=VIP SVIP"` // 会员类型vip/svip
Amount float64 `json:"amount"`
PaymentMethod string `json:"payment_method"`
TransactionId string `json:"transaction_id"`
}
type AgentActivateMembershipResp struct {
MembershipType string `json:"membership_type"` // 最终开通的会员类型
ExpireTime string `json:"expire_time"` // 到期时间
}
type AgentApplyReq struct {
Region string `json:"region"`
Mobile string `json:"mobile"`
WechatID string `json:"wechat_id"`
Code string `json:"code"`
Ancestor string `json:"ancestor,optional"`
}
type AgentApplyResp struct {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
type AgentAuditStatusResp struct {
Status int64 `json:"status"` // 0=待审核1=审核通过2=审核未通过
AuditReason string `json:"audit_reason"`
}
type AgentGeneratingLinkReq struct {
Product string `json:"product"`
Price string `json:"price"`
}
type AgentGeneratingLinkResp struct {
LinkIdentifier string `json:"link_identifier"`
}
type AgentInfoResp struct {
Status int64 `json:"status"` // 0=待审核1=审核通过2=审核未通过3=未申请
IsAgent bool `json:"is_agent"`
AgentID int64 `json:"agent_id"`
Level string `json:"level"`
Region string `json:"region"`
Mobile string `json:"mobile"`
WechatID string `json:"wechat_id"`
}
type AgentMembershipProductConfigReq struct {
ProductID int64 `form:"product_id"`
}
type AgentMembershipProductConfigResp struct {
AgentMembershipUserConfig AgentMembershipUserConfig `json:"agent_membership_user_config"`
ProductConfig ProductConfig `json:"product_config"`
PriceIncreaseMax float64 `json:"price_increase_max"`
PriceIncreaseAmount float64 `json:"price_increase_amount"`
PriceRatio float64 `json:"price_ratio"`
}
type AgentMembershipUserConfig struct {
ProductID int64 `json:"product_id"`
PriceIncreaseAmount float64 `json:"price_increase_amount"`
PriceRangeFrom float64 `json:"price_range_from"`
PriceRangeTo float64 `json:"price_range_to"`
PriceRatio float64 `json:"price_ratio"`
}
type AgentProductConfig struct {
ProductID int64 `json:"product_id"`
CostPrice float64 `json:"cost_price"`
PriceRangeMin float64 `json:"price_range_min"`
PriceRangeMax float64 `json:"price_range_max"`
PPricingStandard float64 `json:"p_pricing_standard"`
POverpricingRatio float64 `json:"p_overpricing_ratio"`
APricingStandard float64 `json:"a_pricing_standard"`
APricingEnd float64 `json:"a_pricing_end"`
AOverpricingRatio float64 `json:"a_overpricing_ratio"`
}
type AgentProductConfigResp struct {
AgentProductConfig []AgentProductConfig
}
type Commission struct {
ProductName string `json:"product_name"`
Amount float64 `json:"amount"`
CreateTime string `json:"create_time"`
}
type DirectPushReport struct {
TotalCommission float64 `json:"total_commission"`
TotalReport int `json:"total_report"`
Today TimeRangeReport `json:"today"` // 近24小时数据
Last7D TimeRangeReport `json:"last7d"` // 近7天数据
Last30D TimeRangeReport `json:"last30d"` // 近30天数据
}
type Feature struct {
ID int64 `json:"id"` // 功能ID
ApiID string `json:"api_id"` // API标识
Name string `json:"name"` // 功能描述
}
type GetAgentRevenueInfoReq struct {
}
type GetAgentRevenueInfoResp struct {
Balance float64 `json:"balance"`
FrozenBalance float64 `json:"frozen_balance"`
TotalEarnings float64 `json:"total_earnings"`
DirectPush DirectPushReport `json:"direct_push"` // 直推报告数据
ActiveReward ActiveReward `json:"active_reward"` // 活跃下级奖励数据
}
type GetCommissionReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数据量
}
type GetCommissionResp struct {
Total int64 `json:"total"` // 总记录数
List []Commission `json:"list"` // 查询列表
}
type GetLinkDataReq struct {
LinkIdentifier string `form:"link_identifier"`
}
type GetLinkDataResp struct {
Product
}
type GetNotificationsResp struct {
Notifications []Notification `json:"notifications"` // 通知列表
Total int64 `json:"total"` // 总记录数
@@ -20,6 +164,26 @@ type GetProductByIDRequest struct {
Id int64 `path:"id"`
}
type GetRewardsReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数据量
}
type GetRewardsResp struct {
Total int64 `json:"total"` // 总记录数
List []Rewards `json:"list"` // 查询列表
}
type GetWithdrawalReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数据量
}
type GetWithdrawalResp struct {
Total int64 `json:"total"` // 总记录数
List []Withdrawal `json:"list"` // 查询列表
}
type IapCallbackReq struct {
OrderID int64 `json:"order_id" validate:"required"`
TransactionReceipt string `json:"transaction_receipt" validate:"required"`
@@ -77,6 +241,13 @@ type Product struct {
Features []Feature `json:"features"` // 关联功能列表
}
type ProductConfig struct {
ProductID int64 `json:"product_id"`
CostPrice float64 `json:"cost_price"`
PriceRangeMin float64 `json:"price_range_min"`
PriceRangeMax float64 `json:"price_range_max"`
}
type ProductResponse struct {
Product
}
@@ -167,12 +338,16 @@ type QueryRetryResp struct {
}
type QueryServiceReq struct {
Product string `path:"product"`
Data string `json:"data" validate:"required"`
Product string `path:"product"`
Data string `json:"data" validate:"required"`
AgentIdentifier string `json:"agent_identifier,optional"`
}
type QueryServiceResp struct {
Id string `json:"id"`
Id string `json:"id"`
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
type RegisterReq struct {
@@ -187,6 +362,25 @@ type RegisterResp struct {
RefreshAfter int64 `json:"refreshAfter"`
}
type Rewards struct {
Type string `json:"type"`
Amount float64 `json:"amount"`
CreateTime string `json:"create_time"`
}
type SaveAgentMembershipUserConfigReq struct {
ProductID int64 `json:"product_id"`
PriceIncreaseAmount float64 `json:"price_increase_amount"`
PriceRangeFrom float64 `json:"price_range_from"`
PriceRangeTo float64 `json:"price_range_to"`
PriceRatio float64 `json:"price_ratio"`
}
type TimeRangeReport struct {
Commission float64 `json:"commission"` // 佣金
Report int `json:"report"` // 报告量
}
type User struct {
Id int64 `json:"id"`
Mobile string `json:"mobile"`
@@ -219,7 +413,27 @@ type WXMiniAuthResp struct {
RefreshAfter int64 `json:"refreshAfter"`
}
type Withdrawal struct {
Status int64 `json:"status"`
Amount float64 `json:"amount"`
WithdrawalNo string `json:"withdrawal_no"`
Remark string `json:"remark"`
PayeeAccount string `json:"payee_account"`
CreateTime string `json:"create_time"`
}
type WithdrawalReq struct {
Amount float64 `json:"amount"` // 提现金额
PayeeAccount string `json:"payee_account"`
PayeeName string `json:"payee_name"`
}
type WithdrawalResp struct {
Status int64 `json:"status"` // 1申请中 2成功 3失败
FailMsg string `json:"fail_msg"`
}
type SendSmsReq struct {
Mobile string `json:"mobile" validate:"required,mobile"`
ActionType string `json:"actionType" validate:"required,oneof=login register query"`
ActionType string `json:"actionType" validate:"required,oneof=login register query agentApply"`
}