今日校园签到Java代码

已更新最新签到程序,请关注公众号后使用 本人已经毕业,后续维护签到随缘! 现将主要代码贴出,很早之前写的有点乱,希望对你有帮助~!

package com.nsk666.wx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.nsk666.wx.mapper.CpMapper;
import com.nsk666.wx.pojo.dao.CpUser;
import com.nsk666.wx.pojo.entity.BaseMessage;
import com.nsk666.wx.pojo.entity.TextMessage;
import com.nsk666.wx.service.CpService;
import com.nsk666.wx.utils.LogUtils;
import com.nsk666.wx.utils.SendEmail;
import com.nsk666.wx.utils.SendMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * 类描述: 今日校园服务类
 *
 * @author coderOx
 * @date 2021-11-17
 */
@Service
public class CpServiceImpl implements CpService {
    @Autowired
    private CpMapper cpMapper;
    @Autowired
    private SendEmail sendEmail;
    @Autowired
    private SendMessage sendMessage;
    /**
     * 方法描述: 接受到消息Content包含 今日校园
     * @param map 数据包
     * @return BaseMessage
     * @author coderOx
     */
    public BaseMessage dealMessage(Map map) {
        BaseMessage message;
        String openId = map.get("FromUserName");
//        CpUser cpUser = cpMapper.getCpUserByOpenId(openId);
        CpUser cpUser = cpMapper.selectById(openId);
        String content = map.get("Content");
        String\\\[\\\] split;


        //发送今日校园
        if (null == cpUser && content.equals("今日校园")) {
            message = new TextMessage(map,
                    "未查询到微信信息!\\\n" +
                            "请取消关注本公众号后再关注!"
            );
            return message;
        } else if (null != cpUser && content.equals("今日校园")) {
            return new TextMessage(map,
                    "请先根据菜单添加你的今日校园账号!\\\n" +
                            "如有疑问请留言!\\\n" +
                            "签到结果通过QQ通知!\\\n" +
                            "请务必添加QQ1170999711接收通知!\\\n" +
                            "QQ为QQ邮箱的QQ!\\\n" +
                            "今日校园菜单:\\\n\\\n" +
                            "1.添加/更新今日校园账户信息(位置信息默认为学校)\\\n" +
                            "2.更新今日校园位置信息,经纬度查询:https://www.toolzl.com/tools/gps.html\\\n" +
                            "3.查看自己的今日校园信息\\\n" +
                            "4.删除今日校园信息\\\n" +
                            "5.修改签到项目(健康或查寝或全部,默认全部签到)\\\n\\\n" +
                            "请发送 今日校园+菜单号进行操作,如:\\\n" +
                            "更新账户信息发送:今日校园1");


        } else if (null != cpUser && content.equals("今日校园1")) {
            return new TextMessage(map,
                    "请严格按照以下格式发送:\\\n" +
                            "今日校园10 手机号 姓名 学号 今日校园密码 邮箱\\\n" +
                            "比如只修改手机号则发送:\\\n" +
                            "今日校园10 12354678911 姓名 学号 今日校园密码 邮箱");
        } else if (null != cpUser && content.contains("今日校园10")) {
            split = content.split(" ");
            if (split.length != 6) {
                return new TextMessage(map, "添加/更新失败!请检查发送的消息格式!\\\n你的信息如下:"+cpUser.toInfo());
            } else {
                //检查手机号、学号、邮箱是否正确
                boolean fla = true;
                if (!split\\\[1\\\].equals("手机号") && split\\\[1\\\].matches("\\\[0-9\\\]{11}"))
                    cpUser.setPhone(split\\\[1\\\]);
                else
                    fla = false;
                if (!split\\\[2\\\].equals("姓名") && !split\\\[2\\\].equals(""))
                    cpUser.setName(split\\\[2\\\]);
                else fla = false;
                if (!split\\\[3\\\].equals("学号") && split\\\[3\\\].matches("\\\[0-9\\\]{11}"))
                    cpUser.setStudentId(split\\\[3\\\]);
                else fla = false;
                if (!split\\\[4\\\].equals("今日校园密码") && !split\\\[4\\\].equals("")) cpUser.setPassword(split\\\[4\\\]);
                if (!split\\\[5\\\].equals("邮箱") && split\\\[5\\\].matches("\\\[0-9a-zA-Z\\\]{1,20}@\\\[0-9a-zA-Z.\\\]{0,20}"))
                    cpUser.setEmail(split\\\[5\\\]);
                else fla = false;
                if (!fla) {
                    return new TextMessage(map, "格式错误:请检查你的手机号/学号/邮箱是否正确!\\\n你的信息如下:"+cpUser.toInfo());
                }
                if (cpUser.getName() != null && cpUser.getStudentId() != null && cpUser.getPassword() != null
                        && cpUser.getEmail() != null) {
                    cpUser.setIsHealthySign(3);
                } else {
                    cpUser.setIsHealthySign(0);
                }

//                int i = cpMapper.updateCpUser(cpUser);
                QueryWrapper wrapper = new QueryWrapper<>();
                wrapper.eq("openid",cpUser.getOpenid());
                int i = cpMapper.update(cpUser,wrapper);
                if (i == 1)
                    return new TextMessage(map, "添加/更新成功,请留意QQ(邮箱)接收签到结果!\\\n" +
                            "你的信息如下:\\\n" + cpUser.toInfo() + "\\\n" +
                            "若有错误请发指令修改!");
                else
                    return new TextMessage(map, "添加/更新失败!\\\n你的信息如下:"+cpUser.toInfo());
            }
        } else if (null != cpUser && content.equals("今日校园2")) {
            return new TextMessage(map,
                    "(可选)请严格按照以下格式发送(注意经纬度顺序):\\\n" +
                            "今日校园20 地址 纬度 经度\\\n" +
                            "比如:\\\n" +
                            "今日校园20 中国浙江省杭州市钱塘区白杨街道文海南路 30.322654 120.389257");
        } else if (null != cpUser && content.contains("今日校园20")) {
            split = content.split(" ");
            if (split.length != 4) {
                return new TextMessage(map, "添加/更新失败!请检查发送的消息格式!\\\n你的信息如下:"+cpUser.toInfo());
            } else {
                if (!split\\\[1\\\].equals("地址") && !split\\\[2\\\].equals("纬度") && !split\\\[3\\\].equals("经度")) {
                    if(split\\\[1\\\].contains("中国浙江省杭州市钱塘区白杨街道文海南路")){
                        cpUser.setAbnormalReason("在校");
                    }else{
                        cpUser.setAbnormalReason("离校");
                    }
                    cpUser.setAddress(split\\\[1\\\]);
                    cpUser.setLat(split\\\[2\\\]);
                    cpUser.setLon(split\\\[3\\\]);
                } else {
                    return new TextMessage(map, "地址信息更新失败!请检查发送的消息格式!\\\n你的信息如下:"+cpUser.toInfo());
                }
//                int i = cpMapper.updateCpUser(cpUser);
                QueryWrapper wrapper = new QueryWrapper<>();
                wrapper.eq("openid",cpUser.getOpenid());
                int i = cpMapper.update(cpUser,wrapper);
                if (i == 1)
                    return new TextMessage(map, "地址信息更新成功!\\\n" +
                            "你的信息如下:\\\n" + cpUser.toInfo() + "\\\n" +
                            "若有错误请发指令修改!");
                else
                    return new TextMessage(map, "地址信息更新失败!\\\n" +
                            "您的信息如下:" + cpUser.toInfo());
            }
        } else if (null != cpUser && content.equals("今日校园3")) {
            return new TextMessage(map,
                    cpUser.toInfo());
        } else if (null != cpUser && content.equals("今日校园4")) {
            LogUtils.getLogger().info(cpUser.getName() + "执行了删除操作信息如下:\\\n" + cpUser.toInfo());
            cpUser.setIsHealthySign(0);
            cpUser.setPassword("");
            cpUser.setStudentId("");
            cpUser.setPhone("");
//            int i = cpMapper.updateCpUser(cpUser);
            QueryWrapper wrapper = new QueryWrapper<>();
            wrapper.eq("openid",cpUser.getOpenid());
            int i = cpMapper.update(cpUser,wrapper);
            if (i == 1)
                return new TextMessage(map, "删除成功!将不会进行签到!");
            else
                return new TextMessage(map, "删除失败!\\\n你的信息如下:"+cpUser.toInfo());
        } else if (null != cpUser && content.equals("今日校园5")) {
            return new TextMessage(map,
                    "(可选)请严格按照以下格式发送:\\\n" +
                            "今日校园50 只健康签到\\\n" +
                            "今日校园50 只查寝签到\\\n" +
                            "今日校园50 全部签到\\\n" +
                            "比如:\\\n" +
                            "今日校园50 全部签到");
        } else if (null != cpUser.getName() && content.startsWith("今日校园50")) {
            split = content.split(" ");
            if (split.length != 2) {
                return new TextMessage(map, "格式错误,请检查!\\\n你的信息如下:"+cpUser.toInfo());
            } else {
                if (cpUser.getName() != null && cpUser.getStudentId() != null && cpUser.getPassword() != null
                        && cpUser.getEmail() != null) {
                    switch (split\\\[1\\\]) {
                        case "只健康签到":
                            cpUser.setIsHealthySign(1);
                            break;
                        case "只查寝签到":
                            cpUser.setIsHealthySign(2);
                            break;
                        case "全部签到":
                            cpUser.setIsHealthySign(3);
                            break;
                        default:
                            return new TextMessage(map, "格式错误,请检查!\\\n你的信息如下:"+cpUser.toInfo());
                    }
//                    int i = cpMapper.updateCpUser(cpUser);
                    QueryWrapper wrapper = new QueryWrapper<>();
                    wrapper.eq("openid",cpUser.getOpenid());
                    int i = cpMapper.update(cpUser,wrapper);
                    if (i == 1) {
                        return new TextMessage(map, "设置成功!\\\n你的信息如下:"+cpUser.toInfo());
                    } else {
                        return new TextMessage(map,
                                "设置失败,请留言!");
                    }
                } else {
                    cpUser.setIsHealthySign(0);
                    return new TextMessage(map, "设置失败!你的信息缺项,请检查!\\\n" +
                            cpUser.toInfo());
                }

            }
        }
        //包含今日校园,但没有按照要求的格式,返回菜单
        else {
            try {
                sendMessage.qqMessage(cpUser.getName(),    "有人发消息错误(今日校园)::" +content, "1229290378");
            } catch (Exception e) {
                sendEmail.sendEmail(cpUser.getName()+"有人发消息错误(今日校园):",cpUser.getName()+content,null);
            }
            return new TextMessage(map, "今日校园个人信息错误\\\n或指令错误!(今日校园10之间没有空格)\\\n" +
                    "请检查个人信息是否有空缺:\\\n你的信息如下:"+cpUser.toInfo());
        }

    }

    @Override
    public Integer updateCpUser(CpUser cpUser) {
//        return cpMapper.updateCpUser(cpUser);
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("openid",cpUser.getOpenid());
        return cpMapper.update(cpUser,wrapper);
    }

    @Override
    public Integer addCpUser(CpUser cpUser) {
//        CpUser c = cpMapper.getCpUserByOpenId(cpUser.getOpenid());
        CpUser c = cpMapper.selectById(cpUser.getOpenid());
        if (c == null)
//            return cpMapper.addCpUser(cpUser);
        return cpMapper.insert(cpUser);
        else
            return -1;
    }

    @Override
    public CpUser getCpUserByOpenId(String openid) {
//        return cpMapper.getCpUserByOpenId(openid);
        return cpMapper.selectById(openid);
    }

    @Override
    public  List getCpUserByName(String name) {
//        return cpMapper.getCpUserByName(name);
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.like("name",name).or().like("openid",name);
        wrapper.orderByDesc("ishealthysign");
        return cpMapper.selectList(wrapper);
    }

    @Override
    public Integer clearCpUserByOpenId(String openid) {
        CpUser cpUser = getCpUserByOpenId(openid);
        cpUser.setPassword("");
        cpUser.setPhone("");
        cpUser.setStudentId("");
        cpUser.setIsHealthySign(0);
        return updateCpUser(cpUser);
    }

    @Override
    public Integer updateCpUserIsSign(CpUser cpUser) {
//        return cpMapper.updateCpUserIsSign(cpUser);
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("openid",cpUser.getOpenid());
        return cpMapper.update(cpUser,wrapper);
    }

    @Override
    public List getAllCpUser() {
//        return cpMapper.getAllCpUser();
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("ishealthysign");
        return cpMapper.selectList(wrapper);
    }

    @Override
    public List getAllHealthyCpUser() {
//        return cpMapper.getAllHealthyCpUser();
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("ishealthysign",1).or().eq("ishealthysign",3);
        return cpMapper.selectList(wrapper);
    }

    @Override
    public List getAllAttendanceCpUser() {
//        return cpMapper.getAllAttendanceCpUser();
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("ishealthysign",2).or().eq("ishealthysign",3);
        return cpMapper.selectList(wrapper);
    }

    @Override
    public Long getCount() {
        return cpMapper.selectCount(null);
    }
}

健康签到:

package com.nsk666.wx.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.nsk666.wx.mapper.CpMapper;
import com.nsk666.wx.pojo.dao.CpUser;
import com.nsk666.wx.service.SignService;
import com.nsk666.wx.utils.*;
import okhttp3.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.util.List;
import java.util.UUID;

/**
 * 类描述: 今日校园服务类
 *
 * @author coderOx
 * @date 2021-11-17
 */
@Service
public class SignServiceImpl implements SignService {
    @Autowired
    private CpMapper cpMapper;
    @Autowired
    private SendMessage sendMessage;

    private final String HOST = "https://zjiet.campusphere.net";
    private final String LOGIN_URL = HOST + "/iap/login?service=https%3A%2F%2Fzjiet.campusphere.net%2Fportal%2Flogin";
    private final String DO_LOGIN = HOST + "/iap/doLogin";
    private final String UNSIGNED\\\_TASK\\\_URL = HOST + "/wec-counselor-sign-apps/stu/sign/getStuSignInfosInOneDay";
    private final String DETAIL\\\_TASK\\\_URL = HOST + "/wec-counselor-sign-apps/stu/sign/detailSignInstance";
    private final String RESULT_NOTICE = "今日校园签到错误通知:";
    private final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");
    private final String UPLOAD_POLICY = HOST + "/wec-counselor-sign-apps/stu/oss/getUploadPolicy";
    private final String PIC_URL = HOST + "/wec-counselor-sign-apps/stu/sign/previewAttachment";
    private final String SUBMIT_URL = HOST + "/wec-counselor-sign-apps/stu/sign/submitSign";


    //每天早上6点0分1秒执行 1 1 6 * * ?
    @Scheduled(cron = "30 14 21 * * ?")
    public void healthySignTimer() {
        LogUtils.getLogger().info("开始健康签到");
        //获取所有的签到权限为1或3的用户
//        List cpUsersList = cpMapper.getAllHealthyCpUser();
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("ishealthysign",1).or().eq("ishealthysign",3);
        List cpUsersList = cpMapper.selectList(wrapper);

        LogUtils.getLogger().info(cpUsersList);
        int fla;
        //遍历用户来时签到
        for (CpUser user : cpUsersList) {
            //如果签到失败,再次尝试签到
            fla = 2;
            LogUtils.getLogger().debug(user.getName() + "的签到权限为:" + user.getIsHealthySign());
            while (fla > 0) {
                if (executeHealthySign(user)) {
                    fla = -1;
                } else {
                    fla--;
                    //隔2秒请求一个
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        LogUtils.getLogger().error("隔2秒发送消息失败!");
                        e.printStackTrace();
                    }
                }
            }
            //隔5秒请求一个
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                LogUtils.getLogger().error("隔2秒发送消息失败!");
                e.printStackTrace();
            }
        }
    }
    /**
    * 2022/2/21 学校更改把查寝签到放入查寝中,而不是签到中,特此更改
    **/
    //每天晚上21点31分执行 30 31 21 * * ?
   // @Scheduled(cron = "30 31 21 * * ?")
    public void attendanceSignTimer() {
        LogUtils.getLogger().info("开始查寝签到");
//        List cpUsersList = cpMapper.getAllAttendanceCpUser();
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("ishealthysign",2).or().eq("ishealthysign",3);
        List cpUsersList = cpMapper.selectList(wrapper);

        LogUtils.getLogger().info(cpUsersList);
        int fla;
        for (CpUser user : cpUsersList) {
            fla = 2;
            LogUtils.getLogger().debug(user.getName() + "的签到权限为:" + user.getIsHealthySign());
            while (fla > 0) {
                if (executeAttendanceSign(user)) {
                    fla = -1;
                } else {
                    fla--;
                    //隔2秒再执行一次
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        LogUtils.getLogger().error("隔5秒发送消息失败!");
                        e.printStackTrace();
                    }
                }
            }
            //隔5秒请求一个
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                LogUtils.getLogger().error("隔5秒发送消息失败!");
                e.printStackTrace();
            }
        }
    }

    /**
     * 方法描述: 执行健康签到
     * 如果签到失败,那么失败原因在么个方法中发邮件
     * 签到成功,通知在此方法通知
     *
     * @param user 签到类型,1为健康签到,2为查寝签到,传参数是为了不同时间执行不同的签到
     * @return
     * @author coderOx
     */
    public boolean executeHealthySign(CpUser user) {
        String headers = nskGetCookies(user);
        //如果返回null说明没有获取到,error说明出错
        if (null == headers || headers.equals("error")) {
            return false;
        }
        JSONObject unSignTask = getUnsignTask(headers, user, 1);
        //如果返回null说明没有获取到,如果包含error说明出错,如果包含success说明么有签到任务,
        if (null == unSignTask || unSignTask.getString("error") != null) {
            return false;
        } else if (unSignTask.getInteger("success") != null) {
            //返回true上层函数不再执行第二次
            return true;
        }
        JSONObject detailTask = getDetailTask(user, headers, unSignTask);
        //如果返回null说明没有获取到,如果包含error说明出错
        if (null == detailTask || detailTask.getString("error") != null) {
            return false;
        }
        JSONObject form = fillForm(detailTask, headers, user);
        //如果返回null说明没有获取到,如果包含error说明出错
        if (null == form || form.getString("error") != null) {
            return false;
        }
        //如果失败,失败信息在方法中通知
        return submitForm(headers, user, form);

    }

    /**
     * 方法描述: 执行查寝签到
     * 如果签到失败,那么失败原因在么个方法中发邮件
     * 签到成功,通知在此方法通知
     *
     * @param user
     * @return
     * @author coderOx
     */
    public boolean executeAttendanceSign(CpUser user) {
        String headers = nskGetCookies(user);
        //如果返回null说明没有获取到,error说明出错
        if (null == headers || headers.equals("error")) {
            return false;
        }
        JSONObject unSignTask = getUnsignTask(headers, user, 2);
        //如果返回null说明没有获取到,如果包含error说明出错,如果包含success说明么有签到任务,
        if (null == unSignTask || unSignTask.getString("error") != null) {
            return false;
        } else if (unSignTask.getInteger("success") != null && unSignTask.getInteger("success") == 1) {
            //不再执行第二次
            return true;
        }
        JSONObject detailTask = getDetailTask(user, headers, unSignTask);
        //如果返回null说明没有获取到,如果包含error说明出错
        if (null == detailTask || detailTask.getString("error") != null) {
            return false;
        }
        JSONObject form = fillForm(detailTask, headers, user);
        //如果返回null说明没有获取到,如果包含error说明出错
        if (null == form || form.getString("error") != null) {
            return false;
        }
        //如果失败,失败信息在方法中通知
        return submitForm(headers, user, form);

    }

    /**
     * 方法描述: 获取登录认证cookies
     *
     * @param user 学生信息
     * @return Headers
     * @author coderOx
     */
    private String nskGetCookies(CpUser user) {
        //获取CONVERSATION=iap-1020045845018065-CONV-eba0daa0-cfd2-487d-835e-e45c9527e43a
        //获取lt
        try {
            Headers headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("Referer", "https://zjiet.campusphere.net/portal/index.html")
                    .build();
            Response response = HttpUtils.sendGet(LOGIN_URL, headers, false);
            LogUtils.getLogger().debug(response.headers());
            //response.code() 应该为302
            if (response == null) {
                sendMessage.singNotice(RESULT_NOTICE, user.getName() + "登录获取Cookie失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "登录获取Cookie失败!");
                return null;
            }
            //获取cookies
            String cookie = splitCookies(response.headers().values("Set-Cookie"));
            if (!cookie.contains("CONVERSATION")) {
                sendMessage.singNotice(RESULT_NOTICE, user.getName() + "获取CONVERSATION失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "获取CONVERSATION失败!");
                return null;
            }
            //获取lt
            String lt = response.header("Location");
            if (null == lt || (lt = lt.split("=")\\\[1\\\]) == null) {
                sendMessage.singNotice(RESULT_NOTICE, user.getName() + "获取lt:Location失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "获取lt:Location失败!");
                return null;
            }
            //不使用response.body().string()需要手动关掉
            response.close();
            //登陆获取
            RequestBody requestBody = new FormBody.Builder()
                    .add("username", user.getStudentId())
                    .add("password", user.getPassword())
                    .add("lt", lt)
                    .build();
            LogUtils.getLogger().debug(user.getStudentId() + user.getPassword() + lt);
            headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("Cookie", cookie)
                    .build();
            response = HttpUtils.sendPost(DO_LOGIN, requestBody, headers);
            String finalUrl;
            if (null == response || null == (finalUrl = response.header("Location"))) {
                LogUtils.getLogger().debug(response.headers());
                sendMessage.singNotice(RESULT_NOTICE, user.getName() + "登录获取CAS令牌失败,请在公众号检查账号密码是否正确!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "登录获取CAS令牌失败!");
                //登录失败。不再次登录
                return "error";
            }
            //不使用response.body().string()需要手动关掉
            response.close();
            requestBody = new FormBody.Builder()
                    .build();
            //获取MOD\\\_AUTH\\\_CAS
            response = HttpUtils.sendPost(finalUrl, requestBody, headers);

            String MOD\\\_AUTH\\\_CAS;
            if (null == response || (MOD\\\_AUTH\\\_CAS = response.headers().get("Set-Cookie")) == null) {
                sendMessage.singNotice(RESULT\\\_NOTICE, "登录获取MOD\\\_AUTH_CAS失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "登录MOD\\\_AUTH\\\_CAS失败!");
                return null;
            }
            response.close();
            return MOD\\\_AUTH\\\_CAS;
        } catch (Exception e) {
            sendMessage.singNotice(RESULT\\\_NOTICE, "登录获取MOD\\\_AUTH_CAS失败!", user.getEmail());
            return "error";
        }
    }

    /**
     * 方法描述: 把获取的Set-Cookies 放到一个字符串里
     *
     * @param list cookies列表
     * @return String
     * @author coderOx
     */
    private String splitCookies(List list) {
        StringBuilder cookie = new StringBuilder();
        for (String s : list) {
            cookie.append(s).append(";");
        }
        return cookie.toString();
    }


    /**
     * 方法描述: 获取未签到信息
     *
     * @param session            包含登录的cookies
     * @param getUnsigedTaskType 1 代表健康签到 2 代表 查寝签到
     * @return
     * @author coderOx
     */
    private JSONObject getUnsignTask(String session, CpUser user, int getUnsigedTaskType) {
        JSONObject jsonObject = new JSONObject();
        try {
            String s = JSONObject.toJSONString(jsonObject);
            RequestBody requestBody = RequestBody.create(s, JSON_TYPE);
            Headers headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("content-type", "application/json;charset=UTF-8'")
                    .add("Cookie", session)
                    .build();
            //请求签到信息
            Response response = HttpUtils.sendPost(
                    UNSIGNED\\\_TASK\\\_URL,
                    requestBody,
                    headers
            );
            if (null == response || response.code() != 200) {
                sendMessage.singNotice(RESULT_NOTICE, "请求签到任务失败!!", user.getEmail());
                return null;
            }
            JSONArray jsonArray;
            jsonObject = JSONObject.parseObject(response.body().string());
            LogUtils.getLogger().debug(MyUtils.jsonFormat(jsonObject));
            //获取成功
            if (jsonObject.getString("code").equals("0")) {
                //获取data
                jsonObject = jsonObject.getJSONObject("datas");
                jsonArray = new JSONArray(jsonObject.getJSONArray("unSignedTasks"));
                //判断是否有未签到信息
                if (jsonArray.isEmpty()) {
                    LogUtils.getLogger().info(user.getName() + "当前没有签到任务");
                    sendMessage.singNotice(RESULT_NOTICE, "当前没有未签到任务!", user.getEmail());
                    //为了让这个用户不在签到第二次
                    jsonObject.put("success", 1);
                    return jsonObject;
                }
                if (getUnsigedTaskType == 1) {
                    JSONObject temp = null;
                    for (Object o : jsonArray) {
                        jsonObject = (JSONObject) o;
                        if (jsonObject.getString("taskName").contains("健")) {
                            temp = new JSONObject();
                            //层层往下穿1为了最后打卡成功的通知
                            temp.put("type", 1);
                            temp.put("signInstanceWid", jsonObject.getString("signInstanceWid"));
                            temp.put("signWid", jsonObject.getString("signWid"));
                        }
                    }
                    if (null == temp) {
                        sendMessage.singNotice(RESULT_NOTICE, user.getName() + "当前没有健康签到任务!", user.getEmail());
                        LogUtils.getLogger().info(user.getName() + "当前没有健康签到任务");
                        jsonObject.put("success", 1);
                        return jsonObject;
                    }
                    return temp;

                } else if (getUnsigedTaskType == 2) {
                    JSONObject temp = null;
                    for (Object o : jsonArray) {
                        jsonObject = (JSONObject) o;
                        if (jsonObject.getString("taskName").contains("寝")) {
                            temp = new JSONObject();
                            //层层往下穿2为了最后打卡成功的通知
                            temp.put("type", 2);
                            temp.put("signInstanceWid", jsonObject.getString("signInstanceWid"));
                            temp.put("signWid", jsonObject.getString("signWid"));
                        }
                    }
                    if (null == temp) {
                        sendMessage.singNotice(RESULT_NOTICE, user.getName() + "当前没有查寝签到任务!", user.getEmail());
                        LogUtils.getLogger().info(user.getName() + "当前没有查寝签到任务");
                        jsonObject.put("success", 1);
                        return jsonObject;
                    }
                    return temp;
                } else {
                    //既没有查寝签到也没有健康签到
                    sendMessage.singNotice(RESULT_NOTICE, user.getName() + "当前没有任何任务!", user.getEmail());
                    LogUtils.getLogger().info(user.getName() + "当前没有任何任务!");
                    jsonObject.put("success", 1);
                    return jsonObject;
                }
            } else {
                sendMessage.singNotice(RESULT_NOTICE, "签到任务查询失败!!", user.getEmail());
                //返回null执行第二次
                return null;
            }
        } catch (Exception e) {
            sendMessage.singNotice(RESULT_NOTICE, "获取任务查询失败,原因:" + e.getMessage(), user.getEmail());
            //返回error执行第二次
            jsonObject.put("error", "error");
            return jsonObject;
        }
    }
    /**
     * 方法描述: 获取签到详细信息
     * @return
     * @author coderOx
     */
    private JSONObject getDetailTask(CpUser user, String session, JSONObject unSignTask) {
        JSONObject jsonObject;
        try {
            LogUtils.getLogger().debug(MyUtils.jsonFormat(unSignTask));
            RequestBody requestBody = RequestBody.create(unSignTask.toJSONString(), JSON_TYPE);
            Headers headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("content-type", "application/json;charset=UTF-8'")
                    .add("Cookie", session)
                    .build();
            //请求签到信息
            Response response = HttpUtils.sendPost(
                    DETAIL\\\_TASK\\\_URL,
                    requestBody,
                    headers
            );

            if (null == response || response.code() != 200) {
                sendMessage.singNotice(RESULT_NOTICE, "请求签到详情失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "请求签到详情失败!");
                //返回null,请求第二次
                return null;
            } else {
                jsonObject = JSONObject.parseObject(response.body().string());
                if (!jsonObject.getString("code").equals("0")) {
                    sendMessage.singNotice(RESULT_NOTICE, "获取签到详情失败!", user.getEmail());
                    LogUtils.getLogger().info(user.getName() + "获取签到详情失败!");
                    //返回null,请求第二次
                    return null;
                }
                LogUtils.getLogger().debug(MyUtils.jsonFormat(jsonObject));
                jsonObject = jsonObject.getJSONObject("datas");
                //添加类型方便下层函数知道是健康还是查寝签到
                jsonObject.put("type", unSignTask.getInteger("type"));
                return jsonObject;
            }
        } catch (Exception e) {
            sendMessage.singNotice(RESULT_NOTICE, "获取签到信息详情失败!原因是:" + e.getMessage(), user.getEmail());
            jsonObject = new JSONObject();
            //失败,请求第二次
            jsonObject.put("error", "error");
            return jsonObject;
        }

    }
    /**
     * 方法描述: 填写表单
     * @return
     * @author coderOx
     */
    private JSONObject fillForm(JSONObject detailTask, String session, CpUser user) {
        if (detailTask == null) {
            return null;
        }
        JSONObject submitForm = new JSONObject();
        submitForm.put("type", detailTask.getInteger("type"));
        try {
            JSONArray jsonArray;
            submitForm.put("signInstanceWid", detailTask.getString("signInstanceWid"));
            submitForm.put("longitude", user.getLon());
            submitForm.put("latitude", user.getLat());
            submitForm.put("isMalposition", detailTask.getString("isMalposition"));
            submitForm.put("abnormalReason", user.getAbnormalReason());
            submitForm.put("position", user.getAddress());
            submitForm.put("qrUuid", "");
            //判断是否需要上传照片
            if (detailTask.getInteger("isPhoto") == 1) {
                String fileUrl = uploadPicture(user, session);
                if (fileUrl == null)
                    //失败请求第二次
                    return null;
                fileUrl = getPictureUrl(fileUrl, session, user);
                if (fileUrl == null)
                    //失败请求第二次
                    return null;
                submitForm.put("signPhotoUrl", fileUrl);
            } else {
                submitForm.put("signPhotoUrl", "");
            }
            //判断签到的时候是否需要额外的选项信息

            if (detailTask.getInteger("isNeedExtra") == 1) {

                jsonArray = detailTask.getJSONObject("signedStuInfo").getJSONArray("extraFieldItemVos");
                JSONArray arrayTemp = new JSONArray();
                //判断是否为空
                if (jsonArray.size() == 0) {
                    LogUtils.getLogger().debug(user.getName() + "的默认签到信息为空!");
                    sendMessage.singNotice(RESULT_NOTICE, "签到失败!没有上次app打卡记录,获取内容为空", user.getEmail());
                    return null;
                } else {
                    //额外信息填写需要字段 
                    JSONObject object;
                    for (Object o : jsonArray) {
                        object = (JSONObject) o;
                        JSONObject t = new JSONObject();
                        LogUtils.getLogger().debug(object);
                        t.put("extraFieldItemValue", object.getString("extraFieldItem"));
                        t.put("extraFieldItemWid", object.getString("extraFieldItemWid"));
                        arrayTemp.add(t);
                    }
                }
                LogUtils.getLogger().debug(arrayTemp);
                submitForm.put("isMalposition", 0);
                submitForm.put("extraFieldItems", arrayTemp);
                submitForm.put("uaIsCpadaily", true);
                submitForm.put("isNeedExtra", detailTask.getInteger("isNeedExtra"));
            }
            LogUtils.getLogger().debug(MyUtils.jsonFormat(submitForm));
            return submitForm;
        } catch (Exception e) {
            sendMessage.singNotice(RESULT_NOTICE, "填写表单失败!", user.getEmail());
            //失败请求第二次
            submitForm.put("error", "error");
            return submitForm;
        }
    }

    /**
     * 方法描述:  上传图片到今日校园的阿里服务器
     *
     * @param session
     * @param user
     * @return
     * @author coderOx
     */
    public String uploadPicture(CpUser user, String session) {
        try {
            JSONObject o = new JSONObject();
            o.put("fileType",1);
            RequestBody requestBody = RequestBody.create(JSONObject.toJSONString(o), JSON_TYPE);
            Headers headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("Content-Type", "application/json")
                    .add("Cookie", session)
                    .build();
            Response response = HttpUtils.sendPost(
                    UPLOAD_POLICY,
                    requestBody,
                    headers);
            JSONObject result;
            o = new JSONObject();
            if (response.code() != 200) {
                sendMessage.singNotice(RESULT_NOTICE, "上传照片URL请求失败!", user.getEmail());
                LogUtils.getLogger().info(user.getName() + "上传照片URL请求失败");
                return null;
            }
            result = JSONObject.parseObject(response.body().string());
            LogUtils.getLogger().debug(result);
            result = result.getJSONObject("datas");
            LogUtils.getLogger().debug(MyUtils.jsonFormat(result));

            ClassPathResource classPathResource = new ClassPathResource("static/default.png");
            InputStream inputStream = classPathResource.getInputStream();
            File file = new File("default.png");
            FileUtils.copyInputStreamToFile(inputStream, file);
            RequestBody r = RequestBody.create(file, MediaType.parse("multipart/form-data"));
//            //获取信息之后再此提交,获取真正的url
            RequestBody fileBody = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart("key", result.getString("fileName") + ".png")
                    .addFormDataPart("policy", result.getString("policy"))
                    .addFormDataPart("OSSAccessKeyId", result.getString("accessid"))
                    .addFormDataPart("success\\\_action\\\_status", "200")
                    .addFormDataPart("signature", result.getString("signature"))
                    .addFormDataPart("file", file.getName(), r)

                    .build();
            response = HttpUtils.sendPost(
                    result.getString("host"),
                    fileBody,
                    getHeaders()
            );
            if (response.code() != 200) {
                sendMessage.singNotice(RESULT_NOTICE, "上传照片请求失败!", user.getEmail());
                LogUtils.getLogger().info(user.getName() + "上传照片请求失败");
                return null;
            }
            LogUtils.getLogger().debug(result.getString("fileName") + ".png");
            return result.getString("fileName") + ".png";
        } catch (IOException e) {
            LogUtils.getLogger().error(user.getName() + "上传照片失败,原因是!" + e.getMessage());
            sendMessage.singNotice(RESULT_NOTICE, user.getName() + "上传照片失败,原因是!" + e.getMessage(), user.getEmail());
            return null;
        }
    }

    /**
     * 方法描述: 获取照片的url
     *
     * @author coderOx
     */
    private String getPictureUrl(String fileUrl, String session, CpUser user) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("ossKey", fileUrl);
            RequestBody requestBody = RequestBody.create(JSONObject.toJSONString(jsonObject), JSON_TYPE);
            Headers headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("Cookie", session)
                    .build();
            Response response = HttpUtils.sendPost(PIC_URL, requestBody, headers);
            if (response.code() != 200) {
                sendMessage.singNotice(RESULT_NOTICE, user.getName() + "转换照片URL请求失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "转换照片URL请求失败");
                return null;
            }
            String r = response.body().string();
            JSONObject object = JSONObject.parseObject(r);
            return object.getString("datas");
        } catch (Exception e) {
            sendMessage.singNotice(RESULT_NOTICE, "转换照片Url失败,原因是!" + e.getMessage(), user.getEmail());
            return null;
        }
    }
    /**
     * 方法描述: 提交表单执行签到
     * @return
     * @author coderOx
     */
    private Boolean submitForm(String session, CpUser user, JSONObject form) {
        try {
            JSONObject extension = new JSONObject();
            extension.put("lon", user.getLon());
            extension.put("lat", user.getLat());
            extension.put("model", "OPPO R11 Plus");
            extension.put("appVersion", "8.1.14");
            extension.put("systemVersion", "8.0");
            extension.put("systemName", "android");
            extension.put("userId", user.getStudentId());
            String uuid = UUID.randomUUID().toString();
            extension.put("deviceId", uuid);
            LogUtils.getLogger().debug(MyUtils.jsonFormat(extension));
            JSONObject data = new JSONObject();
            data.put("lon", user.getLon());
            data.put("lat", user.getLat());
            data.put("model", "OPPO R11 Plus");
            data.put("appVersion", "9.0.12");
            data.put("systemVersion", "8.0");
            data.put("systemName", "android");
            data.put("calVersion", "firstv");
            data.put("userId", user.getStudentId());
            data.put("deviceId", uuid);
            String formatForm = form.toJSONString();
            data.put("bodyString", AesCbc(form.toJSONString()));
            data.put("sign", DesCbc(form.toJSONString()));

            LogUtils.getLogger().debug(formatForm);
            LogUtils.getLogger().debug(MyUtils.jsonFormat(form));
            LogUtils.getLogger().debug(MyUtils.jsonFormat(data));
            Headers headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("Cookie", session)
                    .add("CpdailyStandAlone", "0")
                    .add("extension", "1")
                    .add("Cpdaily-Extension", DesCbc(extension.toJSONString()))
                    .build();
            RequestBody requestBody = RequestBody.create(data.toJSONString(), JSON_TYPE);

            Response response = HttpUtils.sendPost(
                    SUBMIT_URL,
                    requestBody,
                    headers
            );
            if (response.code() != 200) {
                sendMessage.singNotice(RESULT_NOTICE, "提交签到表单失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "提交签到表单");
                return false;
            }
            JSONObject o = JSONObject.parseObject(response.body().string());
            LogUtils.getLogger().debug(o);
            if (o.getString("message").equals("SUCCESS")) {
                if (form.getInteger("type") == 1) {
                    sendMessage.singNotice(user.getName() + "健康签到成功!", "\\\n健康签到成功!", user.getEmail());
                } else if (form.getInteger("type") == 2) {
                    sendMessage.singNotice(user.getName() + "查寝签到成功!", "\\\n查寝签到成功!", user.getEmail());
                }
                return true;
            } else {
                sendMessage.singNotice(RESULT_NOTICE, user.getName() + "签到失败!原因是:" + o.getString("message"), user.getEmail());
                LogUtils.getLogger().info(user.getName() + "签到失败!原因是:" + o.getString("message"));
                return false;
            }
        } catch (Exception e) {
            LogUtils.getLogger().error(user.getName() + "提交签到表单,原因是!" + e.getMessage());
            sendMessage.singNotice(RESULT_NOTICE, user.getName() + "提交签到表单失败,原因是!" + e.getMessage(), user.getEmail());
            return false;
        }
    }

    /**
     * 方法描述: 返回headers 包含了 accept\\\User-agent\\\Authorize
     *
     * @author coderOx
     */
    public Headers getHeaders() {
        return new Headers.Builder()
                .add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
                .add("User-agent", "Mozilla/5.0 (Linux; Android 4.4.4; OPPO R11 Plus Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Safari/537.36 okhttp/3.12.4")
                .add("Authorize", "true")
                .build();
    }

    /**
     * 方法描述: AES加密CBC模式, 秘钥和iv已在方法中写出
     *
     * @param value 需要加密的字符串
     * @return 返回加密后的字符串
     * @author coderOx
     */
    public static String AesCbc(String value) throws Exception {
        String key = "ytUQ7l2ZZu8mLvJZ";
        byte\\\[\\\] a = new byte\\\[\\\]{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7};
        IvParameterSpec iv = new IvParameterSpec(a);
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

        byte\\\[\\\] encrypted = cipher.doFinal(value.getBytes());
        return Base64.encodeBase64String(encrypted);

    }

    /**
     * 方法描述: DES加密cbc模式, 秘钥和iv已在方法中写出
     *
     * @param data 需要加密的字符串
     * @return 返回加密后的字符串
     * @author coderOx
     */
    private static String DesCbc(String data) throws
            InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, UnsupportedEncodingException {
        String key = "b3L26XNL";
        byte\\\[\\\] b = new byte\\\[\\\]{1, 2, 3, 4, 5, 6, 7, 8};
        DESKeySpec dks = new DESKeySpec(key.getBytes(StandardCharsets.UTF_8));

        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        Key secretKey = keyFactory.generateSecret(dks);
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

        AlgorithmParameterSpec paramSpec = new IvParameterSpec(b);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
        byte\\\[\\\] bytes = cipher.doFinal(data.getBytes());

        return new String(Base64.encodeBase64(bytes), StandardCharsets.UTF_8);
    }


}

查寝签到:

package com.nsk666.wx.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.nsk666.wx.mapper.CpMapper;
import com.nsk666.wx.pojo.dao.CpUser;
import com.nsk666.wx.service.SignService;
import com.nsk666.wx.utils.HttpUtils;
import com.nsk666.wx.utils.LogUtils;
import com.nsk666.wx.utils.MyUtils;
import com.nsk666.wx.utils.SendMessage;
import okhttp3.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.util.List;
import java.util.UUID;

/**
 * 类描述: 今日校园服务类
 *
 * @author coderOx
 * @date 2021-11-17
 */
@Service
public class AttendaceSignServiceImpl implements SignService {
    @Autowired
    private CpMapper cpMapper;
    @Autowired
    private SendMessage sendMessage;

    private final String HOST = "https://zjiet.campusphere.net";
    private final String LOGIN_URL = HOST + "/iap/login?service=https%3A%2F%2Fzjiet.campusphere.net%2Fportal%2Flogin";
    private final String DO_LOGIN = HOST + "/iap/doLogin";
    //健康签到
    private final String UNSIGNED\\\_TASK\\\_URL = HOST + "/wec-counselor-sign-apps/stu/sign/getStuSignInfosInOneDay";
    private final String DETAIL\\\_TASK\\\_URL = HOST + "/wec-counselor-sign-apps/stu/sign/detailSignInstance";
    private final String SUBMIT_URL = HOST + "/wec-counselor-sign-apps/stu/sign/submitSign";
    //查寝
    private final String ATT\\\_UNSIGNED\\\_TASK_URL = HOST + "/wec-counselor-attendance-apps/student/attendance/getStuAttendacesInOneDay";
    private final String ATT\\\_DETAIL\\\_TASK_URL = HOST + "/wec-counselor-attendance-apps/student/attendance/detailSignInstance";
    private final String ATT\\\_SUBMIT\\\_URL = HOST+"/wec-counselor-attendance-apps/student/attendance/submitSign";
    private final String RESULT_NOTICE = "今日校园签到错误通知:";
    private final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");
    private final String UPLOAD_POLICY = HOST + "/wec-counselor-attendance-apps/student/attendance/getUploadPolicy";
    private final String PIC_URL = HOST + "/wec-counselor-attendance-apps/student/attendance/previewAttachment";

    //每天早上6点0分1秒执行 1 1 6 * * ?
    //@Scheduled(cron = "1 1 6 * * ?")
    public void healthySignTimer() {
        LogUtils.getLogger().info("开始健康签到");
        //获取所有的签到权限为1或3的用户
//        List cpUsersList = cpMapper.getAllHealthyCpUser();
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("ishealthysign",1).or().eq("ishealthysign",3);
        List cpUsersList = cpMapper.selectList(wrapper);

        LogUtils.getLogger().info(cpUsersList);
        int fla;
        //遍历用户来时签到
        for (CpUser user : cpUsersList) {
            //如果签到失败,再次尝试签到
            fla = 2;
            LogUtils.getLogger().debug(user.getName() + "的签到权限为:" + user.getIsHealthySign());
            while (fla > 0) {
                if (executeHealthySign(user)) {
                    fla = -1;
                } else {
                    fla--;
                    //隔2秒请求一个
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        LogUtils.getLogger().error("隔2秒发送消息失败!");
                        e.printStackTrace();
                    }
                }
            }
            //隔5秒请求一个
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                LogUtils.getLogger().error("隔2秒发送消息失败!");
                e.printStackTrace();
            }
        }
    }

    //每天晚上21点31分执行 30 31 21 * * ?
    @Scheduled(cron = "30 31 21 * * ?")
    public void attendanceSignTimer() {
        LogUtils.getLogger().info("开始查寝签到");
//        List cpUsersList = cpMapper.getAllAttendanceCpUser();
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("ishealthysign",2).or().eq("ishealthysign",3);
        List cpUsersList = cpMapper.selectList(wrapper);

        LogUtils.getLogger().info(cpUsersList);
        int fla;
        for (CpUser user : cpUsersList) {
            fla = 2;
            LogUtils.getLogger().debug(user.getName() + "的签到权限为:" + user.getIsHealthySign());
            while (fla > 0) {
                if (executeAttendanceSign(user)) {
                    fla = -1;
                } else {
                    fla--;
                    //隔2秒再执行一次
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        LogUtils.getLogger().error("隔5秒发送消息失败!");
                        e.printStackTrace();
                    }
                }
            }
            //隔5秒请求一个
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                LogUtils.getLogger().error("隔5秒发送消息失败!");
                e.printStackTrace();
            }
        }
    }

    /**
     * 方法描述: 执行健康签到
     * 如果签到失败,那么失败原因在么个方法中发邮件
     * 签到成功,通知在此方法通知
     *
     * @param user 签到类型,1为健康签到,2为查寝签到,传参数是为了不同时间执行不同的签到
     * @return
     * @author coderOx
     */
    public boolean executeHealthySign(CpUser user) {
        String headers = nskGetCookies(user);
        //如果返回null说明没有获取到,error说明出错
        if (null == headers || headers.equals("error")) {
            return false;
        }
        JSONObject unSignTask = getUnsignTask(headers, user, 1);
        //如果返回null说明没有获取到,如果包含error说明出错,如果包含success说明么有签到任务,
        if (null == unSignTask || unSignTask.getString("error") != null) {
            return false;
        } else if (unSignTask.getInteger("success") != null) {
            //返回true上层函数不再执行第二次
            return true;
        }
        JSONObject detailTask = getDetailTask(user, headers, unSignTask);
        //如果返回null说明没有获取到,如果包含error说明出错
        if (null == detailTask || detailTask.getString("error") != null) {
            return false;
        }
        JSONObject form = fillForm(detailTask, headers, user);
        //如果返回null说明没有获取到,如果包含error说明出错
        if (null == form || form.getString("error") != null) {
            return false;
        }
        //如果失败,失败信息在方法中通知
        return submitForm(headers, user, form);

    }

    /**
     * 方法描述: 执行查寝签到
     * 如果签到失败,那么失败原因在么个方法中发邮件
     * 签到成功,通知在此方法通知
     *
     * @param user
     * @return
     * @author coderOx
     */
    public boolean executeAttendanceSign(CpUser user) {
        String headers = nskGetCookies(user);
        //如果返回null说明没有获取到,error说明出错
        if (null == headers || headers.equals("error")) {
            return false;
        }
        JSONObject unSignTask = getUnsignTask(headers, user, 2);
        //如果返回null说明没有获取到,如果包含error说明出错,如果包含success说明么有签到任务,
        if (null == unSignTask || unSignTask.getString("error") != null) {
            return false;
        } else if (unSignTask.getInteger("success") != null && unSignTask.getInteger("success") == 1) {
            //不再执行第二次
            return true;
        }
        JSONObject detailTask = getDetailTask(user, headers, unSignTask);
        //如果返回null说明没有获取到,如果包含error说明出错
        if (null == detailTask || detailTask.getString("error") != null) {
            return false;
        }
        JSONObject form = fillForm(detailTask, headers, user);
        //如果返回null说明没有获取到,如果包含error说明出错
        if (null == form || form.getString("error") != null) {
            return false;
        }
        //如果失败,失败信息在方法中通知
        return submitForm(headers, user, form);

    }

    /**
     * 方法描述: 获取登录认证cookies
     *
     * @param user 学生信息
     * @return Headers
     * @author coderOx
     */
    private String nskGetCookies(CpUser user) {
        //获取CONVERSATION=iap-1020045845018065-CONV-eba0daa0-cfd2-487d-835e-e45c9527e43a
        //获取lt
        try {
            Headers headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("Referer", "https://zjiet.campusphere.net/portal/index.html")
                    .build();
            Response response = HttpUtils.sendGet(LOGIN_URL, headers, false);
            LogUtils.getLogger().debug(response.headers());
            //response.code() 应该为302
            if (response == null) {
                sendMessage.singNotice(RESULT_NOTICE, user.getName() + "登录获取Cookie失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "登录获取Cookie失败!");
                return null;
            }
            //获取cookies
            String cookie = splitCookies(response.headers().values("Set-Cookie"));
            if (!cookie.contains("CONVERSATION")) {
                sendMessage.singNotice(RESULT_NOTICE, user.getName() + "获取CONVERSATION失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "获取CONVERSATION失败!");
                return null;
            }
            //获取lt
            String lt = response.header("Location");
            if (null == lt || (lt = lt.split("=")\\\[1\\\]) == null) {
                sendMessage.singNotice(RESULT_NOTICE, user.getName() + "获取lt:Location失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "获取lt:Location失败!");
                return null;
            }
            //不使用response.body().string()需要手动关掉
            response.close();
            //登陆获取
            RequestBody requestBody = new FormBody.Builder()
                    .add("username", user.getStudentId())
                    .add("password", user.getPassword())
                    .add("lt", lt)
                    .build();
            LogUtils.getLogger().debug(user.getStudentId() + user.getPassword() + lt);
            headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("Cookie", cookie)
                    .build();
            response = HttpUtils.sendPost(DO_LOGIN, requestBody, headers);
            String finalUrl;
            if (null == response || null == (finalUrl = response.header("Location"))) {
                LogUtils.getLogger().debug(response.headers());
                sendMessage.singNotice(RESULT_NOTICE, user.getName() + "登录获取CAS令牌失败,请在公众号检查账号密码是否正确!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "登录获取CAS令牌失败!");
                //登录失败。不再次登录
                return "error";
            }
            //不使用response.body().string()需要手动关掉
            response.close();
            requestBody = new FormBody.Builder()
                    .build();
            //获取MOD\\\_AUTH\\\_CAS
            response = HttpUtils.sendPost(finalUrl, requestBody, headers);

            String MOD\\\_AUTH\\\_CAS;
            if (null == response || (MOD\\\_AUTH\\\_CAS = response.headers().get("Set-Cookie")) == null) {
                sendMessage.singNotice(RESULT\\\_NOTICE, "登录获取MOD\\\_AUTH_CAS失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "登录MOD\\\_AUTH\\\_CAS失败!");
                return null;
            }
            response.close();
            return MOD\\\_AUTH\\\_CAS;
        } catch (Exception e) {
            sendMessage.singNotice(RESULT\\\_NOTICE, "登录获取MOD\\\_AUTH_CAS失败!", user.getEmail());
            return "error";
        }
    }

    /**
     * 方法描述: 把获取的Set-Cookies 放到一个字符串里
     *
     * @param list cookies列表
     * @return String
     * @author coderOx
     */
    private String splitCookies(List list) {
        StringBuilder cookie = new StringBuilder();
        for (String s : list) {
            cookie.append(s).append(";");
        }
        return cookie.toString();
    }


    /**
     * 方法描述: 获取未签到信息
     *
     * @param session            包含登录的cookies
     * @param getUnsigedTaskType 1 代表健康签到 2 代表 查寝签到
     * @return
     * @author coderOx
     */
    private JSONObject getUnsignTask(String session, CpUser user, int getUnsigedTaskType) {
        JSONObject jsonObject = new JSONObject();
        try {
            String s = JSONObject.toJSONString(jsonObject);
            RequestBody requestBody = RequestBody.create(s, JSON_TYPE);
            Headers headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("content-type", "application/json;charset=UTF-8'")
                    .add("Cookie", session)
                    .build();
            //请求签到信息
            Response response = HttpUtils.sendPost(
                    ATT\\\_UNSIGNED\\\_TASK_URL,
                    requestBody,
                    headers
            );
            if (null == response || response.code() != 200) {
                sendMessage.singNotice(RESULT_NOTICE, "请求签到任务失败!!", user.getEmail());
                return null;
            }
            JSONArray jsonArray;
            jsonObject = JSONObject.parseObject(response.body().string());
            LogUtils.getLogger().debug(MyUtils.jsonFormat(jsonObject));
            //获取成功
            if (jsonObject.getString("code").equals("0")) {
                //获取data
                jsonObject = jsonObject.getJSONObject("datas");
                jsonArray = new JSONArray(jsonObject.getJSONArray("unSignedTasks"));
                //判断是否有未签到信息
                if (jsonArray.isEmpty()) {
                    LogUtils.getLogger().info(user.getName() + "当前没有签到任务");
                    sendMessage.singNotice(RESULT_NOTICE, "当前没有未签到任务!", user.getEmail());
                    //为了让这个用户不在签到第二次
                    jsonObject.put("success", 1);
                    return jsonObject;
                }
                if (getUnsigedTaskType == 1) {
                    JSONObject temp = null;
                    for (Object o : jsonArray) {
                        jsonObject = (JSONObject) o;
                        if (jsonObject.getString("taskName").contains("健")) {
                            temp = new JSONObject();
                            //层层往下穿1为了最后打卡成功的通知
                            temp.put("type", 1);
                            temp.put("signInstanceWid", jsonObject.getString("signInstanceWid"));
                            temp.put("signWid", jsonObject.getString("signWid"));
                        }
                    }
                    if (null == temp) {
                        sendMessage.singNotice(RESULT_NOTICE, user.getName() + "当前没有健康签到任务!", user.getEmail());
                        LogUtils.getLogger().info(user.getName() + "当前没有健康签到任务");
                        jsonObject.put("success", 1);
                        return jsonObject;
                    }
                    return temp;

                } else if (getUnsigedTaskType == 2) {
                    JSONObject temp = null;
                    for (Object o : jsonArray) {
                        jsonObject = (JSONObject) o;
                        if (jsonObject.getString("taskName").contains("寝")) {
                            temp = new JSONObject();
                            //层层往下穿2为了最后打卡成功的通知
                            temp.put("type", 2);
                            temp.put("signInstanceWid", jsonObject.getString("signInstanceWid"));
                            temp.put("signWid", jsonObject.getString("signWid"));
                        }
                    }
                    if (null == temp) {
                        sendMessage.singNotice(RESULT_NOTICE, user.getName() + "当前没有查寝签到任务!", user.getEmail());
                        LogUtils.getLogger().info(user.getName() + "当前没有查寝签到任务");
                        jsonObject.put("success", 1);
                        return jsonObject;
                    }
                    return temp;
                } else {
                    //既没有查寝签到也没有健康签到
                    sendMessage.singNotice(RESULT_NOTICE, user.getName() + "当前没有任何任务!", user.getEmail());
                    LogUtils.getLogger().info(user.getName() + "当前没有任何任务!");
                    jsonObject.put("success", 1);
                    return jsonObject;
                }
            } else {
                sendMessage.singNotice(RESULT_NOTICE, "签到任务查询失败!!", user.getEmail());
                //返回null执行第二次
                return null;
            }
        } catch (Exception e) {
            sendMessage.singNotice(RESULT_NOTICE, "获取任务查询失败,原因:" + e.getMessage(), user.getEmail());
            //返回error执行第二次
            jsonObject.put("error", "error");
            return jsonObject;
        }
    }
    /**
     * 方法描述: 获取签到详细信息
     * @return
     * @author coderOx
     */
    private JSONObject getDetailTask(CpUser user, String session, JSONObject unSignTask) {
        JSONObject jsonObject;
        try {
            LogUtils.getLogger().debug(MyUtils.jsonFormat(unSignTask));
            RequestBody requestBody = RequestBody.create(unSignTask.toJSONString(), JSON_TYPE);
            Headers headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("content-type", "application/json;charset=UTF-8'")
                    .add("Cookie", session)
                    .build();
            //请求签到信息
            Response response = HttpUtils.sendPost(
                    ATT\\\_DETAIL\\\_TASK_URL,
                    requestBody,
                    headers
            );

            if (null == response || response.code() != 200) {
                sendMessage.singNotice(RESULT_NOTICE, "请求签到详情失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "请求签到详情失败!");
                //返回null,请求第二次
                return null;
            } else {
                jsonObject = JSONObject.parseObject(response.body().string());
                if (!jsonObject.getString("code").equals("0")) {
                    sendMessage.singNotice(RESULT_NOTICE, "获取签到详情失败!", user.getEmail());
                    LogUtils.getLogger().info(user.getName() + "获取签到详情失败!");
                    //返回null,请求第二次
                    return null;
                }
                LogUtils.getLogger().debug(MyUtils.jsonFormat(jsonObject));
                jsonObject = jsonObject.getJSONObject("datas");
                //添加类型方便下层函数知道是健康还是查寝签到
                jsonObject.put("type", unSignTask.getInteger("type"));
                return jsonObject;
            }
        } catch (Exception e) {
            sendMessage.singNotice(RESULT_NOTICE, "获取签到信息详情失败!原因是:" + e.getMessage(), user.getEmail());
            jsonObject = new JSONObject();
            //失败,请求第二次
            jsonObject.put("error", "error");
            return jsonObject;
        }

    }
    /**
     * 方法描述: 填写表单
     * @return
     * @author coderOx
     */
    private JSONObject fillForm(JSONObject detailTask, String session, CpUser user) {
        if (detailTask == null) {
            return null;
        }
        JSONObject submitForm = new JSONObject();
        submitForm.put("type", detailTask.getInteger("type"));
        try {
            JSONArray jsonArray;
            submitForm.put("signInstanceWid", detailTask.getString("signInstanceWid"));
            submitForm.put("longitude", user.getLon());
            submitForm.put("latitude", user.getLat());
            submitForm.put("isMalposition", detailTask.getString("isMalposition"));
            submitForm.put("abnormalReason", user.getAbnormalReason());
            submitForm.put("position", user.getAddress());
            submitForm.put("qrUuid", "");
            submitForm.put("uaIsCpadaily",true);
            //判断是否需要上传照片
            if (detailTask.getInteger("isPhoto") == 1) {
                String fileUrl = uploadPicture(user, session);
                if (fileUrl == null)
                    //失败请求第二次
                    return null;
                fileUrl = getPictureUrl(fileUrl, session, user);
                if (fileUrl == null)
                    //失败请求第二次
                    return null;
                submitForm.put("signPhotoUrl", fileUrl);
            } else {
                submitForm.put("signPhotoUrl", "");
            }
            //判断签到的时候是否需要额外的选项信息

//            if (detailTask.getInteger("isNeedExtra") == 1) {
//
//                jsonArray = detailTask.getJSONObject("signedStuInfo").getJSONArray("extraFieldItemVos");
//                JSONArray arrayTemp = new JSONArray();
//                //判断是否为空
//                if (jsonArray.size() == 0) {
//                    LogUtils.getLogger().debug(user.getName() + "的默认签到信息为空!");
//                    sendMessage.singNotice(RESULT_NOTICE, "签到失败!没有上次app打卡记录,获取内容为空", user.getEmail());
//                    return null;
//                } else {
//                    //额外信息填写需要字段
//                /*
//                  \\\[
//                 {'extraFieldItemValue': '绿色', 'extraFieldItemWid': 1316811},
//                 {'extraFieldItemValue': '37.2℃及以下', 'extraFieldItemWid': 1316816},
//                 {'extraFieldItemValue': '否', 'extraFieldItemWid': 1316819},
//                 {'extraFieldItemValue': '否', 'extraFieldItemWid': 1316820}\\\]
//                 */
//                    JSONObject object;
//                    for (Object o : jsonArray) {
//                        object = (JSONObject) o;
//                        JSONObject t = new JSONObject();
//                        LogUtils.getLogger().debug(object);
//                        t.put("extraFieldItemValue", object.getString("extraFieldItem"));
//                        t.put("extraFieldItemWid", object.getString("extraFieldItemWid"));
//                        arrayTemp.add(t);
//                    }
//                }
//                LogUtils.getLogger().debug(arrayTemp);
//                submitForm.put("isMalposition", 0);
//                submitForm.put("extraFieldItems", arrayTemp);
//                submitForm.put("uaIsCpadaily", true);
//                submitForm.put("isNeedExtra", detailTask.getInteger("isNeedExtra"));
//            }
            LogUtils.getLogger().debug(MyUtils.jsonFormat(submitForm));
            return submitForm;
        } catch (Exception e) {
            sendMessage.singNotice(RESULT_NOTICE, "填写表单失败!", user.getEmail());
            //失败请求第二次
            submitForm.put("error", "error");
            return submitForm;
        }
    }

    /**
     * 方法描述:  上传图片到今日校园的阿里服务器
     *
     * @param session
     * @param user
     * @return
     * @author coderOx
     */
    public String uploadPicture(CpUser user, String session) {
        try {
            JSONObject o = new JSONObject();
            o.put("fileType",1);
            RequestBody requestBody = RequestBody.create(JSONObject.toJSONString(o), JSON_TYPE);
            Headers headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("Content-Type", "application/json")
                    .add("Cookie", session)
                    .build();
            Response response = HttpUtils.sendPost(
                    UPLOAD_POLICY,
                    requestBody,
                    headers);
            JSONObject result;
            o = new JSONObject();
            if (response.code() != 200) {
                sendMessage.singNotice(RESULT_NOTICE, "上传照片URL请求失败!", user.getEmail());
                LogUtils.getLogger().info(user.getName() + "上传照片URL请求失败");
                return null;
            }
            result = JSONObject.parseObject(response.body().string());
            LogUtils.getLogger().debug(result);
            result = result.getJSONObject("datas");
            LogUtils.getLogger().debug(MyUtils.jsonFormat(result));

            ClassPathResource classPathResource = new ClassPathResource("static/default.png");
            InputStream inputStream = classPathResource.getInputStream();
            File file = new File("default.png");
            FileUtils.copyInputStreamToFile(inputStream, file);
//            RequestBody r = RequestBody.create(file, MediaType.parse("multipart/form-data"));
//            //获取信息之后再此提交,获取真正的url
//            RequestBody fileBody = new MultipartBody.Builder()
//                    .setType(MultipartBody.FORM)
//                    .addFormDataPart("key", result.getString("fileName") + ".png")
//                    .addFormDataPart("policy", result.getString("policy"))
//                    .addFormDataPart("OSSAccessKeyId", result.getString("accessid"))
//                    .addFormDataPart("success\\\_action\\\_status", "200")
//                    .addFormDataPart("signature", result.getString("signature"))
//                    .addFormDataPart("file", file.getName(), r)
//
//                    .build();
//            response = HttpUtils.sendPost(
//                    result.getString("host"),
//                    fileBody,
//                    getHeaders()
//            );
//            if (response.code() != 200) {
//                sendMessage.singNotice(RESULT_NOTICE, "上传照片请求失败!", user.getEmail());
//                LogUtils.getLogger().info(user.getName() + "上传照片请求失败");
//                return null;
//            }
//            LogUtils.getLogger().debug(result.getString("fileName") + ".png");
            return result.getString("fileName") + ".png";
        } catch (IOException e) {
            LogUtils.getLogger().error(user.getName() + "上传照片失败,原因是!" + e.getMessage());
            sendMessage.singNotice(RESULT_NOTICE, user.getName() + "上传照片失败,原因是!" + e.getMessage(), user.getEmail());
            return null;
        }
    }

    /**
     * 方法描述: 获取照片的url
     *
     * @author coderOx
     */
    private String getPictureUrl(String fileUrl, String session, CpUser user) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("ossKey", fileUrl);
            RequestBody requestBody = RequestBody.create(JSONObject.toJSONString(jsonObject), JSON_TYPE);
            Headers headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("Cookie", session)
                    .build();
            Response response = HttpUtils.sendPost(PIC_URL, requestBody, headers);
            if (response.code() != 200) {
                sendMessage.singNotice(RESULT_NOTICE, user.getName() + "转换照片URL请求失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "转换照片URL请求失败");
                return null;
            }
            String r = response.body().string();
            JSONObject object = JSONObject.parseObject(r);
            return object.getString("datas");
        } catch (Exception e) {
            sendMessage.singNotice(RESULT_NOTICE, "转换照片Url失败,原因是!" + e.getMessage(), user.getEmail());
            return null;
        }
    }
    /**
     * 方法描述: 提交表单执行签到
     * @return
     * @author coderOx
     */
    private Boolean submitForm(String session, CpUser user, JSONObject form) {
        try {
            JSONObject extension = new JSONObject();
            extension.put("lon", user.getLon());
            extension.put("lat", user.getLat());
            extension.put("model", "OPPO R11 Plus");
            extension.put("appVersion", "8.1.14");
            extension.put("systemVersion", "8.0");
            extension.put("systemName", "android");
            extension.put("userId", user.getStudentId());
            String uuid = UUID.randomUUID().toString();
            extension.put("deviceId", uuid);
            LogUtils.getLogger().debug(MyUtils.jsonFormat(extension));
            JSONObject data = new JSONObject();
            data.put("lon", user.getLon());
            data.put("lat", user.getLat());
            data.put("model", "OPPO R11 Plus");
            data.put("appVersion", "9.0.12");
            data.put("systemVersion", "8.0");
            data.put("systemName", "android");
            data.put("calVersion", "firstv");
            data.put("userId", user.getStudentId());
            data.put("deviceId", uuid);
            String formatForm = form.toJSONString();
            data.put("bodyString", AesCbc(form.toJSONString()));
            data.put("sign", DesCbc(form.toJSONString()));

            LogUtils.getLogger().debug(formatForm);
            LogUtils.getLogger().debug(MyUtils.jsonFormat(form));
            LogUtils.getLogger().debug(MyUtils.jsonFormat(data));
            Headers headers = new Headers.Builder()
                    .addAll(getHeaders())
                    .add("Cookie", session)
                    .add("CpdailyStandAlone", "0")
                    .add("extension", "1")
                    .add("Cpdaily-Extension", DesCbc(extension.toJSONString()))
                    .build();
            RequestBody requestBody = RequestBody.create(data.toJSONString(), JSON_TYPE);

            Response response = HttpUtils.sendPost(
                    ATT\\\_SUBMIT\\\_URL,
                    requestBody,
                    headers
            );
            if (response.code() != 200) {
                sendMessage.singNotice(RESULT_NOTICE, "提交签到表单失败!", user.getEmail());
                LogUtils.getLogger().error(user.getName() + "提交签到表单");
                return false;
            }
            JSONObject o = JSONObject.parseObject(response.body().string());
            LogUtils.getLogger().debug(o);
            if (o.getString("message").equals("SUCCESS")) {
                if (form.getInteger("type") == 1) {
                    sendMessage.singNotice(user.getName() + "健康签到成功!", "\\\n健康签到成功!", user.getEmail());
                } else if (form.getInteger("type") == 2) {
                    sendMessage.singNotice(user.getName() + "查寝签到成功!", "\\\n查寝签到成功!", user.getEmail());
                }
                return true;
            } else {
                sendMessage.singNotice(RESULT_NOTICE, user.getName() + "签到失败!原因是:" + o.getString("message"), user.getEmail());
                LogUtils.getLogger().info(user.getName() + "签到失败!原因是:" + o.getString("message"));
                return false;
            }
        } catch (Exception e) {
            LogUtils.getLogger().error(user.getName() + "提交签到表单,原因是!" + e.getMessage());
            sendMessage.singNotice(RESULT_NOTICE, user.getName() + "提交签到表单失败,原因是!" + e.getMessage(), user.getEmail());
            return false;
        }
    }

    /**
     * 方法描述: 返回headers 包含了 accept\\\User-agent\\\Authorize
     *
     * @author coderOx
     */
    public Headers getHeaders() {
        return new Headers.Builder()
                .add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
                .add("User-agent", "Mozilla/5.0 (Linux; Android 4.4.4; OPPO R11 Plus Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Safari/537.36 okhttp/3.12.4")
                .add("Authorize", "true")
                .build();
    }

    /**
     * 方法描述: AES加密CBC模式, 秘钥和iv已在方法中写出
     *
     * @param value 需要加密的字符串
     * @return 返回加密后的字符串
     * @author coderOx
     */
    public static String AesCbc(String value) throws Exception {
        String key = "ytUQ7l2ZZu8mLvJZ";
        byte\\\[\\\] a = new byte\\\[\\\]{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7};
        IvParameterSpec iv = new IvParameterSpec(a);
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

        byte\\\[\\\] encrypted = cipher.doFinal(value.getBytes());
        return Base64.encodeBase64String(encrypted);

    }

    /**
     * 方法描述: DES加密cbc模式, 秘钥和iv已在方法中写出
     *
     * @param data 需要加密的字符串
     * @return 返回加密后的字符串
     * @author coderOx
     */
    private static String DesCbc(String data) throws
            InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, UnsupportedEncodingException {
        String key = "b3L26XNL";
        byte\\\[\\\] b = new byte\\\[\\\]{1, 2, 3, 4, 5, 6, 7, 8};
        DESKeySpec dks = new DESKeySpec(key.getBytes(StandardCharsets.UTF_8));

        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        Key secretKey = keyFactory.generateSecret(dks);
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

        AlgorithmParameterSpec paramSpec = new IvParameterSpec(b);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
        byte\\\[\\\] bytes = cipher.doFinal(data.getBytes());

        return new String(Base64.encodeBase64(bytes), StandardCharsets.UTF_8);
    }


}

测试类:

package com.nsk666.wx;
import com.nsk666.wx.service.CpService;
import com.nsk666.wx.utils.MyUtils;
import lombok.extern.java.Log;
import org.apache.commons.codec.binary.Base64;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.nsk666.wx.mapper.CpMapper;
import com.nsk666.wx.utils.HttpUtils;
import com.nsk666.wx.utils.LogUtils;
import com.nsk666.wx.utils.SendEmail;
import lombok.Data;
import okhttp3.*;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpHeaders;
import org.springframework.util.DigestUtils;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.util.*;

@SpringBootTest
public class CpdailyTest {
    @Autowired
    private CpMapper cpMapper;
    @Autowired
    private SendEmail email;
    @Autowired
    CpService cpService;
    public Headers getHeaders() {
        Headers headers = new Headers.Builder()
                .add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
                .add("User-agent", "Mozilla/5.0 (Linux; Android 4.4.4; OPPO R11 Plus Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Safari/537.36 okhttp/3.12.4")
                .add("Authorize", "true")
                .build();

        return headers;
    }

    @Test
    public void execute() throws Exception { 
        WxUserTest user = new WxUserTest();
        user.setStudentId("xxxx");
        user.setPassword("xxxx");
        for (int i = 0; i < 1; i++) {
            String headers = nskGetCookies(user);
            JSONObject unSignTask = getUnsignTask(headers, user, 1);
            JSONObject detailTask = getDetailTask(user, headers, unSignTask);
            JSONObject form = fillForm(detailTask, headers, user);
            Boolean ok = submitForm(headers, user, form);
        }
    }

    private final String HOST = "https://zjiet.campusphere.net";
    private final String LOGIN_URL = HOST + "/iap/login?service=https%3A%2F%2Fzjiet.campusphere.net%2Fportal%2Flogin";
    private final String DO_LOGIN = HOST + "/iap/doLogin";
    //健康签到
    private final String UNSIGNED\\\_TASK\\\_URL = HOST + "/wec-counselor-sign-apps/stu/sign/getStuSignInfosInOneDay";
    private final String DETAIL\\\_TASK\\\_URL = HOST + "/wec-counselor-sign-apps/stu/sign/detailSignInstance";
    private final String SUBMIT_URL = HOST+"/wec-counselor-sign-apps/stu/sign/submitSign";
    //查寝
    private final String ATT\\\_UNSIGNED\\\_TASK_URL = HOST + "/wec-counselor-attendance-apps/student/attendance/getStuAttendacesInOneDay";
    private final String ATT\\\_DETAIL\\\_TASK_URL = HOST + "/wec-counselor-attendance-apps/student/attendance/detailSignInstance";
    private final String ATT\\\_SUBMIT\\\_URL = HOST+"/wec-counselor-attendance-apps/student/attendance/submitSign";
    private final String HEALTHY\\\_RESULT\\\_NOTICE = "健康签到结果通知:";
    private final String EMAIL_SUFFIX = "@qq.com";
    private final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");
    private final String UPLOAD_POLICY = HOST + "/wec-counselor-attendance-apps/student/attendance/getUploadPolicy";
    private final String PIC_URL = HOST + "/wec-counselor-attendance-apps/student/attendance/previewAttachment";
    private final String ATTENDANCE_URL="https://zjiet.campusphere.net/wec-counselor-attendance-apps/student/attendance/getStuAttendacesInOneDay";
    /**
     * 方法描述: 获取登录认证cookies
     *
     * @param user 学生信息
     * @return Headers
     * @author coderOx
     */
    private String nskGetCookies(WxUserTest user) throws IOException {
        JSONObject object = new JSONObject();
        //获取CONVERSATION=iap-1020045845018065-CONV-eba0daa0-cfd2-487d-835e-e45c9527e43a
        //获取lt
        Headers headers = new Headers.Builder()
                .addAll(getHeaders())
                .add("Referer", "https://zjiet.campusphere.net/portal/index.html")
                .build();
        Response response = HttpUtils.sendGet(LOGIN_URL, headers, false);
        LogUtils.getLogger().debug(response);
        LogUtils.getLogger().debug(response.headers());
        //获取cookies
        String cookie = splitCookies(response.headers().values("Set-Cookie"));
        if (!cookie.contains("CONVERSATION")) {
            LogUtils.getLogger(user.getName() + "获取cookies失败!").error(user.getName() + "获取cookies失败!");
            return null;
        }
        //获取lt
        String lt = response.header("Location");
        if (null == lt) {
            LogUtils.getLogger(user.getName() + "获取lt失败!").error(user.getName() + "获取lt失败!");
            return null;
        }
        lt = lt.split("=")\\\[1\\\];

        //登陆获取
        RequestBody requestBody = new FormBody.Builder()
                .add("username", user.getStudentId())
                .add("password", user.getPassword())
                .add("lt", lt)
                .build();
        headers = new Headers.Builder()
                .addAll(getHeaders())
                .add("Cookie", cookie)
                .build();
        response = HttpUtils.sendPost(DO_LOGIN, requestBody, headers);

        String finalUrl = response.header("Location");
        if (null == finalUrl) {
            LogUtils.getLogger(user.getName() + "获取Location失败!").error(user.getName() + "获取Location失败!");
            return null;
        }

        requestBody = new FormBody.Builder()
                .build();
        //获取MOD\\\_AUTH\\\_CAS
        response = HttpUtils.sendPost(finalUrl, requestBody, headers);
        LogUtils.getLogger().debug(response.headers().get("Set-Cookie"));
        System.out.println(response.headers().get("Set-Cookie"));
        return response.headers().get("Set-Cookie");
    }

    /**
     * 方法描述: 把获取的Set-Cookies 放到一个字符串里
     *
     * @param list cookies列表
     * @return String
     * @author coderOx
     */
    private String splitCookies(List list) {
        StringBuilder cookie = new StringBuilder();
        for (String s : list) {
            cookie.append(s).append(";");
        }
        return cookie.toString();
    }

    /**
     * 方法描述: 获取未签到信息
     *
     * @param session            包含登录的cookies
     * @param getUnsigedTaskType 1 代表健康签到 2 代表 查寝签到
     * @return
     * @author coderOx
     */
    private JSONObject getUnsignTask(String session, WxUserTest user, int getUnsigedTaskType) throws IOException, InterruptedException {

        JSONObject jsonObject = new JSONObject();
        String s = JSONObject.toJSONString(jsonObject);
        RequestBody requestBody = RequestBody.create(s, JSON_TYPE);
        Headers headers = new Headers.Builder()
                .addAll(getHeaders())
                .add("content-type", "application/json;charset=UTF-8'")
                .add("Cookie", session)
                .build();
        //请求签到信息
        Response response = HttpUtils.sendPost(
                UNSIGNED\\\_TASK\\\_URL,
                requestBody,
                headers
        );
        JSONArray jsonArray;
        if (response.code() == 200) {
            jsonObject = JSONObject.parseObject(response.body().string());
           LogUtils.getLogger().debug(jsonObject);
        }
        else return null;
        LogUtils.getLogger().debug(MyUtils.jsonFormat(jsonObject));
        //获取成功
        /** 结果
         {
         "code":"0",
         "datas":{
         "codeRcvdTasks":\\\[\\\],
         "unSignedTasks":\\\[
         {
         "rateSignDate":"2021-11-20 (周六)",
         "rateTaskBeginTime":"06:00",
         "isLeave":"0",
         "signStatus":"2",
         "signWid":"1047638",
         "senderUserName":"信息技术学院(王昌建)",
         "isMalposition":"0",
         "signRate":"1",
         "currentTime":"2021-11-20 10:45",
         "taskType":"4",
         "signInstanceWid":"177923",
         "rateTaskEndTime":"23:59",
         "taskName":"2021:学生每日健康打卡(详情见签到说明)",
         "stuSignWid":"10715381"
         },
         {
         "rateSignDate":"2021-11-20 (周六)",
         "rateTaskBeginTime":"21:30",
         "isLeave":"0",
         "signStatus":"2",
         "signWid":"614422",
         "senderUserName":"信息技术系(黄来浩)",
         "isMalposition":"0",
         "signRate":"1",
         "currentTime":"2021-11-20 10:45",
         "taskType":"4",
         "signInstanceWid":"177663",
         "rateTaskEndTime":"22:30",
         "taskName":"信息系计算机201(本)查寝",
         "stuSignWid":"10700499"
         }
         \\\],
         "leaveTasks":\\\[\\\],
         "dayInMonth":"2021-11-20",
         "signedTasks":\\\[\\\]
         },
         "message":"SUCCESS"
         }
         **/
        if (jsonObject.getString("code").equals("0")) {
            //获取data
            jsonObject = jsonObject.getJSONObject("datas");
            jsonArray = new JSONArray(jsonObject.getJSONArray("signedTasks"));
            //判断是否有未签到信息
            if (jsonArray.isEmpty()) {
                LogUtils.getLogger().debug(user.getName() + "当前没有签到任务");
                email.sendEmail(HEALTHY\\\_RESULT\\\_NOTICE, "当前没有未签到任务!", user.getQq() + EMAIL_SUFFIX);
                return null;
            }
            if (getUnsigedTaskType == 1) {
                JSONObject temp = null;
                for (Object o : jsonArray) {
                    jsonObject = (JSONObject) o;
                    if (jsonObject.getString("taskName").contains("健康")) {
                        temp = new JSONObject();
                        temp.put("signInstanceWid", jsonObject.getString("signInstanceWid"));
                        temp.put("signWid", jsonObject.getString("signWid"));
                    }
                }
                if (null == temp) {
                    email.sendEmail(HEALTHY\\\_RESULT\\\_NOTICE, "当前没有健康签到任务!", user.getQq() + EMAIL_SUFFIX);
                    return null;
                } else {
                    return temp;
                }
            } else if (getUnsigedTaskType == 2) {
                JSONObject temp = null;
                for (Object o : jsonArray) {
                    jsonObject = (JSONObject) o;
                    if (jsonObject.getString("taskName").contains("寝")) {
                        temp = new JSONObject();
                        temp.put("signInstanceWid", jsonObject.getString("signInstanceWid"));
                        temp.put("signWid", jsonObject.getString("signWid"));
                    }
                }
                if (null == temp) {
                    email.sendEmail(HEALTHY\\\_RESULT\\\_NOTICE, "当前没有查寝签到任务!", user.getQq() + EMAIL_SUFFIX);
                    return null;
                } else
                    LogUtils.getLogger().debug(temp);
                return temp;
            }
        } else {
            email.sendEmail(HEALTHY\\\_RESULT\\\_NOTICE, "签到任务查询失败!!", user.getQq() + EMAIL_SUFFIX);
            return null;
        }
        return null;
    }


    private JSONObject getDetailTask(WxUserTest user, String session, JSONObject unSignTask) throws IOException {
        if (unSignTask == null) {
            return null;
        }
        JSONObject jsonObject ;
        LogUtils.getLogger().debug(MyUtils.jsonFormat(unSignTask));
        RequestBody requestBody = RequestBody.create(unSignTask.toJSONString(), JSON_TYPE);
        Headers headers = new Headers.Builder()
                .addAll(getHeaders())
                .add("content-type", "application/json;charset=UTF-8'")
                .add("Cookie", session)
                .build();
        //请求签到信息
        Response response = HttpUtils.sendPost(
                DETAIL\\\_TASK\\\_URL,
                requestBody,
                headers
        );
        LogUtils.getLogger().debug(response.body());
        if (response.code() != 200) {
            email.sendEmail(HEALTHY\\\_RESULT\\\_NOTICE, "请求签到详情失败!", user.getQq() + EMAIL_SUFFIX);
            LogUtils.getLogger().debug("请求签到详情失败!");
            return null;
        } else {
            jsonObject = JSONObject.parseObject(response.body().string());
            if (!jsonObject.getString("code").equals("0")) {
                email.sendEmail(HEALTHY\\\_RESULT\\\_NOTICE, "获取签到详情失败!", user.getQq() + EMAIL_SUFFIX);
                LogUtils.getLogger().debug("获取签到详情失败!");
                return null;
            }
            LogUtils.getLogger().debug(MyUtils.jsonFormat(jsonObject));
            return jsonObject.getJSONObject("datas");
        }
         
    }

    private JSONObject fillForm(JSONObject detailTask, String session, WxUserTest user) throws IOException {
        LogUtils.getLogger().debug(MyUtils.jsonFormat(detailTask));
        if (detailTask == null) {
            return null;
        }
        JSONArray jsonArray;
        JSONObject submitForm = new JSONObject();
        submitForm.put("signInstanceWid", detailTask.getString("signInstanceWid"));
        submitForm.put("longitude", user.getLon());
        submitForm.put("latitude", user.getLat());
        submitForm.put("isMalposition", detailTask.getString("isMalposition"));
        submitForm.put("abnormalReason", user.getAbnormalReason());
        submitForm.put("position", user.getAddress());
        submitForm.put("qrUuid", "");
        submitForm.put("uaIsCpadaily",true);
        //判断是否需要上传照片
        if (detailTask.getInteger("isPhoto") == 1) {
            String fileUrl = uploadPicture(user, session);
            if (fileUrl == null) return null;
            fileUrl = getPictureUrl(fileUrl,session);
            if (fileUrl == null) return null;
            submitForm.put("signPhotoUrl", fileUrl);
        } else {
            submitForm.put("signPhotoUrl", "");
        }
        //判断签到的时候是否需要额外的选项信息
        /**  额外的问题格式
         "extraField":\\\[
         {
         "extraFieldItems":\\\[
         {"isAbnormal":false,"isOtherItems":0,"wid":1316811,"isSelected":true,"value":"绿色","content":"绿色" },
         {"isAbnormal":true,"isOtherItems":0,"wid":1316812,"content":"黄色"},
         {"isAbnormal":true,"isOtherItems":0,"wid":1316813,"content":"红色"},
         {"isAbnormal":true,"isOtherItems":0,"wid":1316814,"content":"橙色"},
         {"isAbnormal":false,"isOtherItems":1,"wid":1316815,"content":"其它"}
         \\\],
         "wid":585887,
         "description":"说明:以杭州健康码为准。",
         "title":"题目一:当日杭州健康码颜色(绿、黄、红、橙)",
         "hasOtherItems":1
         },
         {
         "extraFieldItems":\\\[
         {"isAbnormal":false,"isOtherItems":0, "wid":1316816,"isSelected":true,"value":"37.2℃及以下","content":"37.2℃及以下" },
         {"isAbnormal":false,"isOtherItems":0,"wid":1316817,"content":"37.3℃及以上(体温异常,请及时到当地医院就诊排查)"
         }
         \\\],
         "wid":585888,
         "description":"",
         "title":"题目二:当日体温情况",
         "hasOtherItems":0
         },
         .....
         \\\],
         */

        if (detailTask.getInteger("isNeedExtra") == 1) {
             /* extraFieldItemVos **自动获取上次手机打卡选项
                "extraFieldItemVos":\\\[
            {
               "fieldIndex":0,
               "extraFieldItem":"绿色",
               "isAbnormal":"0",
               "extraFieldItemWid":"1316811",
               "isExtraFieldOtherItem":"0",
               "extraTitle":"题目一:当日杭州健康码颜色(绿、黄、红、橙)",
               "extraDesc":"说明:以杭州健康码为准。"
            },{}\\\]
               */
            jsonArray = detailTask.getJSONObject("signedStuInfo").getJSONArray("extraFieldItemVos");
            JSONArray arrayTemp = new JSONArray();
            //判断是否为空
            if (jsonArray.size() == 0) {
                LogUtils.getLogger().debug(user.getName() + "的默认签到信息为空!");
                email.sendEmail(HEALTHY\\\_RESULT\\\_NOTICE, "签到失败!没有上次app打卡记录,获取内容为空", user.getQq() + EMAIL_SUFFIX);
                return null;
            } else {
                //额外信息填写需要字段
                /*
                  \\\[
                 {'extraFieldItemValue': '绿色', 'extraFieldItemWid': 1316811},
                 {'extraFieldItemValue': '37.2℃及以下', 'extraFieldItemWid': 1316816},
                 {'extraFieldItemValue': '否', 'extraFieldItemWid': 1316819},
                 {'extraFieldItemValue': '否', 'extraFieldItemWid': 1316820}\\\]
                 */
                JSONObject object;
                for (Object o : jsonArray) {
                    object = (JSONObject) o;
                    JSONObject t = new JSONObject();
                    LogUtils.getLogger().debug(object);
                    t.put("extraFieldItemValue", object.getString("extraFieldItem"));
                    t.put("extraFieldItemWid", object.getString("extraFieldItemWid"));
                    arrayTemp.add(t);
                }
            }
            LogUtils.getLogger().debug(arrayTemp);
            submitForm.put("isMalposition",0);
            submitForm.put("extraFieldItems", arrayTemp);
            submitForm.put("uaIsCpadaily", true);
            submitForm.put("isNeedExtra", detailTask.getInteger("isNeedExtra"));
        }

        LogUtils.getLogger().debug(MyUtils.jsonFormat(submitForm));
        return submitForm;
    }


    /**
     * 方法描述:  上传图片到今日校园的阿里服务器
     * @param
     * @return
     * @author   coderOx
     */
    private String uploadPicture(WxUserTest wxUserTest, String session) throws IOException {
        JSONObject o = new JSONObject();
        o.put("fileType", 1);
        RequestBody requestBody = RequestBody.create(JSONObject.toJSONString(o), JSON_TYPE);
        Headers headers = new Headers.Builder()
                .addAll(getHeaders())
                .add("Content-Type", "application/json")
                .add("Cookie", session)
                .build();
        Response response = HttpUtils.sendPost(
                UPLOAD_POLICY,
                requestBody,
                headers);
        JSONObject result;
        o = new JSONObject();
        if (response.code() != 200) {
            email.sendEmail(HEALTHY\\\_RESULT\\\_NOTICE, "上传照片URL请求失败!", wxUserTest.getQq() + EMAIL_SUFFIX);
            LogUtils.getLogger().debug("上传照片URL请求失败");
            return null;
        }
        result = JSONObject.parseObject(response.body().string());
        result = result.getJSONObject("datas");
        LogUtils.getLogger().debug(MyUtils.jsonFormat(result));

        File file = new File("H:\\\\\Workspaces\\\\\MyProjects\\\\\nskWx\\\\\src\\\\\main\\\\\resources\\\\\"+"/static/"+wxUserTest.getPhoto());
        RequestBody r = RequestBody.create(file,MediaType.parse("multipart/form-data"));
        //获取信息之后再此提交,获取真正的url
//        RequestBody fileBody = new MultipartBody.Builder()
//                .setType(MultipartBody.FORM)
//                .addFormDataPart("key", result.getString("fileName") + ".png")
//                .addFormDataPart("policy", result.getString("policy"))
//                .addFormDataPart("OSSAccessKeyId", result.getString("accessid"))
//                .addFormDataPart("success\\\_action\\\_status", "200")
//                .addFormDataPart("signature", result.getString("signature"))
//                .addFormDataPart("file", file.getName(),r)
//
//                .build();
//        response = HttpUtils.sendPost(
//                result.getString("host"),
//                fileBody,
//                getHeaders()
//        );
//        LogUtils.getLogger().debug(response.body().string());
//        if (response.code() != 200) {
//            email.sendEmail(HEALTHY\\\_RESULT\\\_NOTICE, "上传照片请求失败!", wxUserTest.getQq() + EMAIL_SUFFIX);
//            LogUtils.getLogger().debug("上传照片请求失败");
//            return null;
//        }
        LogUtils.getLogger().debug(result.getString("fileName")+".png");
        return result.getString("fileName")+".png";
    }
    /**
     * 方法描述: 获取照片的url
     * @param
     * @return
     * @author   coderOx
     */
    private String getPictureUrl(String fileUrl,String session) throws IOException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("ossKey",fileUrl);
        RequestBody requestBody =RequestBody.create(JSONObject.toJSONString(jsonObject),JSON_TYPE);
        Headers headers = new Headers.Builder()
                .addAll(getHeaders())
                .add("Cookie",session)
                .build();
        Response response = HttpUtils.sendPost(PIC_URL,requestBody,headers);
        LogUtils.getLogger().debug(response);
        if (response.code() != 200) return null;
        String r = response.body().string();
        JSONObject object = JSONObject.parseObject(r);
        return object.getString("datas");
    }

    private Boolean submitForm(String session, WxUserTest user, JSONObject form) throws Exception {
        JSONObject extension = new JSONObject();
        extension.put("lon",user.getLon());
        extension.put("lat",user.getLat());
        extension.put("model","OPPO R11 Plus");
        extension.put("appVersion","8.1.14");
        extension.put("systemVersion","8.0");
        extension.put("systemName","android");
        extension.put("userId",user.getStudentId());
        String uuid = UUID.randomUUID().toString();
        extension.put("deviceId",uuid);
        LogUtils.getLogger().debug(MyUtils.jsonFormat(extension));

        JSONObject data = new JSONObject();
        data.put("lon",user.getLon());
        data.put("lat",user.getLat());
        data.put("model","OPPO R11 Plus");
        data.put("appVersion","9.0.12");
        data.put("systemVersion","8.0");
        data.put("systemName","android");
        data.put("calVersion","firstv");
        data.put("userId",user.getStudentId());
        data.put("deviceId",uuid);
        String formatForm = form.toJSONString();
        data.put("bodyString",AesCbc(form.toJSONString()));
        String formatSign = DigestUtils.md5DigestAsHex(AesCbc(form.toJSONString()).getBytes(StandardCharsets.UTF_8));
        data.put("sign",DesCbc(form.toJSONString()));

        LogUtils.getLogger().debug(formatForm);
        LogUtils.getLogger().debug(MyUtils.jsonFormat(form));
        LogUtils.getLogger().debug(MyUtils.jsonFormat(data));
        //LogUtils.getLogger().debug(AesCbc(formatForm));
        String formatExtension = DesCbc(extension.toJSONString());
        Headers headers = new Headers.Builder()
                .addAll(getHeaders())
                .add("Cookie",session)
                .add("CpdailyStandAlone","0")
                .add("extension","1")
                .add("Cpdaily-Extension", DesCbc(extension.toJSONString()))
                .build();
        RequestBody requestBody =RequestBody.create(data.toJSONString(),JSON_TYPE);

        Response response = HttpUtils.sendPost(
                SUBMIT_URL,
                requestBody,
                headers
        );
        if (response.code() != 200) return null;
        LogUtils.getLogger().debug(response.body().string());

        return null;
    }


    /**
     * 方法描述:  获取验证码
     * {header=
     * \\\[Server:"CloudWAF", Date:"Thu, 18 Nov 2021 08:29:04 GMT",
     * Content-Type:"application/json;charset=UTF-8",
     * Transfer-Encoding:"chunked",
     * Connection:"keep-alive",
     * Set-Cookie:"HWWAFSESID=17ca1738d08a5c1c98; path=/",
     * "HWWAFSESTIME=1637224144585; path=/",
     * "CONVERSATION=iap-1020045845018065-CONV-4853ff1b-6fec-45e4-a697-95960593bbca; Path=/iap; HttpOnly"\\\],
     * body={"code":200,"message":"操作成功",
     * "result":{"_encryptSalt":"1d5509880b1b450d",
     * "_lt":"a4cfc340169f4d2389e0b59941295f9a",
     * "forgetPwdUrl":"/personCenter/new\\\_password\\\_retrieve/main.html",
     * "needCaptcha":false}}}
     *
     * @return 返回map(body,header)
     * @author coderOx
     */
    public String getAuthCode() {
        RequestBody requestBody = new FormBody.Builder().build();
//        String LtUrl = "https://zjiet.campusphere.net/iap/security/lt";
//
//        request = new Request.Builder()
//                .url(LtUrl)
//                .headers(headers)
//                .header("Referer",response.headers().get("Location"))
//                .header("Cookie",cookie)
//                .post(requestBody)
//                .build();
//        call = client.newCall(request);
//
//        response = call.execute();
//        LogUtils.getLogger().debug(response.headers());
//        String b =response.body().string();
//        LogUtils.getLogger().debug(b);
//        JSONObject re = JSONObject.parseObject(b);
//        re = JSONObject.parseObject(re.getString("result"));
//
//        String lt = re.getString("_lt");
//        LogUtils.getLogger().debug(lt);
        return null;
    }

    /**
     * 方法描述: 获取cookie
     *
     * @param
     * @return
     * @author coderOx
     */
    private Map getCookie() {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
        headers.set("User-agent", "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36");
        headers.set("Referer", "https://zjiet.campusphere.net/portal/index.html");
        headers.set("Host", "zjiet.campusphere.net");
        headers.set("Connection", "keep-alive");
        headers.set("Upgrade-Insecure-Requests", "1");
        headers.set("Sec-Fetch-Dest", "document");
        headers.set("Sec-Fetch-Site", "same-origin");
        headers.set("Sec-Fetch-Mode", " navigate");
        headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip,deflate");
        headers.set(HttpHeaders.ACCEPT_LANGUAGE, "zh-CN,en-US;q=0.9");
        headers.set("Cookie", "CONVERSATION=iap-1020045845018065-CONV-3d2cab03-8ec1-426e-b0c9-4d5dd6a25dea; HWWAFSESID=85780735ea2544ef8f; HWWAFSESTIME=1637287745650");
        headers.add("Authorize", "true");


        String url = "https://zjiet.campusphere.net/iap/login?service=https%3A%2F%2Fzjiet.campusphere.net%2Fportal%2Flogin ";
//        String s = HttpUtils.get(url);
//        LogUtils.getLogger().debug(s);
        return null;
    }

    @Test
    void testHtt() throws IOException {

        Headers headers2 = new Headers.Builder().build();
        Headers headers = getHeaders();
        //设置禁止重定向
        OkHttpClient client = new OkHttpClient.Builder()
                .followRedirects(false)
                .build();

        //获取CONVERSATION=iap-1020045845018065-CONV-eba0daa0-cfd2-487d-835e-e45c9527e43a
        Request request = new Request.Builder()
                .url("https://zjiet.campusphere.net/iap/login?service=https%3A%2F%2Fzjiet.campusphere.net%2Fportal%2Flogin")
                .headers(headers)
                .header("Referer", " https://zjiet.campusphere.net/portal/index.html")
                .build();
        Call call = client.newCall(request);
        Response response = call.execute();
        //String cookie = response.headers().get("Set-Cookie");
        String cookie = response.headers().get("Set-Cookie");
        LogUtils.getLogger().debug(cookie);
        LogUtils.getLogger().debug(response.body().string());
        LogUtils.getLogger().debug(response.headers());
        //获取lt
        String lt = response.header("Location").split("=")\\\[1\\\];
        LogUtils.getLogger().debug(lt);

        RequestBody requestBody = new FormBody.Builder().build();
//        String LtUrl = "https://zjiet.campusphere.net/iap/security/lt";
//
//        request = new Request.Builder()
//                .url(LtUrl)
//                .headers(headers)
//                .header("Referer",response.headers().get("Location"))
//                .header("Cookie",cookie)
//                .post(requestBody)
//                .build();
//        call = client.newCall(request);
//
//        response = call.execute();
//        LogUtils.getLogger().debug(response.headers());
//        String b =response.body().string();
//        LogUtils.getLogger().debug(b);
//        JSONObject re = JSONObject.parseObject(b);
//        re = JSONObject.parseObject(re.getString("result"));
//
//        String lt = re.getString("_lt");
//        LogUtils.getLogger().debug(lt);

        //登陆获取
        String login = "https://zjiet.campusphere.net/iap/doLogin";
        requestBody = new FormBody.Builder()
                .add("username", "20202009129")
                .add("password", "iloveme0.0")
                .add("lt", lt)
                .build();
        request = new Request.Builder()
                .url(login)
                .headers(headers)
                .header("Cookie", cookie)
                .post(requestBody)
                .build();
        client = new OkHttpClient.Builder()
                .followRedirects(false)
                .build();

        call = client.newCall(request);

        response = call.execute();
        headers2 = response.headers();
        LogUtils.getLogger().debug(response.headers());
        LogUtils.getLogger().debug(response.body().string());


        requestBody = new FormBody.Builder()
                .build();
        request = new Request.Builder()
                .url(headers2.get("Location"))
                .headers(headers)
                .post(requestBody)
                .build();
        call = client.newCall(request);

        response = call.execute();
        headers2 = response.headers();
        LogUtils.getLogger();
        LogUtils.getLogger().debug(response.headers());
        LogUtils.getLogger().debug(response.body().string());
        requestBody = new FormBody.Builder()
                .build();
        request = new Request.Builder()
                .url(headers2.get("Location"))
                .headers(headers)
                .post(requestBody)
                .build();
        call = client.newCall(request);

        response = call.execute();
        LogUtils.getLogger();
        LogUtils.getLogger().debug(response.headers());
    }
    public static String AesCbc(String value) throws Exception {
        String key = "ytUQ7l2ZZu8mLvJZ";
        byte\\\[\\\] a = new byte\\\[\\\]{1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7};
        IvParameterSpec iv = new IvParameterSpec(a);
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

        byte\\\[\\\] encrypted = cipher.doFinal(value.getBytes());
        return Base64.encodeBase64String(encrypted);

    }
    private static String DesCbc(String data) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, UnsupportedEncodingException {
        String key = "b3L26XNL";
        byte\\\[\\\] b = new byte\\\[\\\]{1,2,3,4,5,6,7,8};
        DESKeySpec dks = new DESKeySpec(key.getBytes("UTF-8"));

        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        Key secretKey = keyFactory.generateSecret(dks);
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

        IvParameterSpec iv = new IvParameterSpec(b);
        AlgorithmParameterSpec paramSpec = iv;
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);

        byte\\\[\\\] bytes = cipher.doFinal(data.getBytes());

        return new String(Base64.encodeBase64(bytes), "UTF-8");
    }

}

/**
 * 类描述: 微信关注用户实体类
 *
 * @author coderOx
 * @date 2021-11-17
 */
@Data
class WxUserTest {
    private String openid;  //微信的openId
    private String wxNickName; //微信昵称
    private String headImgUrl;  //微信头像url
    private Integer isSubscribe; //是否关注 关注为1,取消关注为0
    private String subscribeTime;  //关注时间
    private String qq;
    private String name;
    private String studentId;
    private String password;
    private String address;
    private String school;
    private String lon; //经度
    private String lat; //纬度
    private String abnormalReason; //反馈信息
    private String photo;//照片信息
    private String phone;
    private Integer isHealthySign; //是否健康签到,0不签到,1签到健康打卡,2签到查寝,3签到健康和查寝
    private Integer signStep; //信息注册到第几步


    public WxUserTest() {
        this.openid = "xxx";
        this.wxNickName = "牛";
        this.headImgUrl = "http://thirdwx.qlogo.cn/mmopen/PiajxSqBRaEKYSMRMULCEra3heXG2PNVicpm32TDXfWXI0iaPBibUVRn3JjaL7cIfgcYuvUSc5REqPIj9RxVKTINaw/132";
        this.isSubscribe = 1;
        this.subscribeTime = "1637119712";
        this.qq = "xx";
        this.name = "xxx";
        this.studentId = "xx";
        this.password = "xxx";
        this.phone = "1xxx7";
        this.isHealthySign = 3;
        this.signStep = 2;
        this.address = "xxx";
        this.school = "xxx";
        this.lon = "120.389257";
        this.lat = "30.322654";
        this.abnormalReason = "在校";
        this.photo = "default.png";
    }
}