263 lines
6.9 KiB
Go
263 lines
6.9 KiB
Go
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
|
||
}
|