diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/user/MpUserMapper.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/user/MpUserMapper.java index bd13f925af..472b3575fe 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/user/MpUserMapper.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/user/MpUserMapper.java @@ -21,7 +21,7 @@ public interface MpUserMapper extends BaseMapperX { } default MpUserDO selectByAppIdAndOpenid(String appId, String openid) { - return selectOne(MpUserDO::getAppId, appId, + return selectFirstOne(MpUserDO::getAppId, appId, MpUserDO::getOpenid, openid); } diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/menu/MenuHandler.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/menu/MenuHandler.java index 560c2bda54..83f951715b 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/menu/MenuHandler.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/menu/MenuHandler.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.mp.service.handler.menu; import cn.iocoder.yudao.module.mp.framework.mp.core.context.MpContextHolder; import cn.iocoder.yudao.module.mp.service.menu.MpMenuService; import me.chanjar.weixin.common.session.WxSessionManager; -import me.chanjar.weixin.mp.api.WxMpMenuService; import me.chanjar.weixin.mp.api.WxMpMessageHandler; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; @@ -13,8 +12,6 @@ import org.springframework.stereotype.Component; import jakarta.annotation.Resource; import java.util.Map; -import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType; - /** * 自定义菜单的事件处理器 * diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/message/MessageReceiveHandler.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/message/MessageReceiveHandler.java index 8a740a87e1..1a4605b04e 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/message/MessageReceiveHandler.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/message/MessageReceiveHandler.java @@ -29,7 +29,7 @@ public class MessageReceiveHandler implements WxMpMessageHandler { public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map context, WxMpService wxMpService, WxSessionManager sessionManager) { log.info("[handle][接收到请求消息,内容:{}]", wxMessage); - mpMessageService.receiveMessage(MpContextHolder.getAppId(), wxMessage); + mpMessageService.receiveMessage(wxMpService, MpContextHolder.getAppId(), wxMessage); return null; } diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/message/MpMessageService.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/message/MpMessageService.java index 5ee5818064..4f77cbe504 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/message/MpMessageService.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/message/MpMessageService.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.mp.controller.admin.message.vo.message.MpMessageP import cn.iocoder.yudao.module.mp.controller.admin.message.vo.message.MpMessageSendReqVO; import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpMessageDO; import cn.iocoder.yudao.module.mp.service.message.bo.MpMessageSendOutReqBO; +import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; @@ -31,7 +32,7 @@ public interface MpMessageService { * @param appId 微信公众号 appId * @param wxMessage 消息 */ - void receiveMessage(String appId, WxMpXmlMessage wxMessage); + void receiveMessage(WxMpService weixinService, String appId, WxMpXmlMessage wxMessage); /** * 使用公众号,给粉丝回复消息 diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/message/MpMessageServiceImpl.java b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/message/MpMessageServiceImpl.java index c43021b934..4a511c8b76 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/message/MpMessageServiceImpl.java +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/message/MpMessageServiceImpl.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.mp.service.message; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.mp.controller.admin.message.vo.message.MpMessagePageReqVO; @@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.mp.service.message.bo.MpMessageSendOutReqBO; import cn.iocoder.yudao.module.mp.service.user.MpUserService; import jakarta.annotation.Resource; import jakarta.validation.Validator; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.error.WxErrorException; @@ -27,10 +28,13 @@ import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import me.chanjar.weixin.mp.bean.result.WxMpUser; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.util.concurrent.TimeUnit; + import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants.MESSAGE_SEND_FAIL; @@ -68,18 +72,31 @@ public class MpMessageServiceImpl implements MpMessageService { } @Override - public void receiveMessage(String appId, WxMpXmlMessage wxMessage) { + @SneakyThrows + public void receiveMessage(WxMpService weixinService, String appId, WxMpXmlMessage wxMessage) { // 获得关联信息 MpAccountDO account = mpAccountService.getAccountFromCache(appId); Assert.notNull(account, "公众号账号({}) 不存在", appId); - // 订阅事件不记录,因为此时公众号粉丝表中还没有此粉丝的数据 - // TODO @芋艿:这个修复,后续看看还有啥问题 - if (ObjUtil.equal(wxMessage.getEvent(), WxConsts.EventType.SUBSCRIBE)) { - return; - } - + // 获取用户 MpUserDO user = mpUserService.getUser(appId, wxMessage.getFromUser()); + if (user == null) { + // 特殊情况:因为 receiveMessage 是异步记录,可能 SubscribeHandler 还没存储好 User,此时 sleep 轮询 + for (int i = 0; i < 3; i++) { + ThreadUtil.sleep(5, TimeUnit.SECONDS); + user = mpUserService.getUser(appId, wxMessage.getFromUser()); + if (user != null) { + break; + } + log.warn("[receiveMessage][粉丝({}/{}) 不存在,第 {} 次重试失败]", appId, wxMessage.getFromUser(), i + 1); + } + } + // 特殊情况:可能 SubscribeHandler 没处理正确(例如说发生异常),则主动创建 + if (user == null) { + log.warn("[receiveMessage][粉丝({}/{}) 不存在,主动创建]", appId, wxMessage.getFromUser()); + WxMpUser wxMpUser = weixinService.getUserService().userInfo(wxMessage.getFromUser()); + user = mpUserService.saveUser(appId, wxMpUser); + } Assert.notNull(user, "公众号粉丝({}/{}) 不存在", appId, wxMessage.getFromUser()); // 记录消息