|
@@ -0,0 +1,420 @@
|
|
|
+package com.management.platform.controller;
|
|
|
+
|
|
|
+
|
|
|
+import com.alibaba.fastjson2.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
|
+import com.management.platform.entity.User;
|
|
|
+import com.management.platform.entity.UserQrCode;
|
|
|
+import com.management.platform.entity.WechatAccount;
|
|
|
+import com.management.platform.service.CompanyService;
|
|
|
+import com.management.platform.service.UserQrCodeService;
|
|
|
+import com.management.platform.service.UserService;
|
|
|
+import com.management.platform.service.WechatAccountService;
|
|
|
+import com.management.platform.util.FileZipUtil;
|
|
|
+import com.management.platform.util.HttpRespMsg;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.apache.http.client.HttpClient;
|
|
|
+import org.apache.http.client.methods.CloseableHttpResponse;
|
|
|
+import org.apache.http.client.methods.HttpGet;
|
|
|
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
|
|
+import org.apache.http.impl.client.HttpClients;
|
|
|
+import org.apache.http.ssl.SSLContexts;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.http.*;
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.CompletableFuture;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * <p>
|
|
|
+ * 微信公众号账号表 前端控制器
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @author Seyason
|
|
|
+ * @since 2025-04-15
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@RestController
|
|
|
+@RequestMapping("/wechat-account")
|
|
|
+public class WechatAccountController {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private WechatAccountService wechatAccountService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private UserService userService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private RestTemplate restTemplate;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private UserQrCodeService userQrCodeService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private CompanyService companyService;
|
|
|
+
|
|
|
+ @Value(value ="${upload.path}")
|
|
|
+ private String uploadPath;
|
|
|
+
|
|
|
+ private final static String prefixUrl="https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=";
|
|
|
+
|
|
|
+
|
|
|
+ //保存或修改
|
|
|
+ @RequestMapping("/saveOrUpdate")
|
|
|
+ public HttpRespMsg saveOrUpdate(WechatAccount wechatAccount ,HttpServletRequest request) {
|
|
|
+ HttpRespMsg httpRespMsg = new HttpRespMsg();
|
|
|
+ String token = request.getHeader("Token");
|
|
|
+ User user = userService.getById(token);
|
|
|
+ if (wechatAccount.getId()==null){
|
|
|
+ int count = wechatAccountService.count(new QueryWrapper<WechatAccount>().eq("company_id", user.getCompanyId()));
|
|
|
+ if (count>0){
|
|
|
+ httpRespMsg.setError("公司配置已存在,请传公司关键信息");
|
|
|
+ return httpRespMsg;
|
|
|
+ }
|
|
|
+ wechatAccount.setCompanyId(user.getCompanyId());
|
|
|
+ wechatAccountService.save(wechatAccount);
|
|
|
+ }else {
|
|
|
+ wechatAccountService.update(null,new UpdateWrapper<WechatAccount>()
|
|
|
+ .set("company_name", wechatAccount.getCompanyName())
|
|
|
+ .set("app_id", wechatAccount.getAppId())
|
|
|
+ .set("app_secret", wechatAccount.getAppSecret())
|
|
|
+ .eq("id", wechatAccount.getId()));
|
|
|
+
|
|
|
+ }
|
|
|
+ return httpRespMsg;
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取企业微信公众号配置
|
|
|
+ @RequestMapping("/getCompanyWeiXin")
|
|
|
+ public HttpRespMsg getCompanyWeiXin(HttpServletRequest request) {
|
|
|
+ HttpRespMsg httpRespMsg = new HttpRespMsg();
|
|
|
+ String token = request.getHeader("Token");
|
|
|
+ User user = userService.getById(token);
|
|
|
+ WechatAccount wechatAccount = wechatAccountService.getOne(new QueryWrapper<WechatAccount>().eq("company_id", user.getCompanyId()));
|
|
|
+ httpRespMsg.setData(wechatAccount);
|
|
|
+ return httpRespMsg;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存修改并获取公司对应的accessToken
|
|
|
+ * @param request
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @RequestMapping("/getAccessToken")
|
|
|
+ public HttpRespMsg getAccessToken(HttpServletRequest request) {
|
|
|
+ HttpRespMsg httpRespMsg = new HttpRespMsg();
|
|
|
+ String token = request.getHeader("Token");
|
|
|
+ User user = userService.getById(token);
|
|
|
+ WechatAccount wechatAccount = wechatAccountService.getOne(new QueryWrapper<WechatAccount>().eq("company_id", user.getCompanyId()));
|
|
|
+ if (wechatAccount==null){
|
|
|
+ httpRespMsg.setError("该公司没有配置公众号相关的参数");
|
|
|
+ return httpRespMsg;
|
|
|
+ }
|
|
|
+ String accessToken = wechatAccountService.getAccessToken(user.getCompanyId(), wechatAccount.getAppId());
|
|
|
+ httpRespMsg.setData(accessToken);
|
|
|
+ return httpRespMsg;
|
|
|
+ }
|
|
|
+
|
|
|
+ @RequestMapping(value = "sendInterviewInvitation")
|
|
|
+ public HttpRespMsg sendInterviewInvitation(String userId,HttpServletRequest request) {
|
|
|
+ HttpRespMsg msg = new HttpRespMsg();
|
|
|
+ String token = request.getHeader("Token");
|
|
|
+ User user = userService.getById(token);
|
|
|
+ WechatAccount wechatAccount = wechatAccountService.getOne(new QueryWrapper<WechatAccount>().eq("company_id", user.getCompanyId()));
|
|
|
+ String accessToken = wechatAccountService.getAccessToken(user.getCompanyId(), wechatAccount.getAppId());
|
|
|
+ try {
|
|
|
+
|
|
|
+ String result =createForeverStrTicket(accessToken, userId);
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(result);
|
|
|
+ String ticket = null ;
|
|
|
+ if(null!=jsonObject){
|
|
|
+ ticket = jsonObject.getString("ticket");
|
|
|
+ System.out.println("创建永久带参二维码成功,ticket="+ticket);
|
|
|
+ }
|
|
|
+ msg.data=ticket;
|
|
|
+ return msg;
|
|
|
+ } catch (Exception e) {
|
|
|
+ msg.setData(e.getMessage());
|
|
|
+ }
|
|
|
+ return msg;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //根据用户id获取对应的二维码信息
|
|
|
+ @RequestMapping(value = "getQrCodeFromTableOrWX")
|
|
|
+ public HttpRespMsg getQrCodeFromTableOrWX(String userId,HttpServletRequest request) {
|
|
|
+ HttpRespMsg msg = new HttpRespMsg();
|
|
|
+ String token = request.getHeader("Token");
|
|
|
+ User user = userService.getById(token);
|
|
|
+ UserQrCode qrCode = userQrCodeService.getOne(new QueryWrapper<UserQrCode>().eq("user_id", userId));
|
|
|
+ if (qrCode!=null){
|
|
|
+ qrCode.setUrlPlusTicket(prefixUrl+qrCode.getTicket());
|
|
|
+ msg.data=qrCode;
|
|
|
+ return msg;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ WechatAccount wechatAccount = wechatAccountService.getOne(new QueryWrapper<WechatAccount>().eq("company_id", user.getCompanyId()));
|
|
|
+ if (wechatAccount==null){
|
|
|
+ msg.setError("该公司没有配置公众号相关的参数");
|
|
|
+ return msg;
|
|
|
+ }
|
|
|
+ //获取公众号token
|
|
|
+ String accessToken = wechatAccountService.getAccessToken(user.getCompanyId(), wechatAccount.getAppId());
|
|
|
+ try {
|
|
|
+ //获取二维码相关信息相关
|
|
|
+ String result =createForeverStrTicket(accessToken, userId);
|
|
|
+ if (result==null|| StringUtils.isEmpty(result)){
|
|
|
+ msg.setError("获取二维码信息失败");
|
|
|
+ return msg;
|
|
|
+ }else {
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(result);
|
|
|
+
|
|
|
+ if (null != jsonObject) {
|
|
|
+ String ticket = jsonObject.getString("ticket");
|
|
|
+ System.out.println("创建永久带参二维码成功,ticket=" + ticket);
|
|
|
+ String url = jsonObject.getString("url");
|
|
|
+ System.out.println("创建永久带参二维码成功,url=" + url);
|
|
|
+
|
|
|
+ UserQrCode userQrCode = new UserQrCode();
|
|
|
+ userQrCode.setUserId(userId);
|
|
|
+ userQrCode.setTicket(ticket);
|
|
|
+ userQrCode.setUrl(url);
|
|
|
+ userQrCode.setCompanyId(user.getCompanyId());
|
|
|
+ //保存图片
|
|
|
+ String imgPrefix=(StringUtils.isEmpty(user.getJobNumber())?"":user.getJobNumber())+"_"+user.getName();
|
|
|
+ CompletableFuture<String> future = saveWeChatQrCodeImgHttpClient(prefixUrl + ticket, imgPrefix, uploadPath);
|
|
|
+ String imgName = future.get(10, TimeUnit.SECONDS);// 添加超时
|
|
|
+ if (imgName.isEmpty()){
|
|
|
+ msg.setError("二维码图片保存失败");
|
|
|
+ return msg;
|
|
|
+ }else {
|
|
|
+ userQrCode.setImg(imgName);
|
|
|
+ }
|
|
|
+
|
|
|
+ userQrCodeService.save(userQrCode);
|
|
|
+ userQrCode.setUrlPlusTicket(prefixUrl+userQrCode.getTicket());
|
|
|
+ msg.setData(userQrCode);
|
|
|
+ }
|
|
|
+
|
|
|
+ return msg;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ msg.setData(e.getMessage());
|
|
|
+ }
|
|
|
+ return msg;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //一键生成所有员工的二维码
|
|
|
+ @RequestMapping(value = "oneClickGeneration")
|
|
|
+ public HttpRespMsg oneClickGeneration(HttpServletRequest request) {
|
|
|
+ HttpRespMsg msg = new HttpRespMsg();
|
|
|
+ String token = request.getHeader("Token");
|
|
|
+ User user = userService.getById(token);
|
|
|
+
|
|
|
+ WechatAccount wechatAccount = wechatAccountService.getOne(new QueryWrapper<WechatAccount>().eq("company_id", user.getCompanyId()));
|
|
|
+ if (wechatAccount==null){
|
|
|
+ msg.setError("该公司没有配置公众号相关的参数");
|
|
|
+ return msg;
|
|
|
+ }
|
|
|
+ //获取公众号token
|
|
|
+ String accessToken = wechatAccountService.getAccessToken(user.getCompanyId(), wechatAccount.getAppId());
|
|
|
+
|
|
|
+ List<UserQrCode> qrCodeList = userQrCodeService.list(new QueryWrapper<UserQrCode>().eq("company_id", user.getCompanyId()));
|
|
|
+ List<String> userAlreadyIds = qrCodeList.stream().map(UserQrCode::getUserId).collect(Collectors.toList());//已经生成二维码的员工
|
|
|
+ userAlreadyIds.add("-1");
|
|
|
+
|
|
|
+ List<User> userList = userService.list(new QueryWrapper<User>().notIn("id", userAlreadyIds)
|
|
|
+ .eq("company_id", user.getCompanyId()));//未生成二维码的员工
|
|
|
+ if (!userList.isEmpty()){
|
|
|
+ for (User u : userList) {
|
|
|
+ String userId = u.getId();
|
|
|
+ try {
|
|
|
+ //获取二维码相关信息相关
|
|
|
+ String result =createForeverStrTicket(accessToken, userId);
|
|
|
+ if (result==null|| StringUtils.isEmpty(result)){
|
|
|
+ msg.setError("获取二维码信息失败");
|
|
|
+ return msg;
|
|
|
+ }else {
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(result);
|
|
|
+ if (null != jsonObject) {
|
|
|
+ String ticket = jsonObject.getString("ticket");
|
|
|
+ System.out.println("创建永久带参二维码成功,ticket=" + ticket);
|
|
|
+ String url = jsonObject.getString("url");
|
|
|
+ System.out.println("创建永久带参二维码成功,url=" + url);
|
|
|
+
|
|
|
+ UserQrCode userQrCode = new UserQrCode();
|
|
|
+ userQrCode.setUserId(userId);
|
|
|
+ userQrCode.setTicket(ticket);
|
|
|
+ userQrCode.setUrl(url);
|
|
|
+ userQrCode.setCompanyId(user.getCompanyId());
|
|
|
+ //保存图片
|
|
|
+ String imgPrefix=(StringUtils.isEmpty(u.getJobNumber())?"":u.getJobNumber())+"_"+u.getName();
|
|
|
+ CompletableFuture<String> future = saveWeChatQrCodeImgHttpClient(prefixUrl + ticket, imgPrefix, uploadPath);
|
|
|
+ String imgName = future.get(10, TimeUnit.SECONDS);// 添加超时
|
|
|
+ if (imgName.isEmpty()){
|
|
|
+ msg.setError("二维码图片保存失败");
|
|
|
+ return msg;
|
|
|
+ }else {
|
|
|
+ userQrCode.setImg(imgName);
|
|
|
+ }
|
|
|
+ userQrCodeService.save(userQrCode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ msg.setData(e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return msg;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ @Async("taskExecutor")
|
|
|
+ public CompletableFuture<String> saveWeChatQrCodeImg(String qrCodeUrl, String ticket, String uploadPath) {
|
|
|
+ try {
|
|
|
+ log.info("开始保存二维码图片,ticket: {}", ticket);
|
|
|
+
|
|
|
+ // 确保目录存在
|
|
|
+ File uploadDir = new File(uploadPath);
|
|
|
+ if (!uploadDir.exists() && !uploadDir.mkdirs()) {
|
|
|
+ throw new IOException("无法创建目录: " + uploadPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建目标文件路径
|
|
|
+ String fileName = ticket + ".jpg";
|
|
|
+ File destFile = new File(uploadPath, fileName);
|
|
|
+
|
|
|
+ // 从URL下载图片
|
|
|
+ log.info("qrCodeUrl==>{}", qrCodeUrl);
|
|
|
+ ResponseEntity<byte[]> response = restTemplate.getForEntity(qrCodeUrl, byte[].class);
|
|
|
+
|
|
|
+
|
|
|
+ if (!response.getStatusCode().is2xxSuccessful()) {
|
|
|
+ throw new IOException("下载失败,HTTP 状态码: " + response.getStatusCodeValue());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 写入文件
|
|
|
+ try (FileOutputStream fos = new FileOutputStream(destFile)) {
|
|
|
+ fos.write(response.getBody());
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("二维码图片保存成功,文件名: {}", fileName);
|
|
|
+ return CompletableFuture.completedFuture(fileName);
|
|
|
+
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("保存二维码图片失败,ticket: {}", ticket, e);
|
|
|
+ return CompletableFuture.completedFuture("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Async("taskExecutor")
|
|
|
+ public CompletableFuture<String> saveWeChatQrCodeImgHttpClient(String qrCodeUrl, String imgPrefix, String uploadPath) {
|
|
|
+ try {
|
|
|
+
|
|
|
+
|
|
|
+ // 确保目录存在
|
|
|
+ File uploadDir = new File(uploadPath);
|
|
|
+ if (!uploadDir.exists() && !uploadDir.mkdirs()) {
|
|
|
+ throw new IOException("无法创建目录: " + uploadPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建目标文件路径
|
|
|
+ String fileName = imgPrefix + ".jpg";
|
|
|
+ File destFile = new File(uploadPath, fileName);
|
|
|
+
|
|
|
+
|
|
|
+ log.info("qrCodeUrl==>{}", qrCodeUrl);
|
|
|
+ // 创建信任所有证书的HttpClient
|
|
|
+ HttpClient client = HttpClients.custom()
|
|
|
+ .setSSLContext(SSLContexts.custom().loadTrustMaterial(null, (chain, authType) -> true).build())
|
|
|
+ .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ HttpGet request = new HttpGet(qrCodeUrl);
|
|
|
+ try (CloseableHttpResponse response = (CloseableHttpResponse) client.execute(request);
|
|
|
+ FileOutputStream fos = new FileOutputStream(destFile)) {
|
|
|
+ if (response.getStatusLine().getStatusCode() != 200) {
|
|
|
+ throw new IOException("下载失败: " + response.getStatusLine());
|
|
|
+ }
|
|
|
+ response.getEntity().writeTo(fos);
|
|
|
+ }
|
|
|
+ return CompletableFuture.completedFuture(fileName);
|
|
|
+ } catch (Exception e) {
|
|
|
+ return CompletableFuture.completedFuture("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建永久二维码(字符串)
|
|
|
+ *
|
|
|
+ * @param accessToken
|
|
|
+ * @param sceneStr
|
|
|
+ * 场景str
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public String createForeverStrTicket(String accessToken, String sceneStr){
|
|
|
+ Map<String, String> intMap = new HashMap<>();
|
|
|
+ intMap.put("scene_str", sceneStr);
|
|
|
+ Map<String, Map<String, String>> mapMap = new HashMap<>();
|
|
|
+ mapMap.put("scene", intMap);
|
|
|
+ Map<String, Object> paramsMap = new HashMap<>();
|
|
|
+ paramsMap.put("action_name", "QR_LIMIT_STR_SCENE");
|
|
|
+ paramsMap.put("action_info", mapMap);
|
|
|
+ String jsonObject = JSONObject.toJSONString(paramsMap);
|
|
|
+
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.setContentType(MediaType.APPLICATION_JSON);
|
|
|
+ String requestUrl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+accessToken;
|
|
|
+
|
|
|
+
|
|
|
+ HttpEntity<String> requestEntity = new HttpEntity<String>(jsonObject, headers);
|
|
|
+ ResponseEntity<String> responseEntity = restTemplate.exchange(requestUrl,
|
|
|
+ HttpMethod.POST, requestEntity, String.class);
|
|
|
+
|
|
|
+ if (responseEntity.getStatusCode() == HttpStatus.OK) {
|
|
|
+ JSONObject json = JSONObject.parseObject(responseEntity.getBody());
|
|
|
+ assert json != null;
|
|
|
+ log.info("json.toJSONString()"+json.toJSONString());
|
|
|
+ return json.toJSONString();
|
|
|
+ }
|
|
|
+ else return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 导出
|
|
|
+ */
|
|
|
+ @RequestMapping("/export")
|
|
|
+ public void getExport(HttpServletRequest request, HttpServletResponse response) {
|
|
|
+ String token = request.getHeader("TOKEN");
|
|
|
+ User user = userService.getById(token);
|
|
|
+ List<UserQrCode> codeList = userQrCodeService.list(new QueryWrapper<UserQrCode>().eq("company_id", user.getCompanyId()));
|
|
|
+
|
|
|
+ List<String> fileNames= codeList.stream().map(UserQrCode::getImg).collect(Collectors.toList());
|
|
|
+ if (!fileNames.isEmpty()){
|
|
|
+ FileZipUtil.exportZip(response,uploadPath ,fileNames, "员工微信公众号二维码压缩包", ".zip");
|
|
|
+ }else return;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|