package service import ( "context" "crypto/rand" "encoding/hex" "errors" "fmt" "strings" "time" "pay-bridge/internal/errcode" "pay-bridge/internal/model" "pay-bridge/internal/repository" "pay-bridge/pkg/crypto" ) // AppService 应用服务 type AppService struct { repo *repository.AppRepository encKey string } func NewAppService(repo *repository.AppRepository, encKey string) *AppService { return &AppService{repo: repo, encKey: encKey} } // GetAppSecret 获取 appSecret(用于鉴权中间件) func (s *AppService) GetAppSecret(ctx context.Context, appID string) (string, error) { app, err := s.repo.GetByAppID(ctx, appID) if err != nil { return "", err } if app == nil { return "", errors.New(errcode.ErrAppNotFound) } secret, err := crypto.Decrypt(app.AppSecret, s.encKey) if err != nil { return "", fmt.Errorf("decrypt app secret: %w", err) } return secret, nil } // GetApp 获取应用信息 func (s *AppService) GetApp(ctx context.Context, appID string) (*model.App, error) { return s.repo.GetByAppID(ctx, appID) } // CreateAppResult 创建应用的返回,包含明文 secret(仅展示一次) type CreateAppResult struct { App *model.App PlainSecret string } // CreateApp 创建应用,自动生成 app_id 和 app_secret func (s *AppService) CreateApp(ctx context.Context, appName string) (*CreateAppResult, error) { appID := generateAppID() plainSecret := generateSecret() encSecret, err := crypto.Encrypt(plainSecret, s.encKey) if err != nil { return nil, err } app := &model.App{ AppID: appID, AppSecret: encSecret, AppName: appName, Status: 1, } if err := s.repo.Create(ctx, app); err != nil { return nil, err } return &CreateAppResult{App: app, PlainSecret: plainSecret}, nil } // ListApps 分页查询应用列表 func (s *AppService) ListApps(ctx context.Context, limit, offset int) ([]*model.App, error) { return s.repo.List(ctx, limit, offset) } // DisableApp 禁用应用 func (s *AppService) DisableApp(ctx context.Context, appID string) error { app, err := s.repo.GetByAppIDUnscoped(ctx, appID) if err != nil { return err } if app == nil { return errors.New(errcode.ErrAppNotFound) } return s.repo.UpdateStatus(ctx, appID, 0) } // EnableApp 启用应用 func (s *AppService) EnableApp(ctx context.Context, appID string) error { app, err := s.repo.GetByAppIDUnscoped(ctx, appID) if err != nil { return err } if app == nil { return errors.New(errcode.ErrAppNotFound) } return s.repo.UpdateStatus(ctx, appID, 1) } // ResetSecret 重置应用密钥,返回新的明文 secret(仅此一次) func (s *AppService) ResetSecret(ctx context.Context, appID string) (string, error) { app, err := s.repo.GetByAppIDUnscoped(ctx, appID) if err != nil { return "", err } if app == nil { return "", errors.New(errcode.ErrAppNotFound) } plainSecret := generateSecret() encSecret, err := crypto.Encrypt(plainSecret, s.encKey) if err != nil { return "", err } if err := s.repo.UpdateSecret(ctx, appID, encSecret); err != nil { return "", err } return plainSecret, nil } // generateAppID 生成 app_id:app_ + yyMMdd + 8位随机hex func generateAppID() string { b := make([]byte, 4) _, _ = rand.Read(b) date := time.Now().Format("060102") return "app_" + date + hex.EncodeToString(b) } // generateSecret 生成 32 字节随机 secret(64位hex) func generateSecret() string { b := make([]byte, 32) _, _ = rand.Read(b) return strings.ToUpper(hex.EncodeToString(b)) }