1
This commit is contained in:
@@ -110,22 +110,17 @@ public class WxSendGoofishNotifyClient {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 企微短通知:场景标题 + 订单号 + 必要字段行(不再展示数据来源等冗长前缀)。
|
||||
*/
|
||||
private static String buildContent(String orderNo, String eventType, String source, String message) {
|
||||
String on = orderNo != null ? orderNo : "-";
|
||||
String head = resolveNotifyHeadline(eventType, message);
|
||||
String detail = normalizeNotifyDetailLines(eventType, message);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("【闲鱼订单】").append(orderNo != null ? orderNo : "-").append("\n");
|
||||
String typeLabel = humanEventType(eventType);
|
||||
String srcLabel = humanSource(source);
|
||||
if (StringUtils.hasText(typeLabel)) {
|
||||
sb.append(typeLabel);
|
||||
if (StringUtils.hasText(srcLabel)) {
|
||||
sb.append(" · ").append(srcLabel);
|
||||
}
|
||||
} else if (StringUtils.hasText(srcLabel)) {
|
||||
sb.append(srcLabel);
|
||||
}
|
||||
sb.append("\n");
|
||||
if (StringUtils.hasText(message)) {
|
||||
sb.append(message);
|
||||
sb.append(head).append("\n订单号:").append(on).append('\n');
|
||||
if (StringUtils.hasText(detail)) {
|
||||
sb.append(detail);
|
||||
}
|
||||
String s = sb.toString();
|
||||
if (s.length() > CONTENT_MAX) {
|
||||
@@ -134,48 +129,221 @@ public class WxSendGoofishNotifyClient {
|
||||
return s;
|
||||
}
|
||||
|
||||
/** 企微展示用,与库内 event_type 枚举一致 */
|
||||
private static String humanEventType(String eventType) {
|
||||
if (!StringUtils.hasText(eventType)) {
|
||||
return "";
|
||||
private static String resolveNotifyHeadline(String eventType, String message) {
|
||||
String m = message != null ? message : "";
|
||||
String t = eventType != null ? eventType.trim() : "";
|
||||
if ("SHIP".equals(t)) {
|
||||
if (m.contains("失败") || m.contains("异常") || m.contains("缺地址")) {
|
||||
return "发货失败";
|
||||
}
|
||||
return "发货";
|
||||
}
|
||||
switch (eventType.trim()) {
|
||||
case "ORDER_SYNC":
|
||||
return "订单同步";
|
||||
case "LOGISTICS_SYNC":
|
||||
return "物流同步";
|
||||
case "SHIP":
|
||||
return "发货";
|
||||
default:
|
||||
return eventType.trim();
|
||||
if ("LOGISTICS_SYNC".equals(t)) {
|
||||
return "物流";
|
||||
}
|
||||
if ("ORDER_SYNC".equals(t)) {
|
||||
if (m.startsWith("新订单") || m.contains("新订单入库")) {
|
||||
return "新订单";
|
||||
}
|
||||
if (looksRefundOnlyDiffLine(m)) {
|
||||
return "退款";
|
||||
}
|
||||
return "订单";
|
||||
}
|
||||
return StringUtils.hasText(t) ? t : "订单";
|
||||
}
|
||||
|
||||
/** 企微展示用,与库内 source 一致 */
|
||||
private static String humanSource(String source) {
|
||||
if (!StringUtils.hasText(source)) {
|
||||
/** ORDER_SYNC 正文里是否仅有退款状态变更(单行或多行中的唯一语义块) */
|
||||
private static boolean looksRefundOnlyDiffLine(String message) {
|
||||
if (!StringUtils.hasText(message) || message.contains("新订单")) {
|
||||
return false;
|
||||
}
|
||||
String normalized = message.replace(';', '\n').trim();
|
||||
String[] lines = normalized.split("\n");
|
||||
boolean sawRefund = false;
|
||||
boolean sawOrder = false;
|
||||
for (String raw : lines) {
|
||||
String line = raw.trim();
|
||||
if (line.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith("退款状态")) {
|
||||
sawRefund = true;
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith("订单状态")) {
|
||||
sawOrder = true;
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return sawRefund && !sawOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将内部摘要句转为「字段:值」行;箭头统一为「 → 」。
|
||||
*/
|
||||
private static String normalizeNotifyDetailLines(String eventType, String message) {
|
||||
if (!StringUtils.hasText(message)) {
|
||||
return "";
|
||||
}
|
||||
switch (source.trim()) {
|
||||
case "LIST_UPSERT":
|
||||
return "列表拉单写入";
|
||||
case "NOTIFY_UPSERT":
|
||||
return "推送回调写入";
|
||||
case "LIST":
|
||||
return "列表摘要";
|
||||
case "DETAIL_REFRESH":
|
||||
return "详情刷新";
|
||||
case "NOTIFY":
|
||||
return "推送";
|
||||
case "REDIS_WAYBILL":
|
||||
return "Redis 运单";
|
||||
case "AUTO_SHIP":
|
||||
return "自动发货";
|
||||
case "JD_LOGISTICS_PUSH":
|
||||
return "京东物流扫描";
|
||||
default:
|
||||
return source.trim();
|
||||
String t = eventType != null ? eventType.trim() : "";
|
||||
String m = message.trim();
|
||||
|
||||
if ("SHIP".equals(t)) {
|
||||
if (m.startsWith("发货成功")) {
|
||||
StringBuilder details = new StringBuilder();
|
||||
String wb = extractCommaField(m, "运单 ");
|
||||
if (StringUtils.hasText(wb)) {
|
||||
details.append("物流单号:").append(normalizeArrowSpaces(wb)).append('\n');
|
||||
}
|
||||
String os = extractCommaField(m, "订单状态 ");
|
||||
if (StringUtils.hasText(os)) {
|
||||
details.append("订单状态:").append(normalizeArrowSpaces(os)).append('\n');
|
||||
}
|
||||
String rs = extractCommaField(m, "退款状态 ");
|
||||
if (StringUtils.hasText(rs)) {
|
||||
details.append("退款状态:").append(normalizeArrowSpaces(rs)).append('\n');
|
||||
}
|
||||
if (details.length() > 0) {
|
||||
return details.toString();
|
||||
}
|
||||
}
|
||||
if (m.startsWith("发货失败") || m.startsWith("发货异常")) {
|
||||
int idx = m.indexOf(':');
|
||||
String reason = idx >= 0 && idx < m.length() - 1 ? m.substring(idx + 1).trim() : m;
|
||||
return "原因:" + normalizeArrowSpaces(reason) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ("ORDER_SYNC".equals(t)) {
|
||||
// 新订单入库,订单状态 X,退款状态 Y
|
||||
if (m.contains("新订单入库") && m.contains("订单状态 ") && m.contains("退款状态 ")) {
|
||||
String os = substringBetweenPrefixes(m, "订单状态 ", ",退款状态");
|
||||
String rs = substringAfterPrefix(m, "退款状态 ");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (StringUtils.hasText(os)) {
|
||||
sb.append("订单状态:").append(os.trim()).append('\n');
|
||||
}
|
||||
if (StringUtils.hasText(rs)) {
|
||||
sb.append("退款状态:").append(rs.trim()).append('\n');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
// 订单状态 A → B;退款状态 …(仅输出消息里出现的块)
|
||||
return formatOrderSyncSemicolonParts(m);
|
||||
}
|
||||
|
||||
if ("LOGISTICS_SYNC".equals(t)) {
|
||||
return formatLogisticsParts(m);
|
||||
}
|
||||
|
||||
return normalizeArrowSpaces(m) + "\n";
|
||||
}
|
||||
|
||||
private static String formatOrderSyncSemicolonParts(String m) {
|
||||
String[] parts = m.split(";");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String p : parts) {
|
||||
String line = kvLineOrderOrRefund(p.trim());
|
||||
if (line != null) {
|
||||
sb.append(line).append('\n');
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String kvLineOrderOrRefund(String segment) {
|
||||
if (!StringUtils.hasText(segment)) {
|
||||
return null;
|
||||
}
|
||||
if (segment.startsWith("订单状态 ")) {
|
||||
return "订单状态:" + normalizeArrowSpaces(segment.substring("订单状态 ".length()).trim());
|
||||
}
|
||||
if (segment.startsWith("退款状态 ")) {
|
||||
return "退款状态:" + normalizeArrowSpaces(segment.substring("退款状态 ".length()).trim());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String formatLogisticsParts(String m) {
|
||||
String[] parts = m.split(";");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String p : parts) {
|
||||
String line = logisticsSegmentToKv(p.trim());
|
||||
if (line != null) {
|
||||
sb.append(line).append('\n');
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/** 本地/平台运单 → 对用户展示为物流单号;其它变更行仍可保留技术性标签 */
|
||||
private static String logisticsSegmentToKv(String segment) {
|
||||
if (!StringUtils.hasText(segment)) {
|
||||
return null;
|
||||
}
|
||||
if (segment.startsWith("本地运单 ") || segment.startsWith("平台运单 ")) {
|
||||
int cut = segment.indexOf(' ');
|
||||
String rest = normalizeArrowSpaces(segment.substring(cut + 1).trim());
|
||||
return "物流单号:" + rest;
|
||||
}
|
||||
String kv = logisticLabelToColon(segment);
|
||||
return kv != null ? kv : (normalizeArrowSpaces(segment));
|
||||
}
|
||||
|
||||
private static String logisticLabelToColon(String segment) {
|
||||
String[] prefixes = {"快递编码 ", "快递名称 "};
|
||||
for (String pref : prefixes) {
|
||||
if (segment.startsWith(pref)) {
|
||||
String label = pref.trim();
|
||||
return label.substring(0, label.length() - 1) + ":"
|
||||
+ normalizeArrowSpaces(segment.substring(pref.length()).trim());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String normalizeArrowSpaces(String s) {
|
||||
if (s == null) {
|
||||
return "";
|
||||
}
|
||||
return s.replace("→", " → ").replace(" →", " →").replace("→ ", " → ");
|
||||
}
|
||||
|
||||
/** 从「片段1,片段2,…」中取出以 {@code fieldPrefix} 开头的片段值(去掉前缀) */
|
||||
private static String extractCommaField(String m, String fieldPrefix) {
|
||||
if (!StringUtils.hasText(m) || !StringUtils.hasText(fieldPrefix)) {
|
||||
return null;
|
||||
}
|
||||
for (String part : m.split(",")) {
|
||||
String p = part.trim();
|
||||
if (p.startsWith(fieldPrefix)) {
|
||||
String v = p.substring(fieldPrefix.length()).trim();
|
||||
return v.length() > 0 ? v : null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String substringBetweenPrefixes(String m, String a, String b) {
|
||||
int ia = m.indexOf(a);
|
||||
if (ia < 0) {
|
||||
return null;
|
||||
}
|
||||
int ib = m.indexOf(b, ia + a.length());
|
||||
if (ib < 0) {
|
||||
return null;
|
||||
}
|
||||
return m.substring(ia + a.length(), ib);
|
||||
}
|
||||
|
||||
private static String substringAfterPrefix(String m, String pref) {
|
||||
int i = m.indexOf(pref);
|
||||
if (i < 0) {
|
||||
return null;
|
||||
}
|
||||
return m.substring(i + pref.length()).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user