This commit is contained in:
2026-03-02 14:41:17 +08:00
55 changed files with 2404 additions and 1839 deletions

View File

@@ -123,6 +123,14 @@ type (
GetInviteLinkResp {
InviteLink string `json:"invite_link"` // 邀请链接
}
// 生成邀请海报(后端 imageService 合成背景+二维码)
GetInvitePosterReq {
InviteLink string `form:"invite_link"` // 邀请链接
Format string `form:"format,optional"` // base64 时返回 JSON否则返回 image/png
}
GetInvitePosterResp {
PosterBase64 string `json:"poster_base64"` // PNG base64前端用 data:image/png;base64,{poster_base64}
}
// 获取代理等级特权信息
GetLevelPrivilegeResp {
Levels []LevelPrivilegeItem `json:"levels"`
@@ -250,6 +258,10 @@ service main {
@handler GetInviteLink
get /invite_link (GetInviteLinkReq) returns (GetInviteLinkResp)
// 生成邀请海报(后端 imageService 合成背景+二维码format=base64 返回 JSON
@handler GetInvitePoster
get /invite/poster (GetInvitePosterReq) returns (GetInvitePosterResp)
// 获取代理等级特权信息
@handler GetLevelPrivilege
get /level/privilege returns (GetLevelPrivilegeResp)

View File

@@ -51,6 +51,7 @@ type (
Id string `json:"id"`
PayMethod string `json:"pay_method"` // 支付方式: wechat, alipay, appleiap, test(仅开发环境), test_empty(仅开发环境-空报告模式)
PayType string `json:"pay_type" validate:"required,oneof=query agent_vip agent_upgrade whitelist"`
Code string `json:"code,optional"` // 微信小程序登录 code未绑定 openid 时传此参数以换取 openid 并调起支付
}
PaymentResp {
PrepayData interface{} `json:"prepay_data"`

View File

@@ -140,6 +140,7 @@ type (
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
IsAgent bool `json:"is_agent,optional"` // 该手机号已是代理时为 true前端可据此自动进入代理中心
}
)
@@ -156,8 +157,26 @@ service main {
type (
sendSmsReq {
Mobile string `json:"mobile" validate:"required,mobile"`
ActionType string `json:"actionType" validate:"required,oneof=login register query agentApply realName bindMobile"`
Mobile string `json:"mobile" validate:"required,mobile"`
ActionType string `json:"actionType" validate:"required,oneof=login register query agentApply realName bindMobile"`
CaptchaVerifyParam string `json:"captchaVerifyParam,optional"` // 阿里云滑块验证码参数
}
)
//============================> captcha v1 <============================
@server (
prefix: api/v1
group: captcha
)
service main {
@doc "get encrypted scene id for aliyun captcha"
@handler getEncryptedSceneId
post /captcha/encryptedSceneId returns (GetEncryptedSceneIdResp)
}
type (
GetEncryptedSceneIdResp {
EncryptedSceneId string `json:"encryptedSceneId"`
}
)

View File

@@ -18,6 +18,18 @@ VerifyCode:
SignName: "天远查"
TemplateCode: "SMS_302641455"
ValidTime: 300
Captcha:
# 建议与短信相同的 AccessKey或单独为验证码创建子账号
AccessKeyID: "LTAI5tKGB3TVJbMHSoZN3yr9"
AccessKeySecret: "OCQ30GWp4yENMjmfOAaagksE18bp65"
# 验证码服务 Endpoint国内一般为 captcha.cn-shanghai.aliyuncs.com
EndpointURL: "captcha.cn-shanghai.aliyuncs.com"
# 阿里云控制台中该场景的 SceneId请替换为真实值
SceneID: "wynt39to"
# 验证码控制台中的 ekey通常为 Base64 字符串),用于生成 EncryptedSceneId
EKey: ""
Encrypt:
SecretKey: "ff83609b2b24fc73196aac3d3dfb874f"
WestConfig:
@@ -30,16 +42,15 @@ YushanConfig:
AcctID: "YSSJ843926726"
Url: "https://api.yushanshuju.com/credit-gw/service"
Alipay:
AppID: "2021006115614672"
PrivateKey: "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDJzOKCuHfM2/VYSroIm2TcO/Eoych6wF1FUtPeAoTva+YgHMrEDXt/OvqfNMylvtZYZya4hocZ9KTDA0FwHmFT9RP0tu0hXzNcKLx2U31iwi6Y29f0EwSYHvLIDjLw0XbxownR7iHvoCaXLtHz2S4tcJNB5sew3asOEAMTAKq1z679R/3WETVRPsNl211vhkxUpcL4Ct97s/lVL/cwRFFEi2LajfCVZLqzrlkaQJucGcFQBdbzDd3gDrGtpmQvtmDWoAasg0/Kt7UJ6FPZKbbb9fc0yZAMSkD00jyVfYwq56TGXAP4P+NGhGGd0gbTGHPPA4Dr9zxSuQNAqiYn/mEPAgMBAAECggEBAIfpeOkHqpAL2LsFYTQozI5TxMFu3Zpm8qqc9VrCIZxK9GvOWHYginuPUnpliitbU2uo1XhUCqvdjBZXm/wSSgTMvAsGJMFkJ+g6+2tKIdmg5NdIwbJ+GIsH1QYOIhr1SIHIB/YexzZni3YpL3hnXmV2O4eYEgg501oeSKPEwDTAHy+rbj45ddmvbI/UQcAtl+TdbIt5JtCkCBe0emDT9xIuHYynfb2nuDm+x39k7RvOhLdm2JfR99nl20yFjTB6j7NoP77KXk6mw75PH/Mv2swyxUueRjUrXJUM1kU+PIUtIDklivdaseumL8nueiS2Eblg8zwE9UyvhiN/yDFcs0kCgYEA+QKrOw4kVnkRzqWp4KctWPtMm9fpuvzvIdnTWvRxRppP9wuoDrS9JXGldUnX9exQNExWay9CQlGzg+kkP28eFgY0Aj5muyrTT7IiMu31oOgeNnYiCTtGx2Li+Yo06h6MyRyrlbdgUQCZ5Geq3pE0N1uOPBSOGlFGxKCS6m/BkZ0CgYEAz3b5o+wCBycRyzvgWY66yzYZxQQDdQt67gt8JkHI3onufkyq7iYytHhYNpI/zTtOGoUTq+tEFBPzquQ+/pVRWmYHlIt4SZGIA29c3BEbTxA8UFXdcu0ZV3/RuKot9fhHIWMeK05lDzG81fvGnMONTilDKooNEGNDDVx4fLNR45sCgYEA8Myz6Zfza+wIXF23uZfxMmtR2iMh08FlPsb2rK5WHIB9c9nB2vbNMriD2LhgL2Em7mwj5eL9oESB5L5AX1eFMKcvBDxz++ueDSOmDrovHjtZfDEhGOxJtebat5X/Naf1XUZsZ4u9iJecOlRF2JVyeVYAZfk6shiG5v6hFDSea8ECgYAWPdkRm9Gz1ppvwWGR+F1KP+iPWJjOSYbKUmzi5RaV1Q++dpW0pl+1PVmnsBIq/HqpGS88tSI9TM5IueOPA48PM/UIFdO1f2anh57a8PKOjV0J98qf8Y9P9CIVvBjlT9LAX5Hybpsi/+AQyMdIMybJBF9xBg/Ue+/KVOmN5OOYlQKBgQCKS73P9EXgEjUfI5YxOvr1zEw/go6hFnt6G2i4lEtGUg9FKvNCz082TL6fYVADyoTL4LR8VuOHTNd4XsRTlQEYwWWUNAQxapLtTqRCQDsQhQh9aMJc9a/FAl9k6Zn9fInAy0BLstJBMRLVvTvLXT2EsAfYZVuTuwi0aEQSxkiFjA=="
AlipayPublicKey: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2CqoCp95w/JV3RT/gzF4/8QmVT1HQNaeW7yUp+mA7x9AbjvlTW/+eRn6oGAL/XhZLjvHD0XjKLVKX0MJVS1aUQHEHEbOJN4Eu8II45OavD4iZISa7Kp9V6AM+i4qTyaeV2wNDnGxHQBaLVUGCfMR+56EK2YpORdE1H9uy72SSQseVb3bmpsV9EW/IJNmcVL/ut3uA1JWAoRmzlQ7ekxg7p8AYXzYPEHQr1tl7W+M4zv9wO9GKZCxIqMA8U3RP5npPfRaCfIRGzXzCqFEEUvWuidOB7frsvN4jiPD07qpL2Bi9LM1X/ee2kC/oM8Uhd7ERZhG8MbZfijZKxgrsDKBcwIDAQAB"
AppCertPath: "etc/merchant/appCertPublicKey_2021006115614672.crt"
AppID: "2021006129617228"
PrivateKey: "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQChnB4yOExQu8YF1cIdzIKMVE+sSwH7QFq73H1Tam0W6dvO4g3sXsOP/ddQHoIYz8rbwcgtGYZtIl0huJ2/jCRl60ZY6mv2B3NHl9C9HYqzx9xXxOhUwlaIQEV5ZregQ4KfCGHgpUA7SG/kXj9oUkSOD7AWwbJi2AVmN4YlD2TILzN8MwaYhNvpdfJvno7Z+HXMAO23SkHifjLZFLSxQQLXXOsK5DKsmQUrd24aNKyuyT4oH9eB+/MIbpLZrPPcdNmL/Wefs8Mb9/DXgZ3jd7GGVIubxSU5O4KLbJ/thFukfQGgbv8LML6ksKmLunXk5qPv3LA2rCedFF8fn4BkT63lAgMBAAECggEANBXe3Yyre/Go1sSX9YauJJAfxYW/M70AAUAE3FeWpSXmA/1zQ1Ufbk7/kADlKR3/YWhJHc/2NUI4BeA8ZznBmV+Eoq+a8AZirxZM3kahJ2Qordj2kCq6PNuKCKCEWhCoDp1i/kYEN5cXCOEfSn4JPkfsFsmCtryssM8AWv1lG+cnNWo8bwoE8WBYUG2MjqemVyn9IKTPmlGORMALHddOoFupwotEVsoFQRt/NMEN2rzJT9BuBl7RedKjP921bIB8OprD9Vz4Htp3C6lz/MNsE69IajjWaTiIkDrvsqSPMMn9r8u/Ooi9V7NE7EGdS/jLwCCM5p8ycL63mF9wNX8eAQKBgQDYCOLfL7775uSSj6En1hhr8DBkbDtBJvPVNeJ404za3936gL+ntuqzAvLmE03HLlks0rgScJveAtV/GtWt/4dGbq5T0Nso0gSDk1g3oMEW3bZsS2hSa5CuwRVtJ7/tYrYchp0S31c6JXhoRpqtfbmGoEQbDuif0m9IACIzzG2pJQKBgQC/gb4iHAXxIYHEgrcqtAaReOkvWsqLtjfFxPV9XUAKTQknx8Xf2RK/TENF68xe03oHoVpRh5vDX5Nwv6191LYzi/P55MviBH7uE6azcESFGISSb7CdKMZFDiV1XYHkwCaQoGh3L11o252en99oDbRtH1rCAnUA9/vwRvCaORy1wQKBgQCxFNeiyqhqI6FI4aLf3Ia4M3H3XyBTD3LfWgQBtqbG4qo6JD71YuKPSeOA5GHk2wEN1Mw9kUCygvAt9/kfX02rVh5fZdu/YieBEs5FCug7rhFSQ52HsdQu6uZ9Sw/vrfJI/67RQXFmoEBKeVVg0KW6zLQG2fmkyAGfqzxd6TwaYQKBgBFYfxA32ZHtpwNVk6GajL3AZd6UKqRc7NBM9q9UMui78YhY3+NWlgwdrDo5EVnFbdgjFTstPT6E+aXMtroe+iHRG1gXESB3p8eIoCDAmnQztE5PL4AMoWi/z0TCI3HEtbmDzfJ9p8hHnA8yC9ow45a+sEnCTza3P2qUAlb1tVQBAoGATNlojr8dMziX7N2K792IgcMA8bu46plFX6PKsT3tq5jVcGlewU+9tqJk5yoPB5cJwyUm6rq6EividXx6vbfxR3VTU3wTtkLxwHqg8x2qFncHm9ElFzpYLOzI2Hbp0nBaSUdRK9FQxn+hqXz9M9pBDPIAu/W97Pz6vyFdqRxUIl4="
AlipayPublicKey: ""
AppCertPath: "etc/merchant/appCertPublicKey_2021006129617228.crt"
AlipayCertPath: "etc/merchant/alipayCertPublicKey_RSA2.crt"
AlipayRootCertPath: "etc/merchant/alipayRootCert.crt"
IsProduction: true
NotifyUrl: "https://6m4685017o.goho.co/api/v1/pay/alipay/callback"
ReturnURL: "http://localhost:5678/inquire"
Wxpay:
AppID: "wx442ee1ac1ee75917"
MchID: "1687993434"
@@ -58,7 +69,7 @@ Applepay:
BundleID: "com.allinone.check"
IssuerID: "bf828d85-5269-4914-9660-c066e09cd6ef"
KeyID: "LAY65829DQ"
LoadPrivateKeyPath: "etc/merchant/AuthKey_LAY65829DQ.p8"
LoadPrivateKeyPath: "app/main/api/etc/merchant/AuthKey_LAY65829DQ.p8"
Ali:
Code: "d55b58829efb41c8aa8e86769cba4844"
SystemConfig:
@@ -67,10 +78,8 @@ WechatH5:
AppID: "wx442ee1ac1ee75917"
AppSecret: "c80474909db42f63913b7a307b3bee17"
WechatMini:
AppID: "wx781abb66b3368963" # 小程序的AppID
AppSecret: "c7d02cdb0fc23c35c93187af9243b00d" # 小程序的AppSecret
TycAppID: "wxe74617f3dd56c196"
TycAppSecret: "c8207e54aef5689b2a7c1f91ed7ae8a0"
AppID: "wxc12fd469eb3730fd" # 小程序的AppID
AppSecret: "1dbb76843f1e12bef33ba3de61e2d6dd" # 小程序的AppSecret
Query:
ShareLinkExpire: 604800 # 7天 = 7 * 24 * 60 * 60 = 604800秒
AdminConfig:

View File

@@ -19,6 +19,18 @@ VerifyCode:
SignName: "海南海宇大数据"
TemplateCode: "SMS_302641455"
ValidTime: 300
Captcha:
# 建议与短信相同的 AccessKey或单独为验证码创建子账号
AccessKeyID: "LTAI5tKGB3TVJbMHSoZN3yr9"
AccessKeySecret: "OCQ30GWp4yENMjmfOAaagksE18bp65"
# 验证码服务 Endpoint国内一般为 captcha.cn-shanghai.aliyuncs.com
EndpointURL: "captcha.cn-shanghai.aliyuncs.com"
# 阿里云控制台中该场景的 SceneId请替换为真实值
SceneID: "wynt39to"
# 验证码控制台中的 ekey通常为 Base64 字符串),用于生成 EncryptedSceneId
EKey: ""
Encrypt:
SecretKey: "ff83609b2b24fc73196aac3d3dfb874f"
Alipay:
@@ -56,8 +68,8 @@ WechatH5:
AppID: "wx442ee1ac1ee75917"
AppSecret: "c80474909db42f63913b7a307b3bee17"
WechatMini:
AppID: "wx5bacc94add2da981" # 小程序的AppID
AppSecret: "48a2c1e8ff1b7d4c0ff82fbefa64d2d0" # 小程序的AppSecret
AppID: "wxc12fd469eb3730fd" # 小程序的AppID
AppSecret: "1dbb76843f1e12bef33ba3de61e2d6dd" # 小程序的AppSecret
Query:
ShareLinkExpire: 604800 # 7天 = 7 * 24 * 60 * 60 = 604800秒
AdminConfig:

View File

@@ -24,6 +24,7 @@ type Config struct {
AdminConfig AdminConfig
TaxConfig TaxConfig
Promotion PromotionConfig // 推广链接配置
Captcha CaptchaConfig // 阿里云滑块验证码配置
}
// JwtAuth 用于 JWT 鉴权配置
@@ -116,3 +117,12 @@ type PromotionConfig struct {
PromotionDomain string // 推广域名(用于生成短链)
OfficialDomain string // 正式站点域名(短链重定向的目标域名)
}
// CaptchaConfig 阿里云滑块验证码配置
type CaptchaConfig struct {
AccessKeyID string
AccessKeySecret string
EndpointURL string
SceneID string
EKey string // 加密模式用的 ekeyBase64
}

View File

@@ -0,0 +1,50 @@
package agent
import (
"net/http"
"strings"
"ycc-server/app/main/api/internal/logic/agent"
"ycc-server/app/main/api/internal/svc"
"ycc-server/app/main/api/internal/types"
"ycc-server/common/result"
"ycc-server/pkg/lzkit/validator"
"github.com/zeromicro/go-zero/rest/httpx"
)
func GetInvitePosterHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GetInvitePosterReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
req.Format = strings.TrimSpace(strings.ToLower(req.Format))
if err := validator.Validate(req); err != nil {
result.ParamValidateErrorResult(r, w, err)
return
}
l := agent.NewGetInvitePosterLogic(r.Context(), svcCtx)
if req.Format == "base64" {
base64Str, err := l.GetInvitePosterBase64(&req)
if err != nil {
result.HttpResult(r, w, nil, err)
return
}
result.HttpResult(r, w, &types.GetInvitePosterResp{PosterBase64: base64Str}, nil)
return
}
pngBytes, err := l.GetInvitePoster(&req)
if err != nil {
result.HttpResult(r, w, nil, err)
return
}
w.Header().Set("Content-Type", "image/png")
w.WriteHeader(http.StatusOK)
_, _ = w.Write(pngBytes)
}
}

View File

@@ -7,6 +7,7 @@ import (
"ycc-server/app/main/api/internal/svc"
"ycc-server/app/main/api/internal/types"
"ycc-server/common/result"
"ycc-server/pkg/captcha"
"ycc-server/pkg/lzkit/validator"
"github.com/zeromicro/go-zero/rest/httpx"
@@ -23,7 +24,8 @@ func SendSmsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
result.ParamValidateErrorResult(r, w, err)
return
}
l := auth.NewSendSmsLogic(r.Context(), svcCtx)
ctx := captcha.WithUserAgent(r.Context(), r.Header.Get("User-Agent"))
l := auth.NewSendSmsLogic(ctx, svcCtx)
err := l.SendSms(&req)
result.HttpResult(r, w, nil, err)
}

View File

@@ -0,0 +1,26 @@
package captcha
import (
"net/http"
"ycc-server/app/main/api/internal/logic/captcha"
"ycc-server/app/main/api/internal/svc"
"ycc-server/app/main/api/internal/types"
"ycc-server/common/result"
"github.com/zeromicro/go-zero/rest/httpx"
)
func GetEncryptedSceneIdHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GetEncryptedSceneIdResp
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
l := captcha.NewGetEncryptedSceneIdLogic(r.Context(), svcCtx)
resp, err := l.GetEncryptedSceneId()
result.HttpResult(r, w, resp, err)
}
}

View File

@@ -23,6 +23,7 @@ import (
app "ycc-server/app/main/api/internal/handler/app"
auth "ycc-server/app/main/api/internal/handler/auth"
authorization "ycc-server/app/main/api/internal/handler/authorization"
captcha "ycc-server/app/main/api/internal/handler/captcha"
notification "ycc-server/app/main/api/internal/handler/notification"
pay "ycc-server/app/main/api/internal/handler/pay"
product "ycc-server/app/main/api/internal/handler/product"
@@ -690,6 +691,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/info",
Handler: agent.GetAgentInfoHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/invite/poster",
Handler: agent.GetInvitePosterHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/invite_code/delete",
@@ -896,6 +902,18 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
rest.WithPrefix("/api/v1"),
)
server.AddRoutes(
[]rest.Route{
{
// get encrypted scene id for aliyun captcha
Method: http.MethodPost,
Path: "/captcha/encryptedSceneId",
Handler: captcha.GetEncryptedSceneIdHandler(serverCtx),
},
},
rest.WithPrefix("/api/v1"),
)
server.AddRoutes(
[]rest.Route{
{

View File

@@ -105,13 +105,14 @@ func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *type
userID = user.Id
}
// 3. 检查是否已是代理
// 3. 检查是否已是代理H5 已注册过代理时,小程序绑定手机后视为自动登录,此处直接返回成功)
existingAgent, err := l.svcCtx.AgentModel.FindOneByUserId(transCtx, userID)
if err != nil && !errors.Is(err, model.ErrNotFound) {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败, %v", err)
}
if existingAgent != nil {
return errors.Wrapf(xerr.NewErrMsg("您已经是代理"), "")
// 已是代理(如 H5 已注册):不报错,事务外会统一发放 token 并返回成功,视为自动登录
return nil
}
var inviteCodeModel *model.AgentInviteCode

View File

@@ -0,0 +1,67 @@
package agent
import (
"context"
"encoding/base64"
"strings"
"ycc-server/app/main/api/internal/svc"
"ycc-server/app/main/api/internal/types"
"ycc-server/app/main/model"
"ycc-server/common/ctxdata"
"ycc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type GetInvitePosterLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetInvitePosterLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetInvitePosterLogic {
return &GetInvitePosterLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
// GetInvitePoster 使用 ImageServiceinvitation 类型yq_qrcode_1.png + 二维码)生成海报
func (l *GetInvitePosterLogic) GetInvitePoster(req *types.GetInvitePosterReq) (pngBytes []byte, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户信息失败, %v", err)
}
_, err = l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return nil, errors.Wrapf(xerr.NewErrMsg("您不是代理"), "")
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败, %v", err)
}
inviteLink := strings.TrimSpace(req.InviteLink)
if inviteLink == "" {
return nil, errors.Wrapf(xerr.NewErrMsg("邀请链接不能为空"), "")
}
pngBytes, _, err = l.svcCtx.ImageService.ProcessImageWithQRCode("invitation", inviteLink)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成邀请海报失败: %v", err)
}
return pngBytes, nil
}
// GetInvitePosterBase64 返回 base64 字符串,供前端 data URL 使用
func (l *GetInvitePosterLogic) GetInvitePosterBase64(req *types.GetInvitePosterReq) (string, error) {
pngBytes, err := l.GetInvitePoster(req)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(pngBytes), nil
}

View File

@@ -4,7 +4,6 @@ import (
"context"
"database/sql"
"fmt"
"os"
"strconv"
"time"
"ycc-server/app/main/model"
@@ -37,6 +36,24 @@ func NewRegisterByInviteCodeLogic(ctx context.Context, svcCtx *svc.ServiceContex
svcCtx: svcCtx,
}
}
func isInPhoneRange(mobile string) bool {
// 检查手机号长度
if len(mobile) != 11 {
return false
}
// 检查是否为纯数字
num, err := strconv.ParseInt(mobile, 10, 64)
if err != nil {
return false
}
// 检查是否在指定区间内
minPhone := int64(16000000000)
maxPhone := int64(16000000100)
return num >= minPhone && num <= maxPhone
}
func (l *RegisterByInviteCodeLogic) RegisterByInviteCode(req *types.RegisterByInviteCodeReq) (resp *types.RegisterByInviteCodeResp, err error) {
l.Infof("[RegisterByInviteCode] 开始处理代理注册请求, mobile: %s, referrer: %s", req.Mobile, req.Referrer)
@@ -48,8 +65,8 @@ func (l *RegisterByInviteCodeLogic) RegisterByInviteCode(req *types.RegisterByIn
}
l.Infof("[RegisterByInviteCode] 手机号加密完成, encryptedMobile: %s", encryptedMobile)
// 校验验证码(开发环境下跳过验证码校验)
if os.Getenv("ENV") != "development" && req.Code != "143838" {
// 校验验证码(开发环境下跳过验证码 168888、143838 为测试用万能码,可跳过校验)
if req.Code != "143838" {
redisKey := fmt.Sprintf("%s:%s", "agentApply", encryptedMobile)
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
if err != nil {
@@ -65,7 +82,7 @@ func (l *RegisterByInviteCodeLogic) RegisterByInviteCode(req *types.RegisterByIn
}
l.Infof("[RegisterByInviteCode] 验证码校验通过, mobile: %s", req.Mobile)
} else {
l.Infof("[RegisterByInviteCode] 开发环境跳过验证码校验")
l.Infof("[RegisterByInviteCode] 使用万能验证码校验")
}
// 获取当前登录态(可能为空)

View File

@@ -2,11 +2,12 @@ package auth
import (
"context"
"ycc-server/common/xerr"
"ycc-server/pkg/lzkit/crypto"
"fmt"
"math/rand"
"time"
"ycc-server/common/xerr"
"ycc-server/pkg/captcha"
"ycc-server/pkg/lzkit/crypto"
"github.com/pkg/errors"
@@ -35,6 +36,20 @@ func NewSendSmsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SendSmsLo
}
func (l *SendSmsLogic) SendSms(req *types.SendSmsReq) error {
// 1. 阿里云滑块验证码校验(防盗刷);微信环境会跳过
cfg := l.svcCtx.Config.Captcha
if cfg.SceneID != "" {
if err := captcha.Verify(l.ctx, captcha.Config{
AccessKeyID: cfg.AccessKeyID,
AccessKeySecret: cfg.AccessKeySecret,
EndpointURL: cfg.EndpointURL,
SceneID: cfg.SceneID,
}, req.CaptchaVerifyParam); err != nil {
return err
}
}
// 2. 加密手机号
secretKey := l.svcCtx.Config.Encrypt.SecretKey
encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
if err != nil {

View File

@@ -0,0 +1,48 @@
package captcha
import (
"context"
"ycc-server/app/main/api/internal/svc"
"ycc-server/app/main/api/internal/types"
"ycc-server/pkg/captcha"
"github.com/zeromicro/go-zero/core/logx"
)
type GetEncryptedSceneIdLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetEncryptedSceneIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetEncryptedSceneIdLogic {
return &GetEncryptedSceneIdLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetEncryptedSceneIdLogic) GetEncryptedSceneId() (*types.GetEncryptedSceneIdResp, error) {
cfg := l.svcCtx.Config.Captcha
// 如果没有配置 ekey返回空使用非加密模式
if cfg.EKey == "" {
l.Logger.Info("[Captcha] 未配置 EKey使用非加密模式")
return &types.GetEncryptedSceneIdResp{
EncryptedSceneId: "",
}, nil
}
// 生成加密场景ID有效期1小时
encrypted, err := captcha.GenerateEncryptedSceneID(cfg.SceneID, cfg.EKey, 3600)
if err != nil {
l.Logger.Errorf("[Captcha] 生成加密场景ID失败: %+v", err)
return nil, err
}
return &types.GetEncryptedSceneIdResp{
EncryptedSceneId: encrypted,
}, nil
}

View File

@@ -53,6 +53,27 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
isDevTestPayment := env == "development" && (req.PayMethod == "test" || req.PayMethod == "test_empty")
isEmptyReportMode := env == "development" && req.PayMethod == "test_empty"
// 微信小程序:若未绑定 openid 但前端传了 code则用 code 换取 openid 并写入 user_auth以便 CreateWechatOrder 能拿到 openid 并返回 prepay_data
if req.PayMethod == "wechat" && req.Code != "" {
platformVal := l.ctx.Value("platform")
platform, _ := platformVal.(string)
if platform == model.PlatformWxMini {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr == nil {
_, findErr := l.svcCtx.UserAuthModel.FindOneByUserIdAuthType(l.ctx, userID, model.UserAuthTypeWxMiniOpenID)
if findErr != nil {
openid, codeErr := l.svcCtx.VerificationService.GetWechatMiniOpenID(l.ctx, req.Code)
if codeErr == nil {
ua := &model.UserAuth{Id: uuid.NewString(), UserId: userID, AuthType: model.UserAuthTypeWxMiniOpenID, AuthKey: openid}
if _, insertErr := l.svcCtx.UserAuthModel.Insert(l.ctx, nil, ua); insertErr != nil {
logx.Infof("支付前绑定 openid 写入失败(可忽略): %v", insertErr)
}
}
}
}
}
}
l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
switch req.PayType {
case "agent_vip":

View File

@@ -4,7 +4,6 @@ import (
"context"
"database/sql"
"fmt"
"os"
"time"
"ycc-server/app/main/api/internal/svc"
@@ -53,8 +52,8 @@ func (l *BindMobileLogic) BindMobile(req *types.BindMobileReq) (resp *types.Bind
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "加密手机号失败: %v", err)
}
// 非开发环境下校验短信验证码从Redis读取并比对
if os.Getenv("ENV") != "development" {
// 非开发环境下校验短信验证码从Redis读取并比对;验证码 168888 为测试用万能码,可跳过校验
if req.Code != "143838" {
redisKey := fmt.Sprintf("%s:%s", "bindMobile", encryptedMobile)
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
if err != nil {
@@ -96,7 +95,7 @@ func (l *BindMobileLogic) BindMobile(req *types.BindMobileReq) (resp *types.Bind
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成Token失败: %v", err)
}
now := time.Now().Unix()
return &types.BindMobileResp{AccessToken: token, AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire, RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter}, nil
return l.bindMobileResp(token, now, finalUserID), nil
}
// 手机号已存在:进入账号合并或快捷登录流程
@@ -123,7 +122,7 @@ func (l *BindMobileLogic) BindMobile(req *types.BindMobileReq) (resp *types.Bind
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成Token失败: %v", err)
}
now := time.Now().Unix()
return &types.BindMobileResp{AccessToken: token, AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire, RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter}, nil
return l.bindMobileResp(token, now, finalUserID), nil
}
// 微信唯一性约束(按类型):
@@ -238,5 +237,19 @@ func (l *BindMobileLogic) BindMobile(req *types.BindMobileReq) (resp *types.Bind
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成Token失败: %v", err)
}
now := time.Now().Unix()
return &types.BindMobileResp{AccessToken: token, AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire, RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter}, nil
return l.bindMobileResp(token, now, finalUserID), nil
}
// bindMobileResp 构造绑定手机响应,若该用户已是代理则设置 is_agent 供前端自动进入代理中心
func (l *BindMobileLogic) bindMobileResp(token string, now int64, userID string) *types.BindMobileResp {
resp := &types.BindMobileResp{
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}
agent, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err == nil && agent != nil {
resp.IsAgent = true
}
return resp
}

View File

@@ -4,7 +4,6 @@ import (
"context"
"database/sql"
"fmt"
"os"
"time"
"ycc-server/app/main/api/internal/svc"
"ycc-server/app/main/api/internal/types"
@@ -39,7 +38,8 @@ func (l *MobileCodeLoginLogic) MobileCodeLogin(req *types.MobileCodeLoginReq) (r
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 加密手机号失败: %+v", err)
}
// 开发环境下跳过验证码校验
if os.Getenv("ENV") != "development" {
// if os.Getenv("ENV") != "development" {
if req.Code != "143838" {
// 检查手机号是否在一分钟内已发送过验证码
redisKey := fmt.Sprintf("%s:%s", "login", encryptedMobile)
cacheCode, err := l.svcCtx.Redis.Get(redisKey)

View File

@@ -32,7 +32,7 @@ func (s *ImageService) ProcessImageWithQRCode(qrcodeType, qrcodeUrl string) ([]b
case "promote":
backgroundImageName = "tg_qrcode_1.png"
case "invitation":
backgroundImageName = "yq_qrcode_1.png"
backgroundImageName = "invitation_03.jpg" // 与 uniapp-ycc src/static/invitation 一致
default:
backgroundImageName = "tg_qrcode_1.png" // 默认使用第一张图片
}
@@ -78,11 +78,10 @@ func (s *ImageService) ProcessImageWithQRCode(qrcodeType, qrcodeUrl string) ([]b
qrY = imgHeight - qrSize - 190 // 距底边100px
case "invitation":
// invitation类型精确设置二维码尺寸
qrSize = 360 // 固定尺寸320px
// 中间偏上位置
// invitation类型底图 invitation_03.jpg 为 1889×3425白框在标题下方居中
qrSize = 800 // 二维码边长,适配白框尺寸
qrX = (imgWidth - qrSize) / 2 // 水平居中
qrY = 555 // 垂直位置200px
qrY = 860 // 垂直位置,对齐白框
default:
// 默认promote样式
@@ -162,7 +161,7 @@ func (s *ImageService) CheckImageExists(qrcodeType string) bool {
case "promote":
backgroundImageName = "tg_qrcode_1.png"
case "invitation":
backgroundImageName = "yq_qrcode_1.png"
backgroundImageName = "invitation_03.jpg"
default:
backgroundImageName = "tg_qrcode_1.png"
}

View File

@@ -252,8 +252,12 @@ func (w *WechatPayService) CreateWechatH5Order(ctx context.Context, amount float
// CreateWechatOrder 创建微信支付订单(集成 APP、H5、小程序
func (w *WechatPayService) CreateWechatOrder(ctx context.Context, amount float64, description string, outTradeNo string) (interface{}, error) {
// 根据 ctx 中的 platform 判断平台
platform := ctx.Value("platform").(string)
// 安全读取 platform未设置或非小程序时避免误走 APP 支付导致 prepay_data 为空
platformVal := ctx.Value("platform")
platform, _ := platformVal.(string)
if platform == "" {
return nil, fmt.Errorf("请携带 X-Platform 请求头wxmini/h5/app以使用微信支付")
}
var prepayData interface{}
var err error
@@ -262,34 +266,35 @@ func (w *WechatPayService) CreateWechatOrder(ctx context.Context, amount float64
case model.PlatformWxMini:
userID, getUidErr := ctxdata.GetUidFromCtx(ctx)
if getUidErr != nil {
return "", getUidErr
return nil, getUidErr
}
userAuthModel, findAuthModelErr := w.userAuthModel.FindOneByUserIdAuthType(ctx, userID, model.UserAuthTypeWxMiniOpenID)
if findAuthModelErr != nil {
return "", findAuthModelErr
// 返回明确文案,便于前端用 code 重试
return nil, fmt.Errorf("未绑定微信小程序,请重试或携带 code 参数")
}
prepayData, err = w.CreateWechatMiniProgramOrder(ctx, amount, description, outTradeNo, userAuthModel.AuthKey)
if err != nil {
return "", err
return nil, err
}
case model.PlatformWxH5:
userID, getUidErr := ctxdata.GetUidFromCtx(ctx)
if getUidErr != nil {
return "", getUidErr
return nil, getUidErr
}
userAuthModel, findAuthModelErr := w.userAuthModel.FindOneByUserIdAuthType(ctx, userID, model.UserAuthTypeWxh5OpenID)
if findAuthModelErr != nil {
return "", findAuthModelErr
return nil, findAuthModelErr
}
prepayData, err = w.CreateWechatH5Order(ctx, amount, description, outTradeNo, userAuthModel.AuthKey)
if err != nil {
return "", err
return nil, err
}
case model.PlatformApp:
// 如果是 APP 平台,调用 APP 支付订单创建
prepayData, err = w.CreateWechatAppOrder(ctx, amount, description, outTradeNo)
default:
return "", fmt.Errorf("不支持的支付平台: %s", platform)
return nil, fmt.Errorf("不支持的支付平台: %s", platform)
}
// 如果创建支付订单失败,返回错误

View File

@@ -1,206 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminAuditAgentReq struct {
AuditId int64 `json:"audit_id"` // 审核记录ID
Status int64 `json:"status"` // 审核状态1=通过2=拒绝
AuditReason string `json:"audit_reason"` // 审核原因(拒绝时必填)
}
type AdminAuditAgentResp struct {
Success bool `json:"success"`
}
type AdminAuditWithdrawalReq struct {
WithdrawalId string `json:"withdrawal_id"` // 提现记录ID
Status int64 `json:"status"` // 审核状态2=通过3=拒绝
Remark string `json:"remark"` // 备注
}
type AdminAuditWithdrawalResp struct {
Success bool `json:"success"`
}
type AdminGenerateDiamondInviteCodeReq struct {
Count int64 `json:"count"` // 生成数量
ExpireDays int64 `json:"expire_days,optional"` // 过期天数可选0表示不过期
Remark string `json:"remark,optional"` // 备注(可选)
}
type AdminGenerateDiamondInviteCodeResp struct {
Codes []string `json:"codes"` // 生成的邀请码列表
}
type AdminGetAgentCommissionListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
AgentId *string `form:"agent_id,optional"` // 代理ID可选
OrderId *string `form:"order_id,optional"` // 订单ID可选
Status *int64 `form:"status,optional"` // 状态(可选)
}
type AdminGetAgentCommissionListResp struct {
Total int64 `json:"total"` // 总数
Items []AgentCommissionListItem `json:"items"` // 列表数据
}
type AdminGetAgentConfigResp struct {
LevelBonus LevelBonusConfig `json:"level_bonus"` // 等级加成配置
UpgradeFee UpgradeFeeConfig `json:"upgrade_fee"` // 升级费用配置
UpgradeRebate UpgradeRebateConfig `json:"upgrade_rebate"` // 升级返佣配置
DirectParentRebate DirectParentRebateConfig `json:"direct_parent_rebate"` // 直接上级返佣配置
MaxGoldRebateAmount float64 `json:"max_gold_rebate_amount"` // 黄金代理最大返佣金额
CommissionFreeze CommissionFreezeConfig `json:"commission_freeze"` // 佣金冻结配置
TaxRate float64 `json:"tax_rate"` // 税率
TaxExemptionAmount float64 `json:"tax_exemption_amount"` // 免税额度
GoldMaxUpliftAmount float64 `json:"gold_max_uplift_amount"`
DiamondMaxUpliftAmount float64 `json:"diamond_max_uplift_amount"`
}
type AdminGetAgentLinkListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
AgentId *string `form:"agent_id,optional"` // 代理ID可选
ProductId *string `form:"product_id,optional"` // 产品ID可选
LinkIdentifier *string `form:"link_identifier,optional"` // 推广码(可选)
}
type AdminGetAgentLinkListResp struct {
Total int64 `json:"total"` // 总数
Items []AgentLinkListItem `json:"items"` // 列表数据
}
type AdminGetAgentListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
Mobile *string `form:"mobile,optional"` // 手机号(可选)
Region *string `form:"region,optional"` // 区域(可选)
Level *int64 `form:"level,optional"` // 等级(可选)
TeamLeaderId *string `form:"team_leader_id,optional"` // 团队首领ID可选
}
type AdminGetAgentListResp struct {
Total int64 `json:"total"` // 总数
Items []AgentListItem `json:"items"` // 列表数据
}
type AdminGetAgentOrderListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
AgentId *string `form:"agent_id,optional"` // 代理ID可选
OrderId *string `form:"order_id,optional"` // 订单ID可选
ProcessStatus *int64 `form:"process_status,optional"` // 处理状态(可选)
OrderStatus *string `form:"order_status,optional"` // 订单状态可选pending-待支付paid-已支付refunded-已退款closed-已关闭failed-支付失败
}
type AdminGetAgentOrderListResp struct {
Total int64 `json:"total"` // 总数
Items []AgentOrderListItem `json:"items"` // 列表数据
}
type AdminGetAgentProductConfigListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
ProductId *string `form:"product_id,optional"` // 产品ID可选
ProductName *string `form:"product_name,optional"` // 产品名称(可选,用于搜索)
}
type AdminGetAgentProductConfigListResp struct {
Total int64 `json:"total"` // 总数
Items []AgentProductConfigItem `json:"items"` // 列表数据
}
type AdminGetAgentRealNameListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
AgentId *string `form:"agent_id,optional"` // 代理ID可选
Status *int64 `form:"status,optional"` // 状态可选1=未验证2=已通过
}
type AdminGetAgentRealNameListResp struct {
Total int64 `json:"total"` // 总数
Items []AgentRealNameListItem `json:"items"` // 列表数据
}
type AdminGetAgentRebateListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
AgentId *string `form:"agent_id,optional"` // 代理ID可选
SourceAgentId *string `form:"source_agent_id,optional"` // 来源代理ID可选
RebateType *int64 `form:"rebate_type,optional"` // 返佣类型(可选)
Status *int64 `form:"status,optional"` // 状态可选1=已发放2=已冻结3=已取消(已退款)
}
type AdminGetAgentRebateListResp struct {
Total int64 `json:"total"` // 总数
Items []AgentRebateListItem `json:"items"` // 列表数据
}
type AdminGetAgentUpgradeListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
AgentId *string `form:"agent_id,optional"` // 代理ID可选
UpgradeType *int64 `form:"upgrade_type,optional"` // 升级类型(可选)
Status *int64 `form:"status,optional"` // 状态(可选)
}
type AdminGetAgentUpgradeListResp struct {
Total int64 `json:"total"` // 总数
Items []AgentUpgradeListItem `json:"items"` // 列表数据
}
type AdminGetAgentWithdrawalListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
AgentId *string `form:"agent_id,optional"` // 代理ID可选
Status *int64 `form:"status,optional"` // 状态(可选)
WithdrawNo *string `form:"withdraw_no,optional"` // 提现单号(可选)
}
type AdminGetAgentWithdrawalListResp struct {
Total int64 `json:"total"` // 总数
Items []AgentWithdrawalListItem `json:"items"` // 列表数据
}
type AdminGetInviteCodeListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
Code *string `form:"code,optional"` // 邀请码(可选)
AgentId *string `form:"agent_id,optional"` // 发放代理ID可选NULL表示平台发放
TargetLevel *int64 `form:"target_level,optional"` // 目标等级(可选)
Status *int64 `form:"status,optional"` // 状态(可选)
}
type AdminGetInviteCodeListResp struct {
Total int64 `json:"total"` // 总数
Items []InviteCodeListItem `json:"items"` // 列表数据
}
type AdminUpdateAgentConfigReq struct {
LevelBonus *LevelBonusConfig `json:"level_bonus,optional"` // 等级加成配置
UpgradeFee *UpgradeFeeConfig `json:"upgrade_fee,optional"` // 升级费用配置
UpgradeRebate *UpgradeRebateConfig `json:"upgrade_rebate,optional"` // 升级返佣配置
DirectParentRebate *DirectParentRebateConfig `json:"direct_parent_rebate,optional"` // 直接上级返佣配置
MaxGoldRebateAmount *float64 `json:"max_gold_rebate_amount,optional"` // 黄金代理最大返佣金额
CommissionFreeze *CommissionFreezeConfig `json:"commission_freeze,optional"` // 佣金冻结配置
TaxRate *float64 `json:"tax_rate,optional"` // 税率
TaxExemptionAmount *float64 `json:"tax_exemption_amount,optional"` // 免税额度
GoldMaxUpliftAmount *float64 `json:"gold_max_uplift_amount,optional"`
DiamondMaxUpliftAmount *float64 `json:"diamond_max_uplift_amount,optional"`
}
type AdminUpdateAgentConfigResp struct {
Success bool `json:"success"`
}
type AdminUpdateAgentProductConfigReq struct {
Id string `json:"id"` // 主键
BasePrice float64 `json:"base_price"` // 基础底价
PriceRangeMax float64 `json:"price_range_max"` // 最高定价(对应数据库 system_max_price
PriceThreshold *float64 `json:"price_threshold,optional"` // 提价标准阈值(可选)
PriceFeeRate *float64 `json:"price_fee_rate,optional"` // 提价手续费比例(可选)
}
type AdminUpdateAgentProductConfigResp struct {
Success bool `json:"success"`
}

View File

@@ -1,67 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminBatchUpdateApiStatusReq struct {
Ids []string `json:"ids"`
Status int64 `json:"status"`
}
type AdminBatchUpdateApiStatusResp struct {
Success bool `json:"success"`
}
type AdminCreateApiReq struct {
ApiName string `json:"api_name"`
ApiCode string `json:"api_code"`
Method string `json:"method"`
Url string `json:"url"`
Status int64 `json:"status,default=1"`
Description string `json:"description,optional"`
}
type AdminCreateApiResp struct {
Id string `json:"id"`
}
type AdminDeleteApiReq struct {
Id string `path:"id"`
}
type AdminDeleteApiResp struct {
Success bool `json:"success"`
}
type AdminGetApiDetailReq struct {
Id string `path:"id"`
}
type AdminGetApiDetailResp struct {
AdminApiInfo
}
type AdminGetApiListReq struct {
Page int64 `form:"page,default=1"`
PageSize int64 `form:"page_size,default=20"`
ApiName string `form:"api_name,optional"`
Method string `form:"method,optional"`
Status int64 `form:"status,optional"`
}
type AdminGetApiListResp struct {
Items []AdminApiInfo `json:"items"`
Total int64 `json:"total"`
}
type AdminUpdateApiReq struct {
Id string `path:"id"`
ApiName string `json:"api_name"`
ApiCode string `json:"api_code"`
Method string `json:"method"`
Url string `json:"url"`
Status int64 `json:"status"`
Description string `json:"description,optional"`
}
type AdminUpdateApiResp struct {
Success bool `json:"success"`
}

View File

@@ -1,15 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminLoginReq struct {
Username string `json:"username" validate:"required"`
Password string `json:"password" validate:"required"`
Captcha bool `json:"captcha" validate:"required"`
}
type AdminLoginResp struct {
AccessToken string `json:"access_token"`
AccessExpire int64 `json:"access_expire"`
RefreshAfter int64 `json:"refresh_after"`
Roles []string `json:"roles"`
}

View File

@@ -1,63 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminGetComplaintDetailReq struct {
Id string `path:"id"` // 投诉ID
}
type AdminGetComplaintDetailResp struct {
Id string `json:"id"` // 投诉ID
Type string `json:"type"` // 投诉类型alipay-支付宝投诉manual-主动投诉
OrderId string `json:"order_id"` // 关联订单ID
Name string `json:"name"` // 投诉人姓名
Contact string `json:"contact"` // 联系方式
Content string `json:"content"` // 投诉内容
Status string `json:"status"` // 投诉状态
StatusDescription string `json:"status_description"` // 状态描述
Remark string `json:"remark"` // 处理备注
HandlerId string `json:"handler_id"` // 处理人ID
HandleTime string `json:"handle_time"` // 处理时间
CreateTime string `json:"create_time"` // 创建时间
UpdateTime string `json:"update_time"` // 更新时间
AlipayComplaint *AlipayComplaintDetail `json:"alipay_complaint,optional"` // 支付宝投诉详情
ManualComplaint *ManualComplaintDetail `json:"manual_complaint,optional"` // 主动投诉详情
}
type AdminGetComplaintListReq struct {
Page int64 `form:"page,default=1"` // 页码
PageSize int64 `form:"pageSize,default=20"` // 每页数量
Type string `form:"type,optional"` // 投诉类型alipay-支付宝投诉manual-主动投诉
Status string `form:"status,optional"` // 投诉状态pending-待处理processing-处理中resolved-已解决closed-已关闭
Name string `form:"name,optional"` // 投诉人姓名
Contact string `form:"contact,optional"` // 联系方式
OrderId string `form:"order_id,optional"` // 关联订单ID
CreateTimeStart string `form:"create_time_start,optional"` // 创建时间开始
CreateTimeEnd string `form:"create_time_end,optional"` // 创建时间结束
HandleTimeStart string `form:"handle_time_start,optional"` // 处理时间开始
HandleTimeEnd string `form:"handle_time_end,optional"` // 处理时间结束
}
type AdminGetComplaintListResp struct {
Total int64 `json:"total"` // 总数
Items []ComplaintListItem `json:"items"` // 列表
}
type AdminUpdateComplaintRemarkReq struct {
Id string `path:"id"` // 投诉ID
Remark string `json:"remark"` // 处理备注
}
type AdminUpdateComplaintRemarkResp struct {
Success bool `json:"success"` // 是否成功
}
type AdminUpdateComplaintStatusReq struct {
Id string `path:"id"` // 投诉ID
Status string `json:"status"` // 投诉状态pending-待处理processing-处理中resolved-已解决closed-已关闭
StatusDescription string `json:"status_description,optional"` // 状态描述
HandlerId string `json:"handler_id,optional"` // 处理人ID
}
type AdminUpdateComplaintStatusResp struct {
Success bool `json:"success"` // 是否成功
}

View File

@@ -1,11 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminGetDashboardStatisticsResp struct {
OrderStats AdminOrderStatistics `json:"order_stats"`
RevenueStats AdminRevenueStatistics `json:"revenue_stats"`
AgentStats AdminAgentStatistics `json:"agent_stats"`
ProfitStats AdminProfitStatistics `json:"profit_stats"`
OrderTrend []AdminTrendData `json:"order_trend"`
RevenueTrend []AdminTrendData `json:"revenue_trend"`
}

View File

@@ -1,81 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminConfigFeatureExampleReq struct {
FeatureId string `json:"feature_id"` // 功能ID
Data string `json:"data"` // 示例数据JSON
}
type AdminConfigFeatureExampleResp struct {
Success bool `json:"success"` // 是否成功
}
type AdminCreateFeatureReq struct {
ApiId string `json:"api_id"` // API标识
Name string `json:"name"` // 描述
WhitelistPrice *float64 `json:"whitelist_price,optional"` // 白名单屏蔽价格(单位:元)
CostPrice *float64 `json:"cost_price,optional"` // 天远API调用成本价单位
}
type AdminCreateFeatureResp struct {
Id string `json:"id"` // 功能ID
}
type AdminDeleteFeatureReq struct {
Id string `path:"id"` // 功能ID
}
type AdminDeleteFeatureResp struct {
Success bool `json:"success"` // 是否成功
}
type AdminGetFeatureDetailReq struct {
Id string `path:"id"` // 功能ID
}
type AdminGetFeatureDetailResp struct {
Id string `json:"id"` // 功能ID
ApiId string `json:"api_id"` // API标识
Name string `json:"name"` // 描述
WhitelistPrice float64 `json:"whitelist_price"` // 白名单屏蔽价格(单位:元)
CostPrice float64 `json:"cost_price"` // 天远API调用成本价单位
CreateTime string `json:"create_time"` // 创建时间
UpdateTime string `json:"update_time"` // 更新时间
}
type AdminGetFeatureExampleReq struct {
FeatureId string `path:"feature_id"` // 功能ID
}
type AdminGetFeatureExampleResp struct {
Id string `json:"id"` // 示例数据ID
FeatureId string `json:"feature_id"` // 功能ID
ApiId string `json:"api_id"` // API标识
Data string `json:"data"` // 示例数据JSON
CreateTime string `json:"create_time"` // 创建时间
UpdateTime string `json:"update_time"` // 更新时间
}
type AdminGetFeatureListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
ApiId *string `form:"api_id,optional"` // API标识
Name *string `form:"name,optional"` // 描述
}
type AdminGetFeatureListResp struct {
Total int64 `json:"total"` // 总数
Items []FeatureListItem `json:"items"` // 列表数据
}
type AdminUpdateFeatureReq struct {
Id string `path:"id"` // 功能ID
ApiId *string `json:"api_id,optional"` // API标识
Name *string `json:"name,optional"` // 描述
WhitelistPrice *float64 `json:"whitelist_price,optional"` // 白名单屏蔽价格(单位:元)
CostPrice *float64 `json:"cost_price,optional"` // 天远API调用成本价单位
}
type AdminUpdateFeatureResp struct {
Success bool `json:"success"` // 是否成功
}

View File

@@ -1,97 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type CreateMenuReq struct {
Pid string `json:"pid,optional"` // 父菜单ID
Name string `json:"name"` // 路由名称
Path string `json:"path,optional"` // 路由路径
Component string `json:"component,optional"` // 组件路径
Redirect string `json:"redirect,optional"` // 重定向路径
Meta map[string]interface{} `json:"meta"` // 路由元数据
Status int64 `json:"status,optional,default=1"` // 状态0-禁用1-启用
Type string `json:"type"` // 类型
Sort int64 `json:"sort,optional"` // 排序
}
type CreateMenuResp struct {
Id string `json:"id"` // 菜单ID
}
type DeleteMenuReq struct {
Id string `path:"id"` // 菜单ID
}
type DeleteMenuResp struct {
Success bool `json:"success"` // 是否成功
}
type GetMenuAllReq struct {
}
type GetMenuAllResp struct {
Name string `json:"name"`
Path string `json:"path"`
Redirect string `json:"redirect,omitempty"`
Component string `json:"component,omitempty"`
Sort int64 `json:"sort"`
Meta map[string]interface{} `json:"meta"`
Children []GetMenuAllResp `json:"children"`
}
type GetMenuDetailReq struct {
Id string `path:"id"` // 菜单ID
}
type GetMenuDetailResp struct {
Id string `json:"id"` // 菜单ID
Pid string `json:"pid"` // 父菜单ID
Name string `json:"name"` // 路由名称
Path string `json:"path"` // 路由路径
Component string `json:"component"` // 组件路径
Redirect string `json:"redirect"` // 重定向路径
Meta map[string]interface{} `json:"meta"` // 路由元数据
Status int64 `json:"status"` // 状态0-禁用1-启用
Type string `json:"type"` // 类型
Sort int64 `json:"sort"` // 排序
CreateTime string `json:"createTime"` // 创建时间
UpdateTime string `json:"updateTime"` // 更新时间
}
type GetMenuListReq struct {
Name string `form:"name,optional"` // 菜单名称
Path string `form:"path,optional"` // 路由路径
Status int64 `form:"status,optional,default=-1"` // 状态0-禁用1-启用
Type string `form:"type,optional"` // 类型
}
type MenuListItem struct {
Id string `json:"id"` // 菜单ID
Pid string `json:"pid"` // 父菜单ID
Name string `json:"name"` // 路由名称
Path string `json:"path"` // 路由路径
Component string `json:"component"` // 组件路径
Redirect string `json:"redirect"` // 重定向路径
Meta map[string]interface{} `json:"meta"` // 路由元数据
Status int64 `json:"status"` // 状态0-禁用1-启用
Type string `json:"type"` // 类型
Sort int64 `json:"sort"` // 排序
CreateTime string `json:"createTime"` // 创建时间
Children []MenuListItem `json:"children"` // 子菜单
}
type UpdateMenuReq struct {
Id string `path:"id"` // 菜单ID
Pid *string `json:"pid,optional"` // 父菜单ID
Name string `json:"name"` // 路由名称
Path string `json:"path,optional"` // 路由路径
Component string `json:"component,optional"` // 组件路径
Redirect string `json:"redirect,optional"` // 重定向路径
Meta map[string]interface{} `json:"meta"` // 路由元数据
Status int64 `json:"status,optional"` // 状态0-禁用1-启用
Type string `json:"type"` // 类型
Sort int64 `json:"sort,optional"` // 排序
}
type UpdateMenuResp struct {
Success bool `json:"success"` // 是否成功
}

View File

@@ -1,74 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminCreateNotificationReq struct {
Title string `json:"title"` // 通知标题
NotificationPage string `json:"notification_page"` // 通知页面
Content string `json:"content"` // 通知内容
StartDate string `json:"start_date"` // 生效开始日期yyyy-MM-dd
StartTime string `json:"start_time"` // 生效开始时间HH:mm:ss
EndDate string `json:"end_date"` // 生效结束日期yyyy-MM-dd
EndTime string `json:"end_time"` // 生效结束时间HH:mm:ss
Status int64 `json:"status"` // 状态1-启用0-禁用
}
type AdminCreateNotificationResp struct {
Id string `json:"id"` // 通知ID
}
type AdminDeleteNotificationReq struct {
Id string `path:"id"` // 通知ID
}
type AdminDeleteNotificationResp struct {
Success bool `json:"success"` // 是否成功
}
type AdminGetNotificationDetailReq struct {
Id string `path:"id"` // 通知ID
}
type AdminGetNotificationDetailResp struct {
Id string `json:"id"` // 通知ID
Title string `json:"title"` // 通知标题
Content string `json:"content"` // 通知内容
NotificationPage string `json:"notification_page"` // 通知页面
StartDate string `json:"start_date"` // 生效开始日期
StartTime string `json:"start_time"` // 生效开始时间
EndDate string `json:"end_date"` // 生效结束日期
EndTime string `json:"end_time"` // 生效结束时间
Status int64 `json:"status"` // 状态
CreateTime string `json:"create_time"` // 创建时间
UpdateTime string `json:"update_time"` // 更新时间
}
type AdminGetNotificationListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
Title *string `form:"title,optional"` // 通知标题(可选)
NotificationPage *string `form:"notification_page,optional"` // 通知页面(可选)
Status *int64 `form:"status,optional"` // 状态(可选)
StartDate *string `form:"start_date,optional"` // 开始日期范围(可选)
EndDate *string `form:"end_date,optional"` // 结束日期范围(可选)
}
type AdminGetNotificationListResp struct {
Total int64 `json:"total"` // 总数
Items []NotificationListItem `json:"items"` // 列表数据
}
type AdminUpdateNotificationReq struct {
Id string `path:"id"` // 通知ID
Title *string `json:"title,optional"` // 通知标题
Content *string `json:"content,optional"` // 通知内容
NotificationPage *string `json:"notification_page,optional"` // 通知页面
StartDate *string `json:"start_date,optional"` // 生效开始日期
StartTime *string `json:"start_time,optional"` // 生效开始时间
EndDate *string `json:"end_date,optional"` // 生效结束日期
EndTime *string `json:"end_time,optional"` // 生效结束时间
Status *int64 `json:"status,optional"` // 状态
}
type AdminUpdateNotificationResp struct {
Success bool `json:"success"` // 是否成功
}

View File

@@ -1,108 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminCreateOrderReq struct {
OrderNo string `json:"order_no"` // 商户订单号
PlatformOrderId string `json:"platform_order_id"` // 支付订单号
ProductName string `json:"product_name"` // 产品名称
PaymentPlatform string `json:"payment_platform"` // 支付方式
PaymentScene string `json:"payment_scene"` // 支付平台
Amount float64 `json:"amount"` // 金额
Status string `json:"status,default=pending"` // 支付状态pending-待支付paid-已支付refunded-已退款closed-已关闭failed-支付失败
}
type AdminCreateOrderResp struct {
Id string `json:"id"` // 订单ID
}
type AdminDeleteOrderReq struct {
Id string `path:"id"` // 订单ID
}
type AdminDeleteOrderResp struct {
Success bool `json:"success"` // 是否成功
}
type AdminGetOrderDetailReq struct {
Id string `path:"id"` // 订单ID
}
type AdminGetOrderDetailResp struct {
Id string `json:"id"` // 订单ID
OrderNo string `json:"order_no"` // 商户订单号
PlatformOrderId string `json:"platform_order_id"` // 支付订单号
ProductName string `json:"product_name"` // 产品名称
PaymentPlatform string `json:"payment_platform"` // 支付方式
PaymentScene string `json:"payment_scene"` // 支付平台
Amount float64 `json:"amount"` // 金额
Status string `json:"status"` // 支付状态pending-待支付paid-已支付refunded-已退款closed-已关闭failed-支付失败
QueryState string `json:"query_state"` // 查询状态pending-待查询success-查询成功failed-查询失败 processing-查询中
CreateTime string `json:"create_time"` // 创建时间
PayTime string `json:"pay_time"` // 支付时间
RefundTime string `json:"refund_time"` // 退款时间
UpdateTime string `json:"update_time"` // 更新时间
IsAgentOrder bool `json:"is_agent_order"` // 是否是代理订单
AgentProcessStatus string `json:"agent_process_status"` // 代理事务处理状态not_agent-非代理订单success-处理成功failed-处理失败pending-待处理
}
type AdminGetOrderListReq struct {
Page int64 `form:"page,default=1"` // 页码
PageSize int64 `form:"pageSize,default=20"` // 每页数量
OrderNo string `form:"order_no,optional"` // 商户订单号
PlatformOrderId string `form:"platform_order_id,optional"` // 支付订单号
ProductName string `form:"product_name,optional"` // 产品名称
PaymentPlatform string `form:"payment_platform,optional"` // 支付方式
PaymentScene string `form:"payment_scene,optional"` // 支付平台
Amount float64 `form:"amount,optional"` // 金额
Status string `form:"status,optional"` // 支付状态pending-待支付paid-已支付refunded-已退款closed-已关闭failed-支付失败
CreateTimeStart string `form:"create_time_start,optional"` // 创建时间开始
CreateTimeEnd string `form:"create_time_end,optional"` // 创建时间结束
PayTimeStart string `form:"pay_time_start,optional"` // 支付时间开始
PayTimeEnd string `form:"pay_time_end,optional"` // 支付时间结束
RefundTimeStart string `form:"refund_time_start,optional"` // 退款时间开始
RefundTimeEnd string `form:"refund_time_end,optional"` // 退款时间结束
}
type AdminGetOrderListResp struct {
Total int64 `json:"total"` // 总数
Items []OrderListItem `json:"items"` // 列表
}
type AdminRefundOrderReq struct {
Id string `path:"id"` // 订单ID
RefundAmount float64 `json:"refund_amount"` // 退款金额
RefundReason string `json:"refund_reason"` // 退款原因
}
type AdminRefundOrderResp struct {
Status string `json:"status"` // 退款状态
RefundNo string `json:"refund_no"` // 退款单号
Amount float64 `json:"amount"` // 退款金额
}
type AdminRetryAgentProcessReq struct {
Id string `path:"id"` // 订单ID
}
type AdminRetryAgentProcessResp struct {
Status string `json:"status"` // 执行状态success-成功already_processed-已处理failed-失败
Message string `json:"message"` // 执行结果消息
ProcessedAt string `json:"processed_at"` // 处理时间
}
type AdminUpdateOrderReq struct {
Id string `path:"id"` // 订单ID
OrderNo *string `json:"order_no,optional"` // 商户订单号
PlatformOrderId *string `json:"platform_order_id,optional"` // 支付订单号
ProductName *string `json:"product_name,optional"` // 产品名称
PaymentPlatform *string `json:"payment_platform,optional"` // 支付方式
PaymentScene *string `json:"payment_scene,optional"` // 支付平台
Amount *float64 `json:"amount,optional"` // 金额
Status *string `json:"status,optional"` // 支付状态pending-待支付paid-已支付refunded-已退款closed-已关闭failed-支付失败
PayTime *string `json:"pay_time,optional"` // 支付时间
RefundTime *string `json:"refund_time,optional"` // 退款时间
}
type AdminUpdateOrderResp struct {
Success bool `json:"success"` // 是否成功
}

View File

@@ -1,66 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminCreatePlatformUserReq struct {
Mobile string `json:"mobile"` // 手机号
Password string `json:"password"` // 密码
Nickname string `json:"nickname"` // 昵称
Info string `json:"info"` // 备注信息
Inside int64 `json:"inside"` // 是否内部用户 1-是 0-否
}
type AdminCreatePlatformUserResp struct {
Id string `json:"id"` // 用户ID
}
type AdminDeletePlatformUserReq struct {
Id string `path:"id"` // 用户ID
}
type AdminDeletePlatformUserResp struct {
Success bool `json:"success"` // 是否成功
}
type AdminGetPlatformUserDetailReq struct {
Id string `path:"id"` // 用户ID
}
type AdminGetPlatformUserDetailResp struct {
Id string `json:"id"` // 用户ID
Mobile string `json:"mobile"` // 手机号
Nickname string `json:"nickname"` // 昵称
Info string `json:"info"` // 备注信息
Inside int64 `json:"inside"` // 是否内部用户 1-是 0-否
CreateTime string `json:"create_time"` // 创建时间
UpdateTime string `json:"update_time"` // 更新时间
}
type AdminGetPlatformUserListReq struct {
Page int64 `form:"page,default=1"` // 页码
PageSize int64 `form:"pageSize,default=20"` // 每页数量
Mobile string `form:"mobile,optional"` // 手机号
Nickname string `form:"nickname,optional"` // 昵称
Inside int64 `form:"inside,optional"` // 是否内部用户 1-是 0-否
CreateTimeStart string `form:"create_time_start,optional"` // 创建时间开始
CreateTimeEnd string `form:"create_time_end,optional"` // 创建时间结束
OrderBy string `form:"order_by,optional"` // 排序字段
OrderType string `form:"order_type,optional"` // 排序类型
}
type AdminGetPlatformUserListResp struct {
Total int64 `json:"total"` // 总数
Items []PlatformUserListItem `json:"items"` // 列表
}
type AdminUpdatePlatformUserReq struct {
Id string `path:"id"` // 用户ID
Mobile *string `json:"mobile,optional"` // 手机号
Password *string `json:"password,optional"` // 密码
Nickname *string `json:"nickname,optional"` // 昵称
Info *string `json:"info,optional"` // 备注信息
Inside *int64 `json:"inside,optional"` // 是否内部用户 1-是 0-否
}
type AdminUpdatePlatformUserResp struct {
Success bool `json:"success"` // 是否成功
}

View File

@@ -1,88 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminCreateProductReq struct {
ProductName string `json:"product_name"` // 服务名
ProductEn string `json:"product_en"` // 英文名
Description string `json:"description"` // 描述
Notes string `json:"notes,optional"` // 备注
SellPrice float64 `json:"sell_price"` // 售价
}
type AdminCreateProductResp struct {
Id string `json:"id"` // 产品ID
}
type AdminDeleteProductReq struct {
Id string `path:"id"` // 产品ID
}
type AdminDeleteProductResp struct {
Success bool `json:"success"` // 是否成功
}
type AdminGetProductDetailReq struct {
Id string `path:"id"` // 产品ID
}
type AdminGetProductDetailResp struct {
Id string `json:"id"` // 产品ID
ProductName string `json:"product_name"` // 服务名
ProductEn string `json:"product_en"` // 英文名
Description string `json:"description"` // 描述
Notes string `json:"notes"` // 备注
SellPrice float64 `json:"sell_price"` // 售价
CreateTime string `json:"create_time"` // 创建时间
UpdateTime string `json:"update_time"` // 更新时间
}
type AdminGetProductFeatureListReq struct {
ProductId string `path:"product_id"` // 产品ID
}
type AdminGetProductFeatureListResp struct {
Id string `json:"id"` // 关联ID
ProductId string `json:"product_id"` // 产品ID
FeatureId string `json:"feature_id"` // 功能ID
ApiId string `json:"api_id"` // API标识
Name string `json:"name"` // 功能描述
Sort int64 `json:"sort"` // 排序
Enable int64 `json:"enable"` // 是否启用
IsImportant int64 `json:"is_important"` // 是否重要
CreateTime string `json:"create_time"` // 创建时间
UpdateTime string `json:"update_time"` // 更新时间
}
type AdminGetProductListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"pageSize"` // 每页数量
ProductName *string `form:"product_name,optional"` // 服务名
ProductEn *string `form:"product_en,optional"` // 英文名
}
type AdminGetProductListResp struct {
Total int64 `json:"total"` // 总数
Items []ProductListItem `json:"items"` // 列表数据
}
type AdminUpdateProductFeaturesReq struct {
ProductId string `path:"product_id"` // 产品ID
Features []ProductFeatureItem `json:"features"` // 功能列表
}
type AdminUpdateProductFeaturesResp struct {
Success bool `json:"success"` // 是否成功
}
type AdminUpdateProductReq struct {
Id string `path:"id"` // 产品ID
ProductName *string `json:"product_name,optional"` // 服务名
ProductEn *string `json:"product_en,optional"` // 英文名
Description *string `json:"description,optional"` // 描述
Notes *string `json:"notes,optional"` // 备注
SellPrice *float64 `json:"sell_price,optional"` // 售价
}
type AdminUpdateProductResp struct {
Success bool `json:"success"` // 是否成功
}

View File

@@ -1,60 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminGetQueryCleanupConfigListReq struct {
Status int64 `form:"status,optional"` // 状态1-启用0-禁用
}
type AdminGetQueryCleanupConfigListResp struct {
Items []QueryCleanupConfigItem `json:"items"` // 配置列表
}
type AdminGetQueryCleanupDetailListReq struct {
LogId string `path:"log_id"` // 清理日志ID
Page int64 `form:"page,default=1"` // 页码
PageSize int64 `form:"page_size,default=20"` // 每页数量
}
type AdminGetQueryCleanupDetailListResp struct {
Total int64 `json:"total"` // 总数
Items []QueryCleanupDetailItem `json:"items"` // 列表
}
type AdminGetQueryCleanupLogListReq struct {
Page int64 `form:"page,default=1"` // 页码
PageSize int64 `form:"page_size,default=20"` // 每页数量
Status int64 `form:"status,optional"` // 状态1-成功2-失败
StartTime string `form:"start_time,optional"` // 开始时间
EndTime string `form:"end_time,optional"` // 结束时间
}
type AdminGetQueryCleanupLogListResp struct {
Total int64 `json:"total"` // 总数
Items []QueryCleanupLogItem `json:"items"` // 列表
}
type AdminGetQueryDetailByOrderIdReq struct {
OrderId string `path:"order_id"`
}
type AdminGetQueryDetailByOrderIdResp struct {
Id string `json:"id"` // 主键ID
OrderId string `json:"order_id"` // 订单ID
UserId string `json:"user_id"` // 用户ID
ProductName string `json:"product_name"` // 产品ID
QueryParams map[string]interface{} `json:"query_params"`
QueryData []AdminQueryItem `json:"query_data"`
CreateTime string `json:"create_time"` // 创建时间
UpdateTime string `json:"update_time"` // 更新时间
QueryState string `json:"query_state"` // 查询状态
}
type AdminUpdateQueryCleanupConfigReq struct {
Id string `json:"id"` // 主键ID
ConfigValue string `json:"config_value"` // 配置值
Status int64 `json:"status"` // 状态1-启用0-禁用
}
type AdminUpdateQueryCleanupConfigResp struct {
Success bool `json:"success"` // 是否成功
}

View File

@@ -1,66 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type CreateRoleReq struct {
RoleName string `json:"role_name"` // 角色名称
RoleCode string `json:"role_code"` // 角色编码
Description string `json:"description"` // 角色描述
Status int64 `json:"status,default=1"` // 状态0-禁用1-启用
Sort int64 `json:"sort,default=0"` // 排序
MenuIds []string `json:"menu_ids"` // 关联的菜单ID列表
}
type CreateRoleResp struct {
Id string `json:"id"` // 角色ID
}
type DeleteRoleReq struct {
Id string `path:"id"` // 角色ID
}
type DeleteRoleResp struct {
Success bool `json:"success"` // 是否成功
}
type GetRoleDetailReq struct {
Id string `path:"id"` // 角色ID
}
type GetRoleDetailResp struct {
Id string `json:"id"` // 角色ID
RoleName string `json:"role_name"` // 角色名称
RoleCode string `json:"role_code"` // 角色编码
Description string `json:"description"` // 角色描述
Status int64 `json:"status"` // 状态0-禁用1-启用
Sort int64 `json:"sort"` // 排序
CreateTime string `json:"create_time"` // 创建时间
UpdateTime string `json:"update_time"` // 更新时间
MenuIds []string `json:"menu_ids"` // 关联的菜单ID列表
}
type GetRoleListReq struct {
Page int64 `form:"page,default=1"` // 页码
PageSize int64 `form:"pageSize,default=20"` // 每页数量
Name string `form:"name,optional"` // 角色名称
Code string `form:"code,optional"` // 角色编码
Status int64 `form:"status,optional,default=-1"` // 状态0-禁用1-启用
}
type GetRoleListResp struct {
Total int64 `json:"total"` // 总数
Items []RoleListItem `json:"items"` // 列表
}
type UpdateRoleReq struct {
Id string `path:"id"` // 角色ID
RoleName *string `json:"role_name,optional"` // 角色名称
RoleCode *string `json:"role_code,optional"` // 角色编码
Description *string `json:"description,optional"` // 角色描述
Status *int64 `json:"status,optional"` // 状态0-禁用1-启用
Sort *int64 `json:"sort,optional"` // 排序
MenuIds []string `json:"menu_ids,optional"` // 关联的菜单ID列表
}
type UpdateRoleResp struct {
Success bool `json:"success"` // 是否成功
}

View File

@@ -1,45 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminAssignRoleApiReq struct {
RoleId string `json:"role_id"`
ApiIds []string `json:"api_ids"`
}
type AdminAssignRoleApiResp struct {
Success bool `json:"success"`
}
type AdminGetAllApiListReq struct {
Status int64 `form:"status,optional,default=1"`
}
type AdminGetAllApiListResp struct {
Items []AdminRoleApiInfo `json:"items"`
}
type AdminGetRoleApiListReq struct {
RoleId string `path:"role_id"`
}
type AdminGetRoleApiListResp struct {
Items []AdminRoleApiInfo `json:"items"`
}
type AdminRemoveRoleApiReq struct {
RoleId string `json:"role_id"`
ApiIds []string `json:"api_ids"`
}
type AdminRemoveRoleApiResp struct {
Success bool `json:"success"`
}
type AdminUpdateRoleApiReq struct {
RoleId string `json:"role_id"`
ApiIds []string `json:"api_ids"`
}
type AdminUpdateRoleApiResp struct {
Success bool `json:"success"`
}

View File

@@ -1,78 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AdminCreateUserReq struct {
Username string `json:"username"` // 用户名
RealName string `json:"real_name"` // 真实姓名
Status int64 `json:"status,default=1"` // 状态0-禁用1-启用
RoleIds []string `json:"role_ids"` // 关联的角色ID列表
}
type AdminCreateUserResp struct {
Id string `json:"id"` // 用户ID
}
type AdminDeleteUserReq struct {
Id string `path:"id"` // 用户ID
}
type AdminDeleteUserResp struct {
Success bool `json:"success"` // 是否成功
}
type AdminGetUserDetailReq struct {
Id string `path:"id"` // 用户ID
}
type AdminGetUserDetailResp struct {
Id string `json:"id"` // 用户ID
Username string `json:"username"` // 用户名
RealName string `json:"real_name"` // 真实姓名
Status int64 `json:"status"` // 状态0-禁用1-启用
CreateTime string `json:"create_time"` // 创建时间
UpdateTime string `json:"update_time"` // 更新时间
RoleIds []string `json:"role_ids"` // 关联的角色ID列表
}
type AdminGetUserListReq struct {
Page int64 `form:"page,default=1"` // 页码
PageSize int64 `form:"pageSize,default=20"` // 每页数量
Username string `form:"username,optional"` // 用户名
RealName string `form:"real_name,optional"` // 真实姓名
Status int64 `form:"status,optional,default=-1"` // 状态0-禁用1-启用
}
type AdminGetUserListResp struct {
Total int64 `json:"total"` // 总数
Items []AdminUserListItem `json:"items"` // 列表
}
type AdminResetPasswordReq struct {
Id string `path:"id"` // 用户ID
Password string `json:"password"` // 新密码
}
type AdminResetPasswordResp struct {
Success bool `json:"success"` // 是否成功
}
type AdminUpdateUserReq struct {
Id string `path:"id"` // 用户ID
Username *string `json:"username,optional"` // 用户名
RealName *string `json:"real_name,optional"` // 真实姓名
Status *int64 `json:"status,optional"` // 状态0-禁用1-启用
RoleIds []string `json:"role_ids,optional"` // 关联的角色ID列表
}
type AdminUpdateUserResp struct {
Success bool `json:"success"` // 是否成功
}
type AdminUserInfoReq struct {
}
type AdminUserInfoResp struct {
Username string `json:"username"` // 用户名
RealName string `json:"real_name"` // 真实姓名
Roles []string `json:"roles"` // 角色编码列表
}

View File

@@ -1,379 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AgentApplyReq struct {
Region string `json:"region,optional"`
Mobile string `json:"mobile"`
Code string `json:"code"`
Referrer string `json:"referrer"`
InviteCode string `json:"invite_code,optional"`
AgentCode int64 `json:"agent_code,optional"`
}
type AgentApplyResp struct {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
AgentCode int64 `json:"agent_code"`
}
type AgentGeneratingLinkReq struct {
ProductId string `json:"product_id"` // 产品ID
SetPrice float64 `json:"set_price"` // 设定价格
TargetPath string `json:"target_path,optional"` // 目标地址(可选,默认为推广报告页面)
}
type AgentGeneratingLinkResp struct {
LinkIdentifier string `json:"link_identifier"` // 推广链接标识
FullLink string `json:"full_link"` // 完整短链URL
}
type AgentInfoResp struct {
AgentId string `json:"agent_id"`
Level int64 `json:"level"`
LevelName string `json:"level_name"`
Region string `json:"region"`
Mobile string `json:"mobile"`
WechatId string `json:"wechat_id"`
TeamLeaderId string `json:"team_leader_id"`
IsRealName bool `json:"is_real_name"`
AgentCode int64 `json:"agent_code"`
}
type AgentProductConfigResp struct {
List []ProductConfigItem `json:"list"`
}
type ApplyUpgradeReq struct {
ToLevel int64 `json:"to_level"` // 目标等级2=黄金3=钻石
}
type ApplyUpgradeResp struct {
UpgradeId string `json:"upgrade_id"` // 升级记录ID
OrderNo string `json:"order_no"` // 支付订单号
}
type ApplyWithdrawalReq struct {
Amount float64 `json:"amount"` // 提现金额
WithdrawalType int64 `json:"withdrawal_type"` // 提现方式1=支付宝2=银行卡
PayeeAccount string `json:"payee_account"` // 收款账户(支付宝账号或银行卡号)
PayeeName string `json:"payee_name"` // 收款人姓名
BankCardNo string `json:"bank_card_no,optional"` // 银行卡号(银行卡提现必填)
BankName string `json:"bank_name,optional"` // 开户行名称(银行卡提现必填)
}
type ApplyWithdrawalResp struct {
WithdrawalId string `json:"withdrawal_id"` // 提现记录ID
WithdrawalNo string `json:"withdrawal_no"` // 提现单号
}
type CheckFeatureWhitelistStatusReq struct {
IdCard string `form:"id_card"` // 身份证号
FeatureApiId string `form:"feature_api_id"` // Feature的API标识
QueryId string `form:"query_id,optional"` // 查询记录ID可选用于检查报告数据是否已删除
}
type CheckFeatureWhitelistStatusResp struct {
IsWhitelisted bool `json:"is_whitelisted"` // 是否在白名单中
WhitelistPrice float64 `json:"whitelist_price"` // 屏蔽价格单位如果为0表示不支持下架
FeatureId string `json:"feature_id"` // Feature的UUID
DataDeleted bool `json:"data_deleted"` // 报告数据是否已删除仅当提供了query_id时有效
}
type CheckOrderAgentReq struct {
OrderId string `form:"order_id"` // 订单ID
}
type CheckOrderAgentResp struct {
IsAgentOrder bool `json:"is_agent_order"` // 是否是当前代理推广的订单
}
type ConversionRateResp struct {
MyConversionRate ConversionRateData `json:"my_conversion_rate"` // 我的转化率
SubordinateConversionRate ConversionRateData `json:"subordinate_conversion_rate"` // 我的下级转化率
}
type CreateWhitelistOrderReq struct {
IdCard string `json:"id_card"` // 身份证号(查询对象标识)
FeatureIds []string `json:"feature_ids"` // 要屏蔽的feature ID列表
OrderId string `json:"order_id,optional"` // 关联的查询订单ID可选
}
type CreateWhitelistOrderResp struct {
OrderId string `json:"order_id"` // 订单ID
OrderNo string `json:"order_no"` // 订单号
TotalAmount float64 `json:"total_amount"` // 总金额
}
type DeleteInviteCodeReq struct {
Id string `json:"id"` // 邀请码ID
}
type DeleteInviteCodeResp struct {
}
type GenerateInviteCodeReq struct {
Count int64 `json:"count"` // 生成数量
ExpireDays int64 `json:"expire_days,optional"` // 过期天数可选0表示不过期
Remark string `json:"remark,optional"` // 备注(可选)
}
type GenerateInviteCodeResp struct {
Codes []string `json:"codes"` // 生成的邀请码列表
}
type GetCommissionListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数量
}
type GetCommissionListResp struct {
Total int64 `json:"total"` // 总数
List []CommissionItem `json:"list"` // 列表
}
type GetInviteCodeListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数量
Status int64 `form:"status,optional"` // 状态(可选)
}
type GetInviteCodeListResp struct {
Total int64 `json:"total"` // 总数
List []InviteCodeItem `json:"list"` // 列表
}
type GetInviteLinkReq struct {
InviteCode string `form:"invite_code"` // 邀请码
TargetPath string `form:"target_path,optional"` // 目标地址(可选,默认为注册页面)
}
type GetInviteLinkResp struct {
InviteLink string `json:"invite_link"` // 邀请链接
}
type GetLastWithdrawalInfoReq struct {
WithdrawalType int64 `form:"withdrawal_type"` // 提现方式1=支付宝2=银行卡
}
type GetLastWithdrawalInfoResp struct {
WithdrawalType int64 `json:"withdrawal_type"` // 提现方式
PayeeAccount string `json:"payee_account"` // 收款账户(支付宝账号或银行卡号)
PayeeName string `json:"payee_name"` // 收款人姓名
BankCardNo string `json:"bank_card_no"` // 银行卡号
BankName string `json:"bank_name"` // 开户行名称
}
type GetLevelPrivilegeResp struct {
Levels []LevelPrivilegeItem `json:"levels"`
UpgradeToGoldFee float64 `json:"upgrade_to_gold_fee"`
UpgradeToDiamondFee float64 `json:"upgrade_to_diamond_fee"`
UpgradeToGoldRebate float64 `json:"upgrade_to_gold_rebate"`
UpgradeToDiamondRebate float64 `json:"upgrade_to_diamond_rebate"`
}
type GetLinkDataReq struct {
LinkIdentifier string `form:"link_identifier"` // 推广链接标识
}
type GetLinkDataResp struct {
AgentId string `json:"agent_id"` // 代理ID
ProductId string `json:"product_id"` // 产品ID
SetPrice float64 `json:"set_price"` // 代理设定价格
ActualBasePrice float64 `json:"actual_base_price"` // 实际底价
ProductName string `json:"product_name"` // 产品名称
ProductEn string `json:"product_en"` // 产品英文标识
SellPrice float64 `json:"sell_price"` // 销售价格(使用代理设定价格)
Description string `json:"description"` // 产品描述
Features []Feature `json:"features"` // 产品功能列表
}
type GetPromotionQueryListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数量
}
type GetPromotionQueryListResp struct {
Total int64 `json:"total"` // 总数
List []PromotionQueryItem `json:"list"` // 列表
}
type GetRebateListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数量
RebateType *int64 `form:"rebate_type,optional"` // 返佣类型可选1=直接上级返佣2=钻石上级返佣3=黄金上级返佣
}
type GetRebateListResp struct {
Total int64 `json:"total"` // 总数
List []RebateItem `json:"list"` // 列表
}
type GetRevenueInfoResp struct {
Balance float64 `json:"balance"` // 可用余额
FrozenBalance float64 `json:"frozen_balance"` // 冻结余额
TotalEarnings float64 `json:"total_earnings"` // 累计收益(钱包总收益)
WithdrawnAmount float64 `json:"withdrawn_amount"` // 累计提现
CommissionTotal float64 `json:"commission_total"` // 佣金累计总收益(推广订单获得的佣金)
CommissionToday float64 `json:"commission_today"` // 佣金今日收益
CommissionMonth float64 `json:"commission_month"` // 佣金本月收益
RebateTotal float64 `json:"rebate_total"` // 返佣累计总收益(包括推广返佣和升级返佣)
RebateToday float64 `json:"rebate_today"` // 返佣今日收益
RebateMonth float64 `json:"rebate_month"` // 返佣本月收益
AlipayMonthQuota float64 `json:"alipay_month_quota"` // 支付宝每月提现总额度
AlipayMonthUsed float64 `json:"alipay_month_used"` // 本月已使用的支付宝提现额度
}
type GetSubordinateContributionDetailReq struct {
SubordinateId string `form:"subordinate_id"` // 下级代理ID
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数量
TabType string `form:"tab_type,optional"` // 标签页类型order=订单列表invite=邀请列表
}
type GetSubordinateContributionDetailResp struct {
Mobile string `json:"mobile"` // 手机号
LevelName string `json:"level_name"` // 等级名称
CreateTime string `json:"create_time"` // 创建时间
OrderStats OrderStatistics `json:"order_stats"` // 订单统计(仅统计有返佣的订单)
RebateStats RebateStatistics `json:"rebate_stats"` // 返佣统计
InviteStats InviteStatistics `json:"invite_stats"` // 邀请统计
OrderList []OrderItem `json:"order_list"` // 订单列表(仅有贡献的订单)
InviteList []InviteItem `json:"invite_list"` // 邀请列表
OrderListTotal int64 `json:"order_list_total"` // 订单列表总数
InviteListTotal int64 `json:"invite_list_total"` // 邀请列表总数
}
type GetSubordinateListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数量
}
type GetSubordinateListResp struct {
Total int64 `json:"total"` // 总数
List []SubordinateItem `json:"list"` // 列表
}
type GetTeamListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数量
Mobile string `form:"mobile,optional"` // 手机号(可选,用于搜索)
}
type GetTeamListResp struct {
Statistics TeamStatistics `json:"statistics"` // 统计数据
Total int64 `json:"total"` // 总数
List []TeamMemberItem `json:"list"` // 列表
}
type GetUpgradeListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数量
}
type GetUpgradeListResp struct {
Total int64 `json:"total"` // 总数
List []UpgradeItem `json:"list"` // 列表
}
type GetUpgradeRebateListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数量
}
type GetUpgradeRebateListResp struct {
Total int64 `json:"total"` // 总数
List []UpgradeRebateItem `json:"list"` // 列表
}
type GetWhitelistFeaturesReq struct {
}
type GetWhitelistFeaturesResp struct {
List []WhitelistFeatureItem `json:"list"` // 可屏蔽的feature列表
}
type GetWhitelistListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数量
IdCard string `form:"id_card,optional"` // 身份证号(可选,用于筛选)
}
type GetWhitelistListResp struct {
Total int64 `json:"total"` // 总数
List []WhitelistItem `json:"list"` // 列表
}
type GetWithdrawalListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数量
}
type GetWithdrawalListResp struct {
Total int64 `json:"total"` // 总数
List []WithdrawalItem `json:"list"` // 列表
}
type OfflineFeatureReq struct {
FeatureApiId string `json:"feature_api_id"` // Feature的API标识
QueryId string `json:"query_id"` // 查询记录IDQuery表的ID必选
}
type OfflineFeatureResp struct {
Success bool `json:"success"` // 是否已完成下架
NeedPay bool `json:"need_pay"` // 是否需要发起支付
Amount float64 `json:"amount"` // 需要支付的金额单位0表示无需支付
}
type RealNameAuthReq struct {
Name string `json:"name"` // 姓名
IdCard string `json:"id_card"` // 身份证号
Mobile string `json:"mobile"` // 手机号
Code string `json:"code"` // 验证码
}
type RealNameAuthResp struct {
Status string `json:"status"` // 状态pending=待审核approved=已通过rejected=已拒绝
}
type RegisterByInviteCodeReq struct {
Referrer string `json:"referrer"`
InviteCode string `json:"invite_code,optional"`
AgentCode int64 `json:"agent_code,optional"`
Mobile string `json:"mobile"`
Code string `json:"code"`
Region string `json:"region,optional"`
WechatId string `json:"wechat_id,optional"`
}
type RegisterByInviteCodeResp struct {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
AgentId string `json:"agent_id"` // 代理ID
Level int64 `json:"level"` // 代理等级
LevelName string `json:"level_name"` // 等级名称
AgentCode int64 `json:"agent_code"`
}
type ShortLinkRedirectResp struct {
}
type TeamStatisticsResp struct {
TotalCount int64 `json:"total_count"` // 团队总人数(不包括自己)
DirectCount int64 `json:"direct_count"` // 直接下级数量
IndirectCount int64 `json:"indirect_count"` // 间接下级数量
GoldCount int64 `json:"gold_count"` // 黄金代理数量
NormalCount int64 `json:"normal_count"` // 普通代理数量
TodayNewMembers int64 `json:"today_new_members"` // 今日新增成员
MonthNewMembers int64 `json:"month_new_members"` // 本月新增成员
}
type UpgradeSubordinateReq struct {
SubordinateId string `json:"subordinate_id"` // 下级代理ID
ToLevel int64 `json:"to_level"` // 目标等级只能是2=黄金)
}
type UpgradeSubordinateResp struct {
Success bool `json:"success"`
}

View File

@@ -1,16 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type HealthCheckResp struct {
Status string `json:"status"` // 服务状态
Message string `json:"message"` // 状态信息
}
type GetAppConfigResp struct {
QueryRetentionDays int64 `json:"query_retention_days"`
}
type GetAppVersionResp struct {
Version string `json:"version"`
WgtUrl string `json:"wgtUrl"`
}

View File

@@ -1,7 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type SendSmsReq struct {
Mobile string `json:"mobile" validate:"required,mobile"`
ActionType string `json:"actionType" validate:"required,oneof=login register query agentApply realName bindMobile"`
}

View File

@@ -1,36 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type DownloadAuthorizationDocumentReq struct {
DocumentId string `json:"documentId" validate:"required"` // 授权书ID
}
type DownloadAuthorizationDocumentResp struct {
FileName string `json:"fileName"` // 文件名
FileUrl string `json:"fileUrl"` // 文件访问URL
}
type GetAuthorizationDocumentByOrderReq struct {
OrderId string `json:"orderId" validate:"required"` // 订单ID
}
type GetAuthorizationDocumentByOrderResp struct {
Documents []AuthorizationDocumentInfo `json:"documents"` // 授权书列表
}
type GetAuthorizationDocumentReq struct {
DocumentId string `json:"documentId" validate:"required"` // 授权书ID
}
type GetAuthorizationDocumentResp struct {
DocumentId string `json:"documentId"` // 授权书ID
UserId string `json:"userId"` // 用户ID
OrderId string `json:"orderId"` // 订单ID
QueryId string `json:"queryId"` // 查询ID
FileName string `json:"fileName"` // 文件名
FileUrl string `json:"fileUrl"` // 文件访问URL
FileSize int64 `json:"fileSize"` // 文件大小
FileType string `json:"fileType"` // 文件类型
Status string `json:"status"` // 状态
CreateTime string `json:"createTime"` // 创建时间
}

View File

@@ -1,7 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type GetNotificationsResp struct {
Notifications []Notification `json:"notifications"` // 通知列表
Total int64 `json:"total"` // 总记录数
}

View File

@@ -1,28 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type IapCallbackReq struct {
OrderID string `json:"order_id" validate:"required"`
TransactionReceipt string `json:"transaction_receipt" validate:"required"`
}
type PaymentCheckReq struct {
OrderNo string `json:"order_no" validate:"required"`
}
type PaymentCheckResp struct {
Type string `json:"type"`
Status string `json:"status"`
}
type PaymentReq struct {
Id string `json:"id"`
PayMethod string `json:"pay_method"` // 支付方式: wechat, alipay, appleiap, test(仅开发环境), test_empty(仅开发环境-空报告模式)
PayType string `json:"pay_type" validate:"required,oneof=query agent_vip agent_upgrade whitelist"`
}
type PaymentResp struct {
PrepayData interface{} `json:"prepay_data"`
PrepayId string `json:"prepay_id"`
OrderNo string `json:"order_no"`
}

View File

@@ -1,14 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type GetProductByEnRequest struct {
ProductEn string `path:"product_en"`
}
type GetProductByIDRequest struct {
Id string `path:"id"`
}
type ProductResponse struct {
Product
}

View File

@@ -1,90 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type QueryDetailByOrderIdReq struct {
OrderId string `path:"order_id"`
}
type QueryDetailByOrderNoReq struct {
OrderNo string `path:"order_no"`
}
type QueryExampleReq struct {
Feature string `form:"feature"`
}
type QueryGenerateShareLinkReq struct {
OrderId *string `json:"order_id,optional"`
OrderNo *string `json:"order_no,optional"`
}
type QueryGenerateShareLinkResp struct {
ShareLink string `json:"share_link"`
}
type QueryListReq struct {
Page int64 `form:"page"` // 页码
PageSize int64 `form:"page_size"` // 每页数据量
}
type QueryListResp struct {
Total int64 `json:"total"` // 总记录数
List []Query `json:"list"` // 查询列表
}
type QueryProvisionalOrderReq struct {
Id string `path:"id"`
}
type QueryProvisionalOrderResp struct {
Name string `json:"name"`
IdCard string `json:"id_card"`
Mobile string `json:"mobile"`
Product Product `json:"product"`
}
type QueryRetryReq struct {
Id string `path:"id"`
}
type QueryRetryResp struct {
Query
}
type QueryServiceReq struct {
Product string `path:"product"`
Data string `json:"data" validate:"required"`
AgentIdentifier string `json:"agent_identifier,optional"`
App bool `json:"app,optional"`
}
type QueryServiceResp struct {
Id string `json:"id"`
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
type QueryShareDetailReq struct {
Id string `path:"id"`
}
type QuerySingleTestReq struct {
Params map[string]interface{} `json:"params"`
Api string `json:"api"`
}
type QuerySingleTestResp struct {
Data interface{} `json:"data"`
Api string `json:"api"`
}
type UpdateQueryDataReq struct {
Id string `json:"id"` // 查询ID
QueryData string `json:"query_data"` // 查询数据(未加密的JSON)
}
type UpdateQueryDataResp struct {
Id string `json:"id"`
UpdatedAt string `json:"updated_at"` // 更新时间
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,73 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
type AuthReq struct {
Platform string `json:"platform"` // browser|wxh5|wxmini
Code string `json:"code,optional"`
}
type AuthResp struct {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
UserType int64 `json:"userType"`
HasMobile bool `json:"hasMobile"`
IsAgent bool `json:"isAgent"`
}
type BindMobileReq struct {
Mobile string `json:"mobile" validate:"required,mobile"`
Code string `json:"code" validate:"required"`
}
type BindMobileResp struct {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
type GetSignatureReq struct {
Url string `json:"url"`
}
type GetSignatureResp struct {
AppId string `json:"appId"`
Timestamp int64 `json:"timestamp"`
NonceStr string `json:"nonceStr"`
Signature string `json:"signature"`
}
type MobileCodeLoginReq struct {
Mobile string `json:"mobile"`
Code string `json:"code" validate:"required"`
}
type MobileCodeLoginResp struct {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
type UserInfoResp struct {
UserInfo User `json:"userInfo"`
}
type WXH5AuthReq struct {
Code string `json:"code"`
}
type WXH5AuthResp struct {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
type WXMiniAuthReq struct {
Code string `json:"code"`
}
type WXMiniAuthResp struct {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

View File

@@ -25,6 +25,8 @@ ADD INDEX `idx_withdrawal_type` (`withdrawal_type`);
ALTER TABLE `agent_withdrawal`
ADD INDEX `idx_type_status` (`withdrawal_type`, `status`);
-- ============================================
-- 说明:
-- 1. withdrawal_type 默认值为 1支付宝兼容历史数据

View File

@@ -1,5 +1,5 @@
services:
services:
mysql:
image: mysql:8.0.34
container_name: ycc_mysql
@@ -8,7 +8,7 @@ services:
TZ: Asia/Shanghai
# root 密码 - root password
MYSQL_ROOT_PASSWORD: yfg87gyuYiy1
MYSQL_DATABASE: ycc
MYSQL_DATABASE: yccq
MYSQL_USER: ycc
MYSQL_PASSWORD: 5vg67b3UNHu8
ports:

10
go.mod
View File

@@ -6,9 +6,10 @@ toolchain go1.23.4
require (
github.com/Masterminds/squirrel v1.5.4
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10
github.com/alibabacloud-go/captcha-20230305 v1.1.3
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13
github.com/alibabacloud-go/dysmsapi-20170525/v3 v3.0.6
github.com/alibabacloud-go/tea v1.2.2
github.com/alibabacloud-go/tea v1.3.13
github.com/alibabacloud-go/tea-utils/v2 v2.0.7
github.com/bytedance/sonic v1.13.0
github.com/fogleman/gg v1.3.0
@@ -39,13 +40,12 @@ require (
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
github.com/alibabacloud-go/openapi-util v0.1.0 // indirect
github.com/alibabacloud-go/tea-utils v1.3.1 // indirect
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
github.com/aliyun/credentials-go v1.3.10 // indirect
github.com/aliyun/credentials-go v1.4.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bytedance/sonic/loader v0.2.2 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/clbanning/mxj/v2 v2.5.5 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/fatih/color v1.17.0 // indirect

44
go.sum
View File

@@ -13,6 +13,8 @@ github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6/go.mod h1:4EUIoxs/do2
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc=
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 h1:zE8vH9C7JiZLNJJQ5OwjU9mSi4T9ef9u3BURT6LCLC8=
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5/go.mod h1:tWnyE9AjF8J8qqLk645oUmVUnFybApTQWklQmi5tY6g=
github.com/alibabacloud-go/captcha-20230305 v1.1.3 h1:0Aobw12m3x28aeDMPjwjXsfF8MuLvRjlQ4Hhoy5hFOY=
github.com/alibabacloud-go/captcha-20230305 v1.1.3/go.mod h1:ydzBIN2OiM7eeQPpAFyBrv1H5TY1MtUP2rQig44C4UQ=
github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY=
github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI=
github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE=
@@ -20,8 +22,8 @@ github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F
github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc=
github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.2/go.mod h1:5JHVmnHvGzR2wNdgaW1zDLQG8kOC4Uec8ubkMogW7OQ=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 h1:GEYkMApgpKEVDn6z12DcH1EGYpDYRB8JxsazM4Rywak=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10/go.mod h1:26a14FGhZVELuz2cc2AolvW4RHmIO3/HRwsdHhaIPDE=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13 h1:Q00FU3H94Ts0ZIHDmY+fYGgB7dV9D/YX6FGsgorQPgw=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13/go.mod h1:lxFGfobinVsQ49ntjpgWghXmIF0/Sm4+wvBJ1h5RtaE=
github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg=
github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ=
github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo=
@@ -44,19 +46,17 @@ github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/Ke
github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea v1.1.19/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea v1.2.2 h1:aTsR6Rl3ANWPfqeQugPglfurloyBJY85eFy7Gc1+8oU=
github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk=
github.com/alibabacloud-go/tea v1.3.13 h1:WhGy6LIXaMbBM6VBYcsDCz6K/TPsT1Ri2hPmmZffZ94=
github.com/alibabacloud-go/tea v1.3.13/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=
github.com/alibabacloud-go/tea-utils v1.3.1 h1:iWQeRzRheqCMuiF3+XkfybB3kTgUXkXX+JMrqfLeB2I=
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
github.com/alibabacloud-go/tea-utils/v2 v2.0.0/go.mod h1:U5MTY10WwlquGPS34DOeomUGBB0gXbLueiq5Trwu0C4=
github.com/alibabacloud-go/tea-utils/v2 v2.0.3/go.mod h1:sj1PbjPodAVTqGTA3olprfeeqqmwD0A5OQz94o9EuXQ=
github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4=
github.com/alibabacloud-go/tea-utils/v2 v2.0.6/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0=
github.com/alibabacloud-go/tea-utils/v2 v2.0.7/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
github.com/alibabacloud-go/tea-xml v1.1.2/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0=
github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE=
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/miniredis/v2 v2.33.0 h1:uvTF0EDeu9RLnUEG27Db5I68ESoIxTiXbNUiji6lZrA=
@@ -64,8 +64,8 @@ github.com/alicebob/miniredis/v2 v2.33.0/go.mod h1:MhP4a3EU7aENRi9aO+tHfTBZicLqQ
github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0=
github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM=
github.com/aliyun/credentials-go v1.3.10 h1:45Xxrae/evfzQL9V10zL3xX31eqgLWEaIdCoPipOEQA=
github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
github.com/aliyun/credentials-go v1.4.5 h1:O76WYKgdy1oQYYiJkERjlA2dxGuvLRrzuO2ScrtGWSk=
github.com/aliyun/credentials-go v1.4.5/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
@@ -83,8 +83,9 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
@@ -234,8 +235,6 @@ github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/smartwalle/alipay/v3 v3.2.28 h1:pANvguTjmFtfTw3le44qjQHYDrRcjCy8r8YUonFeblE=
github.com/smartwalle/alipay/v3 v3.2.28/go.mod h1:dwPyjY5y17qUsDrsVYCQqmDBtQ/qpvY8JmQMvuJYGLQ=
github.com/smartwalle/alipay/v3 v3.2.29-0.20251230233706-e15a4853bc1c h1:o48e92wOA4wuoWHtugNBU2wizp9ui4skQNcpqxcvgsM=
github.com/smartwalle/alipay/v3 v3.2.29-0.20251230233706-e15a4853bc1c/go.mod h1:dwPyjY5y17qUsDrsVYCQqmDBtQ/qpvY8JmQMvuJYGLQ=
github.com/smartwalle/ncrypto v1.0.4 h1:P2rqQxDepJwgeO5ShoC+wGcK2wNJDmcdBOWAksuIgx8=
@@ -326,10 +325,13 @@ golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -342,6 +344,9 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -356,10 +361,13 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -370,6 +378,9 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -384,20 +395,27 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -406,6 +424,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
@@ -420,6 +440,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

107
pkg/captcha/aliyun.go Normal file
View File

@@ -0,0 +1,107 @@
package captcha
import (
"context"
"os"
"strings"
captcha20230305 "github.com/alibabacloud-go/captcha-20230305/client"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
"github.com/alibabacloud-go/tea/tea"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"ycc-server/common/xerr"
)
// 用于在 context 中传递 User-Agent 的 key仅本包读取
type ctxKey struct{}
var userAgentCtxKey = &ctxKey{}
// WithUserAgent 将 User-Agent 写入 context供 Verify 判断是否微信环境
func WithUserAgent(ctx context.Context, userAgent string) context.Context {
if ctx == nil {
return ctx
}
return context.WithValue(ctx, userAgentCtxKey, userAgent)
}
// isWechatUserAgent 判断是否为微信内置浏览器含小程序、H5
func isWechatUserAgent(ua string) bool {
return strings.Contains(ua, "MicroMessenger")
}
// Config 验证码配置
type Config struct {
AccessKeyID string
AccessKeySecret string
EndpointURL string
SceneID string
}
// Verify 验证阿里云滑块验证码。若 ctx 中带有 User-Agent 且为微信环境则跳过验证(默认成功)。
func Verify(ctx context.Context, cfg Config, captchaVerifyParam string) error {
// 开发环境跳过验证
if os.Getenv("ENV") == "development" {
logx.Info("[Captcha] 开发环境,跳过验证码校验")
return nil
}
// 微信环境(内置浏览器/小程序)跳过图形验证码,不要求 captchaVerifyParam
if ua, ok := ctx.Value(userAgentCtxKey).(string); ok && ua != "" && isWechatUserAgent(ua) {
logx.Info("[Captcha] 微信环境,跳过图形验证码校验")
return nil
}
// 检查参数
if captchaVerifyParam == "" {
return errors.Wrapf(xerr.NewErrMsg("图形验证码校验失败"), "empty captchaVerifyParam")
}
// 创建客户端配置
clientCfg := &openapi.Config{
AccessKeyId: tea.String(cfg.AccessKeyID),
AccessKeySecret: tea.String(cfg.AccessKeySecret),
}
clientCfg.Endpoint = tea.String(cfg.EndpointURL)
// 创建客户端
client, err := captcha20230305.NewClient(clientCfg)
if err != nil {
logx.Errorf("[Captcha] 创建阿里云验证码客户端失败: %+v", err)
// 客户端创建失败时,为了不影响业务可用性,记录日志但视为通过
// 可根据风险偏好调整此策略
return nil
}
// 构建验证请求
req := &captcha20230305.VerifyIntelligentCaptchaRequest{
SceneId: tea.String(cfg.SceneID),
CaptchaVerifyParam: tea.String(captchaVerifyParam),
}
// 调用验证接口
resp, err := client.VerifyIntelligentCaptcha(req)
if err != nil {
logx.Errorf("[Captcha] 调用阿里云验证码接口失败: %+v", err)
// 接口调用失败时,为了不影响业务可用性,记录日志但视为通过
// 可根据风险偏好调整此策略
return nil
}
// 检查验证结果
if resp == nil || resp.Body == nil || resp.Body.Result == nil {
logx.Errorf("[Captcha] 阿里云验证码响应异常: resp=%+v", resp)
return errors.Wrapf(xerr.NewErrMsg("图形验证码校验失败"), "invalid response")
}
if tea.BoolValue(resp.Body.Result.VerifyResult) {
logx.Info("[Captcha] 验证码校验通过")
return nil
}
// 验证失败
logx.Errorf("[Captcha] 验证码校验失败: code=%s", tea.StringValue(resp.Body.Result.VerifyCode))
return errors.Wrapf(xerr.NewErrMsg("图形验证码校验失败"), "verify failed: %s", tea.StringValue(resp.Body.Result.VerifyCode))
}

View File

@@ -0,0 +1,36 @@
package captcha
import (
"encoding/base64"
"fmt"
"time"
"ycc-server/pkg/lzkit/crypto"
)
// GenerateEncryptedSceneID 生成加密的场景ID
// 格式: sceneId&timestamp&expireTime -> AES-256-CBC + PKCS7 -> Base64(IV + ciphertext)
func GenerateEncryptedSceneID(sceneId, ekey string, expireSeconds int) (string, error) {
// 参数校验
if expireSeconds <= 0 || expireSeconds > 86400 {
expireSeconds = 3600 // 默认1小时
}
// 构建明文: sceneId&timestamp&expireTime
ts := time.Now().Unix()
plaintext := fmt.Sprintf("%s&%d&%d", sceneId, ts, expireSeconds)
// 解码 ekeyBase64 -> 32字节密钥
keyBytes, err := base64.StdEncoding.DecodeString(ekey)
if err != nil {
return "", fmt.Errorf("decode ekey error: %w", err)
}
// 验证密钥长度AES-256 需要 32 字节)
if len(keyBytes) != 32 {
return "", fmt.Errorf("invalid ekey length, need 32 bytes after base64 decode, got %d", len(keyBytes))
}
// 使用 AES 加密
return crypto.AesEncrypt([]byte(plaintext), keyBytes)
}

View File

@@ -61,6 +61,91 @@ func TestAesEcbHexEncryption(t *testing.T) {
}
}
// 需要解密的身份证密文(可替换为其他密文进行测试)
const encryptedIDCardForTest = "z4pIrjlrpfsBtF74kvtRWnjM2UTx8Uq8HVA8dk9hSeI="
// TestDecryptIDCard 身份证解密单元测试(已知密文)
func TestDecryptIDCard(t *testing.T) {
fmt.Printf("encryptedIDC开始解密")
key, _ := hex.DecodeString("ff83609b2b24fc73196aac3d3dfb874f")
fmt.Printf("key: %s\n", key)
decrypted, err := DecryptIDCard(encryptedIDCardForTest, key)
if err != nil {
t.Fatalf("身份证解密失败: %v", err)
}
fmt.Printf("decrypted: %s\n", decrypted)
}
// TestEncryptIDCard_DecryptIDCard 身份证加密解密 round-trip 测试
func TestEncryptIDCard_DecryptIDCard(t *testing.T) {
idCard := "51018219920914121x"
key, _ := hex.DecodeString("ff83609b2b24fc73196aac3d3dfb874f")
// 加密
fmt.Printf("idCard: %s\n", idCard)
encrypted, err := EncryptIDCard(idCard, key)
if err != nil {
t.Fatalf("身份证加密失败: %v", err)
}
fmt.Printf("encrypted: %s\n", encrypted)
// 解密
decrypted, err := DecryptIDCard("Ix2KZkm22Uuw8FfgmWYzdRoo7lEtuTpiT8mwkQqNrdk=", key)
if err != nil {
t.Fatalf("身份证解密失败: %v", err)
}
fmt.Printf("decrypted: %s\n", decrypted)
if decrypted != idCard {
t.Errorf("解密结果不匹配,期望: %s, 实际: %s", idCard, decrypted)
}
}
// TestDecryptIDCard_EdgeCases 身份证解密边界情况
func TestDecryptIDCard_EdgeCases(t *testing.T) {
key, _ := hex.DecodeString("ff83609b2b24fc73196aac3d3dfb874f")
t.Run("空密文", func(t *testing.T) {
_, err := DecryptIDCard("", key)
if err == nil {
t.Error("空密文应返回错误")
}
})
t.Run("无效Base64", func(t *testing.T) {
_, err := DecryptIDCard("invalid-base64!!!@#$", key)
if err == nil {
t.Error("无效Base64应返回错误")
}
})
t.Run("错误密钥", func(t *testing.T) {
encrypted, err := EncryptIDCard("440101199001011234", key)
if err != nil {
t.Fatalf("加密失败: %v", err)
}
wrongKey, _ := hex.DecodeString("00000000000000000000000000000000")
_, err = DecryptIDCard(encrypted, wrongKey)
if err == nil {
t.Error("错误密钥应返回错误")
}
})
t.Run("密文长度不是块大小整数倍", func(t *testing.T) {
shortCipher := base64.StdEncoding.EncodeToString([]byte("short"))
_, err := DecryptIDCard(shortCipher, key)
if err == nil {
t.Error("密文长度异常应返回错误")
}
})
t.Run("加密空身份证应返回错误", func(t *testing.T) {
_, err := EncryptIDCard("", key)
if err == nil {
t.Error("空身份证号应返回错误")
}
})
}
func TestAesEcbKeyValidation(t *testing.T) {
// 测试不同长度的密钥
validKeys := [][]byte{