feat: 一些调整
This commit is contained in:
parent
14c4d7f2cd
commit
6bdc334c91
|
|
@ -6,24 +6,28 @@ import com.itextpdf.html2pdf.HtmlConverter;
|
||||||
import com.itextpdf.layout.font.FontProvider;
|
import com.itextpdf.layout.font.FontProvider;
|
||||||
import com.nflg.mobilebroken.admin.annotation.ApiMark;
|
import com.nflg.mobilebroken.admin.annotation.ApiMark;
|
||||||
import com.nflg.mobilebroken.common.constant.STATE;
|
import com.nflg.mobilebroken.common.constant.STATE;
|
||||||
|
import com.nflg.mobilebroken.common.constant.TicketState;
|
||||||
import com.nflg.mobilebroken.common.exception.NflgException;
|
import com.nflg.mobilebroken.common.exception.NflgException;
|
||||||
import com.nflg.mobilebroken.common.pojo.ApiResult;
|
import com.nflg.mobilebroken.common.pojo.ApiResult;
|
||||||
import com.nflg.mobilebroken.common.pojo.PageData;
|
import com.nflg.mobilebroken.common.pojo.PageData;
|
||||||
|
import com.nflg.mobilebroken.common.pojo.dto.ChatMessageDTO;
|
||||||
|
import com.nflg.mobilebroken.common.pojo.dto.SSEMessageDTO;
|
||||||
|
import com.nflg.mobilebroken.common.pojo.request.AddChatMessageRequest;
|
||||||
import com.nflg.mobilebroken.common.pojo.request.AdminTicketSearchRequest;
|
import com.nflg.mobilebroken.common.pojo.request.AdminTicketSearchRequest;
|
||||||
import com.nflg.mobilebroken.common.pojo.request.AssignmentTicketRequest;
|
import com.nflg.mobilebroken.common.pojo.request.AssignmentTicketRequest;
|
||||||
import com.nflg.mobilebroken.common.pojo.request.FollowRequest;
|
import com.nflg.mobilebroken.common.pojo.request.FollowRequest;
|
||||||
import com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO;
|
import com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO;
|
||||||
import com.nflg.mobilebroken.common.pojo.vo.DeviceInfoVO;
|
import com.nflg.mobilebroken.common.pojo.vo.DeviceInfoVO;
|
||||||
|
import com.nflg.mobilebroken.common.pojo.vo.TicketInfoVO;
|
||||||
import com.nflg.mobilebroken.common.pojo.vo.TicketPdfVO;
|
import com.nflg.mobilebroken.common.pojo.vo.TicketPdfVO;
|
||||||
import com.nflg.mobilebroken.common.util.AdminUserUtil;
|
import com.nflg.mobilebroken.common.util.AdminUserUtil;
|
||||||
import com.nflg.mobilebroken.common.util.EecExcelUtil;
|
import com.nflg.mobilebroken.common.util.EecExcelUtil;
|
||||||
import com.nflg.mobilebroken.common.util.PageUtil;
|
import com.nflg.mobilebroken.common.util.PageUtil;
|
||||||
import com.nflg.mobilebroken.repository.entity.AdminUser;
|
import com.nflg.mobilebroken.common.util.VUtils;
|
||||||
import com.nflg.mobilebroken.repository.entity.AppUser;
|
import com.nflg.mobilebroken.repository.entity.*;
|
||||||
import com.nflg.mobilebroken.repository.entity.TBaseCustomer;
|
|
||||||
import com.nflg.mobilebroken.repository.entity.Ticket;
|
|
||||||
import com.nflg.mobilebroken.repository.service.*;
|
import com.nflg.mobilebroken.repository.service.*;
|
||||||
import com.nflg.mobilebroken.starter.annotation.MethodInfoMark;
|
import com.nflg.mobilebroken.starter.annotation.MethodInfoMark;
|
||||||
|
import com.nflg.mobilebroken.starter.service.impl.APPSSEManagerService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
|
@ -37,9 +41,11 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
@ -69,6 +75,15 @@ public class TicketController extends ControllerBase {
|
||||||
@Resource
|
@Resource
|
||||||
private ITicketFollowService ticketFollowService;
|
private ITicketFollowService ticketFollowService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TicketChatService ticketChatService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private APPSSEManagerService sseManagerService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IAppAreaService appAreaService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取问题类型
|
* 获取问题类型
|
||||||
*
|
*
|
||||||
|
|
@ -230,4 +245,97 @@ public class TicketController extends ControllerBase {
|
||||||
throw new NflgException(STATE.BusinessError, "生成pdf出错");
|
throw new NflgException(STATE.BusinessError, "生成pdf出错");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工单详情
|
||||||
|
*
|
||||||
|
* @param id 工单编号
|
||||||
|
* @return 工单详情
|
||||||
|
**/
|
||||||
|
@GetMapping("getTicket")
|
||||||
|
public ApiResult<TicketInfoVO> getTicket(@Valid @RequestParam @NotNull Integer id) {
|
||||||
|
Ticket ticket = ticketService.getById(id);
|
||||||
|
AppUser user = appUserService.getById(ticket.getUserId());
|
||||||
|
AppArea appArea = appAreaService.getById(user.getAreaId());
|
||||||
|
TBaseCustomer company = customerService.getById(Integer.valueOf(user.getCompanyId()));
|
||||||
|
DeviceInfoVO device = deviceService.getByDeviceNo(ticket.getDeviceNo());
|
||||||
|
String handle = ticket.getHandle();
|
||||||
|
if (StrUtil.isNotBlank(handle)) {
|
||||||
|
List<AdminUser> adminUsers = adminUserService.listByIds(Arrays.stream(handle.split(",")).map(Integer::parseInt).collect(Collectors.toList()));
|
||||||
|
handle = adminUsers.stream().map(AdminUser::getUserName).collect(Collectors.joining(","));
|
||||||
|
}
|
||||||
|
TicketInfoVO vo = new TicketInfoVO()
|
||||||
|
.setId(ticket.getId())
|
||||||
|
.setTitle(ticket.getTitle())
|
||||||
|
.setDeviceNo(ticket.getDeviceNo())
|
||||||
|
.setModelNo(device.getModelNo())
|
||||||
|
.setComponent(ticket.getComponent())
|
||||||
|
.setUseTime(ticket.getUseTime())
|
||||||
|
.setDescription(ticket.getDescription())
|
||||||
|
.setState(ticket.getState())
|
||||||
|
.setImages(StrUtil.isNotBlank(ticket.getImages()) ? StrUtil.split(ticket.getImages(), ",") : Collections.emptyList())
|
||||||
|
.setAttachments(StrUtil.isNotBlank(ticket.getAttachments()) ? StrUtil.split(ticket.getAttachments(), ",") : Collections.emptyList())
|
||||||
|
.setCreateUserId(ticket.getUserId())
|
||||||
|
.setCreateUserName(user.getName())
|
||||||
|
.setCreateUserAvatar(user.getAvatar())
|
||||||
|
.setCreateTime(ticket.getCreateTime())
|
||||||
|
.setAreaName(appArea.getName())
|
||||||
|
.setCompanyName(company.getAgencyCompanyName())
|
||||||
|
.setHandle(handle);
|
||||||
|
return ApiResult.success(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工单聊天记录
|
||||||
|
*
|
||||||
|
* @param ticketId 工单编号
|
||||||
|
* @return 聊天记录
|
||||||
|
**/
|
||||||
|
@GetMapping("getChatMessages")
|
||||||
|
@ApiMark(moduleName = "工单管理", apiName = "获取工单聊天记录")
|
||||||
|
public ApiResult<List<ChatMessageDTO>> getChatMessages(@Valid @RequestParam @NotNull Integer ticketId) {
|
||||||
|
return ApiResult.success(ticketChatService.getMessages(ticketId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加聊天记录
|
||||||
|
*
|
||||||
|
* @param request 请求信息
|
||||||
|
**/
|
||||||
|
@PostMapping("addChatMessage")
|
||||||
|
@ApiMark(moduleName = "工单管理", apiName = "添加聊天记录")
|
||||||
|
public ApiResult<Void> addChatMessage(@Valid @RequestBody AddChatMessageRequest request) {
|
||||||
|
Ticket ticket = ticketService.getById(request.getTicketId());
|
||||||
|
VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在");
|
||||||
|
VUtils.trueThrowBusinessError(Objects.equals(ticket.getState(), TicketState.Revoked.getState())
|
||||||
|
|| Objects.equals(ticket.getState(), TicketState.Closed.getState()))
|
||||||
|
.throwMessage("当前工单状态不允许发送消息");
|
||||||
|
AdminUser user = adminUserService.getById(AdminUserUtil.getUserId());
|
||||||
|
ChatMessageDTO message = new ChatMessageDTO()
|
||||||
|
.setId(cn.hutool.core.util.IdUtil.getSnowflakeNextId())
|
||||||
|
.setFrom("admin")
|
||||||
|
.setSenderId(user.getId())
|
||||||
|
.setSenderName(user.getUserName())
|
||||||
|
.setSenderAvatar(user.getAvatar())
|
||||||
|
.setContent(request.getContent())
|
||||||
|
.setCreateTime(Instant.now())
|
||||||
|
.setAttachments(request.getAttachments())
|
||||||
|
.setImages(request.getImages())
|
||||||
|
.setQuote(request.getQuote());
|
||||||
|
// ticketChatService.pushMessage(request.getTicketId(),message);
|
||||||
|
// TicketChat chat=ticketChatService.findByTicketId(request.getTicketId());
|
||||||
|
// chat.getMessages().add(message);
|
||||||
|
// ticketChatService.save(chat);
|
||||||
|
ticketChatService.addMessage(request.getTicketId(), message);
|
||||||
|
//推送消息
|
||||||
|
try {
|
||||||
|
SSEMessageDTO messageDTO = new SSEMessageDTO()
|
||||||
|
.setType(1)
|
||||||
|
.setData(message);
|
||||||
|
sseManagerService.send(ticket.getUserId(), messageDTO);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("发送SSE消息出错", e);
|
||||||
|
}
|
||||||
|
return ApiResult.success();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -73,6 +73,11 @@
|
||||||
<groupId>cn.dev33</groupId>
|
<groupId>cn.dev33</groupId>
|
||||||
<artifactId>sa-token-spring-boot-starter</artifactId>
|
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.thoughtworks.xstream</groupId>
|
||||||
|
<artifactId>xstream</artifactId>
|
||||||
|
<version>1.4.20</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,19 @@
|
||||||
package com.nflg.mobilebroken.cfs.controller;
|
package com.nflg.mobilebroken.cfs.controller;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import com.nflg.mobilebroken.cfs.service.WXQRCodeService;
|
||||||
import com.nflg.mobilebroken.common.pojo.ApiResult;
|
import com.nflg.mobilebroken.common.pojo.ApiResult;
|
||||||
import com.nflg.mobilebroken.common.pojo.vo.LanguageVO;
|
import com.nflg.mobilebroken.common.pojo.vo.LanguageVO;
|
||||||
|
import com.nflg.mobilebroken.common.util.AppUserUtil;
|
||||||
import com.nflg.mobilebroken.repository.entity.Language;
|
import com.nflg.mobilebroken.repository.entity.Language;
|
||||||
import com.nflg.mobilebroken.repository.service.ILanguageService;
|
import com.nflg.mobilebroken.repository.service.ILanguageService;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
@ -26,6 +30,9 @@ public class SystemController extends ControllerBase {
|
||||||
@Resource
|
@Resource
|
||||||
private ILanguageService languageService;
|
private ILanguageService languageService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private WXQRCodeService wxQRCodeService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取语言列表
|
* 获取语言列表
|
||||||
* @return 取语言列表
|
* @return 取语言列表
|
||||||
|
|
@ -47,4 +54,13 @@ public class SystemController extends ControllerBase {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
return ApiResult.success(vos);
|
return ApiResult.success(vos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成微信服务号关注二维码
|
||||||
|
*/
|
||||||
|
@GetMapping("generateQRCode")
|
||||||
|
public void generateQRCode(HttpServletResponse response) throws Exception {
|
||||||
|
response.setContentType(MediaType.IMAGE_PNG_VALUE);
|
||||||
|
response.getOutputStream().write(wxQRCodeService.generateQRCode(AppUserUtil.getUserId()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -17,7 +17,7 @@ import com.nflg.mobilebroken.common.util.PageUtil;
|
||||||
import com.nflg.mobilebroken.common.util.VUtils;
|
import com.nflg.mobilebroken.common.util.VUtils;
|
||||||
import com.nflg.mobilebroken.repository.entity.*;
|
import com.nflg.mobilebroken.repository.entity.*;
|
||||||
import com.nflg.mobilebroken.repository.service.*;
|
import com.nflg.mobilebroken.repository.service.*;
|
||||||
import com.nflg.mobilebroken.starter.service.impl.APPSSEManagerService;
|
import com.nflg.mobilebroken.starter.service.impl.AdminSSEManagerService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ public class TiketController extends ControllerBase {
|
||||||
private ITBaseCustomerService customerService;
|
private ITBaseCustomerService customerService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private APPSSEManagerService sseManagerService;
|
private AdminSSEManagerService sseManagerService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 搜索设备
|
* 搜索设备
|
||||||
|
|
@ -190,7 +190,9 @@ public class TiketController extends ControllerBase {
|
||||||
.setCreateUserAvatar(user.getAvatar())
|
.setCreateUserAvatar(user.getAvatar())
|
||||||
.setCreateTime(ticket.getCreateTime())
|
.setCreateTime(ticket.getCreateTime())
|
||||||
.setAreaName(appArea.getName())
|
.setAreaName(appArea.getName())
|
||||||
.setCompanyName(company.getAgencyCompanyName());
|
.setCompanyName(company.getAgencyCompanyName())
|
||||||
|
.setHandle(handle);
|
||||||
|
;
|
||||||
return ApiResult.success(vo);
|
return ApiResult.success(vo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
package com.nflg.mobilebroken.cfs.controller;
|
||||||
|
|
||||||
|
import com.nflg.mobilebroken.repository.entity.AdminUser;
|
||||||
|
import com.nflg.mobilebroken.repository.entity.AppUser;
|
||||||
|
import com.nflg.mobilebroken.repository.service.IAdminUserService;
|
||||||
|
import com.nflg.mobilebroken.repository.service.IAppUserService;
|
||||||
|
import com.thoughtworks.xstream.XStream;
|
||||||
|
import com.thoughtworks.xstream.io.xml.DomDriver;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
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 javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/wx")
|
||||||
|
public class WXController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IAdminUserService adminUserService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IAppUserService appUserService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理微信事件推送
|
||||||
|
*
|
||||||
|
* @param request 请求对象
|
||||||
|
* @return 响应消息
|
||||||
|
* @throws IOException IO 异常
|
||||||
|
*/
|
||||||
|
@PostMapping("/event")
|
||||||
|
public ResponseEntity<String> handleWeChatEvent(HttpServletRequest request) throws IOException {
|
||||||
|
// 读取请求体中的 XML 数据
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
request.getReader().lines().forEach(sb::append);
|
||||||
|
String requestBody = sb.toString();
|
||||||
|
log.info("接收到微信推送事件,内容: " + requestBody);
|
||||||
|
// 解析 XML 数据为 Map
|
||||||
|
Map<String, String> eventMap = parseXml(requestBody);
|
||||||
|
// 获取事件类型
|
||||||
|
String msgType = eventMap.get("MsgType");
|
||||||
|
String eventType = eventMap.get("Event");
|
||||||
|
// 根据事件类型处理逻辑
|
||||||
|
String responseMessage = "";
|
||||||
|
if ("event".equals(msgType)) {
|
||||||
|
if ("subscribe".equals(eventType)) {
|
||||||
|
responseMessage = handleSubscribeEvent(eventMap);
|
||||||
|
} else if ("unsubscribe".equals(eventType)) {
|
||||||
|
responseMessage = handleUnsubscribeEvent(eventMap.get("FromUserName"));
|
||||||
|
} else {
|
||||||
|
log.info("忽略的事件: " + eventType);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
responseMessage = "不是事件消息";
|
||||||
|
}
|
||||||
|
// 返回响应消息
|
||||||
|
return new ResponseEntity<>(responseMessage, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析 XML 数据为 Map
|
||||||
|
private Map<String, String> parseXml(String xml) {
|
||||||
|
XStream xstream = new XStream(new DomDriver());
|
||||||
|
xstream.alias("xml", Map.class);
|
||||||
|
return (Map<String, String>) xstream.fromXML(xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理关注事件
|
||||||
|
private String handleSubscribeEvent(Map<String, String> eventMap) {
|
||||||
|
// String fromUserName = eventMap.get("FromUserName");
|
||||||
|
String openId = eventMap.get("ToUserName");
|
||||||
|
String[] scene = eventMap.get("EventKey").split("_");
|
||||||
|
String from = scene[0];
|
||||||
|
Integer userId = Integer.parseInt(scene[1]);
|
||||||
|
if (from.equals("app")) {
|
||||||
|
appUserService.lambdaUpdate()
|
||||||
|
.set(AppUser::getOpenid, openId)
|
||||||
|
.eq(AppUser::getId, userId)
|
||||||
|
.update();
|
||||||
|
} else if (from.equals("admin")) {
|
||||||
|
adminUserService.lambdaUpdate()
|
||||||
|
.set(AdminUser::getOpenid, openId)
|
||||||
|
.eq(AdminUser::getId, userId)
|
||||||
|
.update();
|
||||||
|
} else {
|
||||||
|
log.error("不支持的来源: " + from);
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 构造回复消息
|
||||||
|
// WXMessageBackDTO response = new WXMessageBackDTO();
|
||||||
|
// response.setToUserName(openId);
|
||||||
|
// response.setFromUserName(fromUserName);
|
||||||
|
// response.setCreateTime(System.currentTimeMillis() / 1000);
|
||||||
|
// response.setMsgType("text");
|
||||||
|
// response.setContent("");
|
||||||
|
// return textMessageToXml(response);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理取消关注事件
|
||||||
|
private String handleUnsubscribeEvent(String openId) {
|
||||||
|
appUserService.lambdaUpdate()
|
||||||
|
.set(AppUser::getOpenid, "")
|
||||||
|
.eq(AppUser::getOpenid, openId);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.nflg.mobilebroken.cfs.service;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.nflg.mobilebroken.common.constant.Constant;
|
||||||
|
import com.nflg.mobilebroken.common.pojo.dto.WXTokenDTO;
|
||||||
|
import com.nflg.mobilebroken.common.pojo.request.WXQrcodeActionInfo;
|
||||||
|
import com.nflg.mobilebroken.common.pojo.request.WXQrcodeRequest;
|
||||||
|
import com.nflg.mobilebroken.common.pojo.request.WXQrcodeScene;
|
||||||
|
import com.nflg.mobilebroken.common.pojo.vo.WXQrcodeVO;
|
||||||
|
import com.nflg.mobilebroken.common.util.QRCodeUtil;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class WXQRCodeService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, String> redisTemplate;
|
||||||
|
|
||||||
|
public byte[] generateQRCode(Integer userId) throws Exception {
|
||||||
|
Object obj = redisTemplate.opsForHash().get("wx:url:follow", userId);
|
||||||
|
if (Objects.isNull(obj)) {
|
||||||
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
|
ResponseEntity<String> response1 = restTemplate.getForEntity(Constant.WX_TOKEN_URL, String.class);
|
||||||
|
String text = response1.getBody().substring(1, response1.getBody().length() - 1).replace("\\", "");
|
||||||
|
WXTokenDTO token = JSONUtil.toBean(text, WXTokenDTO.class);
|
||||||
|
String accessToken = token.getAccess_token();
|
||||||
|
String url = Constant.WX_QRCODE + "?access_token=" + accessToken;
|
||||||
|
String scene_str = "app_" + userId;
|
||||||
|
WXQrcodeRequest req = new WXQrcodeRequest().setAction_info(new WXQrcodeActionInfo().setScene(new WXQrcodeScene().setScene_str(scene_str)));
|
||||||
|
WXQrcodeVO qvo = restTemplate.postForObject(url, req, WXQrcodeVO.class);
|
||||||
|
obj = qvo.getUrl();
|
||||||
|
redisTemplate.opsForHash().put("wx:url:follow", userId, obj);
|
||||||
|
}
|
||||||
|
return QRCodeUtil.generateQRCode(obj.toString(), 200, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
|
@ -55,6 +54,14 @@
|
||||||
<groupId>org.springframework.data</groupId>
|
<groupId>org.springframework.data</groupId>
|
||||||
<artifactId>spring-data-mongodb</artifactId>
|
<artifactId>spring-data-mongodb</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.zxing</groupId>
|
||||||
|
<artifactId>core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.zxing</groupId>
|
||||||
|
<artifactId>javase</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
||||||
|
|
@ -19,4 +19,8 @@ public class Constant {
|
||||||
public static final String REDIS_KEY_MESSAGECONFIG_EMAIL = "emailNotifyEnabled";
|
public static final String REDIS_KEY_MESSAGECONFIG_EMAIL = "emailNotifyEnabled";
|
||||||
|
|
||||||
public static final String REDIS_KEY_MESSAGECONFIG_APP = "appNotifyEnabled";
|
public static final String REDIS_KEY_MESSAGECONFIG_APP = "appNotifyEnabled";
|
||||||
|
|
||||||
|
public static final String WX_TOKEN_URL = "http://sfc.nflg.net:8071/api/crm_api!getYdpAccessToken.action";
|
||||||
|
|
||||||
|
public static final String WX_QRCODE = "https://api.weixin.qq.com/cgi-bin/qrcode/create";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.nflg.mobilebroken.common.pojo.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WXMessageBackDTO {
|
||||||
|
|
||||||
|
private String ToUserName;
|
||||||
|
private String FromUserName;
|
||||||
|
private long CreateTime;
|
||||||
|
private String MsgType;
|
||||||
|
private String Content;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.nflg.mobilebroken.common.pojo.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WXTokenDTO {
|
||||||
|
|
||||||
|
private String jsapi_ticket;
|
||||||
|
|
||||||
|
private String access_token;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.nflg.mobilebroken.common.pojo.request;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class WXQrcodeActionInfo {
|
||||||
|
|
||||||
|
//场景值
|
||||||
|
private WXQrcodeScene scene;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.nflg.mobilebroken.common.pojo.request;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class WXQrcodeRequest {
|
||||||
|
|
||||||
|
//二维码类型,QR_SCENE为临时的整型参数值,QR_STR_SCENE为临时的字符串参数值,QR_LIMIT_SCENE为永久的整型参数值,QR_LIMIT_STR_SCENE为永久的字符串参数值
|
||||||
|
private String action_name = "QR_LIMIT_STR_SCENE";
|
||||||
|
|
||||||
|
//二维码详细信息
|
||||||
|
private WXQrcodeActionInfo action_info;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.nflg.mobilebroken.common.pojo.request;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class WXQrcodeScene {
|
||||||
|
|
||||||
|
//场景值ID(字符串形式的ID),字符串类型,长度限制为1到64
|
||||||
|
private String scene_str;
|
||||||
|
}
|
||||||
|
|
@ -52,6 +52,9 @@ public class TicketInfoVO {
|
||||||
//使用时长,单位: 小时
|
//使用时长,单位: 小时
|
||||||
private Integer useTime;
|
private Integer useTime;
|
||||||
|
|
||||||
|
//处理人
|
||||||
|
private String handle;
|
||||||
|
|
||||||
//图片
|
//图片
|
||||||
private List<String> images;
|
private List<String> images;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.nflg.mobilebroken.common.pojo.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WXQrcodeVO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取的二维码ticket,凭借此ticket可以在有效时间内换取二维码。
|
||||||
|
*/
|
||||||
|
private String ticket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天)。
|
||||||
|
*/
|
||||||
|
private Integer expire_seconds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 二维码图片解析后的地址,开发者可根据该地址自行生成需要的二维码图片
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.nflg.mobilebroken.common.util;
|
||||||
|
|
||||||
|
import com.google.zxing.BarcodeFormat;
|
||||||
|
import com.google.zxing.EncodeHintType;
|
||||||
|
import com.google.zxing.MultiFormatWriter;
|
||||||
|
import com.google.zxing.client.j2se.MatrixToImageWriter;
|
||||||
|
import com.google.zxing.common.BitMatrix;
|
||||||
|
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
public class QRCodeUtil {
|
||||||
|
|
||||||
|
public static byte[] generateQRCode(String text, int width, int height) throws Exception {
|
||||||
|
// 配置二维码参数
|
||||||
|
Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
|
||||||
|
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
||||||
|
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
|
||||||
|
hints.put(EncodeHintType.MARGIN, 1);
|
||||||
|
|
||||||
|
// 生成二维码矩阵
|
||||||
|
BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
|
||||||
|
|
||||||
|
// 将二维码矩阵转换为字节数组
|
||||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
MatrixToImageWriter.writeToStream(bitMatrix, "PNG", byteArrayOutputStream);
|
||||||
|
|
||||||
|
return byteArrayOutputStream.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -44,18 +44,17 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.aliyun.oss</groupId>
|
<groupId>com.aliyun.oss</groupId>
|
||||||
<artifactId>aliyun-sdk-oss</artifactId>
|
<artifactId>aliyun-sdk-oss</artifactId>
|
||||||
<version>3.17.4</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.xml.bind</groupId>
|
|
||||||
<artifactId>jaxb-api</artifactId>
|
|
||||||
<version>2.3.1</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.activation</groupId>
|
|
||||||
<artifactId>activation</artifactId>
|
|
||||||
<version>1.1.1</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>javax.xml.bind</groupId>-->
|
||||||
|
<!-- <artifactId>jaxb-api</artifactId>-->
|
||||||
|
<!-- <version>2.3.1</version>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>javax.activation</groupId>-->
|
||||||
|
<!-- <artifactId>activation</artifactId>-->
|
||||||
|
<!-- <version>1.1.1</version>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.binarywang</groupId>
|
<groupId>com.github.binarywang</groupId>
|
||||||
<artifactId>wx-java-mp-spring-boot-starter</artifactId>
|
<artifactId>wx-java-mp-spring-boot-starter</artifactId>
|
||||||
|
|
|
||||||
17
pom.xml
17
pom.xml
|
|
@ -39,6 +39,8 @@
|
||||||
<freemarker.version>2.3.31</freemarker.version>
|
<freemarker.version>2.3.31</freemarker.version>
|
||||||
<sa-token.version>1.39.0</sa-token.version>
|
<sa-token.version>1.39.0</sa-token.version>
|
||||||
<weixin.version>4.7.0</weixin.version>
|
<weixin.version>4.7.0</weixin.version>
|
||||||
|
<zxing.version>3.5.3</zxing.version>
|
||||||
|
<oss.version>3.17.4</oss.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
@ -153,6 +155,21 @@
|
||||||
<artifactId>weixin-java-mp</artifactId>
|
<artifactId>weixin-java-mp</artifactId>
|
||||||
<version>${weixin.version}</version>
|
<version>${weixin.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.zxing</groupId>
|
||||||
|
<artifactId>core</artifactId>
|
||||||
|
<version>${zxing.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.zxing</groupId>
|
||||||
|
<artifactId>javase</artifactId>
|
||||||
|
<version>${zxing.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun.oss</groupId>
|
||||||
|
<artifactId>aliyun-sdk-oss</artifactId>
|
||||||
|
<version>${oss.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue