You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
4.0 KiB
113 lines
4.0 KiB
package comm
|
|
|
|
import (
|
|
"context"
|
|
cryptorand "crypto/rand"
|
|
"yunyan/lego/base"
|
|
"yunyan/lego/core"
|
|
"yunyan/pb"
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
type IService interface {
|
|
base.IRPCXService
|
|
GetUserSession(ctx context.Context, mate map[string]string) (session IUserSession)
|
|
PutUserSession(session IUserSession)
|
|
}
|
|
|
|
// ApiInterceptor API 请求拦截器函数
|
|
// 在 handler 执行前调用,返回 *pb.ErrorData 表示拦截(不继续执行handler),返回 nil 表示放行
|
|
type ApiInterceptor func(apiName string, session IUserSession, msg interface{}) *pb.ErrorData
|
|
|
|
// ApiAuditFunc API 请求审计回调函数
|
|
// apiName: 接口名称, session: 用户会话, reqBody: 请求体, respBody: 响应体, code: 状态码, costMs: 耗时(毫秒)
|
|
type ApiAuditFunc func(apiName string, session IUserSession, reqBody []byte, respBody []byte, code int32, costMs int64)
|
|
|
|
type ISC_HttpRouteComp interface {
|
|
core.IServiceComp
|
|
Rpc_GatewayHttpRoute(ctx context.Context, args *pb.Rpc_GatewayHttpRouteReq, reply *pb.Rpc_GatewayHttpRouteResp) error
|
|
//注册路由
|
|
RegisterRoute(methodName string, isEncrypt bool, comp reflect.Value, msg reflect.Type, handle reflect.Method)
|
|
AddInterceptor(interceptor ApiInterceptor) // 添加 API 请求拦截器
|
|
AddApiAuditHook(hook ApiAuditFunc) // 添加 API 审计回调钩子
|
|
}
|
|
|
|
// 用户会话
|
|
type IUserSession interface {
|
|
context.Context
|
|
SetSession(ctx context.Context, mate map[string]string)
|
|
GetMateToString(key string) string
|
|
GetMateToInt64(key string) int64
|
|
GetMateToUInt64(key string) uint64
|
|
GetMateToInt32(key string) int32
|
|
GetMateToFloat64(key string) float64
|
|
SetMateForFloat64(key string, value float64)
|
|
SetMateForInt64(key string, value int64)
|
|
GetMateToBool(key string) bool
|
|
GetIP() string
|
|
GetUserId() string
|
|
Reset()
|
|
SetMate(name string, value string)
|
|
SetMates(meta map[string]string)
|
|
GetMate(name string) (value string, ok bool)
|
|
SetCache(name string, value interface{})
|
|
GetCache(name string) (value interface{}, ok bool)
|
|
Clone() (session IUserSession) //克隆
|
|
GetMetas() (meta map[string]string)
|
|
}
|
|
|
|
type HttpResult struct {
|
|
// 错误代码
|
|
// @Description 响应结果的错误码 0 表示成功
|
|
// @example 0
|
|
Code pb.ErrorCode `json:"code" example:"0" description:"请求回应Code 0表示成功 非0 请求异常"`
|
|
// 消息说明
|
|
// @Description 响应结果的消息 请求返回的描述信息
|
|
// @example "Success"
|
|
Message string `json:"msg" example:"Success" description:"code 对应的描述信息"`
|
|
// 数据部分,可能是多种类型
|
|
// @Description 响应的数据,类型可变
|
|
// @oneOf User Product Order
|
|
// @example {"id": 1, "name": "John Doe"}
|
|
Data interface{} `json:"data" description:"返回的数据对象"`
|
|
}
|
|
|
|
// ai 工具结构
|
|
type IAITool struct {
|
|
}
|
|
|
|
// ShortCodeCharset 短码字符集(32 字符,去除易混的 0/O/I/1):人眼可读、可手抄/可打印。
|
|
const ShortCodeCharset = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"
|
|
|
|
// GenerateShortCode 生成指定长度的可读短码。厂家公码/批次号/渠道商 id 共用同一字符集,
|
|
// 长度不同以便肉眼区分(公码与批次 6 位、渠道商 8 位)。
|
|
func GenerateShortCode(length int) (string, error) {
|
|
if length <= 0 {
|
|
return "", fmt.Errorf("短码长度必须大于 0")
|
|
}
|
|
buf := make([]byte, length)
|
|
rb := make([]byte, length)
|
|
if _, err := cryptorand.Read(rb); err != nil {
|
|
return "", fmt.Errorf("生成短码失败: %v", err)
|
|
}
|
|
for i := 0; i < length; i++ {
|
|
buf[i] = ShortCodeCharset[int(rb[i])%len(ShortCodeCharset)]
|
|
}
|
|
return string(buf), nil
|
|
}
|
|
|
|
// ChannelIdLength 渠道商 id 短码长度(8 位,与 6 位的公码/批次号区分开)。
|
|
const ChannelIdLength = 8
|
|
|
|
// GeneratePublicCode 生成厂家公码(6 位短码,字符集去除易混的 0/O/I/1)
|
|
// 用于厂家公码场景:人眼可读、可手抄/可打印
|
|
func GeneratePublicCode() (string, error) {
|
|
return GenerateShortCode(6)
|
|
}
|
|
|
|
// GenerateChannelId 生成渠道商 id(8 位短码)。唯一性由表的主键与调用方的重试兜底。
|
|
func GenerateChannelId() (string, error) {
|
|
return GenerateShortCode(ChannelIdLength)
|
|
}
|
|
|
|
|