✨ 添加新特性。 公众号菜单、粉丝、消息 管理

This commit is contained in:
冷冷 committed 2019-03-27 22:06:20 +08:00
1 parent db78501eff
commit f4fa687c78
29 files changed
+1254 -5

No files matched your search

@@ -18,6 +18,8 @@ spring:
username: root
password: root
url: jdbc:mysql://pigx-mysql:3306/coffeewx?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8
hikari:
connection-init-sql: SET NAMES utf8mb4
resources:
static-locations: classpath:/static/,classpath:/views/
@@ -0,0 +1,55 @@
/*
* 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.config;
import com.alibaba.ttl.TransmittableThreadLocal;
import lombok.experimental.UtilityClass;
/**
* @author lengleng
* @date 2019/03/27
* 微信上下文工具类
*/
@UtilityClass
public class WxMpContextHolder {
private final ThreadLocal<String> THREAD_LOCAL_APPID = new TransmittableThreadLocal<>();
/**
* TTL 设置appId
*
* @param appId
*/
public void setAppId(String appId) {
THREAD_LOCAL_APPID.set(appId);
}
/**
* 获取TTL中的appId
*
* @return
*/
public String getAppId() {
return THREAD_LOCAL_APPID.get();
}
public void clear() {
THREAD_LOCAL_APPID.remove();
}
}
@@ -123,4 +123,14 @@ public class WxAccountController {
return wxAccountService.generateQr(appId);
}
/**
* 获取公众号列表
*
* @return
*/
@GetMapping("/list")
public R list() {
return new R<>(wxAccountService.list());
}
}
@@ -103,4 +103,15 @@ public class WxAccountFansController {
return new R<>(wxAccountFansService.removeById(id));
}
/**
* 同步粉丝
*
* @param appId
* @return
*/
@PostMapping("/sync/{appId}")
public R sync(@PathVariable String appId) {
return new R(wxAccountFansService.syncAccountFans(appId));
}
}
@@ -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.WxFansMsg;
import com.pig4cloud.pigx.mp.service.WxFansMsgService;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
* 微信粉丝消息管理
*
* @author lengleng
* @date 2019-03-27 20:45:27
*/
@RestController
@AllArgsConstructor
@RequestMapping("/wxfansmsg")
public class WxFansMsgController {
private final WxFansMsgService wxFansMsgService;
/**
* 分页查询
*
* @param page 分页对象
* @param wxFansMsg lengleng
* @return
*/
@GetMapping("/page")
public R getWxFansMsgPage(Page page, WxFansMsg wxFansMsg) {
return new R<>(wxFansMsgService.page(page, Wrappers.query(wxFansMsg)));
}
/**
* 通过id查询lengleng
*
* @param id id
* @return R
*/
@GetMapping("/{id}")
public R getById(@PathVariable("id") Integer id) {
return new R<>(wxFansMsgService.getById(id));
}
/**
* 新增lengleng
*
* @param wxFansMsg lengleng
* @return R
*/
@SysLog("新增lengleng")
@PostMapping
@PreAuthorize("@pms.hasPermission('mp_wxfansmsg_add')")
public R save(@RequestBody WxFansMsg wxFansMsg) {
return new R<>(wxFansMsgService.save(wxFansMsg));
}
/**
* 修改lengleng
*
* @param wxFansMsg lengleng
* @return R
*/
@SysLog("修改lengleng")
@PutMapping
@PreAuthorize("@pms.hasPermission('mp_wxfansmsg_edit')")
public R updateById(@RequestBody WxFansMsg wxFansMsg) {
return new R<>(wxFansMsgService.updateById(wxFansMsg));
}
/**
* 通过id删除lengleng
*
* @param id id
* @return R
*/
@SysLog("删除lengleng")
@DeleteMapping("/{id}")
@PreAuthorize("@pms.hasPermission('mp_wxfansmsg_del')")
public R removeById(@PathVariable Integer id) {
return new R<>(wxFansMsgService.removeById(id));
}
}
@@ -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.WxFansMsgRes;
import com.pig4cloud.pigx.mp.service.WxFansMsgResService;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
* 微信粉丝消息回复管理
*
* @author lengleng
* @date 2019-03-27 20:45:48
*/
@RestController
@AllArgsConstructor
@RequestMapping("/wxfansmsgres")
public class WxFansMsgResController {
private final WxFansMsgResService wxFansMsgResService;
/**
* 分页查询
*
* @param page 分页对象
* @param wxFansMsgRes lengleng
* @return
*/
@GetMapping("/page")
public R getWxFansMsgResPage(Page page, WxFansMsgRes wxFansMsgRes) {
return new R<>(wxFansMsgResService.page(page, Wrappers.query(wxFansMsgRes)));
}
/**
* 通过id查询lengleng
*
* @param id id
* @return R
*/
@GetMapping("/{id}")
public R getById(@PathVariable("id") Integer id) {
return new R<>(wxFansMsgResService.getById(id));
}
/**
* 新增lengleng
*
* @param wxFansMsgRes lengleng
* @return R
*/
@SysLog("新增lengleng")
@PostMapping
@PreAuthorize("@pms.hasPermission('mp_wxfansmsgres_add')")
public R save(@RequestBody WxFansMsgRes wxFansMsgRes) {
return new R<>(wxFansMsgResService.save(wxFansMsgRes));
}
/**
* 修改lengleng
*
* @param wxFansMsgRes lengleng
* @return R
*/
@SysLog("修改lengleng")
@PutMapping
@PreAuthorize("@pms.hasPermission('mp_wxfansmsgres_edit')")
public R updateById(@RequestBody WxFansMsgRes wxFansMsgRes) {
return new R<>(wxFansMsgResService.updateById(wxFansMsgRes));
}
/**
* 通过id删除lengleng
*
* @param id id
* @return R
*/
@SysLog("删除lengleng")
@DeleteMapping("/{id}")
@PreAuthorize("@pms.hasPermission('mp_wxfansmsgres_del')")
public R removeById(@PathVariable Integer id) {
return new R<>(wxFansMsgResService.removeById(id));
}
}
@@ -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.WxMenu;
import com.pig4cloud.pigx.mp.service.WxMenuService;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
* 微信菜单管理
*
* @author lengleng
* @date 2019-03-27 20:45:18
*/
@RestController
@AllArgsConstructor
@RequestMapping("/wxmenu")
public class WxMenuController {
private final WxMenuService wxMenuService;
/**
* 分页查询
*
* @param page 分页对象
* @param wxMenu lengleng
* @return
*/
@GetMapping("/page")
public R getWxMenuPage(Page page, WxMenu wxMenu) {
return new R<>(wxMenuService.page(page, Wrappers.query(wxMenu)));
}
/**
* 通过id查询lengleng
*
* @param id id
* @return R
*/
@GetMapping("/{id}")
public R getById(@PathVariable("id") Integer id) {
return new R<>(wxMenuService.getById(id));
}
/**
* 新增lengleng
*
* @param wxMenu lengleng
* @return R
*/
@SysLog("新增lengleng")
@PostMapping
@PreAuthorize("@pms.hasPermission('mp_wxmenu_add')")
public R save(@RequestBody WxMenu wxMenu) {
return new R<>(wxMenuService.save(wxMenu));
}
/**
* 修改lengleng
*
* @param wxMenu lengleng
* @return R
*/
@SysLog("修改lengleng")
@PutMapping
@PreAuthorize("@pms.hasPermission('mp_wxmenu_edit')")
public R updateById(@RequestBody WxMenu wxMenu) {
return new R<>(wxMenuService.updateById(wxMenu));
}
/**
* 通过id删除lengleng
*
* @param id id
* @return R
*/
@SysLog("删除lengleng")
@DeleteMapping("/{id}")
@PreAuthorize("@pms.hasPermission('mp_wxmenu_del')")
public R removeById(@PathVariable Integer id) {
return new R<>(wxMenuService.removeById(id));
}
}
@@ -3,6 +3,7 @@ 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 com.pig4cloud.pigx.mp.config.WxMpContextHolder;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
@@ -78,6 +79,8 @@ public class WxPortalController {
@RequestParam("openid") String openid,
@RequestParam(name = "encrypt_type", required = false) String encType,
@RequestParam(name = "msg_signature", required = false) String msgSignature) {
WxMpContextHolder.setAppId(appId);
final WxMpService wxService = WxMpConfiguration.getMpServices().get(appId);
log.info("接收微信请求:[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}],"
@@ -113,6 +116,7 @@ public class WxPortalController {
}
log.debug("组装回复信息:{}", out);
WxMpContextHolder.clear();
return out;
}
@@ -89,4 +89,8 @@ public class WxAccount extends Model<WxAccount> {
@TableLogic
private String delFlag;
/**
* 租户
*/
private Integer tenantId;
}
@@ -94,6 +94,11 @@ public class WxAccountFans extends Model<WxAccountFans> {
* 微信公众号appid
*/
private String wxAccountAppid;
/**
* 微信公众号名
*/
private String wxAccountName;
/**
* 创建时间
*/
@@ -0,0 +1,125 @@
/*
* 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-27 20:45:27
*/
@Data
@TableName("t_wx_fans_msg")
@EqualsAndHashCode(callSuper = true)
public class WxFansMsg extends Model<WxFansMsg> {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId
private Integer id;
/**
* 用户标识
*/
private String openid;
/**
* 昵称
*/
private String nickname;
/**
* 头像地址
*/
private String headimgUrl;
/**
* 微信账号ID
*/
private Integer wxAccountId;
/**
* 微信公众号appid
*/
private String wxAccountAppid;
/**
* 微信公众号名
*/
private String wxAccountName;
/**
* 消息ID
*/
private Long msgId;
/**
* 消息类型
*/
private String msgType;
/**
* 内容
*/
private String content;
/**
* 最近一条回复内容
*/
private String resContent;
/**
* 是否已回复
*/
private String isRes;
/**
* 微信素材ID
*/
private String mediaId;
/**
* 微信图片URL
*/
private String picUrl;
/**
* 本地图片路径
*/
private String picPath;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 是否删除 -1:已删除 0:正常
*/
@TableLogic
private String delFlag;
/**
* 租户
*/
private Integer tenantId;
}
@@ -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.entity;
import com.baomidou.mybatisplus.annotation.TableId;
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-27 20:45:48
*/
@Data
@TableName("t_wx_fans_msg_res")
@EqualsAndHashCode(callSuper = true)
public class WxFansMsgRes extends Model<WxFansMsgRes> {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId
private Integer id;
/**
* 粉丝消息ID
*/
private String fansMsgId;
/**
* 回复内容
*/
private String resContent;
/**
* 用户ID
*/
private String userId;
/**
* 用户名
*/
private String userName;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}
@@ -0,0 +1,93 @@
/*
* 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.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* 微信菜单表
*
* @author lengleng
* @date 2019-03-27 20:45:18
*/
@Data
@TableName("t_wx_menu")
@EqualsAndHashCode(callSuper = true)
public class WxMenu extends Model<WxMenu> {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId
private Integer id;
/**
* 父ID
*/
private String parentId;
/**
* 菜单名称
*/
private String menuName;
/**
* 菜单类型 1文本消息;2图文消息;3网址链接;4小程序
*/
private String menuType;
/**
* 菜单等级
*/
private String menuLevel;
/**
* 模板ID
*/
private String tplId;
/**
* 菜单URL
*/
private String menuUrl;
/**
* 排序
*/
private String menuSort;
/**
* 微信账号ID
*/
private String wxAccountId;
/**
* 小程序appid
*/
private String miniprogramAppid;
/**
* 小程序页面路径
*/
private String miniprogramPagepath;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}
@@ -1,26 +1,62 @@
package com.pig4cloud.pigx.mp.handler;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pig4cloud.pigx.mp.entity.WxAccount;
import com.pig4cloud.pigx.mp.entity.WxFansMsg;
import com.pig4cloud.pigx.mp.service.WxAccountService;
import com.pig4cloud.pigx.mp.service.WxFansMsgService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
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 me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author Binary Wang(https://github.com/binarywang)
* @author lengleng
* <p>
* 保存微信消息
*/
@Slf4j
@Component
@AllArgsConstructor
public class LogHandler extends AbstractHandler {
private final WxFansMsgService wxFansMsgService;
private final WxAccountService wxAccountService;
@Override
@SneakyThrows
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) {
log.info("接收到请求消息,内容:{}", wxMessage.getContent());
log.debug("接收到请求消息,内容:{}", wxMessage.getContent());
WxAccount wxAccount = wxAccountService.getOne(Wrappers.<WxAccount>lambdaQuery()
.eq(WxAccount::getAccount, wxMessage.getToUser()));
WxMpUser wxmpUser = wxMpService.getUserService()
.userInfo(wxMessage.getFromUser());
WxFansMsg wxFansMsg = new WxFansMsg();
wxFansMsg.setOpenid(wxmpUser.getOpenId());
wxFansMsg.setNickname(wxmpUser.getNickname());
wxFansMsg.setHeadimgUrl(wxmpUser.getHeadImgUrl());
wxFansMsg.setWxAccountId(wxAccount.getId());
wxFansMsg.setWxAccountName(wxAccount.getName());
wxFansMsg.setWxAccountAppid(wxAccount.getAppid());
wxFansMsg.setMsgType(wxMessage.getMsgType());
wxFansMsg.setMsgId(wxMessage.getMsgId());
wxFansMsg.setContent(wxMessage.getContent());
wxFansMsg.setTenantId(wxAccount.getTenantId());
wxFansMsgService.save(wxFansMsg);
log.debug("保存微信用户信息成功 {}", wxFansMsg);
return null;
}
}
@@ -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.WxFansMsg;
/**
* lengleng
*
* @author pigx code generator
* @date 2019-03-27 20:45:27
*/
public interface WxFansMsgMapper extends BaseMapper<WxFansMsg> {
}
@@ -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.WxFansMsgRes;
/**
* lengleng
*
* @author pigx code generator
* @date 2019-03-27 20:45:48
*/
public interface WxFansMsgResMapper extends BaseMapper<WxFansMsgRes> {
}
@@ -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.WxMenu;
/**
* lengleng
*
* @author pigx code generator
* @date 2019-03-27 20:45:18
*/
public interface WxMenuMapper extends BaseMapper<WxMenu> {
}
@@ -27,4 +27,11 @@ import com.pig4cloud.pigx.mp.entity.WxAccountFans;
*/
public interface WxAccountFansService extends IService<WxAccountFans> {
/**
* 同步指定公众号粉丝
*
* @param appId
* @return
*/
Boolean syncAccountFans(String appId);
}
@@ -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.WxFansMsgRes;
/**
* 微信消息回复业务
*
* @author lengleng
* @date 2019-03-27 20:45:48
*/
public interface WxFansMsgResService extends IService<WxFansMsgRes> {
}
@@ -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.WxFansMsg;
/**
* 微信消息业务
*
* @author lengleng
* @date 2019-03-27 20:45:27
*/
public interface WxFansMsgService extends IService<WxFansMsg> {
}
@@ -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.WxMenu;
/**
* 微信菜单业务
*
* @author lengleng
* @date 2019-03-27 20:45:18
*/
public interface WxMenuService extends IService<WxMenu> {
}
@@ -16,19 +16,124 @@
*/
package com.pig4cloud.pigx.mp.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.mp.config.WxMpConfiguration;
import com.pig4cloud.pigx.mp.entity.WxAccount;
import com.pig4cloud.pigx.mp.entity.WxAccountFans;
import com.pig4cloud.pigx.mp.mapper.WxAccountFansMapper;
import com.pig4cloud.pigx.mp.mapper.WxAccountMapper;
import com.pig4cloud.pigx.mp.service.WxAccountFansService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxMpUserService;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
/**
* 微信公众号粉丝
*
* @author lengleng
* @date 2019-03-26 22:08:08
* <p>
* 微信公众号粉丝
*/
@Slf4j
@Service
@AllArgsConstructor
public class WxAccountFansServiceImpl extends ServiceImpl<WxAccountFansMapper, WxAccountFans> implements WxAccountFansService {
private static final int SIZE = 100;
private final WxAccountMapper wxAccountMapper;
/**
* 获取公众号粉丝,生产建议异步
*
* @param appId
* @return
*/
@Async
@Override
@SneakyThrows
@Transactional(rollbackFor = Exception.class)
public Boolean syncAccountFans(String appId) {
WxAccount wxAccount = wxAccountMapper
.selectOne(Wrappers.<WxAccount>query().lambda()
.eq(WxAccount::getAppid, appId));
WxMpService wxMpService = WxMpConfiguration.getMpServices().get(appId);
WxMpUserService wxMpUserService = wxMpService.getUserService();
fetchUser(null, wxAccount, wxMpUserService);
return Boolean.TRUE;
}
/**
* 获取微信用户
*
* @param nextOpenid
* @param wxAccount
* @param wxMpUserService
* @throws WxErrorException
*/
private void fetchUser(String nextOpenid, WxAccount wxAccount, WxMpUserService wxMpUserService) throws WxErrorException {
WxMpUserList wxMpUserList = wxMpUserService.userList(nextOpenid);
// openId 分组 每组 100个 openid
CollUtil.split(wxMpUserList.getOpenids(), SIZE)
.stream().filter(CollUtil::isNotEmpty)
.forEach(openIdList -> {
log.info("开始批量获取用户信息 {}", openIdList);
List<WxAccountFans> wxAccountFansList = new ArrayList<>();
try {
wxMpUserService.userInfoList(openIdList).forEach(wxMpUser -> {
WxAccountFans wxAccountFans = baseMapper
.selectOne(Wrappers.<WxAccountFans>query().lambda()
.eq(WxAccountFans::getOpenid, wxMpUser.getOpenId()));
// 为空初始化一个新的对象
if (wxAccountFans == null) {
wxAccountFans = new WxAccountFans();
}
wxAccountFans.setOpenid(wxMpUser.getOpenId());
wxAccountFans.setSubscribeStatus(wxMpUser.getSubscribe() ? "1" : "0");
wxAccountFans.setSubscribeTime(LocalDateTime
.ofInstant(Instant.ofEpochMilli(wxMpUser.getSubscribeTime() * 1000L)
, ZoneId.systemDefault()));
wxAccountFans.setNickname(wxMpUser.getNickname());
wxAccountFans.setGender(String.valueOf(wxMpUser.getSex()));
wxAccountFans.setLanguage(wxMpUser.getLanguage());
wxAccountFans.setCountry(wxMpUser.getCountry());
wxAccountFans.setProvince(wxMpUser.getProvince());
wxAccountFans.setCity(wxMpUser.getCity());
wxAccountFans.setHeadimgUrl(wxMpUser.getHeadImgUrl());
wxAccountFans.setRemark(wxMpUser.getRemark());
wxAccountFans.setWxAccountId(String.valueOf(wxAccount.getId()));
wxAccountFans.setWxAccountAppid(wxAccount.getAppid());
wxAccountFans.setWxAccountName(wxAccount.getName());
wxAccountFansList.add(wxAccountFans);
});
this.saveOrUpdateBatch(wxAccountFansList);
log.info("批量插入用户信息完成 {}", openIdList);
} catch (WxErrorException e) {
log.error("批量同步粉丝失败", e);
}
});
// 如果nextOpenId 不为空,则继续获取
if (StrUtil.isNotBlank(wxMpUserList.getNextOpenid())) {
fetchUser(wxMpUserList.getNextOpenid(), wxAccount, wxMpUserService);
}
log.info("批量同步微信用户信息完成");
}
}
@@ -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.WxFansMsgRes;
import com.pig4cloud.pigx.mp.mapper.WxFansMsgResMapper;
import com.pig4cloud.pigx.mp.service.WxFansMsgResService;
import org.springframework.stereotype.Service;
/**
* 微信消息回复业务
*
* @author lengleng
* @date 2019-03-27 20:45:48
*/
@Service
public class WxFansMsgResServiceImpl extends ServiceImpl<WxFansMsgResMapper, WxFansMsgRes> implements WxFansMsgResService {
}
@@ -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.WxFansMsg;
import com.pig4cloud.pigx.mp.mapper.WxFansMsgMapper;
import com.pig4cloud.pigx.mp.service.WxFansMsgService;
import org.springframework.stereotype.Service;
/**
* 微信消息业务
*
* @author lengleng
* @date 2019-03-27 20:45:27
*/
@Service
public class WxFansMsgServiceImpl extends ServiceImpl<WxFansMsgMapper, WxFansMsg> implements WxFansMsgService {
}
@@ -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.WxMenu;
import com.pig4cloud.pigx.mp.mapper.WxMenuMapper;
import com.pig4cloud.pigx.mp.service.WxMenuService;
import org.springframework.stereotype.Service;
/**
* 微信菜单业务
*
* @author lengleng
* @date 2019-03-27 20:45:18
*/
@Service
public class WxMenuServiceImpl extends ServiceImpl<WxMenuMapper, WxMenu> implements WxMenuService {
}
@@ -38,6 +38,7 @@
<result property="remark" column="remark"/>
<result property="wxAccountId" column="wx_account_id"/>
<result property="wxAccountAppid" column="wx_account_appid"/>
<result property="wxAccountName" column="wx_account_name"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ 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)
~
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pig4cloud.pigx.mp.mapper.WxFansMsgMapper">
<resultMap id="wxFansMsgMap" type="com.pig4cloud.pigx.mp.entity.WxFansMsg">
<id property="id" column="id"/>
<result property="openid" column="openid"/>
<result property="nickname" column="nickname"/>
<result property="headimgUrl" column="headimg_url"/>
<result property="wxAccountId" column="wx_account_id"/>
<result property="wxAccountName" column="wx_account_name"/>
<result property="wxAccountAppid" column="wx_account_appid"/>
<result property="msgType" column="msg_type"/>
<result property="content" column="content"/>
<result property="resContent" column="res_content"/>
<result property="isRes" column="is_res"/>
<result property="mediaId" column="media_id"/>
<result property="picUrl" column="pic_url"/>
<result property="picPath" column="pic_path"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
<result property="tenantId" column="tenant_id"/>
</resultMap>
</mapper>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ 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)
~
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pig4cloud.pigx.mp.mapper.WxFansMsgResMapper">
<resultMap id="wxFansMsgResMap" type="com.pig4cloud.pigx.mp.entity.WxFansMsgRes">
<id property="id" column="id"/>
<result property="fansMsgId" column="fans_msg_id"/>
<result property="resContent" column="res_content"/>
<result property="userId" column="user_id"/>
<result property="userName" column="user_name"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
</mapper>
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ 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)
~
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pig4cloud.pigx.mp.mapper.WxMenuMapper">
<resultMap id="wxMenuMap" type="com.pig4cloud.pigx.mp.entity.WxMenu">
<id property="id" column="id"/>
<result property="parentId" column="parent_id"/>
<result property="menuName" column="menu_name"/>
<result property="menuType" column="menu_type"/>
<result property="menuLevel" column="menu_level"/>
<result property="tplId" column="tpl_id"/>
<result property="menuUrl" column="menu_url"/>
<result property="menuSort" column="menu_sort"/>
<result property="wxAccountId" column="wx_account_id"/>
<result property="miniprogramAppid" column="miniprogram_appid"/>
<result property="miniprogramPagepath" column="miniprogram_pagepath"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
</mapper>