diff --git a/src/main/java/cn/van333/wxsend/business/controller/WXController.java b/src/main/java/cn/van333/wxsend/business/controller/WXController.java index 57aeb1b..2f4c215 100644 --- a/src/main/java/cn/van333/wxsend/business/controller/WXController.java +++ b/src/main/java/cn/van333/wxsend/business/controller/WXController.java @@ -8,6 +8,7 @@ import cn.van333.wxsend.business.service.LogService; import cn.van333.wxsend.enums.WXMessageType; import cn.van333.wxsend.util.SourceForQLUtil; import cn.van333.wxsend.util.TokenUtil; +import cn.van333.wxsend.business.service.WeComApplicationTextPushService; import cn.van333.wxsend.util.WxSendUtil; import cn.van333.wxsend.util.request.MessageRequest; import com.alibaba.fastjson2.JSON; @@ -18,7 +19,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; /** * @author Leo @@ -31,6 +34,9 @@ import javax.servlet.http.HttpServletRequest; public class WXController { private static final Logger logger = LoggerFactory.getLogger(LogService.class); + @Resource + private WeComApplicationTextPushService weComApplicationTextPushService; + @RequestMapping(value = "/send") @ResponseBody @RateLimiter(time = 1, count = 60) @@ -211,6 +217,62 @@ public class WXController { return R.ok(result); } + + /** + * 闲鱼通知:与 {@link #sendToPDD} 相同鉴权(Header vanToken)与请求体 {@link MessageRequest}(title、text、touser), + * 下发到企微自建应用 {@code qywx.app.goofishAgentId}。 + */ + @RequestMapping(value = "/send/goofish") + @ResponseBody + @RateLimiter(time = 2, count = 1) + public R sendToGoofish(HttpServletRequest request, @RequestBody MessageRequest message) { + logger.info("goofish message 打印---{}", JSON.toJSONString(message)); + String vanToken = request.getHeader("vanToken"); + if (StrUtil.isEmpty(vanToken)) { + return R.error("vanToken为空"); + } + if (!TokenUtil.checkToken(vanToken)) { + return R.error("vanToken无效"); + } + if (StrUtil.isEmpty(message.getTouser())) { + return R.error("touser 必填"); + } + String title = message.getTitle(); + String text = message.getText(); + if (StrUtil.isEmpty(text) && StrUtil.isEmpty(title)) { + return R.error("缺少标题和内容"); + } + String content = StrUtil.isEmpty(title) + ? (text != null ? text : "") + : (title + "\n" + (text != null ? text : "")); + String touser = normalizeTouserToPipe(message.getTouser()); + if (StrUtil.isEmpty(touser)) { + return R.error("touser 无效"); + } + try { + weComApplicationTextPushService.sendGoofishTextToUser(touser, content); + return R.ok("sent"); + } catch (Exception e) { + logger.warn("企微闲鱼应用推送失败 toUser={} err={}", touser, e.toString()); + return R.error("推送失败: " + e.getMessage()); + } + } + + /** 逗号或 | 分隔的成员 UserID → 企微 message/send 的 user1|user2 */ + private static String normalizeTouserToPipe(String raw) { + if (StrUtil.isEmpty(raw)) { + return ""; + } + String[] parts = raw.split("[,|]"); + ArrayList ids = new ArrayList<>(); + for (String p : parts) { + if (StrUtil.isNotBlank(p)) { + ids.add(p.trim()); + } + } + return String.join("|", ids); + } + //@RequestMapping("/ok") //@RateLimiter(time = 5, count = 60) //public R ok(HttpServletRequest request,String content) throws Exception { diff --git a/src/main/java/cn/van333/wxsend/business/controller/WeComActivePushController.java b/src/main/java/cn/van333/wxsend/business/controller/WeComActivePushController.java index 8fba0fd..5d03fbb 100644 --- a/src/main/java/cn/van333/wxsend/business/controller/WeComActivePushController.java +++ b/src/main/java/cn/van333/wxsend/business/controller/WeComActivePushController.java @@ -17,8 +17,7 @@ import javax.annotation.Resource; *

* Header: X-WxSend-WeCom-Push-Secret 与 {@code jarvis.wecom.push-secret} 一致 *

- * 闲管家订单状态/自动发货等:{@code POST /wecom/goofish-active-push},使用自建应用 - * {@code qywx.app.goofishAgentId},Header {@link #HEADER_GOOFISH_PUSH_SECRET} + * 闲鱼通知请使用 {@code WXController} 的 {@code POST /wx/send/goofish}(与 {@code /send/pdd} 相同 Header vanToken + 请求体 {@code MessageRequest})。 */ @RestController @RequestMapping("/wecom") @@ -28,15 +27,9 @@ public class WeComActivePushController { public static final String HEADER_PUSH_SECRET = "X-WxSend-WeCom-Push-Secret"; - /** 本地 / ruoyi 调用「闲鱼通知应用」推送时携带,与 {@code jarvis.wecom.goofish-push-secret} 一致 */ - public static final String HEADER_GOOFISH_PUSH_SECRET = "X-WxSend-Goofish-Push-Secret"; - @Value("${jarvis.wecom.push-secret:}") private String pushSecret; - @Value("${jarvis.wecom.goofish-push-secret:}") - private String goofishPushSecret; - @Resource private WeComApplicationTextPushService weComApplicationTextPushService; @@ -61,36 +54,4 @@ public class WeComActivePushController { return R.error("推送失败: " + e.getMessage()); } } - - /** - * 闲鱼订单状态变更、自动发货等:使用企微应用 {@code qywx.app.goofishAgentId}(如 1000013)发文本给成员。 - *

- * 示例:

-     * curl -X POST http://127.0.0.1:36699/wecom/goofish-active-push \
-     *   -H "Content-Type: application/json" \
-     *   -H "X-WxSend-Goofish-Push-Secret: <与 jarvis.wecom.goofish-push-secret 一致>" \
-     *   -d '{"toUser":"UserID","content":"订单 xxx 状态已更新"}'
-     * 
- */ - @PostMapping(value = "/goofish-active-push", consumes = MediaType.APPLICATION_JSON_VALUE) - public R goofishActivePush( - @RequestHeader(value = HEADER_GOOFISH_PUSH_SECRET, required = false) String secret, - @RequestBody WeComActivePushRequest body) { - if (!StringUtils.hasText(goofishPushSecret) || !goofishPushSecret.equals(secret)) { - return R.error(403, "拒绝访问"); - } - if (body == null || !StringUtils.hasText(body.getToUser())) { - return R.error(400, "toUser 必填"); - } - if (!StringUtils.hasText(body.getContent())) { - return R.error(400, "content 不能为空"); - } - try { - weComApplicationTextPushService.sendGoofishTextToUser(body.getToUser().trim(), body.getContent()); - return R.ok("sent"); - } catch (Exception e) { - log.warn("企微闲鱼应用推送失败 toUser={} err={}", body.getToUser(), e.toString()); - return R.error("推送失败: " + e.getMessage()); - } - } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 24ef6ce..f5e19aa 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -72,8 +72,6 @@ jarvis: shared-secret: jarvis_wecom_bridge_change_me # Jarvis 调 POST /wecom/active-push 时的 Header,须与 ruoyi jarvis.wecom.push-secret 一致 push-secret: jarvis_wecom_push_change_me - # 本地/ruoyi 调 POST /wecom/goofish-active-push 时 Header: X-WxSend-Goofish-Push-Secret - goofish-push-secret: jarvis_wecom_goofish_push_change_me qywx: webhook: @@ -86,7 +84,7 @@ qywx: agentId: "1000012" # 与 agentId 对应的应用 Secret(企微后台应用管理),用于 access_token + message/send secret: "" - # 闲鱼订单通知自建应用:POST /wecom/goofish-active-push(corpid 仍用上面 corpId) + # 闲鱼订单通知自建应用:POST /wx/send/goofish(corpid 仍用上面 corpId) # 生产建议仅通过环境变量注入,勿将真实 Secret 提交仓库 goofishAgentId: "1000013" goofishSecret: "${QYWX_GOOFISH_SECRET:hINY8boNFjY3lypOKbcukE8wYnNS9wnXeonB4iTO1rA}"