feat(server): 装配 reward 服务 — 注入 auth/webhook + 挂 /v1/invite、/tasks/telegram/start、/tg/webhook

This commit is contained in:
wangjia
2026-07-13 08:01:01 +08:00
parent e26284d072
commit c29aaf9a2a
+32 -1
View File
@@ -38,6 +38,7 @@ import (
"github.com/wangjia/pangolin/server/internal/provision"
"github.com/wangjia/pangolin/server/internal/provision/providers"
"github.com/wangjia/pangolin/server/internal/redisutil"
"github.com/wangjia/pangolin/server/internal/reward"
"github.com/wangjia/pangolin/server/internal/scheduler"
"github.com/wangjia/pangolin/server/internal/scheduler/probe"
"github.com/wangjia/pangolin/server/internal/sessions"
@@ -279,6 +280,7 @@ func mountV1(r chi.Router, sqlDB *sql.DB, rdb *redis.Client, nodeSvc *nodes.Serv
// ── Auth ──────────────────────────────────────────────────────────────────
var authHandler *auth.Handler
var authSvc *auth.Service
if tm != nil {
var mailer auth.Mailer
if smtpHost := os.Getenv("SMTP_HOST"); smtpHost != "" {
@@ -294,7 +296,7 @@ func mountV1(r chi.Router, sqlDB *sql.DB, rdb *redis.Client, nodeSvc *nodes.Serv
}
rl := auth.NewRateLimiter(rdb, nil)
authStore := auth.NewSQLStore(sqlDB)
authSvc := auth.NewService(authStore, rdb, rl, tm, mailer, auth.ServiceConfig{}, nil)
authSvc = auth.NewService(authStore, rdb, rl, tm, mailer, auth.ServiceConfig{}, nil)
authSvc.SetDeviceRegistrar(authDeviceRegistrar{svc: devicesSvc})
authSvc.SetSessionStore(sessionStore)
authHandler = auth.NewHandler(authSvc)
@@ -319,6 +321,31 @@ func mountV1(r chi.Router, sqlDB *sql.DB, rdb *redis.Client, nodeSvc *nodes.Serv
webhookHandler := codes.NewWebhookHandler(codesStore, rdb,
os.Getenv("WEBHOOK_SECRET"), 5*time.Minute, 15*time.Minute)
// ── Reward(邀请奖励 + 奖励任务)──────────────────────────────────────────
regCap := 10
if v := os.Getenv("INVITE_REG_MONTHLY_CAP"); v != "" {
if n, err := strconv.Atoi(v); err == nil && n > 0 {
regCap = n
}
}
rewardStore := reward.NewStore(sqlDB)
rewardSvc := reward.NewService(sqlDB, rewardStore, codesSvc,
reward.Config{RegDays: 3, PaidDays: 7, TgDays: 3, RegMonthlyCap: regCap}, nil)
rewardSvc.SetRedis(rdb)
tgBotToken := os.Getenv("TG_REWARD_BOT_TOKEN")
tgEnabled := tgBotToken != ""
if tgEnabled {
rewardSvc.SetTelegram(
getenvDefault("TG_REWARD_BOT_USER", "pangolin_reward_bot"),
getenvDefault("TG_REWARD_CHANNEL", "@pangolin_app"),
tgBotToken, os.Getenv("TG_WEBHOOK_SECRET"))
}
rewardHandler := reward.NewHandler(rewardSvc, rewardStore, tgEnabled,
getenvDefault("TG_REWARD_CHANNEL", "@pangolin_app"))
if authSvc != nil {
authSvc.SetReferralHook(rewardSvc)
}
// ── Pay(pay v2 统一支付网关;PAY_BASE_URL 未配则整组不挂载)──────────────
var payHandler *pay.Handler
var payWebhook *pay.WebhookHandler
@@ -333,6 +360,7 @@ func mountV1(r chi.Router, sqlDB *sql.DB, rdb *redis.Client, nodeSvc *nodes.Serv
payHandler = pay.NewHandler(payClient, payStore, sqlDB)
payWebhook = pay.NewWebhookHandler(payStore, codesSvc, sqlDB, rdb,
paySystem, paySecret, 5*time.Minute, 15*time.Minute)
payWebhook.SetRewarder(rewardSvc)
} else {
log.Printf("PAY_BASE_URL 未配置 — /v1/pay 支付端点不挂载")
}
@@ -421,6 +449,7 @@ func mountV1(r chi.Router, sqlDB *sql.DB, rdb *redis.Client, nodeSvc *nodes.Serv
if payWebhook != nil {
v1.Post("/webhook/pay", payWebhook.ServeHTTP)
}
v1.Post("/tg/webhook", rewardHandler.TelegramWebhook)
// Protected: all routes that require a valid Bearer JWT.
if tm != nil {
@@ -458,6 +487,8 @@ func mountV1(r chi.Router, sqlDB *sql.DB, rdb *redis.Client, nodeSvc *nodes.Serv
protected.Post("/pay/orders/{orderNo}/retry", payHandler.Retry)
protected.Post("/pay/orders/{orderNo}/cancel", payHandler.Cancel)
}
protected.Get("/invite", rewardHandler.GetInvite)
protected.Get("/tasks/telegram/start", rewardHandler.TelegramStart)
if nodeAPI != nil {
protected.Get("/nodes", nodeAPI.ListNodes)