pet-ai/server/plugin/wechat-integration/service/mp_user_service.go

263 lines
6.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"errors"
"fmt"
"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) {
// 从数据库获取微信公众号配置
var mpConfig model.MpConfig
err := global.GVA_DB.Where("config_type = ?", model.ConfigTypeMP).First(&mpConfig).Error
if err != nil {
return nil, fmt.Errorf("获取微信公众号配置失败: %v", err)
}
if mpConfig.AppID == "" || mpConfig.AppSecret == "" {
return nil, errors.New("微信公众号配置不完整")
}
wc := wechat.NewWechat()
memory := cache.NewMemory()
cfg := &config.Config{
AppID: mpConfig.AppID,
AppSecret: mpConfig.AppSecret,
Cache: memory,
}
// 如果有Token设置服务器配置
if mpConfig.Token != nil && *mpConfig.Token != "" {
cfg.Token = *mpConfig.Token
}
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
}