提交 acb1580e authored 作者: 吕本才's avatar 吕本才

feat(wechat): 实现微信公众号用户管理功能

上级 bd3ae3a9
package com.link.hub.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author : liqiulin
* @date : 2024-04-25 13
* @describe :
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
...@@ -26,8 +26,6 @@ public class LotteryQueryController { ...@@ -26,8 +26,6 @@ public class LotteryQueryController {
public List<LotteryVo> list() { public List<LotteryVo> list() {
// 查询活动列表 // 查询活动列表
List<LotteryVo> lotteryVos = lotteryActivityService.queryList(); List<LotteryVo> lotteryVos = lotteryActivityService.queryList();
return lotteryVos; return lotteryVos;
} }
......
package com.link.hub.controller.oa.query;
import com.link.hub.service.officeAccount.WechatOfficeAccountService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* 微信公众号
*/
@RestController
@RequestMapping("/oa")
public class WeChatOaController {
@Resource
private WechatOfficeAccountService weChatOaService;
@RequestMapping("/query/list")
public List<String> list(String nextOpenId) {
List<String> userList = weChatOaService.getUserList(nextOpenId);
return userList;
}
/**
* 保存用户列表
*/
@PostMapping("/saveBatch/UserList")
public String saveUserList() {
Integer count = weChatOaService.saveUserList();
return "保存用户列表成功:" + count;
}
@PostMapping("/saveBatch/detail")
public String saveUserDetail(Integer pageNum, Integer pageSize) {
weChatOaService.saveUserDetail(pageNum, pageSize);
return "查询并保存用户详情成功";
}
@PostMapping("/saveAllBatch/detail")
public String saveAllUserDetail() {
weChatOaService.saveAllUserDetail();
return "查询并保存用户详情成功";
}
}
...@@ -6,4 +6,6 @@ import com.link.hub.domain.weChatMiniProgram.wq.WechatMiniProgramUserWq; ...@@ -6,4 +6,6 @@ import com.link.hub.domain.weChatMiniProgram.wq.WechatMiniProgramUserWq;
public interface WechatMiniProgramUserDao { public interface WechatMiniProgramUserDao {
WechatMiniProgramUser queryMiniProgramUserOne(WechatMiniProgramUserWq wechatMiniProgramUserWq); WechatMiniProgramUser queryMiniProgramUserOne(WechatMiniProgramUserWq wechatMiniProgramUserWq);
void insert(WechatMiniProgramUser wechatMiniProgramUser); void insert(WechatMiniProgramUser wechatMiniProgramUser);
void updateById(WechatMiniProgramUser wechatMiniProgramUser);
} }
...@@ -34,4 +34,9 @@ public class WechatMiniProgramUserDaoImpl implements WechatMiniProgramUserDao { ...@@ -34,4 +34,9 @@ public class WechatMiniProgramUserDaoImpl implements WechatMiniProgramUserDao {
public void insert(WechatMiniProgramUser wechatMiniProgramUser) { public void insert(WechatMiniProgramUser wechatMiniProgramUser) {
wechatMiniProgramUserMapper.insert(wechatMiniProgramUser); wechatMiniProgramUserMapper.insert(wechatMiniProgramUser);
} }
@Override
public void updateById(WechatMiniProgramUser wechatMiniProgramUser) {
wechatMiniProgramUserMapper.updateById(wechatMiniProgramUser);
}
} }
package com.link.hub.domain.weChatMiniProgram.entity; package com.link.hub.domain.weChatMiniProgram.entity;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.annotation.*;
import com.link.hub.pojo.mp.dto.MpOpenIdDTO;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
...@@ -103,4 +106,17 @@ public class WechatMiniProgramUser implements Serializable { ...@@ -103,4 +106,17 @@ public class WechatMiniProgramUser implements Serializable {
*/ */
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Date updateTime; private Date updateTime;
public static WechatMiniProgramUser create(MpOpenIdDTO mpOpenIdDTO) {
WechatMiniProgramUser wechatMiniProgramUser = new WechatMiniProgramUser();
wechatMiniProgramUser.setOpenid(mpOpenIdDTO.getOpenid());
wechatMiniProgramUser.setUnionid(mpOpenIdDTO.getUnionid());
wechatMiniProgramUser.setNickname(mpOpenIdDTO.getNickname());
wechatMiniProgramUser.setAvatarUrl(mpOpenIdDTO.getAvatarUrl());
wechatMiniProgramUser.setLastLoginTime(DateUtil.date());
wechatMiniProgramUser.setCreateTime(DateUtil.date());
wechatMiniProgramUser.setUpdateTime(DateUtil.date());
return wechatMiniProgramUser;
}
} }
package com.link.hub.domain.weChatOfficialAccount.dao;
import com.link.hub.domain.weChatOfficialAccount.entity.WechatOfficialAccountUser;
import com.link.hub.domain.weChatOfficialAccount.mq.WeChatOaUserQueryWq;
import com.link.hub.pojo.oa.dto.WechatOaUserDto;
import com.link.hub.pojo.oa.dto.WechatOaUserResDto;
import com.sfa.common.core.web.domain.PageInfo;
import java.util.List;
import java.util.Set;
/**
* 微信公众号用户 DAO 接口
*/
public interface WechatOfficialAccountUserDao {
/**
* 根据openid查询用户
*/
WechatOfficialAccountUser getUserByOpenId(String openId);
/**
* 保存或更新用户
*/
boolean saveOrUpdateUser(WechatOfficialAccountUser user);
void updateBatch(List<WechatOaUserDto> officialAccountUsers);
void saveBatch(List<WechatOaUserDto> officialAccountUsers);
List<WechatOfficialAccountUser> selectByOpenIds(Set<String> allOpenIds);
List<WechatOfficialAccountUser> selectList();
PageInfo selectPageList(Integer pageNum, Integer pageSize);
void updateUserInfoBatch(List<WechatOaUserResDto> userInfoBatch);
WechatOfficialAccountUser selectOne(WeChatOaUserQueryWq wq);
}
package com.link.hub.domain.weChatOfficialAccount.dao.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.link.hub.domain.weChatOfficialAccount.dao.WechatOfficialAccountUserDao;
import com.link.hub.domain.weChatOfficialAccount.entity.WechatOfficialAccountUser;
import com.link.hub.domain.weChatOfficialAccount.mapper.WechatOfficialAccountUserMapper;
import com.link.hub.domain.weChatOfficialAccount.mq.WeChatOaUserQueryWq;
import com.link.hub.pojo.oa.dto.WechatOaUserDto;
import com.link.hub.pojo.oa.dto.WechatOaUserResDto;
import com.sfa.common.core.web.domain.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Set;
/**
* 微信公众号用户 DAO 实现类
*/
@Repository
public class WechatOfficialAccountUserDaoImpl implements WechatOfficialAccountUserDao {
private final WechatOfficialAccountUserMapper userMapper;
@Autowired
public WechatOfficialAccountUserDaoImpl(WechatOfficialAccountUserMapper userMapper) {
this.userMapper = userMapper;
}
@Override
public WechatOfficialAccountUser getUserByOpenId(String openId) {
return userMapper.selectByOpenId(openId);
}
@Override
public boolean saveOrUpdateUser(WechatOfficialAccountUser user) {
if (user.getId() == null) {
// 新增用户
return userMapper.insert(user) > 0;
} else {
// 更新用户
return userMapper.updateById(user) > 0;
}
}
@Override
public void saveBatch(List<WechatOaUserDto> officialAccountUsers) {
// 批量保存 1000条保存一次
int batchSize = 1000;
for (int i = 0; i < officialAccountUsers.size(); i += batchSize) {
List<WechatOaUserDto> batch = officialAccountUsers.subList(i, Math.min(i + batchSize, officialAccountUsers.size()));
for (WechatOaUserDto userDto : batch) {
WechatOfficialAccountUser user = WechatOfficialAccountUser.convert(userDto);
userMapper.insert(user);
}
}
}
/**
* 批量更新
* 通过openid更新
*
* @param officialAccountUsers
*/
@Override
public void updateBatch(List<WechatOaUserDto> officialAccountUsers) {
// 批量保存 1000条保存一次
int batchSize = 1000;
for (int i = 0; i < officialAccountUsers.size(); i += batchSize) {
List<WechatOaUserDto> batch = officialAccountUsers.subList(i, Math.min(i + batchSize, officialAccountUsers.size()));
for (WechatOaUserDto userDto : batch) {
WechatOfficialAccountUser user = WechatOfficialAccountUser.convert(userDto);
userMapper.update(user, new LambdaQueryWrapper<WechatOfficialAccountUser>()
.eq(WechatOfficialAccountUser::getOpenid, user.getOpenid()));
}
}
}
@Override
public List<WechatOfficialAccountUser> selectByOpenIds(Set<String> allOpenIds) {
return userMapper.selectList(new LambdaQueryWrapper<WechatOfficialAccountUser>()
.in(WechatOfficialAccountUser::getOpenid, allOpenIds));
}
@Override
public List<WechatOfficialAccountUser> selectList() {
// 分页查询
LambdaQueryWrapper<WechatOfficialAccountUser> wrapper = new LambdaQueryWrapper<WechatOfficialAccountUser>()
.last("limit 10")
.orderByDesc(WechatOfficialAccountUser::getId);
List<WechatOfficialAccountUser> officialAccountUsers = userMapper.selectList(wrapper);
return officialAccountUsers;
}
@Override
public PageInfo selectPageList(Integer pageNum, Integer pageSize) {
// 分页查询
LambdaQueryWrapper<WechatOfficialAccountUser> wrapper = new LambdaQueryWrapper<WechatOfficialAccountUser>();
wrapper.isNotNull(WechatOfficialAccountUser::getUnionid);
wrapper.orderByDesc(WechatOfficialAccountUser::getId);
Page<WechatOfficialAccountUser> pageRes = new Page<>(pageNum, pageSize);
IPage<WechatOfficialAccountUser> page = userMapper.selectPage(pageRes, wrapper);
PageInfo pageInfo = new PageInfo<>(page);
return pageInfo;
}
@Override
public void updateUserInfoBatch(List<WechatOaUserResDto> userInfoBatchs) {
for (int i = 0; i < userInfoBatchs.size(); i++) {
WechatOaUserResDto userInfo = userInfoBatchs.get(i);
WechatOfficialAccountUser user = WechatOfficialAccountUser.convertByUserInfo(userInfo);
userMapper.update(user, new LambdaQueryWrapper<WechatOfficialAccountUser>()
.eq(WechatOfficialAccountUser::getOpenid, user.getOpenid()));
}
}
@Override
public WechatOfficialAccountUser selectOne(WeChatOaUserQueryWq wq) {
LambdaQueryWrapper<WechatOfficialAccountUser> wrapper = buildWrapper(wq);
WechatOfficialAccountUser wechatOfficialAccountUser = userMapper.selectOne(wrapper);
return wechatOfficialAccountUser;
}
private LambdaQueryWrapper<WechatOfficialAccountUser> buildWrapper(WeChatOaUserQueryWq wq) {
LambdaQueryWrapper<WechatOfficialAccountUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ObjectUtil.isNotEmpty(wq.getUnionid()),WechatOfficialAccountUser::getUnionid, wq.getUnionid());
queryWrapper.eq(ObjectUtil.isNotEmpty(wq.getOpenid()),WechatOfficialAccountUser::getOpenid, wq.getOpenid());
return queryWrapper;
}
}
package com.link.hub.domain.weChatOfficialAccount.entity; package com.link.hub.domain.weChatOfficialAccount.entity;
import com.baomidou.mybatisplus.annotation.*; import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.link.hub.pojo.oa.dto.WechatOaUserDto;
import com.link.hub.pojo.oa.dto.WechatOaUserResDto;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
...@@ -10,15 +16,17 @@ import java.util.Date; ...@@ -10,15 +16,17 @@ import java.util.Date;
* 微信公众号用户表 POJO/PO * 微信公众号用户表 POJO/PO
* 对应表:wechat_official_account_user * 对应表:wechat_official_account_user
*/ */
@Data // Lombok注解:自动生成get/set/toString/equals/hashCode @Data
@TableName("wechat_official_account_user") // MyBatis-Plus绑定数据库表名 @TableName("wechat_official_account_user")
public class WechatOfficialAccountUser implements Serializable { public class WechatOfficialAccountUser implements Serializable {
private static final long serialVersionUID = 1L; // 序列化版本号 // 序列化版本号
private static final long serialVersionUID = 1L;
/** /**
* 主键ID * 主键ID
* 主键自增,匹配MySQL的AUTO_INCREMENT
*/ */
@TableId(type = IdType.AUTO) // 主键自增,匹配MySQL的AUTO_INCREMENT @TableId(type = IdType.AUTO)
private Long id; private Long id;
/** /**
...@@ -102,12 +110,46 @@ public class WechatOfficialAccountUser implements Serializable { ...@@ -102,12 +110,46 @@ public class WechatOfficialAccountUser implements Serializable {
/** /**
* 记录创建时间(MySQL默认CURRENT_TIMESTAMP) * 记录创建时间(MySQL默认CURRENT_TIMESTAMP)
*/ */
@TableField(value = "create_time", fill = FieldFill.INSERT) // 插入时自动填充
private Date createTime; private Date createTime;
/** /**
* 记录更新时间(MySQL默认ON UPDATE CURRENT_TIMESTAMP) * 记录更新时间(MySQL默认ON UPDATE CURRENT_TIMESTAMP)
*/ */
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) // 插入/更新时自动填充
private Date updateTime; private Date updateTime;
public static WechatOfficialAccountUser create(String openId) {
WechatOfficialAccountUser wechatOfficialAccountUser = new WechatOfficialAccountUser();
wechatOfficialAccountUser.setOpenid(openId);
wechatOfficialAccountUser.setLanguage("zh_CN");
return wechatOfficialAccountUser;
}
public static WechatOfficialAccountUser convert(WechatOaUserDto userDto) {
WechatOfficialAccountUser user = new WechatOfficialAccountUser();
user.setOpenid(userDto.getOpenid());
user.setLanguage(userDto.getLanguage());
return user;
}
public static WechatOfficialAccountUser convertByUserInfo(WechatOaUserResDto userInfo) {
WechatOfficialAccountUser user = new WechatOfficialAccountUser();
user.setOpenid(userInfo.getOpenid());
user.setNickname(userInfo.getNickname());
user.setAvatarUrl(userInfo.getHeadimgurl());
user.setSex(userInfo.getSex());
user.setCountry(userInfo.getCountry());
user.setProvince(userInfo.getProvince());
user.setCity(userInfo.getCity());
user.setLanguage(userInfo.getLanguage());
user.setSubscribeStatus(userInfo.getSubscribe());
user.setSubscribeTime(ObjectUtil.isNotNull(userInfo.getSubscribeTime())?new Date(userInfo.getSubscribeTime() * 1000):null);
user.setUnionid(userInfo.getUnionid());
user.setRemark(userInfo.getRemark());
// user.setGroupid(userInfo.getGroupid());
// user.setTagidList(userInfo.getTagidList());
return user;
}
} }
package com.link.hub.domain.weChatOfficialAccount.mapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.link.hub.domain.weChatOfficialAccount.entity.WechatOfficialAccountUser;
import org.apache.ibatis.annotations.Mapper;
/**
* 微信公众号用户 Mapper 接口
*/
@Mapper
public interface WechatOfficialAccountUserMapper extends BaseMapper<WechatOfficialAccountUser> {
/**
* 根据 openId 查询用户
* @param openId 公众号用户唯一标识
* @return 用户实体
*/
default WechatOfficialAccountUser selectByOpenId(String openId) {
return selectOne(new LambdaQueryWrapper<WechatOfficialAccountUser>()
.eq(WechatOfficialAccountUser::getOpenid, openId));
}
}
package com.link.hub.domain.weChatOfficialAccount.mq;
import lombok.Data;
@Data
public class WeChatOaUserQueryWq {
/**
* 微信开放平台统一标识
*/
private String unionid;
/**
* 用户唯一标识
*/
private String openid;
}
...@@ -4,6 +4,12 @@ import lombok.Data; ...@@ -4,6 +4,12 @@ import lombok.Data;
@Data @Data
public class MpOpenIdDTO { public class MpOpenIdDTO {
private String openid; private Long id;
private String unionid; // 头像
private String avatarUrl;
// 昵称
private String nickname;
private String openid;
private String unionid;
} }
...@@ -3,7 +3,7 @@ package com.link.hub.pojo.mp.dto; ...@@ -3,7 +3,7 @@ package com.link.hub.pojo.mp.dto;
import lombok.Data; import lombok.Data;
@Data @Data
public class MpUserDto { public class WeChatMpUserDto {
/** /**
* 主键ID * 主键ID
......
package com.link.hub.pojo.oa.dto;
import lombok.Data;
@Data
public class WeChatOaUserQueryDto {
/**
* 主键ID
*/
private Long id;
/**
* 小程序用户唯一标识
*/
private String openid;
/**
* 微信开放平台统一标识
*/
private String unionid;
/**
* 用户昵称
*/
private String nickname;
}
package com.link.hub.pojo.oa.dto;
import lombok.Data;
/**
* 微信公众号用户DTO类
*/
@Data
public class WechatOaUserDto {
private String openid;
private String language;
public static WechatOaUserDto create(String userOpenid) {
WechatOaUserDto user = new WechatOaUserDto();
user.setOpenid(userOpenid);
user.setLanguage("zh_CN");
return user;
}
}
package com.link.hub.pojo.oa.dto;
import lombok.Data;
/**
* 微信公众号用户基本信息
*/
@Data
public class WechatOaUserResDto {
private Integer subscribe;
private String nickname;
private Integer sex;
private String city;
private String province;
private String country;
private String headimgurl;
private Long subscribeTime;
private String unionid;
private String remark;
private Integer groupid;
private String[] tagidList;
private String subscribeScene;
private Integer qrScene;
private String qrSceneStr;
private String language;
private String openid;
}
package com.link.hub.service.officeAccount; package com.link.hub.service.officeAccount;
import com.link.hub.pojo.oa.dto.WechatOaUserDto;
import java.util.List;
public interface WechatOfficeAccountService { public interface WechatOfficeAccountService {
Boolean isSubscribe(String openid); Boolean isSubscribe(String openid);
List<String> getUserList(String nextOpenId);
Integer saveUserList();
List<WechatOaUserDto> saveUserDetail(Integer pageNum, Integer pageSize);
void saveAllUserDetail();
} }
// 包路径:com.link.hub.application.service
package com.link.hub.service.officeAccount;
import com.link.hub.domain.weChatOfficialAccount.entity.WechatOfficialAccountUser;
import com.link.hub.pojo.oa.dto.WeChatOaUserQueryDto;
import com.link.hub.pojo.oa.dto.WechatOaUserDto;
import com.link.hub.pojo.oa.dto.WechatOaUserResDto;
import java.util.List;
/**
* 微信公众号用户 服务接口
*/
public interface WechatOfficialAccountUserService {
/**
* 根据 openId 获取用户信息
* @param openId 公众号用户唯一标识
* @return 用户实体
*/
WechatOfficialAccountUser getUserByOpenId(String openId);
/**
* 保存或更新用户信息
* @param user 用户实体
* @return 操作结果
*/
boolean saveOrUpdateUser(WechatOfficialAccountUser user);
void saveOrUpdateBatch(List<WechatOaUserDto> officialAccountUsers);
WechatOfficialAccountUser selectMaxIdUser();
List<WechatOaUserDto> selectPageList(Integer pageNum, Integer pageSize);
void updateUserInfoBatch(List<WechatOaUserResDto> userInfoBatch);
WechatOfficialAccountUser selectOne(WeChatOaUserQueryDto oaUserDto);
}
package com.link.hub.service.officeAccount.impl; package com.link.hub.service.officeAccount.impl;
import com.link.hub.config.WeChatMiniProgramConfig; import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.link.hub.config.WeChatOfficeAccountConfig; import com.link.hub.config.WeChatOfficeAccountConfig;
import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser;
import com.link.hub.domain.weChatOfficialAccount.entity.WechatOfficialAccountUser;
import com.link.hub.pojo.mp.dto.WeChatMpUserDto;
import com.link.hub.pojo.oa.dto.WeChatOaUserQueryDto;
import com.link.hub.pojo.oa.dto.WechatOaUserDto;
import com.link.hub.pojo.oa.dto.WechatOaUserResDto;
import com.link.hub.service.officeAccount.WechatOfficeAccountService; import com.link.hub.service.officeAccount.WechatOfficeAccountService;
import com.link.hub.service.officeAccount.WechatOfficialAccountUserService;
import com.link.hub.service.weChatMiniProgram.WechatMiniProgramUserService;
import com.link.hub.util.WeChatPlatFormUtils;
import com.sfa.common.redis.service.RedisService; import com.sfa.common.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/** /**
...@@ -19,46 +33,155 @@ public class WechatOfficeAccountServiceServiceImpl implements WechatOfficeAccoun ...@@ -19,46 +33,155 @@ public class WechatOfficeAccountServiceServiceImpl implements WechatOfficeAccoun
@Resource @Resource
private WeChatOfficeAccountConfig officeAccountConfig; private WeChatOfficeAccountConfig officeAccountConfig;
@Resource @Resource
private WeChatMiniProgramConfig weChatMiniProgramConfig;
@Resource
private RedisService redisService; private RedisService redisService;
@Resource
private WechatOfficialAccountUserService oaUserService;
@Resource
private WechatMiniProgramUserService miniProgramUserService;
@Resource
private WeChatOfficeAccountConfig accountConfig;
@Override @Override
public Boolean isSubscribe(String openid) { public Boolean isSubscribe(String openid) {
// 使用 openid openid查询小程序用户 // 使用 openid openid查询小程序用户
// JSONObject user = redisService.getCacheObject(CacheConstants.HUB_USER_MINI_PROGRAM + openid); WeChatMpUserDto dto = new WeChatMpUserDto();
// if (user == null) { dto.setOpenid(openid);
// throw new ServiceException("用户未关联小程序"); WechatMiniProgramUser user = miniProgramUserService.queryMiniProgramUserOne(dto);
// }
// log.info("unionid: {}", user);
// log.info("unionid: {}", user);
// // 使用unionid查询微信公众号用户 // // 使用unionid查询微信公众号用户
//// JSONObject user = redisService.getCacheMap(CacheConstants.HUB_USER_OFFICE_ACCOUNT + openid); WeChatOaUserQueryDto oaUserDto = new WeChatOaUserQueryDto();
// oaUserDto.setUnionid(user.getUnionid());
// if (user == null) { WechatOfficialAccountUser wechatOfficialAccountUser = oaUserService.selectOne(oaUserDto);
if (wechatOfficialAccountUser == null) {
log.error("用户还未关注公众号,openid: {},unionid: {}", openid,user.getUnionid());
// throw new ServiceException("用户还未关注公众号");
return false;
}
if(wechatOfficialAccountUser.getSubscribeStatus() == 0){
log.error("用户未关注公众号,状态是未关注,openid: {},unionid: {}", openid,user.getUnionid());
// throw new ServiceException("用户未关联公众号"); // throw new ServiceException("用户未关联公众号");
// } return false;
return true; }
// 使用模板消息方案不可运行,暂时放弃 return wechatOfficialAccountUser.getSubscribeStatus() == 1;
// 用户的OpenID }
// String openId = "o94pT1395dZcu8Cjlwopkc2TijOA";
// // 一个不存在的模板ID
//
// String templateId = "一个不存在的模板ID"; @Override
// // 公众号的access_token public List<String> getUserList(String nextOpenId) {
// JSONObject bodyJson = WeChatPlatFormUtils.getMiniappAccessToken(officeAccountConfig.getAppId(), officeAccountConfig.getAppSecret()); try {
//// JSONObject bodyJson = WeChatPlatFormUtils.getMiniappToken(weChatMiniProgramConfig.getAppId(), weChatMiniProgramConfig.getAppSecret()); String accessToken = WeChatPlatFormUtils.getStableAccessToken(accountConfig.getAppId(), accountConfig.getAppSecret());
// String url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=" + accessToken;
// String accessToken = bodyJson.getString("access_token"); if (nextOpenId != null && !nextOpenId.isEmpty()) {
// log.info("access_token: {}", accessToken); url += "&next_openid=" + nextOpenId;
// // 调用方法判断用户是否关注了模板消息 }
// log.info("用户{}是否关注了模板消息{}: {}", openId, templateId);
// log.info("openid: {}", openId); String result = HttpUtil.get(url);
// if (accessToken == null) {
// throw new ServiceException("access_token is null"); log.info("WeChat Official Account user list ");
// }
// return WeChatPlatFormUtils.isSubscribe(openId, templateId, accessToken); JSONObject jsonObject = JSON.parseObject(result);
String total = jsonObject.get("total").toString();
Integer count = jsonObject.getInteger("count");
String nextOpenIdNew = jsonObject.getString("next_openid");
if (count == 0) {
log.info("没有更多用户了,total: {},count: {}", total, count);
return new ArrayList<>();
}
JSONObject dataJson = jsonObject.getJSONObject("data");
List<String> openids = dataJson.getList("openid", String.class);
log.info("total: {},返回{}条", total, openids.size());
return openids;
} catch (Exception e) {
log.error("Failed to get official account user list", e);
throw new RuntimeException("获取公众号用户列表失败", e);
}
}
@Override
public Integer saveUserList() {
boolean flag = true;
String nextOpenId = null;
// 从数据库查询最大id的openid
WechatOfficialAccountUser maxIdUser = oaUserService.selectMaxIdUser();
// 从数据库查询最大id的openid
if (maxIdUser != null) {
nextOpenId = maxIdUser.getOpenid();
}
Integer count = 0;
while (flag) {
List<String> openIdList = getUserList(nextOpenId);
if (openIdList == null || openIdList.isEmpty()) {
flag = false;
break;
}
count += openIdList.size();
// 保存入库 分批次按照1000条处理一次
int batchSize = 1000;
int offset = 0;
for (int i = offset; i < openIdList.size(); i += batchSize) {
List<String> opeIds = openIdList.subList(offset, Math.min(offset + batchSize, openIdList.size()));
List<WechatOaUserDto> officialAccountUsers = new ArrayList<>();
for (int j = 0; j < opeIds.size(); j++) {
String userOpenid = opeIds.get(j);
WechatOaUserDto wechatOfficialAccountUser = WechatOaUserDto.create(userOpenid);
officialAccountUsers.add(wechatOfficialAccountUser);
}
oaUserService.saveOrUpdateBatch(officialAccountUsers);
offset += batchSize;
}
flag = true;
nextOpenId = openIdList.get(openIdList.size() - 1);
}
return count;
}
@Transactional(rollbackFor = Exception.class)
@Override
public List<WechatOaUserDto> saveUserDetail(Integer pageNum, Integer pageSize) {
// 分页批量获取用户基本信息
List<WechatOaUserDto> userDtos = oaUserService.selectPageList(pageNum, pageSize);
if (userDtos == null || userDtos.isEmpty()) {
return userDtos;
}
// 请求微信 批量返回用户基本信息
List<WechatOaUserResDto> userInfoBatch = WeChatPlatFormUtils.getUserInfoBatch(userDtos, officeAccountConfig.getAppId(), officeAccountConfig.getAppSecret());
oaUserService.updateUserInfoBatch(userInfoBatch);
return userDtos;
}
@Override
public void saveAllUserDetail() {
// 分页批量获取用户基本信息
Integer pageNum = 1;
Integer pageSize = 100;
while (true) {
List<WechatOaUserDto> userDtos = saveUserDetail(pageNum, pageSize);
if (userDtos == null || userDtos.isEmpty()) {
break;
}
pageNum++;
// 请求微信 批量返回用户基本信息
List<WechatOaUserResDto> userInfoBatch = WeChatPlatFormUtils.getUserInfoBatch(userDtos, officeAccountConfig.getAppId(), officeAccountConfig.getAppSecret());
oaUserService.updateUserInfoBatch(userInfoBatch);
}
} }
} }
// 包路径:com.link.hub.application.service.impl
package com.link.hub.service.officeAccount.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.link.hub.domain.weChatOfficialAccount.dao.WechatOfficialAccountUserDao;
import com.link.hub.domain.weChatOfficialAccount.entity.WechatOfficialAccountUser;
import com.link.hub.domain.weChatOfficialAccount.mapper.WechatOfficialAccountUserMapper;
import com.link.hub.domain.weChatOfficialAccount.mq.WeChatOaUserQueryWq;
import com.link.hub.pojo.oa.dto.WeChatOaUserQueryDto;
import com.link.hub.pojo.oa.dto.WechatOaUserDto;
import com.link.hub.pojo.oa.dto.WechatOaUserResDto;
import com.link.hub.service.officeAccount.WechatOfficialAccountUserService;
import com.sfa.common.core.web.domain.PageInfo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 微信公众号用户 服务实现类
*/
@Service
public class WechatOfficialAccountUserServiceImpl
extends ServiceImpl<WechatOfficialAccountUserMapper, WechatOfficialAccountUser>
implements WechatOfficialAccountUserService {
@Resource
private WechatOfficialAccountUserDao dao;
@Override
public WechatOfficialAccountUser getUserByOpenId(String openId) {
return getBaseMapper().selectByOpenId(openId);
}
@Override
public boolean saveOrUpdateUser(WechatOfficialAccountUser user) {
// 可添加业务校验逻辑
return super.saveOrUpdate(user);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void saveOrUpdateBatch(List<WechatOaUserDto> officialAccountUsers) {
if (officialAccountUsers.isEmpty()) {
return;
}
// 收集所有 openId
Set<String> allOpenIds = officialAccountUsers.stream()
.filter(user -> user.getOpenid() != null)
.map(WechatOaUserDto::getOpenid)
.collect(Collectors.toSet());
// 批量查询已存在的 openId
List<WechatOfficialAccountUser> existingUsers = dao.selectByOpenIds(allOpenIds);
Set<String> existingOpenIds = existingUsers.stream()
.map(WechatOfficialAccountUser::getOpenid)
.collect(Collectors.toSet());
// 分组:需更新 & 需新增
List<WechatOaUserDto> usersToUpdates = officialAccountUsers.stream()
.filter(user -> existingOpenIds.contains(user.getOpenid()))
.collect(Collectors.toList());
List<WechatOaUserDto> usersToSaves = officialAccountUsers.stream()
.filter(user -> !existingOpenIds.contains(user.getOpenid()))
.collect(Collectors.toList());
// 批量操作
if (!usersToUpdates.isEmpty()) {
dao.updateBatch(usersToUpdates);
}
if (!usersToSaves.isEmpty()) {
dao.saveBatch(usersToSaves);
}
}
@Override
public WechatOfficialAccountUser selectMaxIdUser() {
List<WechatOfficialAccountUser> officialAccountUsers = dao.selectList();
if(officialAccountUsers.isEmpty()){
return null;
}
return officialAccountUsers.get(0);
}
@Override
public List<WechatOaUserDto> selectPageList(Integer pageNum, Integer pageSize) {
PageInfo<WechatOfficialAccountUser> officialAccountUsers = dao.selectPageList(pageNum, pageSize);
List<WechatOaUserDto> wechatOaUserDtos = officialAccountUsers.getRows().stream()
.map(user -> {
WechatOaUserDto dto = new WechatOaUserDto();
dto.setOpenid(user.getOpenid());
dto.setLanguage(user.getLanguage());
return dto;
})
.collect(Collectors.toList());
return wechatOaUserDtos;
}
@Override
public void updateUserInfoBatch(List<WechatOaUserResDto> userInfoBatch) {
if (userInfoBatch.isEmpty()) {
return;
}
dao.updateUserInfoBatch(userInfoBatch);
}
@Override
public WechatOfficialAccountUser selectOne(WeChatOaUserQueryDto oaUserDto) {
WeChatOaUserQueryWq wq = new WeChatOaUserQueryWq();
wq.setUnionid(oaUserDto.getUnionid());
WechatOfficialAccountUser wechatOfficialAccountUser = dao.selectOne(wq);
return wechatOfficialAccountUser;
}
}
...@@ -2,10 +2,12 @@ package com.link.hub.service.weChatMiniProgram; ...@@ -2,10 +2,12 @@ package com.link.hub.service.weChatMiniProgram;
import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser; import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser;
import com.link.hub.pojo.mp.dto.MpOpenIdDTO; import com.link.hub.pojo.mp.dto.MpOpenIdDTO;
import com.link.hub.pojo.mp.dto.MpUserDto; import com.link.hub.pojo.mp.dto.WeChatMpUserDto;
public interface WechatMiniProgramUserService { public interface WechatMiniProgramUserService {
WechatMiniProgramUser queryMiniProgramUserOne(MpUserDto openid); WechatMiniProgramUser queryMiniProgramUserOne(WeChatMpUserDto dto);
Long saveMiniProgramUser(MpOpenIdDTO mpOpenIdDTO); Long saveMiniProgramUser(MpOpenIdDTO mpOpenIdDTO);
Long updateMiniProgramUser(MpOpenIdDTO mpOpenIdDTO);
} }
...@@ -7,7 +7,7 @@ import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser; ...@@ -7,7 +7,7 @@ import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser;
import com.link.hub.domain.weChatMiniProgram.enums.SourceEnum; import com.link.hub.domain.weChatMiniProgram.enums.SourceEnum;
import com.link.hub.domain.weChatMiniProgram.mapper.LotteryParticipateMapper; import com.link.hub.domain.weChatMiniProgram.mapper.LotteryParticipateMapper;
import com.link.hub.pojo.mp.dto.LotteryParticipateDto; import com.link.hub.pojo.mp.dto.LotteryParticipateDto;
import com.link.hub.pojo.mp.dto.MpUserDto; import com.link.hub.pojo.mp.dto.WeChatMpUserDto;
import com.link.hub.pojo.mp.vo.LotteryParticipateVo; import com.link.hub.pojo.mp.vo.LotteryParticipateVo;
import com.link.hub.pojo.mp.vo.LotteryVo; import com.link.hub.pojo.mp.vo.LotteryVo;
import com.link.hub.service.officeAccount.WechatOfficeAccountService; import com.link.hub.service.officeAccount.WechatOfficeAccountService;
...@@ -40,7 +40,7 @@ public class LotteryParticipateServiceImpl extends ServiceImpl<LotteryParticipat ...@@ -40,7 +40,7 @@ public class LotteryParticipateServiceImpl extends ServiceImpl<LotteryParticipat
public LotteryParticipate participateLottery(LotteryVo lotteryVo) { public LotteryParticipate participateLottery(LotteryVo lotteryVo) {
// 检验是否关注公众号 // 检验是否关注公众号
MpUserDto mpUserDto = new MpUserDto(); WeChatMpUserDto mpUserDto = new WeChatMpUserDto();
mpUserDto.setId(SecurityUtils.getUserId()); mpUserDto.setId(SecurityUtils.getUserId());
WechatMiniProgramUser wechatMiniProgramUser = wechatMiniProgramUserService.queryMiniProgramUserOne(mpUserDto); WechatMiniProgramUser wechatMiniProgramUser = wechatMiniProgramUserService.queryMiniProgramUserOne(mpUserDto);
// 根据用户id查询小程序的用户信息 // 根据用户id查询小程序的用户信息
......
...@@ -5,17 +5,17 @@ import com.alibaba.fastjson2.JSONObject; ...@@ -5,17 +5,17 @@ import com.alibaba.fastjson2.JSONObject;
import com.link.hub.config.WeChatMiniProgramConfig; import com.link.hub.config.WeChatMiniProgramConfig;
import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser; import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser;
import com.link.hub.pojo.mp.dto.MpOpenIdDTO; import com.link.hub.pojo.mp.dto.MpOpenIdDTO;
import com.link.hub.pojo.mp.dto.MpUserDto; import com.link.hub.pojo.mp.dto.WeChatMpUserDto;
import com.link.hub.pojo.mp.vo.MiniProgramOpenIdVO; import com.link.hub.pojo.mp.vo.MiniProgramOpenIdVO;
import com.link.hub.pojo.mp.vo.MpLoginVo; import com.link.hub.pojo.mp.vo.MpLoginVo;
import com.link.hub.service.weChatMiniProgram.WechatMiniProgramService; import com.link.hub.service.weChatMiniProgram.WechatMiniProgramService;
import com.link.hub.service.weChatMiniProgram.WechatMiniProgramUserService; import com.link.hub.service.weChatMiniProgram.WechatMiniProgramUserService;
import com.link.hub.util.WeChatPlatFormUtils;
import com.sfa.common.core.constant.SecurityConstants; import com.sfa.common.core.constant.SecurityConstants;
import com.sfa.common.core.exception.ServiceException; import com.sfa.common.core.exception.ServiceException;
import com.sfa.common.core.utils.JwtUtils; import com.sfa.common.core.utils.JwtUtils;
import com.sfa.common.core.utils.ip.IpUtils; import com.sfa.common.core.utils.ip.IpUtils;
import com.sfa.common.core.utils.uuid.IdUtils; import com.sfa.common.core.utils.uuid.IdUtils;
import com.sfa.common.core.utils.wechat.WeChatPlatFormUtils;
import com.sfa.common.security.service.TokenService; import com.sfa.common.security.service.TokenService;
import com.sfa.system.api.model.LoginUser; import com.sfa.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -57,7 +57,7 @@ public class WechatMiniProgramServiceServiceImpl implements WechatMiniProgramSer ...@@ -57,7 +57,7 @@ public class WechatMiniProgramServiceServiceImpl implements WechatMiniProgramSer
log.error("获取openid失败,code:{},返回信息:{}", code,jsonObject.toString()); log.error("获取openid失败,code:{},返回信息:{}", code,jsonObject.toString());
throw new ServiceException("获取openid失败"); throw new ServiceException("获取openid失败");
} }
MpUserDto mpUserDto = new MpUserDto(); WeChatMpUserDto mpUserDto = new WeChatMpUserDto();
mpUserDto.setOpenid(openid); mpUserDto.setOpenid(openid);
mpUserDto.setUnionid(unionid); mpUserDto.setUnionid(unionid);
WechatMiniProgramUser wechatMiniProgramUser = miniProgramUserService.queryMiniProgramUserOne(mpUserDto); WechatMiniProgramUser wechatMiniProgramUser = miniProgramUserService.queryMiniProgramUserOne(mpUserDto);
...@@ -66,9 +66,19 @@ public class WechatMiniProgramServiceServiceImpl implements WechatMiniProgramSer ...@@ -66,9 +66,19 @@ public class WechatMiniProgramServiceServiceImpl implements WechatMiniProgramSer
if (ObjectUtil.isNotEmpty(wechatMiniProgramUser)) { if (ObjectUtil.isNotEmpty(wechatMiniProgramUser)) {
// 查询到数据不再新增 // 查询到数据不再新增
userId = wechatMiniProgramUser.getId(); userId = wechatMiniProgramUser.getId();
MpOpenIdDTO mpOpenIdDTO = new MpOpenIdDTO();
mpOpenIdDTO.setId(userId);
mpOpenIdDTO.setAvatarUrl(vo.getAvatarUrl());
mpOpenIdDTO.setNickname(vo.getNickname());
mpOpenIdDTO.setOpenid(openid);
mpOpenIdDTO.setUnionid(unionid);
userId = miniProgramUserService.updateMiniProgramUser(mpOpenIdDTO);
} else { } else {
// 保存小程序用户信息 新增小程序用户信息 // 保存小程序用户信息 新增小程序用户信息
MpOpenIdDTO mpOpenIdDTO = new MpOpenIdDTO(); MpOpenIdDTO mpOpenIdDTO = new MpOpenIdDTO();
mpOpenIdDTO.setAvatarUrl(vo.getAvatarUrl());
mpOpenIdDTO.setNickname(vo.getNickname());
mpOpenIdDTO.setOpenid(openid); mpOpenIdDTO.setOpenid(openid);
mpOpenIdDTO.setUnionid(unionid); mpOpenIdDTO.setUnionid(unionid);
userId = miniProgramUserService.saveMiniProgramUser(mpOpenIdDTO); userId = miniProgramUserService.saveMiniProgramUser(mpOpenIdDTO);
...@@ -99,7 +109,7 @@ public class WechatMiniProgramServiceServiceImpl implements WechatMiniProgramSer ...@@ -99,7 +109,7 @@ public class WechatMiniProgramServiceServiceImpl implements WechatMiniProgramSer
// miniProgramOpenIdVO.setSubscribeFlag(true); // miniProgramOpenIdVO.setSubscribeFlag(true);
// miniProgramOpenIdVO.setSubscribeTime(DateUtil.date()); // miniProgramOpenIdVO.setSubscribeTime(DateUtil.date());
miniProgramOpenIdVO.setToken(jwtToken); miniProgramOpenIdVO.setToken(jwtToken);
miniProgramOpenIdVO.setUserId(userId); // miniProgramOpenIdVO.setUserId(userId);
return miniProgramOpenIdVO; return miniProgramOpenIdVO;
} }
...@@ -120,9 +130,7 @@ public class WechatMiniProgramServiceServiceImpl implements WechatMiniProgramSer ...@@ -120,9 +130,7 @@ public class WechatMiniProgramServiceServiceImpl implements WechatMiniProgramSer
String templateId = "一个不存在的模板ID"; String templateId = "一个不存在的模板ID";
// 公众号的access_token // 公众号的access_token
JSONObject bodyJson = WeChatPlatFormUtils.getMiniappAccessToken(weChatMiniProgramConfig.getAppId(), weChatMiniProgramConfig.getAppSecret()); String accessToken = WeChatPlatFormUtils.getMiniappAccessToken(weChatMiniProgramConfig.getAppId(), weChatMiniProgramConfig.getAppSecret());
return WeChatPlatFormUtils.isSubscribe(openId, templateId, accessToken);
String accessToken = bodyJson.getString("access_token");
return WeChatPlatFormUtils.isSubscribe(openId, templateId, accessToken);
} }
} }
package com.link.hub.service.weChatMiniProgram.impl; package com.link.hub.service.weChatMiniProgram.impl;
import cn.hutool.core.date.DateUtil;
import com.link.hub.domain.weChatMiniProgram.dao.WechatMiniProgramUserDao; import com.link.hub.domain.weChatMiniProgram.dao.WechatMiniProgramUserDao;
import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser; import com.link.hub.domain.weChatMiniProgram.entity.WechatMiniProgramUser;
import com.link.hub.domain.weChatMiniProgram.wq.WechatMiniProgramUserWq; import com.link.hub.domain.weChatMiniProgram.wq.WechatMiniProgramUserWq;
import com.link.hub.pojo.mp.dto.MpOpenIdDTO; import com.link.hub.pojo.mp.dto.MpOpenIdDTO;
import com.link.hub.pojo.mp.dto.MpUserDto; import com.link.hub.pojo.mp.dto.WeChatMpUserDto;
import com.link.hub.service.weChatMiniProgram.WechatMiniProgramUserService; import com.link.hub.service.weChatMiniProgram.WechatMiniProgramUserService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -29,7 +28,7 @@ public class WechatMiniProgramUserServiceServiceImpl implements WechatMiniProgra ...@@ -29,7 +28,7 @@ public class WechatMiniProgramUserServiceServiceImpl implements WechatMiniProgra
* @return * @return
*/ */
@Override @Override
public WechatMiniProgramUser queryMiniProgramUserOne(MpUserDto mpUserDto) { public WechatMiniProgramUser queryMiniProgramUserOne(WeChatMpUserDto mpUserDto) {
WechatMiniProgramUserWq wechatMiniProgramUserWq = new WechatMiniProgramUserWq(); WechatMiniProgramUserWq wechatMiniProgramUserWq = new WechatMiniProgramUserWq();
wechatMiniProgramUserWq.setOpenid(mpUserDto.getOpenid()); wechatMiniProgramUserWq.setOpenid(mpUserDto.getOpenid());
wechatMiniProgramUserWq.setUserId(mpUserDto.getId()); wechatMiniProgramUserWq.setUserId(mpUserDto.getId());
...@@ -40,12 +39,15 @@ public class WechatMiniProgramUserServiceServiceImpl implements WechatMiniProgra ...@@ -40,12 +39,15 @@ public class WechatMiniProgramUserServiceServiceImpl implements WechatMiniProgra
@Override @Override
public Long saveMiniProgramUser(MpOpenIdDTO mpOpenIdDTO) { public Long saveMiniProgramUser(MpOpenIdDTO mpOpenIdDTO) {
WechatMiniProgramUser wechatMiniProgramUser = new WechatMiniProgramUser(); WechatMiniProgramUser wechatMiniProgramUser = WechatMiniProgramUser.create(mpOpenIdDTO);
wechatMiniProgramUser.setOpenid(mpOpenIdDTO.getOpenid());
wechatMiniProgramUser.setUnionid(mpOpenIdDTO.getUnionid());
wechatMiniProgramUser.setCreateTime(DateUtil.date());
wechatMiniProgramUser.setUpdateTime(DateUtil.date());
wechatMiniProgramUserDao.insert(wechatMiniProgramUser); wechatMiniProgramUserDao.insert(wechatMiniProgramUser);
return wechatMiniProgramUser.getId(); return wechatMiniProgramUser.getId();
} }
@Override
public Long updateMiniProgramUser(MpOpenIdDTO mpOpenIdDTO) {
WechatMiniProgramUser wechatMiniProgramUser = WechatMiniProgramUser.create(mpOpenIdDTO);
wechatMiniProgramUserDao.updateById(wechatMiniProgramUser);
return wechatMiniProgramUser.getId();
}
} }
package com.link.hub.util;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.link.hub.pojo.oa.dto.WechatOaUserDto;
import com.link.hub.pojo.oa.dto.WechatOaUserResDto;
import com.sfa.common.core.exception.ServiceException;
import com.sfa.common.core.utils.SpringUtils;
import com.sfa.common.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* @author : liqiulin
*Coate : 2024-04-15 15
* @describe :
*/
@Slf4j
@Component
public class WeChatPlatFormUtils {
// 微信模板消息接口地址
private static final String TEMPLATE_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send";
private static final String MINI_PROGRAM_CODE2SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session";
private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
private static final String STABLE_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/stable_token";
private static String BATCH_USER_INFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info/batchget";
public static Object isSubscribe(String openId, String templateId, String accessToken) {
String url = TEMPLATE_SEND_URL + "?access_token=" + accessToken;
// 构造一个无效的模板消息内容
String jsonBody = String.format(
"{\"touser\":\"%s\",\"template_id\":\"%s\",\"data\":{\"keyword1\":{\"value\":\"test\"}}}",
openId, templateId
);
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new StringEntity(jsonBody, "UTF-8"));
httpPost.setHeader("Content-type", "application/json");
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
JSONObject jsonObject = JSON.parseObject(result);
log.info("result: {}", jsonObject.toString());
Integer errCode = jsonObject.getInteger("errcode");
log.info("errCode: {}", errCode);
// 根据错误码判断
if (errCode != null) {
return errCode != 43004;
}
}
} catch (Exception e) {
e.printStackTrace();
log.error("获取"+templateId+"是否订阅"+openId+"失败"+e.getMessage(), e);
}
return false;
}
/**
* 服务号、小程序获取access_token
* @param appId
* @param appSecret
* @return
*/
public static String getMiniappAccessToken(String appId, String appSecret) {
String cacheKey = "hub:wx_access_token_" + appId;
Object accessToken = SpringUtils.getBean(RedisService.class).getCacheObject(cacheKey);
if (accessToken != null) {
return accessToken.toString();
}
String url = ACCESS_TOKEN_URL +"?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
String body = HttpUtil.createGet(url).execute().body();
JSONObject jsonObject = JSONObject.parseObject(body);
String accessTokenNew = jsonObject.getString("access_token");
// 缓存到redis
SpringUtils.getBean(RedisService.class).setCacheObject(cacheKey, accessTokenNew, 7000L, TimeUnit.SECONDS);
return accessTokenNew;
}
/**
* 服务号、小程序获取access_token
* @param appId
* @param appSecret
* @return
*/
public static String getStableAccessToken(String appId, String appSecret) {
String cacheKey = "hub:wx_access_token_" + appId;
Object cacheObject = SpringUtils.getBean(RedisService.class).getCacheObject(cacheKey);
if (cacheObject != null) {
return cacheObject.toString();
}
// String url = STABLE_ACCESS_TOKEN_URL +"?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
String url = STABLE_ACCESS_TOKEN_URL ;
// 构造请求体参数(JSON 格式)
JSONObject param = new JSONObject();
param.put("grant_type", "client_credential");
param.put("appid", appId);
param.put("secret", appSecret);
String body = HttpUtil.createPost(url).body(param.toJSONString()).execute().body();
JSONObject jsonObject = JSONObject.parseObject(body);
String accessToken = jsonObject.getString("access_token");
if(accessToken == null){
throw new ServiceException("获取用户列表失败");
}
// 缓存到redis
SpringUtils.getBean(RedisService.class).setCacheObject(cacheKey, accessToken, 7000L, TimeUnit.SECONDS);
return accessToken;
}
/**
* 服务号批量获取用户基本信息 batchUserinfo
* POST https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=ACCESS_TOKEN
* @param userDtos
* @param appId
* @param appSecret
* @return
*/
public static List<WechatOaUserResDto> getUserInfoBatch(List<WechatOaUserDto> userDtos, String appId, String appSecret) {
String url = BATCH_USER_INFO_URL+"?access_token=" + getMiniappAccessToken(appId, appSecret);
JSONObject param = new JSONObject();
param.put("user_list", userDtos);
String body = HttpUtil.createPost(url).body(param.toString()).execute().body();
JSONObject jsonObject = JSONObject.parseObject(body);
if(jsonObject.getInteger("errcode") != null){
throw new ServiceException("获取用户列表失败");
}
List<WechatOaUserResDto> userInfoList = jsonObject.getList("user_info_list", WechatOaUserResDto.class);
return userInfoList;
}
public JSONObject getUserPhoneByAccessToken(String accessToken, String code) {
JSONObject param = new JSONObject();
param.put("code", code);
String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
String body = HttpUtil.createPost(url).body(param.toString()).execute().body();
return JSONObject.parseObject(body);
}
public static JSONObject getOpenid(String jsCode, String xltAppId, String xltAppSecret) {
String url = MINI_PROGRAM_CODE2SESSION_URL +"?appid=" + xltAppId + "&secret=" + xltAppSecret + "&js_code=" + jsCode + "&grant_type=authorization_code";
String body = HttpUtil.createGet(url).execute().body();
return JSONObject.parseObject(body);
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论