|
|
package handler |
|
|
|
|
|
import ( |
|
|
"fmt" |
|
|
"log" |
|
|
"net/http" |
|
|
"strings" |
|
|
"time" |
|
|
|
|
|
"github.com/gin-gonic/gin" |
|
|
"zencoder-2api/internal/database" |
|
|
"zencoder-2api/internal/model" |
|
|
"zencoder-2api/internal/service" |
|
|
) |
|
|
|
|
|
type ExternalHandler struct{} |
|
|
|
|
|
func NewExternalHandler() *ExternalHandler { |
|
|
return &ExternalHandler{} |
|
|
} |
|
|
|
|
|
|
|
|
type ExternalTokenRequest struct { |
|
|
AccessToken string `json:"access_token"` |
|
|
RefreshToken string `json:"refresh_token"` |
|
|
Proxy string `json:"proxy"` |
|
|
} |
|
|
|
|
|
|
|
|
type ExternalTokenResponse struct { |
|
|
Success bool `json:"success"` |
|
|
Message string `json:"message"` |
|
|
Account *model.Account `json:"account,omitempty"` |
|
|
Error string `json:"error,omitempty"` |
|
|
} |
|
|
|
|
|
|
|
|
func (h *ExternalHandler) SubmitTokens(c *gin.Context) { |
|
|
var req ExternalTokenRequest |
|
|
if err := c.ShouldBindJSON(&req); err != nil { |
|
|
c.JSON(http.StatusBadRequest, ExternalTokenResponse{ |
|
|
Success: false, |
|
|
Error: "请求格式错误: " + err.Error(), |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if req.AccessToken == "" && req.RefreshToken == "" { |
|
|
c.JSON(http.StatusBadRequest, ExternalTokenResponse{ |
|
|
Success: false, |
|
|
Error: "必须提供 access_token 或 refresh_token", |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
log.Printf("[外部API] 收到token提交请求,access_token长度: %d, refresh_token长度: %d", |
|
|
len(req.AccessToken), len(req.RefreshToken)) |
|
|
|
|
|
|
|
|
var masterToken string |
|
|
|
|
|
if req.AccessToken != "" { |
|
|
|
|
|
masterToken = req.AccessToken |
|
|
log.Printf("[外部API] 使用提供的 access_token") |
|
|
} else { |
|
|
|
|
|
tokenResp, err := service.RefreshAccessToken(req.RefreshToken, req.Proxy) |
|
|
if err != nil { |
|
|
c.JSON(http.StatusBadRequest, ExternalTokenResponse{ |
|
|
Success: false, |
|
|
Error: "RefreshToken 无效: " + err.Error(), |
|
|
}) |
|
|
return |
|
|
} |
|
|
masterToken = tokenResp.AccessToken |
|
|
log.Printf("[外部API] 通过 RefreshToken 获取了 access_token") |
|
|
} |
|
|
|
|
|
log.Printf("[外部API] 开始生成账号凭证") |
|
|
|
|
|
|
|
|
cred, err := service.GenerateCredential(masterToken) |
|
|
if err != nil { |
|
|
c.JSON(http.StatusInternalServerError, ExternalTokenResponse{ |
|
|
Success: false, |
|
|
Error: fmt.Sprintf("生成失败: %v", err), |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
log.Printf("[外部API] 凭证生成成功: ClientID=%s", cred.ClientID) |
|
|
|
|
|
|
|
|
account := model.Account{ |
|
|
ClientID: cred.ClientID, |
|
|
ClientSecret: cred.Secret, |
|
|
Proxy: req.Proxy, |
|
|
IsActive: true, |
|
|
Status: "normal", |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
maxRetries := 3 |
|
|
retryDelay := 2 * time.Second |
|
|
var lastErr error |
|
|
|
|
|
for attempt := 1; attempt <= maxRetries; attempt++ { |
|
|
log.Printf("[外部API] 尝试获取token,第 %d/%d 次", attempt, maxRetries) |
|
|
|
|
|
if _, err := service.RefreshToken(&account); err != nil { |
|
|
lastErr = err |
|
|
log.Printf("[外部API] 第 %d 次获取token失败: %v", attempt, err) |
|
|
|
|
|
if attempt < maxRetries { |
|
|
log.Printf("[外部API] 等待 %v 后重试", retryDelay) |
|
|
time.Sleep(retryDelay) |
|
|
continue |
|
|
} |
|
|
} else { |
|
|
log.Printf("[外部API] 第 %d 次获取token成功", attempt) |
|
|
lastErr = nil |
|
|
break |
|
|
} |
|
|
} |
|
|
|
|
|
if lastErr != nil { |
|
|
c.JSON(http.StatusBadRequest, ExternalTokenResponse{ |
|
|
Success: false, |
|
|
Error: fmt.Sprintf("认证失败(重试 %d 次后): %v", maxRetries, lastErr), |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
|
|
|
if payload, err := service.ParseJWT(account.AccessToken); err == nil { |
|
|
account.Email = payload.Email |
|
|
account.SubscriptionStartDate = service.GetSubscriptionDate(payload) |
|
|
|
|
|
if payload.Expiration > 0 { |
|
|
account.TokenExpiry = time.Unix(payload.Expiration, 0) |
|
|
} |
|
|
|
|
|
plan := payload.CustomClaims.Plan |
|
|
if plan != "" { |
|
|
plan = strings.ToUpper(plan[:1]) + plan[1:] |
|
|
} |
|
|
if plan != "" { |
|
|
account.PlanType = model.PlanType(plan) |
|
|
} |
|
|
} |
|
|
if account.PlanType == "" { |
|
|
account.PlanType = model.PlanFree |
|
|
} |
|
|
|
|
|
|
|
|
var existing model.Account |
|
|
var count int64 |
|
|
database.GetDB().Model(&model.Account{}).Where("client_id = ?", account.ClientID).Count(&count) |
|
|
if count > 0 { |
|
|
|
|
|
database.GetDB().Where("client_id = ?", account.ClientID).First(&existing) |
|
|
|
|
|
existing.AccessToken = account.AccessToken |
|
|
existing.TokenExpiry = account.TokenExpiry |
|
|
existing.PlanType = account.PlanType |
|
|
existing.Email = account.Email |
|
|
existing.SubscriptionStartDate = account.SubscriptionStartDate |
|
|
existing.IsActive = true |
|
|
existing.Status = "normal" |
|
|
existing.ClientSecret = account.ClientSecret |
|
|
if account.Proxy != "" { |
|
|
existing.Proxy = account.Proxy |
|
|
} |
|
|
|
|
|
if err := database.GetDB().Save(&existing).Error; err != nil { |
|
|
c.JSON(http.StatusInternalServerError, ExternalTokenResponse{ |
|
|
Success: false, |
|
|
Error: fmt.Sprintf("更新失败: %v", err), |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
log.Printf("[外部API] 账号更新成功: ClientID=%s, Email=%s, Plan=%s", existing.ClientID, existing.Email, existing.PlanType) |
|
|
c.JSON(http.StatusOK, ExternalTokenResponse{ |
|
|
Success: true, |
|
|
Message: "账号更新成功", |
|
|
Account: &existing, |
|
|
}) |
|
|
} else { |
|
|
|
|
|
if err := database.GetDB().Create(&account).Error; err != nil { |
|
|
c.JSON(http.StatusInternalServerError, ExternalTokenResponse{ |
|
|
Success: false, |
|
|
Error: fmt.Sprintf("创建失败: %v", err), |
|
|
}) |
|
|
return |
|
|
} |
|
|
|
|
|
log.Printf("[外部API] 新账号创建成功: ClientID=%s, Email=%s, Plan=%s", account.ClientID, account.Email, account.PlanType) |
|
|
c.JSON(http.StatusCreated, ExternalTokenResponse{ |
|
|
Success: true, |
|
|
Message: "账号创建成功", |
|
|
Account: &account, |
|
|
}) |
|
|
} |
|
|
} |