liusheng
6 天以前 cc479e6a056785103996cc7ea67dbd5faa3e800e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package com.ruoyi.message.wechat.support;
 
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.apache.commons.lang3.StringUtils;
 
import java.util.Map;
 
/**
 * 微信公众号消息发送工具类(微信官方 SDK 通道)。
 * <p>
 * 支持:文本客服消息、模板消息。
 * <p>
 * 迁移说明:原类为 {@code com.ruoyi.common.utils.WxMpUtils},行为未改动,仅换包。
 * 现状:全项目<b>没有业务调用点</b>(只有 {@code SysLoginController} 与
 * {@code WeChatService} 里的注释/测试代码),属于「已具备能力但未接入」的通道。
 */
@Slf4j
public class WxMpUtils {
 
    private final WxMpService wxMpService;
 
    /**
     * 构造方法,通过 appId 和 appSecret 初始化微信公众号服务
     *
     * @param appId     微信公众号 AppID
     * @param appSecret 微信公众号 AppSecret
     */
    public WxMpUtils(String appId, String appSecret) {
        WxMpInMemoryConfigStorage configStorage = new WxMpInMemoryConfigStorage();
        configStorage.setAppId(appId);
        configStorage.setSecret(appSecret);
        wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(configStorage);
    }
 
    // -------------------------------------------------------------------------
    // 文本客服消息
    // -------------------------------------------------------------------------
 
    /**
     * 向指定 openid 的用户发送文本客服消息。
     * 注意:用户需在48小时内与公众号有过交互才可发送。
     *
     * @param openid  用户的微信 openid
     * @param content 消息内容
     * @return 发送成功返回 true,失败返回 false
     */
    public boolean sendTextMessage(String openid, String content) {
        if (StringUtils.isEmpty(openid)) {
            log.warn("【WxMpUtils】sendTextMessage 失败:openid 为空");
            return false;
        }
        if (StringUtils.isEmpty(content)) {
            log.warn("【WxMpUtils】sendTextMessage 失败:content 为空");
            return false;
        }
        try {
            WxMpKefuMessage message = WxMpKefuMessage.TEXT().toUser(openid).content(content).build();
            boolean result = wxMpService.getKefuService().sendKefuMessage(message);
            log.info("【WxMpUtils】文本客服消息发送{},openid:{}", result ? "成功" : "失败", openid);
            return result;
        } catch (WxErrorException e) {
            log.error("【WxMpUtils】文本客服消息发送异常,openid:{},错误:{}", openid, e.getError(), e);
            return false;
        }
    }
 
    // -------------------------------------------------------------------------
    // 模板消息
    // -------------------------------------------------------------------------
 
    /**
     * 向指定 openid 的用户发送模板消息(含跳转URL)
     *
     * @param openid     用户的微信 openid
     * @param templateId 模板消息 ID(在微信公众平台配置)
     * @param url        点击消息后的跳转 URL,不需要跳转可传 null
     * @param dataMap    模板数据,key 为模板字段名,value 为 WxMpTemplateData(含值和颜色)
     * @return 发送成功返回微信返回的 msgid,失败返回 null
     */
    public String sendTemplateMessage(String openid, String templateId, String url, Map<String, WxMpTemplateData> dataMap) {
        if (StringUtils.isEmpty(openid)) {
            log.warn("【WxMpUtils】sendTemplateMessage 失败:openid 为空");
            return null;
        }
        if (StringUtils.isEmpty(templateId)) {
            log.warn("【WxMpUtils】sendTemplateMessage 失败:templateId 为空");
            return null;
        }
        try {
            WxMpTemplateMessage templateMessage = new WxMpTemplateMessage();
            templateMessage.setToUser(openid);
            templateMessage.setTemplateId(templateId);
            if (StringUtils.isNotEmpty(url)) {
                templateMessage.setUrl(url);
            }
            if (dataMap != null) {
                for (WxMpTemplateData data : dataMap.values()) {
                    templateMessage.addData(data);
                }
            }
            String msgId = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
            log.info("【WxMpUtils】模板消息发送成功,openid:{},msgId:{}", openid, msgId);
            return msgId;
        } catch (WxErrorException e) {
            log.error("【WxMpUtils】模板消息发送异常,openid:{},templateId:{},错误:{}", openid, templateId, e.getError(), e);
            return null;
        }
    }
 
    /**
     * 向指定 openid 的用户发送模板消息(简化版,value 统一使用默认颜色)
     *
     * @param openid       用户的微信 openid
     * @param templateId   模板消息 ID
     * @param url          点击消息后的跳转 URL,不需要跳转可传 null
     * @param dataMap      模板数据,key 为模板字段名,value 为字段显示的文本内容
     * @param defaultColor 默认颜色
     * @return 发送成功返回微信返回的 msgid,失败返回 null
     */
    public String sendTemplateMessage(String openid, String templateId, String url, Map<String, String> dataMap, String defaultColor) {
        if (StringUtils.isEmpty(openid)) {
            log.warn("【WxMpUtils】sendTemplateMessage 失败:openid 为空");
            return null;
        }
        if (StringUtils.isEmpty(templateId)) {
            log.warn("【WxMpUtils】sendTemplateMessage 失败:templateId 为空");
            return null;
        }
        try {
            WxMpTemplateMessage templateMessage = new WxMpTemplateMessage();
            templateMessage.setToUser(openid);
            templateMessage.setTemplateId(templateId);
            if (StringUtils.isNotEmpty(url)) {
                templateMessage.setUrl(url);
            }
            if (dataMap != null) {
                String color = StringUtils.isEmpty(defaultColor) ? "#173177" : defaultColor;
                for (Map.Entry<String, String> entry : dataMap.entrySet()) {
                    templateMessage.addData(new WxMpTemplateData(entry.getKey(), entry.getValue(), color));
                }
            }
            String msgId = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
            log.info("【WxMpUtils】模板消息发送成功,openid:{},msgId:{}", openid, msgId);
            return msgId;
        } catch (WxErrorException e) {
            log.error("【WxMpUtils】模板消息发送异常,openid:{},templateId:{},错误:{}", openid, templateId, e.getError(), e);
            return null;
        }
    }
 
    // -------------------------------------------------------------------------
    // 静态工厂方法(快速构造)
    // -------------------------------------------------------------------------
 
    /**
     * 快速创建 WxMpUtils 实例
     *
     * @param appId     微信公众号 AppID
     * @param appSecret 微信公众号 AppSecret
     * @return WxMpUtils 实例
     */
    public static WxMpUtils of(String appId, String appSecret) {
        return new WxMpUtils(appId, appSecret);
    }
}