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
|
|
}
|