Files
pet-ai/server/plugin/wechat-integration/service/mp_user_service.go
T
2025-08-05 17:46:15 +08:00

251 lines
6.7 KiB
Go

package service
import (
"errors"
"time"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/wechat-integration/model"
"github.com/silenceper/wechat/v2"
"github.com/silenceper/wechat/v2/cache"
"github.com/silenceper/wechat/v2/officialaccount"
"github.com/silenceper/wechat/v2/officialaccount/config"
"gorm.io/gorm"
)
type MpUserService struct{}
// GetOfficialAccount 获取微信公众号实例
func (m *MpUserService) GetOfficialAccount() (*officialaccount.OfficialAccount, error) {
if global.GVA_CONFIG.Wechat.OfficialAppID == "" || global.GVA_CONFIG.Wechat.OfficialAppSecret == "" {
return nil, errors.New("微信公众号配置不完整")
}
wc := wechat.NewWechat()
memory := cache.NewMemory()
cfg := &config.Config{
AppID: global.GVA_CONFIG.Wechat.OfficialAppID,
AppSecret: global.GVA_CONFIG.Wechat.OfficialAppSecret,
Token: global.GVA_CONFIG.Wechat.OfficialToken,
Cache: memory,
}
return wc.GetOfficialAccount(cfg), nil
}
// SyncUser 同步微信用户信息
func (m *MpUserService) SyncUser(openid string) (*model.MpUser, error) {
oa, err := m.GetOfficialAccount()
if err != nil {
return nil, err
}
// 从微信获取用户信息
userInfo, err := oa.GetUser().GetUserInfo(openid)
if err != nil {
global.GVA_LOG.Error("获取微信用户信息失败: " + err.Error())
return nil, err
}
// 查找或创建用户
var user model.MpUser
err = global.GVA_DB.Where("openid = ?", openid).First(&user).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
// 创建新用户
user = model.MpUser{
OpenID: userInfo.OpenID,
SubscribeStatus: int(userInfo.Subscribe),
}
if userInfo.Nickname != "" {
user.Nickname = &userInfo.Nickname
}
if userInfo.Headimgurl != "" {
user.HeadImageURL = &userInfo.Headimgurl
}
if userInfo.Language != "" {
user.Language = &userInfo.Language
}
if userInfo.Country != "" {
user.Country = &userInfo.Country
}
if userInfo.Province != "" {
user.Province = &userInfo.Province
}
if userInfo.City != "" {
user.City = &userInfo.City
}
// 设置关注时间
if userInfo.Subscribe == 1 && userInfo.SubscribeTime > 0 {
subscribeTime := time.Unix(int64(userInfo.SubscribeTime), 0)
user.SubscribeTime = &subscribeTime
}
// 设置 UnionID (仅用于记录,公众号不关联系统用户)
if userInfo.UnionID != "" {
user.UnionID = &userInfo.UnionID
global.GVA_LOG.Info("公众号用户 UnionID: " + userInfo.UnionID)
}
err = global.GVA_DB.Create(&user).Error
if err != nil {
global.GVA_LOG.Error("创建微信公众号用户失败: " + err.Error())
return nil, err
}
} else {
global.GVA_LOG.Error("查询微信公众号用户失败: " + err.Error())
return nil, err
}
} else {
// 更新用户信息
user.SubscribeStatus = int(userInfo.Subscribe)
if userInfo.Nickname != "" {
user.Nickname = &userInfo.Nickname
}
if userInfo.Headimgurl != "" {
user.HeadImageURL = &userInfo.Headimgurl
}
if userInfo.Language != "" {
user.Language = &userInfo.Language
}
if userInfo.Country != "" {
user.Country = &userInfo.Country
}
if userInfo.Province != "" {
user.Province = &userInfo.Province
}
if userInfo.City != "" {
user.City = &userInfo.City
}
// 更新关注状态和时间
if userInfo.Subscribe == 1 && userInfo.SubscribeTime > 0 {
subscribeTime := time.Unix(int64(userInfo.SubscribeTime), 0)
user.SubscribeTime = &subscribeTime
user.UnsubscribeTime = nil
} else if userInfo.Subscribe == 0 {
now := time.Now()
user.UnsubscribeTime = &now
}
// 如果还没有关联系统用户且有 unionid,尝试关联
// 注意:这里需要根据实际业务需求决定是否需要重新关联
err = global.GVA_DB.Save(&user).Error
if err != nil {
global.GVA_LOG.Error("更新微信公众号用户失败: " + err.Error())
return nil, err
}
}
return &user, nil
}
// GetUserByOpenID 根据 OpenID 获取用户
func (m *MpUserService) GetUserByOpenID(openid string) (*model.MpUser, error) {
var user model.MpUser
err := global.GVA_DB.Where("openid = ?", openid).First(&user).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("用户不存在")
}
return nil, err
}
return &user, nil
}
// GetUserList 获取用户列表
func (m *MpUserService) GetUserList(page, pageSize int, subscribeStatus *int) ([]model.MpUser, int64, error) {
var users []model.MpUser
var total int64
db := global.GVA_DB.Model(&model.MpUser{})
// 根据关注状态筛选
if subscribeStatus != nil {
db = db.Where("subscribe_status = ?", *subscribeStatus)
}
// 获取总数
err := db.Count(&total).Error
if err != nil {
return nil, 0, err
}
// 分页查询
offset := (page - 1) * pageSize
err = db.Offset(offset).Limit(pageSize).Order("created_at desc").Find(&users).Error
if err != nil {
return nil, 0, err
}
return users, total, nil
}
// UpdateUserRemark 更新用户备注
func (m *MpUserService) UpdateUserRemark(openid, remark string) error {
// 先更新微信服务器
oa, err := m.GetOfficialAccount()
if err != nil {
return err
}
err = oa.GetUser().UpdateRemark(openid, remark)
if err != nil {
global.GVA_LOG.Error("更新微信用户备注失败: " + err.Error())
return err
}
// 更新本地数据库
err = global.GVA_DB.Model(&model.MpUser{}).Where("openid = ?", openid).Update("remark", remark).Error
if err != nil {
global.GVA_LOG.Error("更新本地用户备注失败: " + err.Error())
return err
}
return nil
}
// SubscribeUser 用户关注事件处理
func (m *MpUserService) SubscribeUser(openid string) error {
// 同步用户信息
_, err := m.SyncUser(openid)
if err != nil {
return err
}
global.GVA_LOG.Info("用户关注: " + openid)
return nil
}
// UnsubscribeUser 用户取消关注事件处理
func (m *MpUserService) UnsubscribeUser(openid string) error {
now := time.Now()
err := global.GVA_DB.Model(&model.MpUser{}).Where("openid = ?", openid).Updates(map[string]interface{}{
"subscribe_status": 0,
"unsubscribe_time": now,
}).Error
if err != nil {
global.GVA_LOG.Error("处理用户取消关注失败: " + err.Error())
return err
}
global.GVA_LOG.Info("用户取消关注: " + openid)
return nil
}
// GetUserByUnionID 根据 UnionID 获取公众号用户信息 (仅用于查询,不关联系统用户)
func (m *MpUserService) GetUserByUnionID(unionid string) (*model.MpUser, error) {
var user model.MpUser
err := global.GVA_DB.Where("unionid = ?", unionid).First(&user).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("用户不存在")
}
return nil, err
}
return &user, nil
}