让七月迭代具备可直接部署的配置基线

补齐三套环境配置、测试环境部署门禁与 system_config 初始化,并按当前无企微应用的约束将企微凭据改为明文存储。

Constraint: 当前测试环境尚无企微应用及历史企微密文数据

Rejected: 使用启动环境变量加密企微凭据 | 用户明确要求直接明文保存并移除加密密钥

Confidence: high

Scope-risk: moderate

Directive: 企微真实闭环完成前保持两个旧审批入口开关为 true

Tested: gofmt;git diff --check;bash -n;docker compose config;Gitea workflow YAML 解析;OpenAPI 重新生成

Not-tested: go test;常规 go build;LSP;实际数据库迁移;真实测试环境部署;企微真实联调
This commit is contained in:
2026-07-25 18:18:45 +08:00
parent 73f5125d3d
commit cb26217205
29 changed files with 277 additions and 232 deletions

View File

@@ -34,11 +34,6 @@ type TokenApplicationRepository interface {
MarkConnected(ctx context.Context, applicationID uint, connectedAt time.Time) error
}
// TokenCredentialCipher 定义 access_token Provider 所需的凭据解密边界。
type TokenCredentialCipher interface {
Decrypt(ciphertext []byte) (string, error)
}
// TokenIntegrationLog 定义企微外呼的 Integration Log 边界。
type TokenIntegrationLog interface {
Start(ctx context.Context, input integrationlog.Attempt) (*model.IntegrationLog, error)
@@ -48,7 +43,6 @@ type TokenIntegrationLog interface {
// TokenProvider 按应用缓存企业微信 access_token并用 Redis 短锁抑制并发回源。
type TokenProvider struct {
repo TokenApplicationRepository
cipher TokenCredentialCipher
redis *redis.Client
integration TokenIntegrationLog
httpClient *http.Client
@@ -60,7 +54,6 @@ type TokenProvider struct {
// NewTokenProvider 创建企业微信 access_token Provider。
func NewTokenProvider(
repo TokenApplicationRepository,
cipher TokenCredentialCipher,
redisClient *redis.Client,
integration TokenIntegrationLog,
baseURL string,
@@ -71,7 +64,7 @@ func NewTokenProvider(
timeout = constants.WeComDefaultHTTPTimeout
}
return &TokenProvider{
repo: repo, cipher: cipher, redis: redisClient, integration: integration,
repo: repo, redis: redisClient, integration: integration,
httpClient: &http.Client{Timeout: timeout}, baseURL: strings.TrimRight(baseURL, "/"),
logger: logger, now: time.Now,
}
@@ -79,7 +72,7 @@ func NewTokenProvider(
// GetAccessToken 优先读取应用缓存,未命中时串行调用企业微信 Token 接口。
func (p *TokenProvider) GetAccessToken(ctx context.Context, applicationID uint) (string, error) {
if p == nil || p.repo == nil || p.cipher == nil || p.integration == nil || p.httpClient == nil || applicationID == 0 {
if p == nil || p.repo == nil || p.integration == nil || p.httpClient == nil || applicationID == 0 {
return "", errors.New(errors.CodeWeComCredentialInvalid)
}
cacheKey := constants.RedisWeComAccessTokenKey(applicationID)
@@ -162,11 +155,7 @@ func (p *TokenProvider) fetchAndCache(ctx context.Context, applicationID uint, c
if err != nil {
return "", err
}
secret, err := p.cipher.Decrypt(application.SecretCiphertext)
if err != nil {
return "", err
}
request, err := p.newTokenRequest(ctx, application.CorpID, secret)
request, err := p.newTokenRequest(ctx, application.CorpID, application.Secret)
if err != nil {
return "", err
}