This commit is contained in:
Mrx
2026-02-26 17:45:58 +08:00
parent e1fbf72437
commit f4deb0063b
15 changed files with 296 additions and 17 deletions

View File

@@ -26,6 +26,7 @@ type Config struct {
AdminPromotion AdminPromotion
TaxConfig TaxConfig
ExtensionTime int64
Captcha CaptchaConfig // 阿里云验证码配置
}
// JwtAuth 用于 JWT 鉴权配置
@@ -129,3 +130,12 @@ type TianyuanapiConfig struct {
type AuthorizationConfig struct {
FileBaseURL string // 授权书文件访问基础URL
}
// CaptchaConfig 阿里云验证码配置
type CaptchaConfig struct {
AccessKeyID string // 阿里云 AccessKey ID
AccessKeySecret string // 阿里云 AccessKey Secret
EndpointURL string // 验证码服务端点URL
SceneID string // 业务场景ID
EKey string // 网页验证码业务密钥
}

View File

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

View File

@@ -22,6 +22,7 @@ import (
app "tydata-server/app/main/api/internal/handler/app"
auth "tydata-server/app/main/api/internal/handler/auth"
authorization "tydata-server/app/main/api/internal/handler/authorization"
captcha "tydata-server/app/main/api/internal/handler/captcha"
notification "tydata-server/app/main/api/internal/handler/notification"
pay "tydata-server/app/main/api/internal/handler/pay"
product "tydata-server/app/main/api/internal/handler/product"
@@ -952,6 +953,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

@@ -7,6 +7,7 @@ import (
"os"
"time"
"tydata-server/common/xerr"
"tydata-server/pkg/captcha"
"tydata-server/pkg/lzkit/crypto"
"github.com/pkg/errors"
@@ -53,6 +54,23 @@ func (l *SendSmsLogic) SendSms(req *types.SendSmsReq) error {
return errors.Wrapf(xerr.NewErrMsg("一分钟内不能重复发送验证码"), "短信发送, 手机号1分钟内重复请求发送验证码: %s", encryptedMobile)
}
// 验证码校验
if os.Getenv("ENV") != "development" {
if req.CaptchaVerifyParam == "" {
return errors.Wrapf(xerr.NewErrMsg("图形验证码校验失败"), "短信发送, 验证码参数为空: %s", encryptedMobile)
}
captchaCfg := l.svcCtx.Config.Captcha
err = captcha.Verify(captcha.Config{
AccessKeyID: captchaCfg.AccessKeyID,
AccessKeySecret: captchaCfg.AccessKeySecret,
EndpointURL: captchaCfg.EndpointURL,
SceneID: captchaCfg.SceneID,
}, req.CaptchaVerifyParam)
if err != nil {
return errors.Wrapf(xerr.NewErrMsg("图形验证码校验失败"), "短信发送, 验证码校验失败: %s", encryptedMobile)
}
}
// 开发环境固定验证码为138888
env := os.Getenv("ENV")
var code string

View File

@@ -0,0 +1,38 @@
package captcha
import (
"context"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"tydata-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() (resp *types.GetEncryptedSceneIdResp, err error) {
captchaCfg := l.svcCtx.Config.Captcha
encryptedSceneId, err := captcha.GenerateEncryptedSceneID(captchaCfg.SceneID, captchaCfg.EKey, 3600)
if err != nil {
return nil, err
}
return &types.GetEncryptedSceneIdResp{
EncryptedSceneId: encryptedSceneId,
}, nil
}

View File

@@ -12,6 +12,7 @@ import (
"tydata-server/app/main/model"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"tydata-server/pkg/captcha"
"tydata-server/pkg/lzkit/crypto"
"tydata-server/pkg/lzkit/validator"
@@ -60,8 +61,23 @@ var productProcessors = map[string]func(*QueryServiceLogic, *types.QueryServiceR
}
func (l *QueryServiceLogic) PreprocessLogic(req *types.QueryServiceReq, product string) (*types.QueryServiceResp, error) {
if os.Getenv("ENV") != "development" {
if req.CaptchaVerifyParam == "" {
return nil, errors.Wrapf(xerr.NewErrMsg("图形验证码校验失败"), "查询服务, 验证码参数为空: %s", req.Product)
}
captchaCfg := l.svcCtx.Config.Captcha
err := captcha.Verify(captcha.Config{
AccessKeyID: captchaCfg.AccessKeyID,
AccessKeySecret: captchaCfg.AccessKeySecret,
EndpointURL: captchaCfg.EndpointURL,
SceneID: captchaCfg.SceneID,
}, req.CaptchaVerifyParam)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrMsg("图形验证码校验失败"), "查询服务, 验证码校验失败: %s", req.Product)
}
}
if processor, exists := productProcessors[product]; exists {
return processor(l, req) // 调用对应的处理函数
return processor(l, req)
}
return nil, errors.New("未找到相应的处理程序")
}

View File

@@ -1540,6 +1540,10 @@ type GetCommissionResp struct {
List []Commission `json:"list"` // 查询列表
}
type GetEncryptedSceneIdResp struct {
EncryptedSceneId string `json:"encryptedSceneId"`
}
type GetLinkDataReq struct {
LinkIdentifier string `form:"link_identifier"`
}
@@ -2043,10 +2047,11 @@ type QueryRetryResp struct {
}
type QueryServiceReq struct {
Product string `path:"product"`
Data string `json:"data" validate:"required"`
AgentIdentifier string `json:"agent_identifier,optional"`
App bool `json:"app,optional"`
Product string `path:"product"`
Data string `json:"data" validate:"required"`
AgentIdentifier string `json:"agent_identifier,optional"`
App bool `json:"app,optional"`
CaptchaVerifyParam string `json:"captchaVerifyParam"`
}
type QueryServiceResp struct {
@@ -2220,6 +2225,7 @@ type GetAppVersionResp struct {
}
type SendSmsReq struct {
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"`
}