diff --git a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/TicketController.java b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/TicketController.java index bde3eeb5..d38e934a 100644 --- a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/TicketController.java +++ b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/TicketController.java @@ -6,24 +6,28 @@ import com.itextpdf.html2pdf.HtmlConverter; import com.itextpdf.layout.font.FontProvider; import com.nflg.mobilebroken.admin.annotation.ApiMark; 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.pojo.ApiResult; 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.AssignmentTicketRequest; import com.nflg.mobilebroken.common.pojo.request.FollowRequest; import com.nflg.mobilebroken.common.pojo.vo.AdminTicketVO; 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.util.AdminUserUtil; import com.nflg.mobilebroken.common.util.EecExcelUtil; import com.nflg.mobilebroken.common.util.PageUtil; -import com.nflg.mobilebroken.repository.entity.AdminUser; -import com.nflg.mobilebroken.repository.entity.AppUser; -import com.nflg.mobilebroken.repository.entity.TBaseCustomer; -import com.nflg.mobilebroken.repository.entity.Ticket; +import com.nflg.mobilebroken.common.util.VUtils; +import com.nflg.mobilebroken.repository.entity.*; import com.nflg.mobilebroken.repository.service.*; import com.nflg.mobilebroken.starter.annotation.MethodInfoMark; +import com.nflg.mobilebroken.starter.service.impl.APPSSEManagerService; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -37,9 +41,11 @@ import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.time.Instant; import java.util.*; import java.util.stream.Collectors; @@ -69,6 +75,15 @@ public class TicketController extends ControllerBase { @Resource 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出错"); } } + + /** + * 获取工单详情 + * + * @param id 工单编号 + * @return 工单详情 + **/ + @GetMapping("getTicket") + public ApiResult 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 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> getChatMessages(@Valid @RequestParam @NotNull Integer ticketId) { + return ApiResult.success(ticketChatService.getMessages(ticketId)); + } + + /** + * 添加聊天记录 + * + * @param request 请求信息 + **/ + @PostMapping("addChatMessage") + @ApiMark(moduleName = "工单管理", apiName = "添加聊天记录") + public ApiResult 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(); + } } \ No newline at end of file diff --git a/nflg-mobilebroken-cfs-app/pom.xml b/nflg-mobilebroken-cfs-app/pom.xml index 26885a0d..ceb5c608 100644 --- a/nflg-mobilebroken-cfs-app/pom.xml +++ b/nflg-mobilebroken-cfs-app/pom.xml @@ -73,6 +73,11 @@ cn.dev33 sa-token-spring-boot-starter + + com.thoughtworks.xstream + xstream + 1.4.20 + diff --git a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/SystemController.java b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/SystemController.java index 89ead5f3..1ccd6a8c 100644 --- a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/SystemController.java +++ b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/SystemController.java @@ -1,15 +1,19 @@ package com.nflg.mobilebroken.cfs.controller; 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.vo.LanguageVO; +import com.nflg.mobilebroken.common.util.AppUserUtil; import com.nflg.mobilebroken.repository.entity.Language; 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.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -26,6 +30,9 @@ public class SystemController extends ControllerBase { @Resource private ILanguageService languageService; + @Resource + private WXQRCodeService wxQRCodeService; + /** * 获取语言列表 * @return 取语言列表 @@ -47,4 +54,13 @@ public class SystemController extends ControllerBase { .collect(Collectors.toList()); 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())); + } } \ No newline at end of file diff --git a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/TiketController.java b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/TiketController.java index 386e7291..d051e814 100644 --- a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/TiketController.java +++ b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/TiketController.java @@ -17,7 +17,7 @@ import com.nflg.mobilebroken.common.util.PageUtil; import com.nflg.mobilebroken.common.util.VUtils; import com.nflg.mobilebroken.repository.entity.*; 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 org.springframework.web.bind.annotation.*; @@ -77,7 +77,7 @@ public class TiketController extends ControllerBase { private ITBaseCustomerService customerService; @Resource - private APPSSEManagerService sseManagerService; + private AdminSSEManagerService sseManagerService; /** * 搜索设备 @@ -190,7 +190,9 @@ public class TiketController extends ControllerBase { .setCreateUserAvatar(user.getAvatar()) .setCreateTime(ticket.getCreateTime()) .setAreaName(appArea.getName()) - .setCompanyName(company.getAgencyCompanyName()); + .setCompanyName(company.getAgencyCompanyName()) + .setHandle(handle); + ; return ApiResult.success(vo); } diff --git a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/WXController.java b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/WXController.java new file mode 100644 index 00000000..4e35d085 --- /dev/null +++ b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/WXController.java @@ -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 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 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 parseXml(String xml) { + XStream xstream = new XStream(new DomDriver()); + xstream.alias("xml", Map.class); + return (Map) xstream.fromXML(xml); + } + + // 处理关注事件 + private String handleSubscribeEvent(Map 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 ""; + } +} diff --git a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/service/WXQRCodeService.java b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/service/WXQRCodeService.java new file mode 100644 index 00000000..330dbe74 --- /dev/null +++ b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/service/WXQRCodeService.java @@ -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 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 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); + } +} diff --git a/nflg-mobilebroken-common/pom.xml b/nflg-mobilebroken-common/pom.xml index 77458965..cd7aa95c 100644 --- a/nflg-mobilebroken-common/pom.xml +++ b/nflg-mobilebroken-common/pom.xml @@ -15,7 +15,6 @@ cn.hutool hutool-all - org.junit.jupiter @@ -55,6 +54,14 @@ org.springframework.data spring-data-mongodb + + com.google.zxing + core + + + com.google.zxing + javase + diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/constant/Constant.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/constant/Constant.java index 0c01fcf1..4826857e 100644 --- a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/constant/Constant.java +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/constant/Constant.java @@ -19,4 +19,8 @@ public class Constant { public static final String REDIS_KEY_MESSAGECONFIG_EMAIL = "emailNotifyEnabled"; 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"; } diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/dto/WXMessageBackDTO.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/dto/WXMessageBackDTO.java new file mode 100644 index 00000000..95b9d37b --- /dev/null +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/dto/WXMessageBackDTO.java @@ -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; +} diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/dto/WXTokenDTO.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/dto/WXTokenDTO.java new file mode 100644 index 00000000..0e5df140 --- /dev/null +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/dto/WXTokenDTO.java @@ -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; +} diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/WXQrcodeActionInfo.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/WXQrcodeActionInfo.java new file mode 100644 index 00000000..540f1a7d --- /dev/null +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/WXQrcodeActionInfo.java @@ -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; +} diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/WXQrcodeRequest.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/WXQrcodeRequest.java new file mode 100644 index 00000000..afb2a9fe --- /dev/null +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/WXQrcodeRequest.java @@ -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; +} diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/WXQrcodeScene.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/WXQrcodeScene.java new file mode 100644 index 00000000..1bd1314a --- /dev/null +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/WXQrcodeScene.java @@ -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; +} diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/TicketInfoVO.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/TicketInfoVO.java index b42cb592..e272aef6 100644 --- a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/TicketInfoVO.java +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/TicketInfoVO.java @@ -52,6 +52,9 @@ public class TicketInfoVO { //使用时长,单位: 小时 private Integer useTime; + //处理人 + private String handle; + //图片 private List images; diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/WXQrcodeVO.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/WXQrcodeVO.java new file mode 100644 index 00000000..29ef70a5 --- /dev/null +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/WXQrcodeVO.java @@ -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; +} diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/util/QRCodeUtil.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/util/QRCodeUtil.java new file mode 100644 index 00000000..150a9767 --- /dev/null +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/util/QRCodeUtil.java @@ -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 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(); + } +} diff --git a/nflg-mobilebroken-starter/pom.xml b/nflg-mobilebroken-starter/pom.xml index 7e6d0f2f..984a81a9 100644 --- a/nflg-mobilebroken-starter/pom.xml +++ b/nflg-mobilebroken-starter/pom.xml @@ -44,18 +44,17 @@ com.aliyun.oss aliyun-sdk-oss - 3.17.4 - - - javax.xml.bind - jaxb-api - 2.3.1 - - - javax.activation - activation - 1.1.1 + + + + + + + + + + com.github.binarywang wx-java-mp-spring-boot-starter diff --git a/pom.xml b/pom.xml index 7219e6aa..9ba9b7b3 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,8 @@ 2.3.31 1.39.0 4.7.0 + 3.5.3 + 3.17.4 @@ -153,6 +155,21 @@ weixin-java-mp ${weixin.version} + + com.google.zxing + core + ${zxing.version} + + + com.google.zxing + javase + ${zxing.version} + + + com.aliyun.oss + aliyun-sdk-oss + ${oss.version} +