1
This commit is contained in:
@@ -16,23 +16,22 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 调用 wxSend 闲鱼自建应用文本推送(POST /wecom/goofish-active-push,agent 见 wxSend qywx.app.goofishAgentId)。
|
||||
* 调用 wxSend 闲鱼自建应用文本推送,与 /wx/send/pdd 一致:Header vanToken + JSON(title、text、touser)。
|
||||
*/
|
||||
@Component
|
||||
public class WxSendGoofishNotifyClient {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(WxSendGoofishNotifyClient.class);
|
||||
|
||||
public static final String HEADER_GOOFISH_PUSH_SECRET = "X-WxSend-Goofish-Push-Secret";
|
||||
|
||||
/** 与企微 message/send 文本 content 上限对齐,预留余量 */
|
||||
private static final int CONTENT_MAX = 2000;
|
||||
|
||||
@Value("${jarvis.wecom.wxsend-base-url:}")
|
||||
private String wxsendBaseUrl;
|
||||
|
||||
@Value("${jarvis.wecom.goofish-push-secret:}")
|
||||
private String goofishPushSecret;
|
||||
/** 与 wxSend TokenUtil 校验一致,请求头 vanToken */
|
||||
@Value("${jarvis.wecom.wxsend-van-token:}")
|
||||
private String wxsendVanToken;
|
||||
|
||||
/**
|
||||
* 接收通知的成员 UserID(企微管理后台可见),多个用英文逗号或 | 分隔;
|
||||
@@ -50,7 +49,7 @@ public class WxSendGoofishNotifyClient {
|
||||
* @param message 已截断的说明文案
|
||||
*/
|
||||
public void notifyGoofishEvent(String orderNo, String eventType, String source, String message) {
|
||||
if (!StringUtils.hasText(wxsendBaseUrl) || !StringUtils.hasText(goofishPushSecret)) {
|
||||
if (!StringUtils.hasText(wxsendBaseUrl) || !StringUtils.hasText(wxsendVanToken)) {
|
||||
return;
|
||||
}
|
||||
String toUser = buildTouserParam(goofishNotifyTouser);
|
||||
@@ -63,22 +62,24 @@ public class WxSendGoofishNotifyClient {
|
||||
}
|
||||
try {
|
||||
String base = normalizeBase(wxsendBaseUrl);
|
||||
String url = base + "/wecom/goofish-active-push";
|
||||
postJson(url, toUser, content);
|
||||
String url = base + "/wx/send/goofish";
|
||||
postMessageReturnsOk(url, wxsendVanToken, "", content, toUser);
|
||||
} catch (Exception e) {
|
||||
log.warn("wxSend goofish-active-push 失败 orderNo={} err={}", orderNo, e.toString());
|
||||
log.warn("wxSend /wx/send/goofish 失败 orderNo={} err={}", orderNo, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 京东物流扫描等:全文发往企微「闲鱼」自建应用(wxSend qywx.app.goofishAgentId)。
|
||||
* 京东物流扫描等:发往企微「闲鱼」自建应用,请求体与 PDD 推送一致(title + text + touser)。
|
||||
*
|
||||
* @param optionalToUser 非空时用与 logistics.push.touser.* 相同的成员 ID(逗号/| 亦可);空则用 goofish-notify-touser
|
||||
* @return HTTP 2xx 为 true;未配置密钥或 toUser 为空返回 false
|
||||
* @param title 与 {@code LogisticsServiceImpl} 推 PDD 时的 title 一致,可为空
|
||||
* @param textBody 正文(对应 PDD 的 text)
|
||||
* @return wxSend 业务 code=200 为 true;未配置 token 或 touser 为空返回 false
|
||||
*/
|
||||
public boolean pushGoofishAgentText(String optionalToUser, String content) {
|
||||
if (!StringUtils.hasText(wxsendBaseUrl) || !StringUtils.hasText(goofishPushSecret)) {
|
||||
log.debug("wxSend 闲鱼应用物流推送跳过:未配置 wxsend-base-url 或 goofish-push-secret");
|
||||
public boolean pushGoofishAgentText(String optionalToUser, String title, String textBody) {
|
||||
if (!StringUtils.hasText(wxsendBaseUrl) || !StringUtils.hasText(wxsendVanToken)) {
|
||||
log.debug("wxSend 闲鱼应用物流推送跳过:未配置 wxsend-base-url 或 wxsend-van-token");
|
||||
return false;
|
||||
}
|
||||
String rawTouser = StringUtils.hasText(optionalToUser) ? optionalToUser : goofishNotifyTouser;
|
||||
@@ -87,16 +88,24 @@ public class WxSendGoofishNotifyClient {
|
||||
log.warn("wxSend 闲鱼应用物流推送跳过:无接收人(请配置 jarvis.wecom.goofish-notify-touser 或 logistics.push.touser)");
|
||||
return false;
|
||||
}
|
||||
String text = content != null ? content : "";
|
||||
if (text.length() > CONTENT_MAX) {
|
||||
text = text.substring(0, CONTENT_MAX - 1) + "…";
|
||||
String t = title != null ? title : "";
|
||||
String body = textBody != null ? textBody : "";
|
||||
if (t.length() > CONTENT_MAX) {
|
||||
t = t.substring(0, CONTENT_MAX - 1) + "…";
|
||||
body = "";
|
||||
} else {
|
||||
int overhead = StringUtils.hasText(t) ? t.length() + 1 : 0;
|
||||
int maxBody = Math.max(0, CONTENT_MAX - overhead);
|
||||
if (body.length() > maxBody) {
|
||||
body = body.substring(0, Math.max(0, maxBody - 1)) + "…";
|
||||
}
|
||||
}
|
||||
try {
|
||||
String base = normalizeBase(wxsendBaseUrl);
|
||||
String url = base + "/wecom/goofish-active-push";
|
||||
return postJsonReturnsOk(url, toUser, text);
|
||||
String url = base + "/wx/send/goofish";
|
||||
return postMessageReturnsOk(url, wxsendVanToken, t, body, toUser);
|
||||
} catch (Exception e) {
|
||||
log.warn("wxSend goofish-active-push 物流全文失败 err={}", e.toString());
|
||||
log.warn("wxSend /wx/send/goofish 物流全文失败 err={}", e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -157,40 +166,41 @@ public class WxSendGoofishNotifyClient {
|
||||
if (!StringUtils.hasText(wxsendBaseUrl)) {
|
||||
return "";
|
||||
}
|
||||
return normalizeBase(wxsendBaseUrl) + "/wecom/goofish-active-push";
|
||||
return normalizeBase(wxsendBaseUrl) + "/wx/send/goofish";
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务监控手动测试:经 wxSend 向企微「闲鱼」应用发一条文本。
|
||||
*
|
||||
* @return null 表示 HTTP 2xx 且调用链未抛错;非空为可直接展示的失败原因
|
||||
* @return null 表示 HTTP 2xx 且 wxSend 返回 code=200;非空为可直接展示的失败原因
|
||||
*/
|
||||
public String testGoofishNotify() {
|
||||
if (!StringUtils.hasText(wxsendBaseUrl)) {
|
||||
return "未配置 jarvis.wecom.wxsend-base-url";
|
||||
}
|
||||
if (!StringUtils.hasText(goofishPushSecret)) {
|
||||
return "未配置 jarvis.wecom.goofish-push-secret";
|
||||
if (!StringUtils.hasText(wxsendVanToken)) {
|
||||
return "未配置 jarvis.wecom.wxsend-van-token(须与 wxSend TokenUtil 一致)";
|
||||
}
|
||||
if (!StringUtils.hasText(goofishNotifyTouser)) {
|
||||
return "未配置 jarvis.wecom.goofish-notify-touser(接收人为空)";
|
||||
}
|
||||
String content = "【服务监控·闲鱼通知测试】RuoYi 手动触发 " + new java.util.Date();
|
||||
boolean ok = pushGoofishAgentText(null, content);
|
||||
boolean ok = pushGoofishAgentText(null, "", content);
|
||||
if (ok) {
|
||||
return null;
|
||||
}
|
||||
return "推送未成功:请核对 wxSend 与企微应用、密钥及接收人,或查看服务端日志";
|
||||
return "推送未成功:请核对 wxSend 服务、vanToken、企微闲鱼应用及接收人,或查看服务端日志";
|
||||
}
|
||||
|
||||
private void postJson(String url, String toUser, String content) throws Exception {
|
||||
postJsonReturnsOk(url, toUser, content);
|
||||
}
|
||||
|
||||
private boolean postJsonReturnsOk(String url, String toUser, String content) throws Exception {
|
||||
/**
|
||||
* POST {@code /wx/send/goofish}:body 与 {@code /wx/send/pdd} 相同字段名(title、text、touser)。
|
||||
*/
|
||||
private boolean postMessageReturnsOk(String url, String vanToken, String title, String text, String touserPipeJoined)
|
||||
throws Exception {
|
||||
JSONObject body = new JSONObject();
|
||||
body.put("toUser", toUser);
|
||||
body.put("content", content);
|
||||
body.put("title", title != null ? title : "");
|
||||
body.put("text", text != null ? text : "");
|
||||
body.put("touser", touserPipeJoined);
|
||||
byte[] bytes = body.toJSONString().getBytes(StandardCharsets.UTF_8);
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
@@ -200,19 +210,32 @@ public class WxSendGoofishNotifyClient {
|
||||
conn.setReadTimeout(60000);
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
|
||||
conn.setRequestProperty(HEADER_GOOFISH_PUSH_SECRET, goofishPushSecret);
|
||||
conn.setRequestProperty("vanToken", vanToken);
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
os.write(bytes);
|
||||
}
|
||||
int code = conn.getResponseCode();
|
||||
InputStream is = code >= 200 && code < 300 ? conn.getInputStream() : conn.getErrorStream();
|
||||
int httpCode = conn.getResponseCode();
|
||||
InputStream is = httpCode >= 200 && httpCode < 300 ? conn.getInputStream() : conn.getErrorStream();
|
||||
String resp = readAll(is);
|
||||
if (code < 200 || code >= 300) {
|
||||
log.warn("wxSend goofish-active-push HTTP {} body={}", code, resp);
|
||||
if (httpCode < 200 || httpCode >= 300) {
|
||||
log.warn("wxSend /wx/send/goofish HTTP {} body={}", httpCode, resp);
|
||||
return false;
|
||||
}
|
||||
log.debug("wxSend goofish-active-push OK http={} resp={}", code, resp);
|
||||
return true;
|
||||
Integer bizCode = null;
|
||||
try {
|
||||
JSONObject jo = JSONObject.parseObject(resp);
|
||||
if (jo != null) {
|
||||
bizCode = jo.getInteger("code");
|
||||
}
|
||||
} catch (Exception parseEx) {
|
||||
log.debug("解析 wxSend 响应: {}", parseEx.toString());
|
||||
}
|
||||
if (bizCode != null && bizCode == 200) {
|
||||
log.debug("wxSend /wx/send/goofish OK resp={}", resp);
|
||||
return true;
|
||||
}
|
||||
log.warn("wxSend /wx/send/goofish 业务未成功 resp={}", resp);
|
||||
return false;
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
|
||||
Reference in New Issue
Block a user