This commit is contained in:
2026-03-13 15:51:59 +08:00
parent 4db2386bbf
commit 4e91f4cede
133 changed files with 19502 additions and 37 deletions

View File

@@ -0,0 +1,141 @@
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_idapp_ + 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 字节随机 secret64位hex
func generateSecret() string {
b := make([]byte, 32)
_, _ = rand.Read(b)
return strings.ToUpper(hex.EncodeToString(b))
}