DriverJob.java 16.1 KB
package com.ruoyi.job;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.driver.domain.Driver;
import com.ruoyi.driver.service.IDriverService;
import com.ruoyi.pojo.request.PersonnelRequestVo;
import com.ruoyi.pojo.request.TokenRequestVo;
import com.ruoyi.pojo.response.ResponseScheduling;
import com.ruoyi.pojo.response.personnel.*;
import com.ruoyi.service.ThreadJobService;
import com.ruoyi.utils.ConstDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.ruoyi.common.redispre.GlobalRedisPreName.DRIVER_SCHEDULING_PRE;
import static com.ruoyi.common.redispre.GlobalRedisPreName.REDIS_PERSONNEL_TOKEN;

/**
 * 该定时任务用户获取驾驶员信息
 *
 * @author 20412
 */
@Component("driverJob")
@Slf4j
public class DriverJob implements InitializingBean {

    @Autowired
    private RedisCache redisCache;

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private ThreadJobService threadJobService;

    @Autowired
    private IDriverService driverService;

    @Value("${api.url.getDriverInfo}")
    private String getDriverInfoUrl;


    @Value("${api.personnel.token.tokenUrl}")
    private String tokenUrl;

    @Value("${api.personnel.token.appKey}")
    private String appKey;

    @Value("${api.personnel.token.appSecret}")
    private String appSecret;

    @Value("${api.url.getSchedulingInfo}")
    private String getSchedulingInfoUrl;

    @Value("${api.config.password}")
    private String password;

    @Value("${api.config.nonce}")
    private String nonce;

    private static ThreadJobService THREAD_JOB_SERVICE;
    private static String APP_KEY;
    private static String TOKEN_URL;
    private static String APP_SECRET;
    private static IDriverService DRIVER_SERVICE;
    private static RedisCache REDIS_CACHE;
    private static RestTemplate RESTTEMPLATE;


    private static String GET_SCHEDULING_INFO_URL;
    private static String GET_DRIVER_INFO_URL;
    private static String PASSWORD;
    private static String NONCE;

    /**
     * 通过该定时任务获取驾驶员信息 并保存到数据库
     * 排班信息映射 不低于2小时更新一次
     */
    public void getDriverInfo(String params) throws Exception {
        try {
//            String getDriverInfoUrl = String.format(GET_DRIVER_INFO_URL, params);
            //获取token
            TokenResponseVo tokenVo = getToken(TOKEN_URL);
            // 获取驾驶员信息
            getDrivers(tokenVo.getAccessToken());

        } catch (Exception e) {
            log.info("执行失败:" + e.getMessage());
        }
        log.info("执行结束");
    }

    private static void saveDrivers(List<Driver> drivers, String accessToken) {
        // 多线程插入数据
        log.info("开始插入");
        THREAD_JOB_SERVICE.asyncUploadDriverWithUpdateImageUrl(drivers, accessToken);
//        String downloadImage = getDownloadImage(url, accessToken, "");

    }

//    public static void main(String[] args) {
//        String str = "[{\"previewUrl\":\"/ossFileHandle?appType=APP_HV8J7X8PFRXLJJW8JTZK&fileName=APP_HV8J7X8PFRXLJJW8JTZK_bWFuYWdlcjgxNF9QRTg2Nk1EMThYTUNaNkxVN002QTQ3N0hQV0E2MlNYMTMwQ0tMQTQ$.png&instId=&type=open&process=image/resize,m_fill,w_200,h_200,limit_0/quality,q_80\",\"size\":621992,\"name\":\"0332d25e3b9e80bca3d90daf0d5857d.png\",\"downloadUrl\":\"/ossFileHandle?appType=APP_HV8J7X8PFRXLJJW8JTZK&fileName=APP_HV8J7X8PFRXLJJW8JTZK_bWFuYWdlcjgxNF9QRTg2Nk1EMThYTUNaNkxVN002QTQ3N0hQV0E2MlNYMTMwQ0tMQTQ$.png&instId=&type=download\",\"fileUuid\":\"APP_HV8J7X8PFRXLJJW8JTZK_bWFuYWdlcjgxNF9QRTg2Nk1EMThYTUNaNkxVN002QTQ3N0hQV0E2MlNYMTMwQ0tMQTQ$.png\",\"url\":\"/ossFileHandle?appType=APP_HV8J7X8PFRXLJJW8JTZK&fileName=APP_HV8J7X8PFRXLJJW8JTZK_bWFuYWdlcjgxNF9QRTg2Nk1EMThYTUNaNkxVN002QTQ3N0hQV0E2MlNYMTMwQ0tMQTQ$.png&instId=&type=download\"}]";
////        List<List> lists = JSONArray.parseArray(str, List.class);
//        List<ImageField_lk9mk228> lists = JSONArray.parseArray(str, ImageField_lk9mk228.class);
//        System.out.println(lists);
//    }

    public static String getDownloadImageUrl(String accessToken, String preViewUrl) {
        accessToken = REDIS_CACHE.getCacheObject(REDIS_PERSONNEL_TOKEN);
        String url = "https://api.dingtalk.com/v1.0/yida/apps/temporaryUrls/APP_HV8J7X8PFRXLJJW8JTZK";
        String fileUrl = "https://scroix.aliwork.com";
        try {
            fileUrl = URLEncoder.encode(fileUrl + preViewUrl, String.valueOf(StandardCharsets.UTF_8));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        url = url + "?userId=InterfaceManagement&timeout=7200000&fileUrl=" + fileUrl + "&systemToken=16A66291CHE9K5DPE1IDO9E63FOE2VWA09QFLV";
        Map<String, Object> param = new HashMap<>();
        param.put("userId", "InterfaceManagement");
        param.put("timeout", 7200000L);
        param.put("fileUrl", fileUrl);
        param.put("systemToken", "16A66291CHE9K5DPE1IDO9E63FOE2VWA09QFLV");
        Map<String, String> header = new HashMap<>();
        header.put("x-acs-dingtalk-access-token", accessToken);
        header.put("Content-Type", "application/json");
        String result = "";
        try {
            String body = HttpUtil.createGet(url).addHeaders(header).form(new HashMap<>()).execute().body();
            result = JSON.parseObject(body, ImageUrlResultResponseVo.class).getResult();
            // 可能需要重新获取token
        } catch (Exception e) {
            String token = DriverJob.getToken(TOKEN_URL).getAccessToken();
            header.put("x-acs-dingtalk-access-token", token);
            String body = HttpUtil.createGet(url).addHeaders(header).form(new HashMap<>()).execute().body();
            ImageUrlResultResponseVo vo = JSON.parseObject(body, ImageUrlResultResponseVo.class);
            result = vo.getResult();
        }
        return result;
    }

    /**
     * 获取排班任务请求
     * 24小时执行一次
     */
    public void getSchedulingInfo() {
        // 获取排班请求
        long timestamp = System.currentTimeMillis();
        String getSchedulingInfoUrl = null;
        try {
            getSchedulingInfoUrl = String.format(GET_SCHEDULING_INFO_URL, "99", ConstDateUtil.formatDate("yyyyMMdd"), timestamp, NONCE, PASSWORD, getSHA1(getStringStringMap(String.valueOf(timestamp))));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // 获取排班信息并存入redis
        saveSchedulingToRedis(getSchedulingInfoUrl, ConstDateUtil.formatDate("yyyyMMdd"));
    }

    /**
     * 计算是否全部设备完成了对应的用户人脸注册
     */
    public void computedFaceSignIn() {
        DRIVER_SERVICE.updateDriverByComputed();
    }

    public Map<String, List<ResponseScheduling>> saveSchedulingToRedis(String getSchedulingInfoUrl, String dateKey) {
        List<ResponseScheduling> originSchedulingList = RESTTEMPLATE.exchange(
                getSchedulingInfoUrl,
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<ResponseScheduling>>() {
                }).getBody();

        Map<String, List<ResponseScheduling>> driverSchedulingMap = new HashMap<>(200);
        // 按照员工工号来获取排班信息
        originSchedulingList = originSchedulingList.stream()
                .map(subItem -> {
                    subItem.setJobCode(subItem.getJsy().split("/")[0]);
                    return subItem;
                }).collect(Collectors.toList());
        // 以员工号为key存入排班集合
        originSchedulingList.stream().forEach(item -> {
            // 员工号为key
            String jobCode = item.getJsy().split("/")[0];
            item.setJobCode(jobCode);
            if (Objects.isNull(driverSchedulingMap.get(jobCode))) {
                List<ResponseScheduling> oneDriverSchedulings = new ArrayList<>();
                oneDriverSchedulings.add(item);
                driverSchedulingMap.put(jobCode, oneDriverSchedulings);
            } else {
                driverSchedulingMap.get(jobCode).add(item);
            }
        });
        // 存入数据库
//        DRIVER_SERVICE.saveDriverScheduling(originSchedulingList);
        // 存入redis
        REDIS_CACHE.setCacheMap(DRIVER_SCHEDULING_PRE + dateKey, driverSchedulingMap, 1, TimeUnit.DAYS);
        return driverSchedulingMap;
    }

    public static void getDrivers(String accessToken) throws Exception {
//        Map<String, String> configMap = getStringStringMap(timestamp);
//        String sign = getSHA1(configMap);
        Date date = new Date();
        int pageSize = 100;
        PersonnelResultResponseVo vo = getPersonInfo(accessToken, pageSize, 1);
        int countPage = vo.getTotalCount() / pageSize;
        countPage = vo.getTotalCount() % pageSize == 0 ? countPage : countPage + 1;
        List<Driver> drivers = getDrivers(date, vo);
//        updateDrivers(drivers);
        saveDrivers(drivers, accessToken);
        for (int i = 1; i <= countPage; ) {
            if (++i <= countPage) {
                vo = getPersonInfo(accessToken, 100, i);
                drivers = getDrivers(date, vo);
//                updateDrivers(drivers);
                saveDrivers(drivers, accessToken);
            }
        }
    }

    private static void updateDrivers(List<Driver> drivers) {
        DRIVER_SERVICE.updateDrivers(drivers);
    }

    private static List<Driver> getDrivers(Date date, PersonnelResultResponseVo vo) {
        List<Driver> drivers = vo.getData().stream().map(item -> {
            Driver driver = new Driver();
            FormData formData = item.getFormData();
            driver.setUpdateTime(date);
            driver.setJobCode(formData.getTextField_lk9mk222());
            driver.setPersonnelName(formData.getTextField_lk9mk224());
            driver.setPosts(formData.getTextField_lk9mk226());
            // 解析JSON字符串
            List<ImageField_lk9mk228> lists = JSONArray.parseArray(formData.getImageField_lk9mk228(), ImageField_lk9mk228.class);
            driver.setImage(lists.get(0).getPreviewUrl());
            driver.setLineName(formData.getTextField_lkmgdvnu());
            driver.setFleetName(formData.getTextField_lkmgdvnv());
            return driver;
        }).collect(Collectors.toList());
        return drivers;
    }

    private static PersonnelResultResponseVo getPersonInfo(String accessToken, Integer pageSize, Integer currentPage) {
        RestTemplate restTemplate = new RestTemplate();
        String url = "https://api.dingtalk.com/v1.0/yida/forms/instances/search";
        PersonnelRequestVo vo = new PersonnelRequestVo();
        vo.setAppType("APP_HV8J7X8PFRXLJJW8JTZK");
        vo.setFormUuid("FORM-D2B665D1LQMCRRGS9WE6F54QTVYF25BXHM9KL4");
        vo.setUserId("InterfaceManagement");
        vo.setSystemToken("16A66291CHE9K5DPE1IDO9E63FOE2VWA09QFLV");
        vo.setCurrentPage(currentPage);
        vo.setPageSize(pageSize);
        // 工号组件
//        vo.setSearchFieldJson(" size = 4");
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("x-acs-dingtalk-access-token", accessToken);
        // 创建HttpEntity对象
        HttpEntity<String> requestEntity = new HttpEntity<>(JSON.toJSONString(vo), headers);

        // 发送POST请求
        ResponseEntity<PersonnelResultResponseVo> result = restTemplate.postForEntity(url, requestEntity, PersonnelResultResponseVo.class);
        PersonnelResultResponseVo body = result.getBody();
        return body;
    }

    public static TokenResponseVo getToken(String url) {
        TokenRequestVo request = new TokenRequestVo();
        request.setAppKey(APP_KEY);
        request.setAppSecret(APP_SECRET);
        String requestBody = JSON.toJSONString(request);
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        // 创建HttpEntity对象
        HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
        // 发送POST请求
        ResponseEntity<TokenResponseVo> responseEntity = RESTTEMPLATE.postForEntity(url, requestEntity, TokenResponseVo.class);
        TokenResponseVo vo = responseEntity.getBody();
        REDIS_CACHE.setCacheObject(REDIS_PERSONNEL_TOKEN, vo.getAccessToken(), vo.getExpireIn(), TimeUnit.SECONDS);

        return vo;
    }

    public Map<String, String> getStringStringMap(String timestamp) {
        Map<String, String> configMap = new HashMap<>(5);
        configMap.put("timestamp", String.valueOf(timestamp));
        configMap.put("nonce", NONCE);
        configMap.put("password", PASSWORD);
        return configMap;
    }


    /**
     * 获取签名
     *
     * @param map
     * @return
     * @throws Exception
     */
    public String getSHA1(Map<String, String> map) throws Exception {
        try {
            String[] array = new String[map.size()];
            map.values().toArray(array);
            StringBuffer sb = new StringBuffer();
            // 字符串排序
            Arrays.sort(array);
            for (int i = 0; i < array.length; i++) {
                sb.append(array[i]);
            }
            String str = sb.toString();
            // SHA1签名生成
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(str.getBytes());
            byte[] digest = md.digest();
            StringBuffer hexstr = new StringBuffer();
            String shaHex = "";
            for (int i = 0; i < digest.length; i++) {
                shaHex = Integer.toHexString(digest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexstr.append(0);
                }
                hexstr.append(shaHex);
            }
            return hexstr.toString();
        } catch (Exception e) {
            throw e;
        }


    }

//    public static void main(String[] args) throws Exception {
//        RestTemplate restTemplate1 = new RestTemplate();
////        String url = "http://101.95.136.206:9089/webservice/rest/person/company/%s";
//        String url = "http://101.95.136.206:9089/webservice/rest/schedule_real/sch_jk/%s/%s?timestamp=%d&nonce=%s&password=%s&sign=%s";
//
//        long timestamp = System.currentTimeMillis();
//        Map<String, String> configMap = new HashMap<>(5);
//        configMap.put("timestamp", String.valueOf(timestamp));
//        configMap.put("nonce", "NONCE");
//        configMap.put("password", "c4dd3d8cb9a82f6d6a625818618b28ca7bebb464");
//        String format = String.format(url, "99", DateUtils.getDate("yyyyMMdd"), timestamp, "NONCE", "c4dd3d8cb9a82f6d6a625818618b28ca7bebb464", getSHA1(configMap));
////        String sign = getSHA1(configMap);
////        String httpUrl = format
////                + "?timestamp=" + timestamp
////                + "&nonce=" + "NONCE"
////                + "&password=" + "c4dd3d8cb9a82f6d6a625818618b28ca7bebb464"
////                + "&sign=" + sign;
//        Object forObject = restTemplate1.getForObject(format, Object.class);
//    }

    @Override
    public void afterPropertiesSet() throws Exception {
        GET_DRIVER_INFO_URL = getDriverInfoUrl;
        NONCE = nonce;
        PASSWORD = password;
        RESTTEMPLATE = restTemplate;
        DRIVER_SERVICE = driverService;
        REDIS_CACHE = redisCache;
        GET_SCHEDULING_INFO_URL = getSchedulingInfoUrl;
        THREAD_JOB_SERVICE = threadJobService;
        TOKEN_URL = tokenUrl;
        APP_KEY = appKey;
        APP_SECRET = appSecret;
    }
}