Refactor WeChat integration to support multiple mini programs, removing hardcoded WeChat credentials and updating user model and authentication flow accordingly.

This commit is contained in:
nepiedg
2025-12-29 11:25:35 +00:00
parent 9b47421b45
commit 589223ebd3
10 changed files with 224 additions and 79 deletions
+63 -25
View File
@@ -4,46 +4,67 @@ import (
"context"
"errors"
"fmt"
"strings"
"sync"
"wx_service/internal/model"
"gorm.io/gorm"
)
var ErrCodeRequired = errors.New("code is required")
var (
ErrCodeRequired = errors.New("code is required")
ErrMiniProgramRequired = errors.New("mini program id is required")
ErrMiniProgramNotFound = errors.New("mini program not found")
)
type AuthService struct {
db *gorm.DB
wechat *WeChatClient
db *gorm.DB
miniProgramSvc *MiniProgramService
wechatClientCache map[uint]*WeChatClient
cacheMu sync.RWMutex
}
type LoginRequest struct {
Code string
NickName string
AvatarURL string
Gender *int
Phone string
MiniProgramID uint
Code string
NickName string
AvatarURL string
Gender *int
Phone string
}
type LoginResult struct {
User *model.User
SessionKey string
User *model.User
SessionKey string
MiniProgram *model.MiniProgram
}
func NewAuthService(db *gorm.DB, wechat *WeChatClient) *AuthService {
func NewAuthService(db *gorm.DB, miniProgramSvc *MiniProgramService) *AuthService {
return &AuthService{
db: db,
wechat: wechat,
db: db,
miniProgramSvc: miniProgramSvc,
wechatClientCache: make(map[uint]*WeChatClient),
}
}
func (s *AuthService) LoginWithCode(ctx context.Context, req LoginRequest) (*LoginResult, error) {
if strings.TrimSpace(req.Code) == "" {
if req.MiniProgramID == 0 {
return nil, ErrMiniProgramRequired
}
if req.Code == "" {
return nil, ErrCodeRequired
}
session, err := s.wechat.Code2Session(ctx, req.Code)
miniProgram, err := s.miniProgramSvc.GetByID(ctx, req.MiniProgramID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrMiniProgramNotFound
}
return nil, fmt.Errorf("load mini program: %w", err)
}
client := s.getWeChatClient(miniProgram)
session, err := client.Code2Session(ctx, req.Code)
if err != nil {
return nil, err
}
@@ -53,15 +74,16 @@ func (s *AuthService) LoginWithCode(ctx context.Context, req LoginRequest) (*Log
tx := s.db.WithContext(ctx)
var user model.User
err = tx.Where("open_id = ?", session.OpenID).First(&user).Error
err = tx.Where("mini_program_id = ? AND open_id = ?", miniProgram.ID, session.OpenID).First(&user).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
user = model.User{
OpenID: session.OpenID,
UnionID: session.UnionID,
NickName: req.NickName,
AvatarURL: req.AvatarURL,
Phone: req.Phone,
SessionKey: session.SessionKey,
MiniProgramID: miniProgram.ID,
OpenID: session.OpenID,
UnionID: session.UnionID,
NickName: req.NickName,
AvatarURL: req.AvatarURL,
Phone: req.Phone,
SessionKey: session.SessionKey,
}
if req.Gender != nil {
user.Gender = *req.Gender
@@ -104,8 +126,24 @@ func (s *AuthService) LoginWithCode(ctx context.Context, req LoginRequest) (*Log
}
result := &LoginResult{
User: &user,
SessionKey: session.SessionKey,
User: &user,
SessionKey: session.SessionKey,
MiniProgram: miniProgram,
}
return result, nil
}
func (s *AuthService) getWeChatClient(mp *model.MiniProgram) *WeChatClient {
s.cacheMu.RLock()
client, ok := s.wechatClientCache[mp.ID]
s.cacheMu.RUnlock()
if ok {
return client
}
newClient := NewWeChatClient(mp.AppID, mp.AppSecret, nil)
s.cacheMu.Lock()
s.wechatClientCache[mp.ID] = newClient
s.cacheMu.Unlock()
return newClient
}
+25
View File
@@ -0,0 +1,25 @@
package service
import (
"context"
"wx_service/internal/model"
"gorm.io/gorm"
)
type MiniProgramService struct {
db *gorm.DB
}
func NewMiniProgramService(db *gorm.DB) *MiniProgramService {
return &MiniProgramService{db: db}
}
func (s *MiniProgramService) GetByID(ctx context.Context, id uint) (*model.MiniProgram, error) {
var mp model.MiniProgram
if err := s.db.WithContext(ctx).Where("id = ?", id).First(&mp).Error; err != nil {
return nil, err
}
return &mp, nil
}