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

165 lines
4.6 KiB
Go

package service
import (
"errors"
"fmt"
"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/basic"
"github.com/silenceper/wechat/v2/officialaccount/config"
)
type WechatMpService struct{}
// GetWechatOfficialAccount 获取微信公众号实例
func (w *WechatMpService) GetWechatOfficialAccount(mpConfig *model.MpConfig) (*officialaccount.OfficialAccount, error) {
if mpConfig == nil {
return nil, errors.New("微信公众号配置不能为空")
}
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和EncodingAESKey,设置服务器配置
if mpConfig.Token != nil && *mpConfig.Token != "" {
cfg.Token = *mpConfig.Token
}
if mpConfig.EncodingAESKey != nil && *mpConfig.EncodingAESKey != "" {
cfg.EncodingAESKey = *mpConfig.EncodingAESKey
}
return wc.GetOfficialAccount(cfg), nil
}
// GenerateQrCode 生成公众号二维码
func (w *WechatMpService) GenerateQrCode(mpConfig *model.MpConfig) (string, error) {
oa, err := w.GetWechatOfficialAccount(mpConfig)
if err != nil {
return "", err
}
// 获取基础服务
basicService := oa.GetBasic()
// 创建永久二维码请求
qrRequest := basic.NewLimitQrRequest("mp_config_qr")
// 获取二维码ticket
ticket, err := basicService.GetQRTicket(qrRequest)
if err != nil {
global.GVA_LOG.Error("获取二维码ticket失败: " + err.Error())
return "", fmt.Errorf("获取二维码ticket失败: %v", err)
}
// 生成二维码图片URL
qrCodeURL := basic.ShowQRCode(ticket)
global.GVA_LOG.Info("生成公众号二维码成功: " + qrCodeURL)
return qrCodeURL, nil
}
// ClearQuota 清空API配额
func (w *WechatMpService) ClearQuota(mpConfig *model.MpConfig) error {
oa, err := w.GetWechatOfficialAccount(mpConfig)
if err != nil {
return err
}
// 调用清空API配额接口
basic := oa.GetBasic()
err = basic.ClearQuota()
if err != nil {
global.GVA_LOG.Error("清空API配额失败: " + err.Error())
return fmt.Errorf("清空API配额失败: %v", err)
}
global.GVA_LOG.Info("清空API配额成功")
return nil
}
// ValidateConfig 验证公众号配置
func (w *WechatMpService) ValidateConfig(mpConfig *model.MpConfig) error {
oa, err := w.GetWechatOfficialAccount(mpConfig)
if err != nil {
return err
}
// 通过获取access_token来验证配置是否正确
basic := oa.GetBasic()
token, err := basic.GetAccessToken()
if err != nil {
global.GVA_LOG.Error("验证公众号配置失败: " + err.Error())
return fmt.Errorf("验证配置失败: %v", err)
}
if token == "" {
return errors.New("获取access_token失败,请检查AppID和AppSecret")
}
global.GVA_LOG.Info("验证公众号配置成功")
return nil
}
// GetServerIPs 获取微信服务器IP地址
func (w *WechatMpService) GetServerIPs(mpConfig *model.MpConfig) ([]string, error) {
oa, err := w.GetWechatOfficialAccount(mpConfig)
if err != nil {
return nil, err
}
basic := oa.GetBasic()
ips, err := basic.GetCallbackIP()
if err != nil {
global.GVA_LOG.Error("获取微信服务器IP失败: " + err.Error())
return nil, fmt.Errorf("获取微信服务器IP失败: %v", err)
}
return ips, nil
}
// GetUserInfo 获取用户基本信息
func (w *WechatMpService) GetUserInfo(mpConfig *model.MpConfig, openID string) (map[string]interface{}, error) {
oa, err := w.GetWechatOfficialAccount(mpConfig)
if err != nil {
return nil, err
}
user := oa.GetUser()
userInfo, err := user.GetUserInfo(openID)
if err != nil {
global.GVA_LOG.Error("获取用户信息失败: " + err.Error())
return nil, fmt.Errorf("获取用户信息失败: %v", err)
}
return map[string]interface{}{
"openid": userInfo.OpenID,
"nickname": userInfo.Nickname,
"sex": userInfo.Sex,
"province": userInfo.Province,
"city": userInfo.City,
"country": userInfo.Country,
"headimgurl": userInfo.Headimgurl,
"unionid": userInfo.UnionID,
}, nil
}
// SendTextMessage 发送文本消息 (暂时注释,需要正确的API调用方式)
// func (w *WechatMpService) SendTextMessage(mpConfig *model.MpConfig, openID, content string) error {
// // TODO: 实现发送文本消息功能
// return errors.New("发送消息功能暂未实现")
// }