findMenuByRoleId(Integer roleId) {
return baseMapper.listMenusByRoleId(roleId);
}
diff --git a/pigx-upms/pigx-upms-biz/src/test/java/com/pig4cloud/pigx/admin/BitMapTest.java b/pigx-upms/pigx-upms-biz/src/test/java/com/pig4cloud/pigx/admin/BitMapTest.java
new file mode 100644
index 000000000..f9344df9e
--- /dev/null
+++ b/pigx-upms/pigx-upms-biz/src/test/java/com/pig4cloud/pigx/admin/BitMapTest.java
@@ -0,0 +1,86 @@
+package com.pig4cloud.pigx.admin;
+
+import java.util.BitSet;
+
+/**
+ * @author lengleng
+ * @date 2019-03-26
+ */
+public class BitMapTest {
+ private int[] bigArray;
+
+ public BitMapTest(long size) {
+ bigArray = new int[(int) (size / 32 + 1)];
+ }
+
+ public void set1(int num) {
+ //确定数组 index
+ int arrayIndex = num >> 5;
+ //确定bit index
+ int bitIndex = num & 31;
+ //设置0
+ bigArray[arrayIndex] |= 1 << bitIndex;
+
+ System.out.println(bigArray[arrayIndex]);
+ }
+
+ public void set0(int num) {
+ //确定数组 index
+ int arrayIndex = num >> 5;
+ //确定bit index
+ int bitIndex = num & 31;
+ //设置0
+ bigArray[arrayIndex] &= ~(1 << bitIndex);
+ System.out.println(get32BitBinString(bigArray[arrayIndex]));
+ }
+
+ public boolean isExist(int num) {
+ //确定数组 index
+ int arrayIndex = num >> 5;
+ //确定bit index
+ int bitIndex = num & 31;
+
+ //判断是否存在
+ return (bigArray[arrayIndex] & ((1 << bitIndex))) != 0;
+ }
+
+ /**
+ * 将整型数字转换为二进制字符串,一共32位,不舍弃前面的0
+ *
+ * @param number 整型数字
+ * @return 二进制字符串
+ */
+ private static String get32BitBinString(int number) {
+ StringBuilder sBuilder = new StringBuilder();
+ for (int i = 0; i < 32; i++) {
+ sBuilder.append(number & 1);
+ number = number >>> 1;
+ }
+ return sBuilder.reverse().toString();
+ }
+
+ public static void main(String[] args) {
+
+ int[] array = new int[]{1, 2, 3, 22, 0, 3, 63};
+ BitSet bitSet = new BitSet(1);
+ System.out.println(bitSet.size()); //64
+ bitSet = new BitSet(65);
+ System.out.println(bitSet.size()); //128
+ bitSet = new BitSet(23);
+ System.out.println(bitSet.size()); //64
+
+ //将数组内容组bitmap
+ for (int i = 0; i < array.length; i++) {
+ bitSet.set(array[i], true);
+ }
+
+ System.out.println(bitSet.get(22));
+ System.out.println(bitSet.get(60));
+
+ System.out.println("下面开始遍历BitSet:");
+ for (int i = 0; i < bitSet.size(); i++) {
+ System.out.println(bitSet.get(i));
+ }
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/Dockerfile b/pigx-visual/pigx-mp-manager/Dockerfile
new file mode 100644
index 000000000..702a7171c
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/Dockerfile
@@ -0,0 +1,15 @@
+FROM anapsix/alpine-java:8_server-jre_unlimited
+
+MAINTAINER wangiegie@gmail.com
+
+RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
+
+RUN mkdir -p /pigx-mp-manager
+
+WORKDIR /pigx-mp-manager
+
+EXPOSE 5003
+
+ADD ./pigx-visual/pigx-mp-manager/target/pigx-mp-manager.jar ./
+
+CMD java -Djava.security.egd=file:/dev/./urandom -jar pigx-mp-manager.jar
diff --git a/pigx-visual/pigx-mp-manager/pom.xml b/pigx-visual/pigx-mp-manager/pom.xml
new file mode 100755
index 000000000..cb9b513c3
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/pom.xml
@@ -0,0 +1,85 @@
+
+
+ 4.0.0
+
+
+ com.pig4cloud
+ pigx-visual
+ 2.6.0
+
+
+ pigx-mp-manager
+ jar
+
+ 微信公众号管理模块
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+
+ com.pig4cloud
+ pigx-common-data
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ com.pig4cloud
+ pigx-common-core
+
+
+
+ com.pig4cloud
+ pigx-common-swagger
+
+
+
+ com.pig4cloud
+ pigx-common-security
+
+
+ com.pig4cloud
+ pigx-common-log
+
+
+
+ com.github.binarywang
+ weixin-java-mp
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ com.spotify
+ docker-maven-plugin
+
+
+
+
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/PigxMpManagerApplication.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/PigxMpManagerApplication.java
new file mode 100755
index 000000000..ee64a45b6
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/PigxMpManagerApplication.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.mp;
+
+import com.pig4cloud.pigx.common.security.annotation.EnablePigxFeignClients;
+import com.pig4cloud.pigx.common.security.annotation.EnablePigxResourceServer;
+import com.pig4cloud.pigx.common.swagger.annotation.EnablePigxSwagger2;
+import org.springframework.boot.SpringApplication;
+import org.springframework.cloud.client.SpringCloudApplication;
+
+/**
+ * @author lengleng
+ * @date 2019/03/25
+ * 代码生成模块
+ */
+@EnablePigxSwagger2
+@SpringCloudApplication
+@EnablePigxFeignClients
+@EnablePigxResourceServer
+public class PigxMpManagerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(PigxMpManagerApplication.class, args);
+ }
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/AbstractBuilder.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/AbstractBuilder.java
new file mode 100755
index 000000000..7a94beb73
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/AbstractBuilder.java
@@ -0,0 +1,21 @@
+package com.pig4cloud.pigx.mp.builder;
+
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+public abstract class AbstractBuilder {
+ /**
+ * 构建返回微信消息报文
+ *
+ * @param content
+ * @param wxMessage
+ * @param service
+ * @return
+ */
+ public abstract WxMpXmlOutMessage build(String content,
+ WxMpXmlMessage wxMessage, WxMpService service);
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/ImageBuilder.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/ImageBuilder.java
new file mode 100755
index 000000000..07d8686f6
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/ImageBuilder.java
@@ -0,0 +1,24 @@
+package com.pig4cloud.pigx.mp.builder;
+
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+public class ImageBuilder extends AbstractBuilder {
+
+ @Override
+ public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
+ WxMpService service) {
+
+ WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId(content)
+ .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
+ .build();
+
+ return m;
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/TextBuilder.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/TextBuilder.java
new file mode 100755
index 000000000..a212ddc27
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/builder/TextBuilder.java
@@ -0,0 +1,22 @@
+package com.pig4cloud.pigx.mp.builder;
+
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+public class TextBuilder extends AbstractBuilder {
+
+ @Override
+ public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
+ WxMpService service) {
+ WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content)
+ .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
+ .build();
+ return m;
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/config/WxMpConfiguration.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/config/WxMpConfiguration.java
new file mode 100755
index 000000000..6211b502a
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/config/WxMpConfiguration.java
@@ -0,0 +1,149 @@
+package com.pig4cloud.pigx.mp.config;
+
+import com.google.common.collect.Maps;
+import com.pig4cloud.pigx.mp.handler.*;
+import com.pig4cloud.pigx.mp.service.WxAccountService;
+import me.chanjar.weixin.mp.api.WxMpMessageRouter;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
+import me.chanjar.weixin.mp.constant.WxMpEventConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.core.RedisTemplate;
+
+import javax.annotation.PostConstruct;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static me.chanjar.weixin.common.api.WxConsts.*;
+
+/**
+ * @author Binary Wang
+ * @author lengleng
+ *
+ * 微信公众号基础配置,初始化配置
+ */
+@Configuration
+public class WxMpConfiguration {
+ public static Map getRouters() {
+ return routers;
+ }
+
+ public static Map getMpServices() {
+ return mpServices;
+ }
+
+ private WxAccountService accountService;
+ private LogHandler logHandler;
+ private NullHandler nullHandler;
+ private KfSessionHandler kfSessionHandler;
+ private StoreCheckNotifyHandler storeCheckNotifyHandler;
+ private LocationHandler locationHandler;
+ private MenuHandler menuHandler;
+ private MsgHandler msgHandler;
+ private UnsubscribeHandler unsubscribeHandler;
+ private SubscribeHandler subscribeHandler;
+ private ScanHandler scanHandler;
+ private RedisTemplate redisTemplate;
+
+ private static Map routers = Maps.newHashMap();
+ private static Map mpServices = Maps.newHashMap();
+
+ @Autowired
+ public WxMpConfiguration(WxAccountService accountService, LogHandler logHandler, NullHandler nullHandler
+ , KfSessionHandler kfSessionHandler, StoreCheckNotifyHandler storeCheckNotifyHandler
+ , LocationHandler locationHandler, MenuHandler menuHandler
+ , MsgHandler msgHandler, UnsubscribeHandler unsubscribeHandler
+ , SubscribeHandler subscribeHandler, ScanHandler scanHandler
+ , RedisTemplate pigxRedisTemplate) {
+ this.accountService = accountService;
+ this.logHandler = logHandler;
+ this.nullHandler = nullHandler;
+ this.kfSessionHandler = kfSessionHandler;
+ this.storeCheckNotifyHandler = storeCheckNotifyHandler;
+ this.locationHandler = locationHandler;
+ this.menuHandler = menuHandler;
+ this.msgHandler = msgHandler;
+ this.unsubscribeHandler = unsubscribeHandler;
+ this.subscribeHandler = subscribeHandler;
+ this.scanHandler = scanHandler;
+ this.redisTemplate = pigxRedisTemplate;
+ }
+
+ @PostConstruct
+ public void initServices() {
+ mpServices = accountService.list().stream().map(a -> {
+ WxMpInRedisConfigStorage configStorage = new WxMpInRedisConfigStorage(redisTemplate);
+ configStorage.setAppId(a.getAppid());
+ configStorage.setSecret(a.getAppsecret());
+ configStorage.setToken(a.getToken());
+ configStorage.setAesKey(a.getAeskey());
+
+ WxMpService service = new WxMpServiceImpl();
+ service.setWxMpConfigStorage(configStorage);
+ routers.put(a.getAppid(), this.newRouter(service));
+ return service;
+ }).collect(Collectors.toMap(s -> s.getWxMpConfigStorage().getAppId(), a -> a));
+ }
+
+ private WxMpMessageRouter newRouter(WxMpService wxMpService) {
+ final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);
+
+ // 记录所有事件的日志 (异步执行)
+ newRouter.rule().handler(this.logHandler).next();
+
+ // 接收客服会话管理事件
+ newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
+ .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION)
+ .handler(this.kfSessionHandler).end();
+ newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
+ .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION)
+ .handler(this.kfSessionHandler)
+ .end();
+ newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
+ .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION)
+ .handler(this.kfSessionHandler).end();
+
+ // 门店审核事件
+ newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
+ .event(WxMpEventConstants.POI_CHECK_NOTIFY)
+ .handler(this.storeCheckNotifyHandler).end();
+
+ // 自定义菜单事件
+ newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
+ .event(MenuButtonType.CLICK).handler(this.menuHandler).end();
+
+ // 点击菜单连接事件
+ newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
+ .event(MenuButtonType.VIEW).handler(this.nullHandler).end();
+
+ // 关注事件
+ newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
+ .event(EventType.SUBSCRIBE).handler(this.subscribeHandler)
+ .end();
+
+ // 取消关注事件
+ newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
+ .event(EventType.UNSUBSCRIBE)
+ .handler(this.unsubscribeHandler).end();
+
+ // 上报地理位置事件
+ newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
+ .event(EventType.LOCATION).handler(this.locationHandler)
+ .end();
+
+ // 接收地理位置消息
+ newRouter.rule().async(false).msgType(XmlMsgType.LOCATION)
+ .handler(this.locationHandler).end();
+
+ // 扫码事件
+ newRouter.rule().async(false).msgType(XmlMsgType.EVENT)
+ .event(EventType.SCAN).handler(this.scanHandler).end();
+
+ // 默认
+ newRouter.rule().async(false).handler(this.msgHandler).end();
+
+ return newRouter;
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInRedisConfigStorage.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInRedisConfigStorage.java
new file mode 100644
index 000000000..a045b6ca5
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInRedisConfigStorage.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2018-2025, 云集汇通 All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the yunjihuitong.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ */
+
+package com.pig4cloud.pigx.mp.config;
+
+import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
+import me.chanjar.weixin.mp.enums.TicketType;
+import org.springframework.data.redis.core.RedisTemplate;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author lengleng
+ * @date 2019/03/26
+ *
+ * 微信SDK redis扩展
+ */
+public class WxMpInRedisConfigStorage extends WxMpInMemoryConfigStorage {
+
+ private final static String ACCESS_TOKEN_KEY = "wechat:access_token_";
+
+ private final static String JSAPI_TICKET_KEY = "wechat:jsapi_ticket_";
+
+ private final static String CARDAPI_TICKET_KEY = "wechat:cardapi_ticket_";
+
+ private final RedisTemplate redisTemplate;
+
+ private String accessTokenKey;
+
+ private String jsapiTicketKey;
+
+ private String cardapiTicketKey;
+
+ public WxMpInRedisConfigStorage(RedisTemplate redisTemplate) {
+ this.redisTemplate = redisTemplate;
+ }
+
+ /**
+ * 每个公众号生成独有的存储key
+ *
+ * @param appId
+ */
+ @Override
+ public void setAppId(String appId) {
+ super.setAppId(appId);
+ this.accessTokenKey = ACCESS_TOKEN_KEY.concat(appId);
+ this.jsapiTicketKey = JSAPI_TICKET_KEY.concat(appId);
+ this.cardapiTicketKey = CARDAPI_TICKET_KEY.concat(appId);
+ }
+
+ @Override
+ public String getAccessToken() {
+ return redisTemplate.opsForValue().get(this.accessTokenKey);
+ }
+
+ @Override
+ public boolean isAccessTokenExpired() {
+ return redisTemplate.getExpire(accessTokenKey) < 2L;
+ }
+
+ @Override
+ public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {
+ redisTemplate.opsForValue().set(accessTokenKey, accessToken, expiresInSeconds - 200, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void expireAccessToken() {
+ redisTemplate.expire(this.accessTokenKey, 0, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public String getJsapiTicket() {
+ return redisTemplate.opsForValue().get(this.jsapiTicketKey);
+ }
+
+
+ @Override
+ public String getCardApiTicket() {
+ return redisTemplate.opsForValue().get(cardapiTicketKey);
+ }
+
+
+ @Override
+ public String getTicket(TicketType type) {
+ return redisTemplate.opsForValue().get(getTicketRedisKey(type));
+ }
+
+ @Override
+ public boolean isTicketExpired(TicketType type) {
+ return redisTemplate.getExpire(this.getTicketRedisKey(type)) < 2;
+ }
+
+ @Override
+ public synchronized void updateTicket(TicketType type, String jsapiTicket, int expiresInSeconds) {
+ redisTemplate.opsForValue().set(getTicketRedisKey(type), jsapiTicket, expiresInSeconds - 200, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void expireTicket(TicketType type) {
+ redisTemplate.expire(getTicketRedisKey(type), 0, TimeUnit.SECONDS);
+ }
+
+ private String getTicketRedisKey(TicketType type) {
+ return String.format("wechat:ticket:key:%s:%s", this.appId, type.getCode());
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountController.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountController.java
new file mode 100755
index 000000000..322d0dc9b
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountController.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+package com.pig4cloud.pigx.mp.controller;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.pig4cloud.pigx.common.core.util.R;
+import com.pig4cloud.pigx.common.log.annotation.SysLog;
+import com.pig4cloud.pigx.mp.config.WxMpConfiguration;
+import com.pig4cloud.pigx.mp.entity.WxAccount;
+import com.pig4cloud.pigx.mp.service.WxAccountService;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+
+/**
+ * 公众号账户
+ *
+ * @author lengleng
+ * @date 2019-03-26 22:07:53
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/wxaccount")
+public class WxAccountController {
+ private final WxMpConfiguration wxMpConfiguration;
+ private final WxAccountService wxAccountService;
+
+ /**
+ * 分页查询
+ *
+ * @param page 分页对象
+ * @param wxAccount 公众号账户
+ * @return
+ */
+ @GetMapping("/page")
+ public R getWxAccountPage(Page page, WxAccount wxAccount) {
+ return new R<>(wxAccountService.page(page, Wrappers.query(wxAccount)));
+ }
+
+
+ /**
+ * 通过id查询公众号账户
+ *
+ * @param id id
+ * @return R
+ */
+ @GetMapping("/{id}")
+ public R getById(@PathVariable("id") Integer id) {
+ return new R<>(wxAccountService.getById(id));
+ }
+
+ /**
+ * 新增公众号账户
+ *
+ * @param wxAccount 公众号账户
+ * @return R
+ */
+ @SysLog("新增公众号账户")
+ @PostMapping
+ @PreAuthorize("@pms.hasPermission('mp_wxaccount_add')")
+ public R save(@RequestBody WxAccount wxAccount) {
+ wxAccountService.save(wxAccount);
+ wxMpConfiguration.initServices();
+ return new R<>();
+ }
+
+ /**
+ * 修改公众号账户
+ *
+ * @param wxAccount 公众号账户
+ * @return R
+ */
+ @SysLog("修改公众号账户")
+ @PutMapping
+ @PreAuthorize("@pms.hasPermission('mp_wxaccount_edit')")
+ public R updateById(@RequestBody WxAccount wxAccount) {
+ wxAccountService.updateById(wxAccount);
+ wxMpConfiguration.initServices();
+ return new R<>();
+ }
+
+ /**
+ * 通过id删除公众号账户
+ *
+ * @param id id
+ * @return R
+ */
+ @SysLog("删除公众号账户")
+ @DeleteMapping("/{id}")
+ @PreAuthorize("@pms.hasPermission('mp_wxaccount_del')")
+ public R removeById(@PathVariable Integer id) {
+ wxAccountService.removeById(id);
+ wxMpConfiguration.initServices();
+ return new R<>();
+ }
+
+ /**
+ * 生成公众号二维码
+ *
+ * @param appId
+ * @return
+ */
+ @SysLog("生成公众号二维码")
+ @PostMapping("/qr/{appId}")
+ @PreAuthorize("@pms.hasPermission('mp_wxaccount_add')")
+ public R qr(@PathVariable String appId) {
+ return wxAccountService.generateQr(appId);
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountFansController.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountFansController.java
new file mode 100755
index 000000000..550ca3d80
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxAccountFansController.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+package com.pig4cloud.pigx.mp.controller;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.pig4cloud.pigx.common.core.util.R;
+import com.pig4cloud.pigx.common.log.annotation.SysLog;
+import com.pig4cloud.pigx.mp.entity.WxAccountFans;
+import com.pig4cloud.pigx.mp.service.WxAccountFansService;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+
+/**
+ * 微信公众号粉丝管理
+ *
+ * @author lengleng
+ * @date 2019-03-26 22:08:08
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/wxaccountfans")
+public class WxAccountFansController {
+
+ private final WxAccountFansService wxAccountFansService;
+
+ /**
+ * 分页查询
+ *
+ * @param page 分页对象
+ * @param wxAccountFans 微信公众号粉丝
+ * @return
+ */
+ @GetMapping("/page")
+ public R getWxAccountFansPage(Page page, WxAccountFans wxAccountFans) {
+ return new R<>(wxAccountFansService.page(page, Wrappers.query(wxAccountFans)));
+ }
+
+
+ /**
+ * 通过id查询微信公众号粉丝
+ *
+ * @param id id
+ * @return R
+ */
+ @GetMapping("/{id}")
+ public R getById(@PathVariable("id") Integer id) {
+ return new R<>(wxAccountFansService.getById(id));
+ }
+
+ /**
+ * 新增微信公众号粉丝
+ *
+ * @param wxAccountFans 微信公众号粉丝
+ * @return R
+ */
+ @SysLog("新增微信公众号粉丝")
+ @PostMapping
+ @PreAuthorize("@pms.hasPermission('mp_wxaccountfans_add')")
+ public R save(@RequestBody WxAccountFans wxAccountFans) {
+ return new R<>(wxAccountFansService.save(wxAccountFans));
+ }
+
+ /**
+ * 修改微信公众号粉丝
+ *
+ * @param wxAccountFans 微信公众号粉丝
+ * @return R
+ */
+ @SysLog("修改微信公众号粉丝")
+ @PutMapping
+ @PreAuthorize("@pms.hasPermission('mp_wxaccountfans_edit')")
+ public R updateById(@RequestBody WxAccountFans wxAccountFans) {
+ return new R<>(wxAccountFansService.updateById(wxAccountFans));
+ }
+
+ /**
+ * 通过id删除微信公众号粉丝
+ *
+ * @param id id
+ * @return R
+ */
+ @SysLog("删除微信公众号粉丝")
+ @DeleteMapping("/{id}")
+ @PreAuthorize("@pms.hasPermission('mp_wxaccountfans_del')")
+ public R removeById(@PathVariable Integer id) {
+ return new R<>(wxAccountFansService.removeById(id));
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxPortalController.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxPortalController.java
new file mode 100755
index 000000000..a9afd103c
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxPortalController.java
@@ -0,0 +1,119 @@
+package com.pig4cloud.pigx.mp.controller;
+
+import cn.hutool.core.util.StrUtil;
+import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
+import com.pig4cloud.pigx.mp.config.WxMpConfiguration;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author Binary Wang
+ * @author lengleng
+ *
+ * 微信接入入口
+ */
+@Slf4j
+@RestController
+@RequestMapping("/{appId}/portal")
+public class WxPortalController {
+
+ /**
+ * 微信接入校验处理
+ *
+ * @param appId 多公众号标志位
+ * @param signature 微信签名
+ * @param timestamp 时间戳
+ * @param nonce 随机数
+ * @param echostr 随机字符串
+ * @return
+ */
+ @GetMapping(produces = "text/plain;charset=utf-8")
+ public String authGet(@PathVariable("appId") String appId,
+ @RequestParam(name = "signature", required = false) String signature,
+ @RequestParam(name = "timestamp", required = false) String timestamp,
+ @RequestParam(name = "nonce", required = false) String nonce,
+ @RequestParam(name = "echostr", required = false) String echostr) {
+
+ log.info("接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", signature, timestamp, nonce, echostr);
+
+ if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
+ throw new IllegalArgumentException("请求参数非法,请核实!");
+ }
+
+ final WxMpService wxService = WxMpConfiguration.getMpServices().get(appId);
+
+ if (wxService == null) {
+ throw new IllegalArgumentException(String.format("未找到对应appid=[%d]的配置,请核实!", appId));
+ }
+
+ if (wxService.checkSignature(timestamp, nonce, signature)) {
+ return echostr;
+ }
+
+ return "非法请求";
+ }
+
+ /**
+ * 微信消息处理
+ *
+ * @param appId 多公众号标志位
+ * @param requestBody 请求报文体
+ * @param signature 微信签名
+ * @param encType 加签方式
+ * @param msgSignature 微信签名
+ * @param timestamp 时间戳
+ * @param nonce 随机数
+ * @return
+ */
+ @PostMapping(produces = "application/xml; charset=UTF-8")
+ public String post(@PathVariable("appId") String appId,
+ @RequestBody String requestBody,
+ @RequestParam("signature") String signature,
+ @RequestParam("timestamp") String timestamp,
+ @RequestParam("nonce") String nonce,
+ @RequestParam("openid") String openid,
+ @RequestParam(name = "encrypt_type", required = false) String encType,
+ @RequestParam(name = "msg_signature", required = false) String msgSignature) {
+ final WxMpService wxService = WxMpConfiguration.getMpServices().get(appId);
+
+ log.info("接收微信请求:[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}],"
+ + " timestamp=[{}], nonce=[{}], requestBody=[{}] ",
+ openid, signature, encType, msgSignature, timestamp, nonce, requestBody);
+
+ if (!wxService.checkSignature(timestamp, nonce, signature)) {
+ throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
+ }
+
+ String out = null;
+
+ // 明文模式
+ if (StrUtil.isBlank(encType)) {
+ WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
+ WxMpXmlOutMessage outMessage = WxMpConfiguration.getRouters().get(appId).route(inMessage);
+ if (outMessage != null) {
+ out = outMessage.toXml();
+ }
+ }
+
+ // aes加密模式
+ if (SecurityConstants.AES.equalsIgnoreCase(encType)) {
+ WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(),
+ timestamp, nonce, msgSignature);
+
+ log.debug("消息解密后内容为:{} ", inMessage.toString());
+
+ WxMpXmlOutMessage outMessage = WxMpConfiguration.getRouters().get(appId).route(inMessage);
+ if (outMessage != null) {
+ out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage());
+ }
+ }
+
+ log.debug("组装回复信息:{}", out);
+ return out;
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxRedirectController.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxRedirectController.java
new file mode 100755
index 000000000..e0c48c36b
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/controller/WxRedirectController.java
@@ -0,0 +1,37 @@
+package com.pig4cloud.pigx.mp.controller;
+
+import com.pig4cloud.pigx.mp.config.WxMpConfiguration;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
+import me.chanjar.weixin.mp.bean.result.WxMpUser;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * @author Edward
+ */
+@Controller
+@RequestMapping("/wx/redirect/{appid}")
+public class WxRedirectController {
+
+
+ @RequestMapping("/greet")
+ public String greetUser(@PathVariable String appid, @RequestParam String code, ModelMap map) {
+
+ WxMpService mpService = WxMpConfiguration.getMpServices().get(appid);
+
+ try {
+ WxMpOAuth2AccessToken accessToken = mpService.oauth2getAccessToken(code);
+ WxMpUser user = mpService.oauth2getUserInfo(accessToken, null);
+ map.put("user", user);
+ } catch (WxErrorException e) {
+ e.printStackTrace();
+ }
+
+ return "greet_user";
+ }
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccount.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccount.java
new file mode 100755
index 000000000..76623d276
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccount.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+package com.pig4cloud.pigx.mp.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+
+/**
+ * 公众号账户
+ *
+ * @author lengleng
+ * @date 2019-03-26 22:07:53
+ */
+@Data
+@TableName("t_wx_account")
+@EqualsAndHashCode(callSuper = true)
+public class WxAccount extends Model {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键
+ */
+ @TableId
+ private Integer id;
+ /**
+ * 公众号名称
+ */
+ private String name;
+ /**
+ * 公众号账户
+ */
+ private String account;
+ /**
+ * 公众号appid
+ */
+ private String appid;
+ /**
+ * 公众号密钥
+ */
+ private String appsecret;
+ /**
+ * 公众号url
+ */
+ private String url;
+ /**
+ * 公众号token
+ */
+ private String token;
+ /**
+ * 加密密钥
+ */
+ private String aeskey;
+ /**
+ * 二维码图片URL
+ */
+ private String qrUrl;
+ /**
+ * 创建时间
+ */
+ private LocalDateTime createTime;
+ /**
+ * 更新时间
+ */
+ private LocalDateTime updateTime;
+
+ /**
+ * 是否删除 -1:已删除 0:正常
+ */
+ @TableLogic
+ private String delFlag;
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccountFans.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccountFans.java
new file mode 100755
index 000000000..a2ec8af50
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/entity/WxAccountFans.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+package com.pig4cloud.pigx.mp.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+
+/**
+ * 微信公众号粉丝
+ *
+ * @author lengleng
+ * @date 2019-03-26 22:08:08
+ */
+@Data
+@TableName("t_wx_account_fans")
+@EqualsAndHashCode(callSuper = true)
+public class WxAccountFans extends Model {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键
+ */
+ @TableId
+ private Integer id;
+ /**
+ * 用户标识
+ */
+ private String openid;
+ /**
+ * 订阅状态,0未关注,1已关注
+ */
+ private String subscribeStatus;
+ /**
+ * 订阅时间
+ */
+ private LocalDateTime subscribeTime;
+ /**
+ * 昵称
+ */
+ private String nickname;
+ /**
+ * 性别,1男,2女,0未知
+ */
+ private String gender;
+ /**
+ * 语言
+ */
+ private String language;
+ /**
+ * 国家
+ */
+ private String country;
+ /**
+ * 省份
+ */
+ private String province;
+ /**
+ * 城市
+ */
+ private String city;
+ /**
+ * 头像地址
+ */
+ private String headimgUrl;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 微信公众号ID
+ */
+ private String wxAccountId;
+ /**
+ * 微信公众号appid
+ */
+ private String wxAccountAppid;
+ /**
+ * 创建时间
+ */
+ private LocalDateTime createTime;
+ /**
+ * 更新时间
+ */
+ private LocalDateTime updateTime;
+ /**
+ * 是否删除 -1:已删除 0:正常
+ */
+ @TableLogic
+ private String delFlag;
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/AbstractHandler.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/AbstractHandler.java
new file mode 100755
index 000000000..c59c54c4e
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/AbstractHandler.java
@@ -0,0 +1,9 @@
+package com.pig4cloud.pigx.mp.handler;
+
+import me.chanjar.weixin.mp.api.WxMpMessageHandler;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+public abstract class AbstractHandler implements WxMpMessageHandler {
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/KfSessionHandler.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/KfSessionHandler.java
new file mode 100755
index 000000000..a6792b40c
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/KfSessionHandler.java
@@ -0,0 +1,24 @@
+package com.pig4cloud.pigx.mp.handler;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class KfSessionHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService wxMpService,
+ WxSessionManager sessionManager) {
+ return null;
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/LocationHandler.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/LocationHandler.java
new file mode 100755
index 000000000..76c442ce0
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/LocationHandler.java
@@ -0,0 +1,34 @@
+package com.pig4cloud.pigx.mp.handler;
+
+import com.pig4cloud.pigx.mp.builder.TextBuilder;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Slf4j
+@Component
+public class LocationHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService wxMpService,
+ WxSessionManager sessionManager) {
+ //上报地理位置事件
+ log.info("上报地理位置,纬度 : {},经度 : {},精度 : {}",
+ wxMessage.getLatitude(), wxMessage.getLongitude(), wxMessage.getPrecision());
+
+ //TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用
+
+ String content = "感谢反馈,您的的地理位置已收到!";
+ return new TextBuilder().build(content, wxMessage, null);
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/LogHandler.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/LogHandler.java
new file mode 100755
index 000000000..0294e435c
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/LogHandler.java
@@ -0,0 +1,26 @@
+package com.pig4cloud.pigx.mp.handler;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Slf4j
+@Component
+public class LogHandler extends AbstractHandler {
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService wxMpService,
+ WxSessionManager sessionManager) {
+ log.info("接收到请求消息,内容:{}", wxMessage.getContent());
+ return null;
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/MenuHandler.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/MenuHandler.java
new file mode 100755
index 000000000..630c33535
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/MenuHandler.java
@@ -0,0 +1,36 @@
+package com.pig4cloud.pigx.mp.handler;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class MenuHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService weixinService,
+ WxSessionManager sessionManager) {
+
+ String msg = String.format("type:%s, event:%s, key:%s",
+ wxMessage.getMsgType(), wxMessage.getEvent(),
+ wxMessage.getEventKey());
+ if (MenuButtonType.VIEW.equals(wxMessage.getEvent())) {
+ return null;
+ }
+
+ return WxMpXmlOutMessage.TEXT().content(msg)
+ .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
+ .build();
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/MsgHandler.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/MsgHandler.java
new file mode 100755
index 000000000..21feece52
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/MsgHandler.java
@@ -0,0 +1,49 @@
+package com.pig4cloud.pigx.mp.handler;
+
+import com.pig4cloud.pigx.mp.builder.TextBuilder;
+import lombok.SneakyThrows;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class MsgHandler extends AbstractHandler {
+
+ @Override
+ @SneakyThrows
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService weixinService,
+ WxSessionManager sessionManager) {
+
+ if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) {
+ //TODO 可以选择将消息保存到本地
+ }
+
+ //当用户输入关键词如“你好”,“客服”等,并且有客服在线时,把消息转发给在线客服
+ if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "客服")
+ && weixinService.getKefuService().kfOnlineList()
+ .getKfOnlineList().size() > 0) {
+ return WxMpXmlOutMessage.TRANSFER_CUSTOMER_SERVICE()
+ .fromUser(wxMessage.getToUser())
+ .toUser(wxMessage.getFromUser()).build();
+ }
+
+
+ //TODO 组装回复消息
+ String content = "收到信息内容:" + wxMessage.getContent();
+
+ return new TextBuilder().build(content, wxMessage, weixinService);
+
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/NullHandler.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/NullHandler.java
new file mode 100755
index 000000000..5f961b871
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/NullHandler.java
@@ -0,0 +1,24 @@
+package com.pig4cloud.pigx.mp.handler;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class NullHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService wxMpService,
+ WxSessionManager sessionManager) {
+ return null;
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/ScanHandler.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/ScanHandler.java
new file mode 100755
index 000000000..0173764f6
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/ScanHandler.java
@@ -0,0 +1,24 @@
+package com.pig4cloud.pigx.mp.handler;
+
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class ScanHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map map,
+ WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException {
+ // 扫码事件处理
+ return null;
+ }
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/StoreCheckNotifyHandler.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/StoreCheckNotifyHandler.java
new file mode 100755
index 000000000..1d75ea153
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/StoreCheckNotifyHandler.java
@@ -0,0 +1,27 @@
+package com.pig4cloud.pigx.mp.handler;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * 门店审核事件处理
+ *
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Component
+public class StoreCheckNotifyHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService wxMpService,
+ WxSessionManager sessionManager) {
+ // TODO 处理门店审核事件
+ return null;
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/SubscribeHandler.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/SubscribeHandler.java
new file mode 100755
index 000000000..a90c174d3
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/SubscribeHandler.java
@@ -0,0 +1,72 @@
+package com.pig4cloud.pigx.mp.handler;
+
+import com.pig4cloud.pigx.mp.builder.TextBuilder;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+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.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Slf4j
+@Component
+public class SubscribeHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService weixinService,
+ WxSessionManager sessionManager) throws WxErrorException {
+
+ log.info("新关注用户 OPENID: " + wxMessage.getFromUser());
+
+ // 获取微信用户基本信息
+ try {
+ WxMpUser userWxInfo = weixinService.getUserService()
+ .userInfo(wxMessage.getFromUser(), null);
+ if (userWxInfo != null) {
+ // TODO 可以添加关注用户到本地数据库
+ }
+ } catch (WxErrorException e) {
+ if (e.getError().getErrorCode() == 48001) {
+ log.info("该公众号没有获取用户信息权限!");
+ }
+ }
+
+
+ WxMpXmlOutMessage responseResult = null;
+ try {
+ responseResult = this.handleSpecial(wxMessage);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+
+ if (responseResult != null) {
+ return responseResult;
+ }
+
+ try {
+ return new TextBuilder().build("感谢关注", wxMessage, weixinService);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+
+ return null;
+ }
+
+ /**
+ * 处理特殊请求,比如如果是扫码进来的,可以做相应处理
+ */
+ private WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage)
+ throws Exception {
+ //TODO
+ return null;
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/UnsubscribeHandler.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/UnsubscribeHandler.java
new file mode 100755
index 000000000..7dde34f32
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/handler/UnsubscribeHandler.java
@@ -0,0 +1,29 @@
+package com.pig4cloud.pigx.mp.handler;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * @author Binary Wang(https://github.com/binarywang)
+ */
+@Slf4j
+@Component
+public class UnsubscribeHandler extends AbstractHandler {
+
+ @Override
+ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+ Map context, WxMpService wxMpService,
+ WxSessionManager sessionManager) {
+ String openId = wxMessage.getFromUser();
+ log.info("取消关注用户 OPENID: " + openId);
+ // TODO 可以更新本地数据库为取消关注状态
+ return null;
+ }
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountFansMapper.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountFansMapper.java
new file mode 100755
index 000000000..010329ea7
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountFansMapper.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+package com.pig4cloud.pigx.mp.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pig4cloud.pigx.mp.entity.WxAccountFans;
+
+/**
+ * 微信公众号粉丝
+ *
+ * @author lengleng
+ * @date 2019-03-26 22:08:08
+ */
+public interface WxAccountFansMapper extends BaseMapper {
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountMapper.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountMapper.java
new file mode 100755
index 000000000..899c95124
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/mapper/WxAccountMapper.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+package com.pig4cloud.pigx.mp.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pig4cloud.pigx.mp.entity.WxAccount;
+
+/**
+ * 公众号账户
+ *
+ * @author lengleng
+ * @date 2019-03-26 22:07:53
+ */
+public interface WxAccountMapper extends BaseMapper {
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountFansService.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountFansService.java
new file mode 100755
index 000000000..e0c374795
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountFansService.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+package com.pig4cloud.pigx.mp.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.pig4cloud.pigx.mp.entity.WxAccountFans;
+
+/**
+ * 微信公众号粉丝
+ *
+ * @author lengleng
+ * @date 2019-03-26 22:08:08
+ */
+public interface WxAccountFansService extends IService {
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountService.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountService.java
new file mode 100755
index 000000000..926091d84
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/WxAccountService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+package com.pig4cloud.pigx.mp.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.pig4cloud.pigx.common.core.util.R;
+import com.pig4cloud.pigx.mp.entity.WxAccount;
+
+/**
+ * 公众号账户
+ *
+ * @author lengleng
+ * @date 2019-03-26 22:07:53
+ */
+public interface WxAccountService extends IService {
+
+ /**
+ * 生成公众号二维码
+ *
+ * @param appId
+ * @return
+ */
+ R generateQr(String appId);
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountFansServiceImpl.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountFansServiceImpl.java
new file mode 100755
index 000000000..45b45fc99
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountFansServiceImpl.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+package com.pig4cloud.pigx.mp.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.pig4cloud.pigx.mp.entity.WxAccountFans;
+import com.pig4cloud.pigx.mp.mapper.WxAccountFansMapper;
+import com.pig4cloud.pigx.mp.service.WxAccountFansService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 微信公众号粉丝
+ *
+ * @author lengleng
+ * @date 2019-03-26 22:08:08
+ */
+@Service
+public class WxAccountFansServiceImpl extends ServiceImpl implements WxAccountFansService {
+
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountServiceImpl.java b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountServiceImpl.java
new file mode 100755
index 000000000..d5cbe95e3
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/java/com/pig4cloud/pigx/mp/service/impl/WxAccountServiceImpl.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+package com.pig4cloud.pigx.mp.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.pig4cloud.pigx.common.core.constant.CommonConstants;
+import com.pig4cloud.pigx.common.core.util.R;
+import com.pig4cloud.pigx.mp.config.WxMpConfiguration;
+import com.pig4cloud.pigx.mp.entity.WxAccount;
+import com.pig4cloud.pigx.mp.mapper.WxAccountMapper;
+import com.pig4cloud.pigx.mp.service.WxAccountService;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
+import org.springframework.stereotype.Service;
+
+/**
+ * 公众号账户
+ *
+ * @author lengleng
+ * @date 2019-03-26 22:07:53
+ */
+@Slf4j
+@Service
+public class WxAccountServiceImpl extends ServiceImpl implements WxAccountService {
+
+ /**
+ * 生成公众号二维码
+ *
+ * @param appId
+ * @return
+ */
+
+ @Override
+ public R generateQr(String appId) {
+ WxMpService wxMpService = WxMpConfiguration.getMpServices().get(appId);
+ try {
+ WxMpQrCodeTicket ticket = wxMpService.getQrcodeService().qrCodeCreateLastTicket(1);
+ String url = wxMpService.getQrcodeService().qrCodePictureUrl(ticket.getTicket());
+
+ WxAccount wxAccount = baseMapper
+ .selectOne(Wrappers.query().lambda()
+ .eq(WxAccount::getAppid, appId));
+ wxAccount.setQrUrl(url);
+ baseMapper.updateById(wxAccount);
+ } catch (WxErrorException e) {
+ log.error(" 获取公众号二维码失败", e);
+ return R.builder().code(CommonConstants.FAIL).msg("更新公众号二维码失败").build();
+ }
+
+ return R.builder().build();
+ }
+}
diff --git a/pigx-visual/pigx-mp-manager/src/main/resources/bootstrap.yml b/pigx-visual/pigx-mp-manager/src/main/resources/bootstrap.yml
new file mode 100644
index 000000000..672fc6f1f
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/resources/bootstrap.yml
@@ -0,0 +1,25 @@
+server:
+ port: 6000
+
+spring:
+ application:
+ name: @artifactId@
+ #配置中心
+ cloud:
+ config:
+ fail-fast: true
+ name: ${spring.application.name}
+ profile: ${spring.profiles.active}
+ discovery:
+ enabled: true
+ service-id: pigx-config
+ profiles:
+ active: dev
+
+# 注册中心配置
+eureka:
+ instance:
+ prefer-ip-address: true
+ client:
+ service-url:
+ defaultZone: http://pig:pig@pigx-eureka:8761/eureka/
diff --git a/pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxAccountFansMapper.xml b/pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxAccountFansMapper.xml
new file mode 100755
index 000000000..347559fab
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxAccountFansMapper.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxAccountMapper.xml b/pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxAccountMapper.xml
new file mode 100755
index 000000000..a5aba8ec8
--- /dev/null
+++ b/pigx-visual/pigx-mp-manager/src/main/resources/mapper/WxAccountMapper.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pigx-visual/pom.xml b/pigx-visual/pom.xml
index 9661d6c4d..d397cab3a 100644
--- a/pigx-visual/pom.xml
+++ b/pigx-visual/pom.xml
@@ -37,6 +37,7 @@
pigx-daemon-elastic-job
pigx-daemon-quartz
pigx-monitor
+ pigx-mp-manager
pigx-sso-client-demo
pigx-tx-manager
pigx-zipkin