Kaynağa Gözat

PC端微信公众号绑定+设备故障给所有售后成员推送

tanbin 1 yıl önce
ebeveyn
işleme
f050dc9091

+ 0 - 98
sys-api-service/src/main/java/com/xy/config/WeChatOfficialConfig.java

@@ -1,98 +0,0 @@
-package com.xy.config;
- 
-import lombok.Data;
-import me.chanjar.weixin.common.api.WxConsts;
-import me.chanjar.weixin.mp.api.WxMpMessageHandler;
-import me.chanjar.weixin.mp.api.WxMpMessageRouter;
-import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
-import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
-import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.stereotype.Component;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.PostConstruct;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-
-@Component
-@Data
-public class WeChatOfficialConfig {
-    public static final String ENCRYPT_TYPE = "encrypt_type";
-    public static final String RAW = "raw";
-    public static final String AES = "aes";
-    public static final String SIGNATURE = "signature";
-    public static final String ECHO_STR = "echostr";
-    public static final String NONCE = "nonce";
-    public static final String TIMESTAMP = "timestamp";
-
-
-    private static final String APP_ID = "wx95d729fe985ef9de";
-    private static final String SECRET = "e76dffd8329ad6c5943cc5e1f6ff95f2";
-    private static final String TOKEN = "111";
-    private static final String AES_KEY = "111";
-    public static final String MSG_SIGNATURE = "msg_signature";
-    public static final String SCAN_HANDLER = "scanHandler";
-    public static final String SUBSCRIBE_HANDLER = "subscribeHandler";
-    public static final String UNSUBSCRIBE_HANDLER = "unSubscribeHandler";
-
-    /**
-     * 微信服务号 登录 相关对象
-     */
-    private WxMpService officialAccountLoginService;
-    private WxMpDefaultConfigImpl config;
-    private WxMpMessageRouter wxMpMessageRouter;
-
-    @Autowired
-    private Map<String, WxMpMessageHandler> wxMpMessageHandlers;
-
-
-    @PostConstruct
-    private void init() {
-        officialAccountLoginService = getWxMpService();
-        initConfig();
-        initRouter();
-    }
-
-    /**
-     * 初始化微信服务号
-     *
-     * @return {@link WxMpService}
-     */
-    public WxMpService getWxMpService() {
-        WxMpService service = new WxMpServiceImpl();
-        WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
-        configStorage.setAppId(APP_ID);
-        configStorage.setSecret(SECRET);
-        configStorage.setToken(TOKEN);
-        configStorage.setAesKey(AES_KEY);
-        service.setWxMpConfigStorage(configStorage);
-        return service;
-    }
-
-    /**
-     * 初始化路由器
-     * 扫码、关注、取消关注
-     */
-    private void initRouter() {
-        wxMpMessageRouter = new WxMpMessageRouter(officialAccountLoginService);
-        wxMpMessageRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.SUBSCRIBE).handler(wxMpMessageHandlers.get(SUBSCRIBE_HANDLER)).end();
-        wxMpMessageRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.SCAN).handler(wxMpMessageHandlers.get(SCAN_HANDLER)).end();
-        wxMpMessageRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.UNSUBSCRIBE).handler(wxMpMessageHandlers.get(UNSUBSCRIBE_HANDLER)).end();
-    }
-
-    /**
-     * 初始化配置信息
-     */
-    private void initConfig() {
-        config = new WxMpDefaultConfigImpl();
-        config.setAppId(APP_ID);
-        config.setToken(TOKEN);
-        config.setSecret(SECRET);
-    }
-
-}

+ 35 - 0
sys-api-service/src/main/java/com/xy/handler/ScanHandler.java

@@ -0,0 +1,35 @@
+package com.xy.handler;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpMessageHandler;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * 微信服务号扫码处理器
+ */
+@Component("scanHandler")
+@Slf4j
+public class ScanHandler implements WxMpMessageHandler {
+
+    /**
+     * 扫码事件 (暂不实现逻辑)
+     *
+     * @param wxMessage
+     * @param context
+     * @param wxMpService
+     * @param sessionManager
+     * @return
+     */
+    @Override
+    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) {
+        return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
+                .content("扫一扫关注公众号").build();
+    }
+
+}

+ 58 - 0
sys-api-service/src/main/java/com/xy/handler/SubscribeHandler.java

@@ -0,0 +1,58 @@
+package com.xy.handler;
+
+import com.alibaba.fastjson.JSON;
+import com.google.common.base.Throwables;
+
+import com.xy.config.WeChatOfficialConfig;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpMessageHandler;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.result.WxMpUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * 微信服务号 关注 事件 处理器
+ * 将eventKey 存储在 redis
+ *
+ * @author 谭斌
+ * @date 2024/02/21
+ */
+@Component("subscribeHandler")
+@Slf4j
+public class SubscribeHandler implements WxMpMessageHandler {
+
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+
+    /**
+     * 拿到场景值和用户信息,写入到redis
+     *
+     * @param wxMessage
+     * @param context
+     * @param wxMpService
+     * @param sessionManager
+     * @return
+     */
+    @Override
+    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService
+            , WxSessionManager sessionManager) {
+        try {
+            WxMpUser user = wxMpService.getUserService().userInfo(wxMessage.getFromUser());
+            String eventKey = wxMessage.getEventKey().replaceAll(WeChatOfficialConfig.QR_CODE_SCENE_PREFIX, "");
+            redisTemplate.opsForValue().set(eventKey, JSON.toJSONString(user), 30, TimeUnit.DAYS);
+        } catch (Exception e) {
+            log.error("SubscribeHandler#handle fail:{}", Throwables.getStackTraceAsString(e));
+        }
+        return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
+                .content("感谢您的关注!").build();
+    }
+}

+ 29 - 0
sys-api-service/src/main/java/com/xy/handler/UnSubscribeHandler.java

@@ -0,0 +1,29 @@
+package com.xy.handler;
+
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpMessageHandler;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+
+/**
+ * 取关
+ *
+ * @author 谭斌
+ * @date 2024/02/21
+ */
+@Component("unSubscribeHandler")
+@Slf4j
+public class UnSubscribeHandler implements WxMpMessageHandler {
+
+    @Override
+    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) {
+        return WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
+                .content("我会想你的!").build();
+    }
+}

+ 31 - 168
sys-api-service/src/main/java/com/xy/service/UserInfoServiceImpl.java

@@ -1,57 +1,37 @@
 package com.xy.service;
 
+import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.text.CharSequenceUtil;
-import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
-import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.github.yitter.idgen.YitIdHelper;
-import com.google.common.base.Throwables;
 import com.xy.annotation.Lock;
-import com.xy.collections.list.JArrayList;
-import com.xy.collections.list.JList;
-import com.xy.config.WeChatOfficialConfig;
 import com.xy.config.WebMqttConfig;
-import com.xy.device.EnumDeviceQrCode;
-import com.xy.device.EnumDeviceType;
-import com.xy.dto.MercDeviceQrConfigDto;
+import com.xy.consts.CommConsts;
 import com.xy.dto.SysWorkUser.AddDto;
 import com.xy.dto.SysWorkUser.DelDto;
+import com.xy.dto.SysWorkUser.ListByRoleDto;
 import com.xy.dto.SysWorkUser.UpdateDto;
 import com.xy.dto.UserInfoDto;
-import com.xy.dto.WxServiceMsgDto;
 import com.xy.entity.UserInfo;
-import com.xy.error.CommRuntimeException;
 import com.xy.mapper.UserInfoMapper;
 import com.xy.utils.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
-import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
-import me.chanjar.weixin.common.api.WxConsts;
-import me.chanjar.weixin.mp.api.WxMpMessageHandler;
-import me.chanjar.weixin.mp.api.WxMpMessageRouter;
-import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
-import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
-import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
 
-import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.stream.Collectors;
 
 import static com.xy.utils.Beans.copy;
 import static com.xy.utils.PlusBeans.toIPage;
@@ -76,10 +56,33 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> i
 
     private WebMqttConfig webMqttConfig;
 
-    private WxMpService wxService;
+    private static final Long BIZ_SYS_ID = 374535878972677L;
 
-    private WeChatOfficialConfig weChatOfficialConfig;
 
+    @ApiOperation("获取所有售后权限用户ID")
+    @Override
+    public R<UserInfoDto.SaleBackUsersVO> getSaleBackUsers() {
+        UserInfoDto.SaleBackUsersVO vo = new UserInfoDto.SaleBackUsersVO();
+        ListByRoleDto listByRoleDto = new ListByRoleDto();
+        listByRoleDto.setRoleCode(CommConsts.MERC_SH_ADMIN);
+        listByRoleDto.setSysId(BIZ_SYS_ID);
+        List<Long> userIds = R.feignCheckData(sysWorkUserService.getUserIdListByRole(listByRoleDto));
+        //所有售后管理员及管理员创建的用户
+        List<UserInfo> userInfoList = this.list(Wrappers.<UserInfo>lambdaQuery()
+                .and(deviceAlgorithmChargingLambdaQueryWrapper -> deviceAlgorithmChargingLambdaQueryWrapper
+                        .in(UserInfo::getCreateUser, userIds)
+                        .or()
+                        .in(UserInfo::getAuthorizeUserId, userIds)
+                )
+        );
+        if (CollUtil.isNotEmpty(userInfoList)) {
+            List<Long> ids = userInfoList.stream().map(UserInfo::getAuthorizeUserId).distinct().collect(Collectors.toList());
+            List<String> wxMpOpenIds = userInfoList.stream().map(UserInfo::getMpOpenid).distinct().collect(Collectors.toList());
+            vo.setAuthUserIds(ids);
+            vo.setMpOpenIds(wxMpOpenIds);
+        }
+        return R.ok(vo);
+    }
 
     @Override
     @ApiOperation("集合查询")
@@ -248,144 +251,4 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> i
     }
 
 
-    @SneakyThrows
-    @PostMapping("wxQrCode")
-    @ApiOperation("获取微信服务号二维码-扫码关注公众号并绑定")
-    public R<UserInfoDto.WxQrCodeVO> getQrCode(@RequestBody @Validated UserInfoDto.WxQrCode wxQrCode) {
-        WxMpService wxMpService = weChatOfficialConfig.getWxMpService();
-        if (wxMpService == null) {
-            throw new CommRuntimeException("获取微信公众号配置信息失败!");
-        }
-        //指定用户
-        String userId = wxQrCode.getUserId();
-        if (StrUtil.isEmpty(userId)) {
-            //当前登录用户
-            userId = AuthorizeUtils.getLoginId(String.class);
-        }
-        WxMpQrCodeTicket ticket = wxService.getQrcodeService().qrCodeCreateTmpTicket(userId, 2592000);
-        String tk = ticket.getTicket();
-        String url = wxService.getQrcodeService().qrCodePictureUrl(tk);
-        JList<String> contents = new JArrayList<>();
-        contents.set(url);
-        JList<String> text = new JArrayList<>();
-        text.set("使用微信[扫一扫]关注");
-        List<String> base64s = QRCodeUtils.create(contents, 400, 400, "back1.png", text).base64();
-        UserInfoDto.WxQrCodeVO vo = new UserInfoDto.WxQrCodeVO();
-        log.info("获取微信服务号二维码 usrId:{},tk:{}", userId, tk);
-        return R.ok(vo.setImgList(base64s).setTicket(tk));
-    }
-
-
-    private WxMpMessageRouter wxMpMessageRouter;
-
-    @Autowired
-    private Map<String, WxMpMessageHandler> wxMpMessageHandlers;
-
-    /**
-     * 接收微信的事件消息
-     * https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
-     *
-     * @return
-     */
-    @RequestMapping(value = "/receipt", produces = {"application/xml; charset=UTF-8"})
-    @ApiOperation("接收微信的事件消息")
-    public String receiptMessage(@RequestBody(required = false) WxServiceMsgDto wxServiceMsgDto, HttpServletRequest request) {
-
-        WxMpService wxMpService = weChatOfficialConfig.getWxMpService();
-        if (wxMpService == null) {
-            throw new CommRuntimeException("获取微信公众号配置信息失败!");
-        }
-        String echoStr = request.getParameter(WeChatOfficialConfig.ECHO_STR);
-        // echoStr!=null,说明只是微信调试的请求
-        if (CharSequenceUtil.isNotBlank(echoStr)) {
-            return echoStr;
-        }
-        String signature = request.getParameter(WeChatOfficialConfig.SIGNATURE);
-        String nonce = request.getParameter(WeChatOfficialConfig.NONCE);
-        String timestamp = request.getParameter(WeChatOfficialConfig.TIMESTAMP);
-        if (!wxService.checkSignature(timestamp, nonce, signature)) {
-            throw new CommRuntimeException("接收微信的事件消息,验签异常!");
-        }
-        log.info("接收微信的事件消息:{}", wxServiceMsgDto);
-        //处理带参数请求
-        if (null != wxServiceMsgDto &&
-                !StrUtil.isEmpty(wxServiceMsgDto.getMsgType()) &&
-                !StrUtil.isEmpty(wxServiceMsgDto.getEvent()) &&
-                !StrUtil.isEmpty(wxServiceMsgDto.getEventKey()) && !wxServiceMsgDto.getEventKey().equals("null") &&
-                (wxServiceMsgDto.getEventKey().equals("subscribe") || wxServiceMsgDto.getEvent().equals("SCAN"))
-        ) {
-
-            //关注
-            if (wxServiceMsgDto.getEvent().equals("subscribe")) {
-                log.info("关注: " + wxServiceMsgDto.getFromUserName());
-                setCacheTicket("1", wxServiceMsgDto.getFromUserName());
-                if (wxServiceMsgDto.getEventKey().contains("FenXiangMa")) {
-                    log.info("优惠券领取");
-                }
-            }
-
-            //扫码
-            if (wxServiceMsgDto.getEvent().equals("SCAN")) {
-                log.info("扫码: " + wxServiceMsgDto.getFromUserName());
-                if (wxServiceMsgDto.getEventKey().contains("YaoQingMa")) {
-                    log.info("新用户邀请");
-                }
-            }
-
-            log.info("参数: " + wxServiceMsgDto.getEventKey());
-        }
-        return "";
-
-
-//
-//        String encryptType = CharSequenceUtil.isBlank(request.getParameter(WeChatOfficialConfig.ENCRYPT_TYPE)) ? WeChatOfficialConfig.RAW : request.getParameter(WeChatOfficialConfig.ENCRYPT_TYPE);
-//        if (WeChatOfficialConfig.RAW.equals(encryptType)) {
-//            WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getInputStream());
-//            log.info("raw inMessage:{}", JSON.toJSONString(inMessage));
-//            WxMpXmlOutMessage outMessage = weChatOfficialConfig.getWxMpMessageRouter().route(inMessage);
-//            return outMessage.toXml();
-//        } else if (WeChatOfficialConfig.AES.equals(encryptType)) {
-//            String msgSignature = request.getParameter(WeChatOfficialConfig.MSG_SIGNATURE);
-//            WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(request.getInputStream(), weChatOfficialConfig.getConfig(), timestamp, nonce, msgSignature);
-//            log.info("aes inMessage:{}", JSON.toJSONString(inMessage));
-//            WxMpXmlOutMessage outMessage = weChatOfficialConfig.getWxMpMessageRouter().route(inMessage);
-//            return outMessage.toEncryptedXml(weChatOfficialConfig.getConfig());
-//        }
-//        return "ok";
-
-
-    }
-
-    /**
-     * 缓存ticket
-     *
-     * @param tk
-     * @param openId
-     */
-    public static void setCacheTicket(String tk, String openId) {
-        RedisService<String> redisService = SpringBeanUtils.getBean(RedisService.class);
-        redisService.set("wechat:scan:ticket:" + tk, openId, 3600);//1h
-    }
-
-    /**
-     * 获取tk
-     *
-     * @param tk
-     * @return {@link String}
-     */
-    public static String getCacheTicket(String tk) {
-        RedisService<String> redisService = SpringBeanUtils.getBean(RedisService.class);
-        return redisService.get("wechat:scan:ticket:" + tk);
-    }
-
-    /**
-     * 刪除ticket
-     *
-     * @param tk
-     */
-    public static void delCacheTicket(String tk) {
-        RedisService<String> redisService = SpringBeanUtils.getBean(RedisService.class);
-        redisService.remove("wechat:scan:ticket:" + tk);
-    }
-
 }

+ 32 - 0
sys-api/src/main/java/com/xy/dto/UserInfoDto.java

@@ -143,6 +143,28 @@ public class UserInfoDto {
         private String mpOpenid;
     }
 
+    @Data
+    @Accessors(chain = true)
+    public static class SaleBackUsersVO {
+        @ApiModelProperty(value = "所有售后用户ID")
+        private List<Long> authUserIds;
+        @ApiModelProperty(value = "所有售后用户openID")
+        private List<String> mpOpenIds;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class SaleBackUsersDTO {
+        @NotEmpty(message = "角色编号不可为空")
+        @ApiModelProperty(value = "角色编号", required = true)
+        private String roleCode;
+        @NotEmpty(message = "系统ID不可为空")
+        @ApiModelProperty(value = "用户ID", required = true)
+        private Long sysId;
+
+    }
+
+
     @Data
     @Accessors(chain = true)
     public static class Vo {
@@ -287,4 +309,14 @@ public class UserInfoDto {
         @ApiModelProperty(value = "ticket")
         private String ticket;
     }
+
+    @Data
+    @Accessors(chain = true)
+    public static class CheckSubWx {
+        @NotBlank(message = "ticketId不可为空")
+        @ApiModelProperty(value = "ticketId")
+        private String ticketId;
+        @ApiModelProperty(value = "userId")
+        private String userId;
+    }
 }

+ 4 - 6
sys-api/src/main/java/com/xy/dto/WxServiceMsgDto.java

@@ -15,22 +15,20 @@ import javax.xml.bind.annotation.XmlRootElement;
 @Data
 public class WxServiceMsgDto {
 
-    @XmlElement(name = "事件类型,scancode_push")
+    @XmlElement(name = "Event")
     private String event;
 
     @XmlElement(name = "Content")
     private String content;
 
-    @XmlElement(name = "消息类型,event")
+    @XmlElement(name = "MsgType")
     private String msgType;
 
-    @XmlElement(name = "扫描类型,一般是qrcode")
-    private String ScanType;
 
-    @XmlElement(name = "开发者 微信号")
+    @XmlElement(name = "ToUserName")
     private String toUserName;
 
-    @XmlElement(name = "事件KEY值,由开发者在创建菜单时设定")
+    @XmlElement(name = "EventKey")
     private String eventKey;
 
     @XmlElement(name = "CreateTime")

+ 10 - 0
sys-api/src/main/java/com/xy/service/UserInfoService.java

@@ -69,6 +69,7 @@ public interface UserInfoService {
 
     /**
      * 修改支付宝信息
+     *
      * @param dto
      * @return
      */
@@ -78,9 +79,18 @@ public interface UserInfoService {
 
     /**
      * 修改微信信息
+     *
      * @param dto
      * @return
      */
     @PostMapping("updateByWechat")
     R updateByWechat(@RequestBody @Validated UserInfoDto.UpdateByWechat dto);
+
+    /**
+     * 获取所有售后权限用户ID
+     *
+     * @return {@link R}<{@link List}<{@link UserInfoDto.SaleBackUsersVO}>>
+     */
+    R<UserInfoDto.SaleBackUsersVO> getSaleBackUsers();
+
 }

BIN
sys-start/src/main/resources/back1.png