Files
wangjia b5ab92a57e
ci / server (push) Failing after 13s
ci / design-tokens (push) Failing after 11s
fix: 应用 xhigh 代码评审的跨端修复
来自 xhigh code review 的正确性/健壮性修复,覆盖全部五端:
- server:鉴权 fail-closed、计量交叉校验与配额扣穿处理、WS 网关并发与关闭顺序、
  billing 行锁、redis Lua 过期与设备槽刷新、config 解析
- desktop:会话 epoch 防串话、WS 重连与 401 处理、api 客户端复用、统一 usePoll 轮询
- android:握手时序、请求头封装、账户状态派生、按需重组
- ios:finalize 宽限、串行采集、错误文案服务端优先、删除死代码 CommitController

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 11:50:08 +08:00

110 lines
3.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package config 环境变量配置(密钥经部署注入,本地开发用 .env.local / docker compose)。
package config
import (
"encoding/json"
"log/slog"
"os"
"strconv"
"dudu/server/pkg/protocol"
)
type Config struct {
Addr string // HTTP 监听地址
PostgresDSN string
RedisAddr string
RedisDB int
JWTSecret string
JWTTTLHours int
// 微信开放平台 / 商户号(申请中可留空,相关模块降级为 mock)
WechatWebAppID string
WechatWebSecret string
WechatMobileAppID string
WechatMobileSecret string
WxPayMchID string
WxPayCertSerial string
WxPayPrivateKeyPEM string
WxPayAPIv3Key string
WxPayNotifyURL string
// ASR
ASRProvider string // gummy | mock
DashScopeAPIKey string
// OSS(反馈图片)
OSSEndpoint string
OSSBucket string
OSSKeyID string
OSSKeySecret string
// AppLatest 启动时解析 APP_LATEST_JSON 一次(17G):平台→版本信息。
// 解析失败或未配置则为 nil/空,handler 据此返回 204,不 fail-fast。
AppLatest map[string]protocol.AppLatestResponse
}
func Load() Config {
return Config{
Addr: getenv("ADDR", ":8080"),
PostgresDSN: getenv("POSTGRES_DSN", "host=localhost user=dudu password=dudu dbname=dudu port=5432 sslmode=disable TimeZone=Asia/Shanghai"),
RedisAddr: getenv("REDIS_ADDR", "localhost:6379"),
RedisDB: getint("REDIS_DB", 0),
JWTSecret: getenv("JWT_SECRET", "dev-secret-change-me"),
JWTTTLHours: getint("JWT_TTL_HOURS", 24*7),
WechatWebAppID: os.Getenv("WECHAT_WEB_APPID"),
WechatWebSecret: os.Getenv("WECHAT_WEB_SECRET"),
WechatMobileAppID: os.Getenv("WECHAT_MOBILE_APPID"),
WechatMobileSecret: os.Getenv("WECHAT_MOBILE_SECRET"),
WxPayMchID: os.Getenv("WXPAY_MCHID"),
WxPayCertSerial: os.Getenv("WXPAY_CERT_SERIAL"),
WxPayPrivateKeyPEM: os.Getenv("WXPAY_PRIVATE_KEY_PEM"),
WxPayAPIv3Key: os.Getenv("WXPAY_APIV3_KEY"),
WxPayNotifyURL: os.Getenv("WXPAY_NOTIFY_URL"),
ASRProvider: getenv("ASR_PROVIDER", "mock"),
DashScopeAPIKey: os.Getenv("DASHSCOPE_API_KEY"),
OSSEndpoint: os.Getenv("OSS_ENDPOINT"),
OSSBucket: os.Getenv("OSS_BUCKET"),
OSSKeyID: os.Getenv("OSS_KEY_ID"),
OSSKeySecret: os.Getenv("OSS_KEY_SECRET"),
AppLatest: loadAppLatest(),
}
}
// loadAppLatest 启动时解析一次 APP_LATEST_JSON17G)。失败仅告警并返回 nil,
// 不 fail-fast——未配置此项时服务仍需正常启动。
func loadAppLatest() map[string]protocol.AppLatestResponse {
raw := os.Getenv("APP_LATEST_JSON")
if raw == "" {
return nil
}
var all map[string]protocol.AppLatestResponse
if err := json.Unmarshal([]byte(raw), &all); err != nil {
slog.Warn("invalid APP_LATEST_JSON, app update disabled", "err", err)
return nil
}
return all
}
func getenv(k, def string) string {
if v := os.Getenv(k); v != "" {
return v
}
return def
}
func getint(k string, def int) int {
if v := os.Getenv(k); v != "" {
if n, err := strconv.Atoi(v); err == nil {
return n
}
}
return def
}