Java对接企业微信的审批功能

1、配置application.yml

wechat:
  # 企业ID
  corpId: ww8c813e720XXXXXX
  # 审批应用ID
  agentId: 3010040
  # 审批应用Secret
  corpSecret: vyzTn1Y3T4bryyJlDh8Od8AF0lXMsbQDb80uPIliqvo
  # 审批流模版ID
  templateId: 3WKhWLB6TVH4wxf1j3AVVoQBTTBAphYPmQQoBe2y
  # 回调校验的Token
  sToken: guoli123456
  # 回调校验的Key
  sEncodingAESKey: 5QVSyFkf5IvZrlcV5WVxhLGMWZGMzj5SDmsWDQqYGBL

2、Controller

package com.XXX.workWechat.constroller;

import com.XXX.common.core.domain.ReturnResult;
import com.XXX.common.utils.base.ErrorMessageException;
import com.XXX.workWechat.util.AesException;
import com.XXX.workWechat.service.WeChatFlowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;


@RestController
@RequestMapping("/workWeChat/workWeChat")
public class WeChatFlowController {
    @Autowired
    private WeChatFlowService weChatFlowService;

    @GetMapping("/getToken")
    public ReturnResult<String> getToken() {
        //获取access_token
        try{
            weChatFlowService.getToken();
            return ReturnResult.success();
        } catch (ErrorMessageException e) {
            return ReturnResult.error(e.getMessage());
        }
    }

    @GetMapping("/getTemplateDetail")
    public ReturnResult getTemplateDetail(){
        //获取审批模板详情
        try{
             weChatFlowService.getTemplateDetail();
            return ReturnResult.success();
        } catch (ErrorMessageException e) {
            return ReturnResult.error(e.getMessage());
        }
    }

    @GetMapping("/getUserDetail")
    public ReturnResult getUserDetail() {
        //获取用户详情
        try{
            weChatFlowService.getUserDetail();
            return ReturnResult.success();
        } catch (ErrorMessageException e) {
            return ReturnResult.error(e.getMessage());
        }
    }

//    @GetMapping("/commitApprovalApply")
//    public ReturnResult commitApprovalApply() {
//        //提交审批申请
//        try{
            weChatFlowService.commitApprovalApply();
//            return ReturnResult.success();
//        } catch (ErrorMessageException e) {
//            return ReturnResult.error(e.getMessage());
//        }
//    }

    @GetMapping("/feedbackFromWx")
    public ReturnResult<String> feedbackFromWxVerifyURL(String msg_signature, String timestamp, String nonce, String echostr) {
        try{
            String msg = weChatFlowService.feedbackFromWxVerifyURL(msg_signature,timestamp,nonce,echostr);
            return ReturnResult.success(msg);
        } catch (AesException e) {
            return ReturnResult.error(e.getMessage());
        }
    }

    @PostMapping("/feedbackFromWx")
    public ReturnResult<String> feedbackFromWxData(String msg_signature, String timestamp, String nonce, @RequestBody String data) {

        try{
            String msg = weChatFlowService.feedbackFromWxData(msg_signature,timestamp,nonce,data);
            return ReturnResult.success(msg);
        } catch (AesException e) {
            return ReturnResult.error(e.getMessage());
        } catch (ParserConfigurationException e) {
            return ReturnResult.error(e.getMessage());
        }catch (IOException e) {
            return ReturnResult.error(e.getMessage());
        }catch (SAXException e) {
            return ReturnResult.error(e.getMessage());
        }
    }
}

3、 DTO

package com.XXX.workWechat.dto;

import lombok.Data;

@Data
public class AccessTokenResult {
    /**
     * errcode : 0
     * errmsg : ok
     * access_token : accesstoken000001
     * expires_in : 7200
     */

    private int errcode;
    private String errmsg;
    private String access_token;
    private int expires_in;

}
package com.XXX.workWechat.dto;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.experimental.Accessors;

import java.util.List;
 
@Data
@Accessors(chain = true)
public class CommitApprovalApplyParam {


    /*
     * creator_userid : WangXiaoMing
     * template_id : 3Tka1eD6v6JfzhDMqPd3aMkFdxqtJMc2ZRioeFXkaaa
     * use_template_approver : 0
     * approver : [{"attr":2,"userid":["WuJunJie","WangXiaoMing"]},{"attr":1,"userid":["LiuXiaoGang"]}]
     * notifyer : ["WuJunJie","WangXiaoMing"]
     * notify_type : 1
     * apply_data : {"contents":[{"control":"Text","id":"Text-15111111111","value":{"text":"文本填写的内容"}}]}
     * summary_list : [{"summary_info":[{"text":"摘要第1行","lang":"zh_CN"}]},{"summary_info":[{"text":"摘要第2行","lang":"zh_CN"}]},{"summary_info":[{"text":"摘要第3行","lang":"zh_CN"}]}]
     */

    /**
     * 申请人userid
     */
    private String creator_userid;
    /**
     * 模板id
     */
    private String template_id;
    /**
     * 审批人模式:0-通过接口指定审批人、抄送人(此时approver、notifyer等参数可用); 1-使用此模板在管理后台设置的审批流程,支持条件审批。默认为0
     */
    private int use_template_approver;
    /**
     * 抄送方式:1-提单时抄送(默认值); 2-单据通过后抄送;3-提单和单据通过后抄送。仅use_template_approver为0时生效。
     */
    private int notify_type;
    /**
     * 抄送人节点userid列表,仅use_template_approver为0时生效。
     */
    private String[] notifyer;
    /**
     * 审批申请数据,可定义审批申请中各个控件的值,其中必填项必须有值,选填项可为空,数据结构同“获取审批申请详情”接口返回值中同名参数“apply_data”
     */
    private JSONObject apply_data;
    /**
     * 审批流程信息,用于指定审批申请的审批流程,支持单人审批、多人会签、多人或签,可能有多个审批节点,仅use_template_approver为0时生效。
     */
    private JSONArray approver;
    /**
     * 摘要信息,用于显示在审批通知卡片、审批列表的摘要信息,最多3行
     */
    private JSONArray summary_list;

    public CommitApprovalApplyParam() {
        this.use_template_approver = 0;
        this.apply_data = new JSONObject();
        this.approver = new JSONArray();
        this.summary_list = new JSONArray();
    }

    public CommitApprovalApplyParam(String creator_userid, String template_id) {
        this();
        this.creator_userid = creator_userid;
        this.template_id = template_id;
    }

    public void  setNotifyer(String... notifyer){
        this.notifyer = notifyer;
    }
    /**
     * 添加审批人
     *
     * @param attr   节点审批方式:1-或签;2-会签,仅在节点为多人审批时有效
     *               会签:指同一个审批节点设置多个人,如ABC三人,三人会同时收到审批,需全部同意之后,审批才可到下一审批节点;
     *               或签:指同一个审批节点设置多个人,如ABC三人,三人会同时收到审批,只要其中任意一人审批即可到下一审批节点;
     * @param userId 审批节点审批人userid列表,若为多人会签、多人或签,需填写每个人的userid
     */
    public void addApprover(int attr, String... userId) {
        JSONObject json = new JSONObject();
        json.put("attr", attr);
        json.put("userid", userId);
        this.approver.add(json);
    }

    /**
     * 审批申请详情
     *
     * @param contents 审批申请详情,由多个表单控件及其内容组成,其中包含需要对控件赋值的信息
     */
    public void setApplyDataContents(JSONObject... contents) {
        // 审批申请详情,由多个表单控件及其内容组成,其中包含需要对控件赋值的信息
        this.apply_data.put("contents", contents);
    }
    /**
     * 摘要信息,用于显示在审批通知卡片、审批列表的摘要信息,最多3行
     *
     * @param text 摘要行显示文字,用于记录列表和消息通知的显示,不要超过20个字符
     */
    public void setSummaryInfo(String... text) {
        for (String s : text) {
            JSONArray summaryInfoArr = new JSONArray();
            JSONObject textObj = new JSONObject();
            textObj.put("text",s);
            textObj.put("lang","zh_CN");
            summaryInfoArr.add(textObj);
            JSONObject summaryInfo = new JSONObject();
            summaryInfo.put("summary_info",summaryInfoArr);
            // 摘要信息,用于显示在审批通知卡片、审批列表的摘要信息,最多3行
            this.summary_list.add(summaryInfo);
        }
    }

    /**
     * 文本/多行文本控件(control参数为Text或Textarea)
     *
     * @param id   控件ID
     * @param text 文本内容,在此填写文本/多行文本控件的输入值
     */
    public JSONObject controlText(String id, String text) {
        JSONObject value = new JSONObject();
        value.put("text", text);

        return createControl(id, ControlType.text, value);
    }

    /**
     * 数字控件(control参数为Number)
     *
     * @param id         控件ID
     * @param new_number 数字内容,在此填写数字控件的输入值
     */
    public JSONObject controlNumber(String id, String new_number) {
        JSONObject value = new JSONObject();
        value.put("new_number", new_number);

        return createControl(id, ControlType.number, value);
    }

    /**
     * 金额控件(control参数为Money)
     *
     * @param id        控件ID
     * @param new_money 金额内容,在此填写金额控件的输入值
     */
    public JSONObject controlMoney(String id, String new_money) {
        JSONObject value = new JSONObject();
        value.put("new_money", new_money);

        return createControl(id, ControlType.money, value);
    }

    /**
     * 日期/日期+时间控件(control参数为Date)
     *
     * @param id          控件ID
     * @param type        时间展示类型:day-日期;hour-日期+时间 ,和对应模板控件属性一致
     * @param s_timestamp 时间戳-字符串类型,在此填写日期/日期+时间控件的选择值,以此为准
     */
    public JSONObject controlDate(String id, String type, String s_timestamp) {
        //{
        //    "date": {
        //        "type": "day",
        //        "s_timestamp": "1569859200"
        //    }
        //}
        JSONObject value = new JSONObject();
        JSONObject date = new JSONObject();
        value.put("date", date);
        date.put("type", type);
        date.put("s_timestamp", s_timestamp);

        return createControl(id, ControlType.date, value);
    }

    /**
     * 单选/多选控件(control参数为Selector)
     *
     * @param id   控件ID
     * @param type 选择方式:single-单选;multi-多选
     * @param key  选项key,可通过“获取审批模板详情”接口获得
     */
    public JSONObject controlSelector(String id, String type, String... key) {
        //{
        //    "selector": {
        //        "type": "multi",
        //        "options": [
        //            {
        //                "key": "option-15111111111",
        //            },
        //            {
        //                "key": "option-15222222222",
        //            }
        //        ]
        //    }
        //}
        JSONObject value = new JSONObject();
        JSONObject selector = new JSONObject();
        JSONArray options = new JSONArray();
        value.put("selector", selector);
        selector.put("type", type);
        selector.put("options", options);

        for (String s : key) {
            JSONObject option = new JSONObject();
            option.put("key", s);
            options.add(option);
        }

        return createControl(id, ControlType.selector, value);
    }

    /**
     * 成员控件(control参数为Contact,且value参数为members)
     *
     * @param id      控件ID
     * @param userIds 所选成员的userid
     * @param names   成员名
     */
    public JSONObject controlMembers(String id, List<String> userIds, List<String> names) {
        //{
        //    "members": [
        //        {
        //            "userid": "WuJunJie",
        //            "name": "Jackie"
        //        },
        //        {
        //            "userid": "WangXiaoMing"
        //            "name": "Tom"
        //        }
        //    ]
        //}
        JSONObject value = new JSONObject();
        JSONArray members = new JSONArray();
        value.put("members", members);
        for (int i = 0; i < userIds.size(); i++) {
            JSONObject member = new JSONObject();
            member.put("userid", userIds.get(i));
            member.put("name", names.get(i));
            members.add(member);
        }

        return createControl(id, ControlType.contact, value);
    }

    /**
     * 部门控件(control参数为Contact,且value参数为departments)
     *
     * @param id        控件ID
     * @param openapiId 所选部门id
     * @param names     所选部门名
     */
    public JSONObject controlDepartments(String id, List<String> openapiId, List<String> names) {
        //{
        //    "departments": [
        //        {
        //            "openapi_id": "2",
        //            "name": "销售部",
        //        },
        //        {
        //            "openapi_id": "3",
        //            "name": "生产部",
        //        }
        //    ]
        //}
        JSONObject value = new JSONObject();
        JSONArray members = new JSONArray();
        value.put("departments", members);
        for (int i = 0; i < openapiId.size(); i++) {
            JSONObject member = new JSONObject();
            member.put("openapi_id", openapiId.get(i));
            member.put("name", names.get(i));
            members.add(member);
        }

        return createControl(id, ControlType.contact, value);
    }

    /**
     * 附件控件(control参数为File,且value参数为files)
     *
     * @param id     控件ID
     * @param fileid 文件id,该id为临时素材上传接口返回的的media_id,注:提单后将作为单据内容转换为长期文件存储;目前一个审批申请单,全局仅支持上传6个附件,否则将失败。
     */
    public JSONObject controlFile(String id, String... fileid) {
        //{
        //    "files": [
        //        {
        //            "file_id": "1G6nrLmr5EC3MMb_-zK1dDdzmd0p7cNliYu9V5w7o8K1aaa"
        //        }
        //    ]
        //}
        JSONObject value = new JSONObject();
        JSONArray files = new JSONArray();
        value.put("files", files);
        for (String s : fileid) {

            JSONObject file = new JSONObject();
            file.put("file_id", s);
            files.add(file);
        }

        return createControl(id, ControlType.file, value);
    }
    /**
     * 明细控件(control参数为Table)
     *
     * @param id     控件ID
     * @param table children 明细内容,一个明细控件可能包含多个子明细
     *              list 子明细列表,在此填写子明细的所有子控件的值,子控件的数据结构同一般控件
     */
    public JSONObject controlTable(String id, JSONObject[]... table) {
        //{
        //    "children": [
        //        {
        //            "list": [
        //                {
        //                    "control": "Text",
        //                    "id": "Text-15111111111",
        //                    "title": [
        //                        {
        //                            "text": "明细内文本控件",
        //                            "lang": "zh_CN"
        //                        }
        //                    ],
        //                    "value": {
        //                        "text": "明细文本"
        //                    }
        //                }
        //            ]
        //        }
        //    ]
        //}
        JSONObject value = new JSONObject();
        JSONArray rows = new JSONArray();
        value.put("children", rows);
        for (JSONObject[] row : table) {
            JSONObject rowValue = new JSONObject();
            rowValue.put("list",row);
            rows.add(rowValue);
        }
        return createControl(id, ControlType.file, value);
    }

    /**
     * table 明细
     * @param cols 这里就是多个控件值调用createControl方法
     * @return 控件数组
     */
    public JSONObject[] tableRow(JSONObject... cols){
        return cols;
    }

    public JSONObject createControl(String id, String type, JSONObject value) {
        JSONObject control = new JSONObject();
        control.put("id", id);
        control.put("control", type);
        control.put("value", value);
        return control;
    }

    public JSONObject controlVacation(String id,String key,String text,Long beginDate,Long endDate,Long durationTime){
        JSONArray optionsValueVal = new JSONArray();
        JSONObject optionsValueValItem = new JSONObject();
        optionsValueValItem.put("text",text);
        optionsValueValItem.put("lang","zh_CN");
        optionsValueVal.add(optionsValueValItem);

        JSONObject optionsValue = new JSONObject();
        optionsValue.put("value",optionsValueVal);
        optionsValue.put("key",key);

        JSONObject selector = new JSONObject();
        JSONArray selectorOptions = new JSONArray();
        selectorOptions.add(optionsValue);
        selector.put("options",selectorOptions);
        selector.put("type","single");
        selector.put("exp_type",0);

        JSONObject vacationValue = new JSONObject();
        vacationValue.put("selector",selector);

        JSONObject dateRangeValue = new JSONObject();
        dateRangeValue.put("type","hour");
        dateRangeValue.put("new_begin",beginDate);
        dateRangeValue.put("new_end",endDate);
        dateRangeValue.put("new_duration",durationTime);

        JSONObject attendanceValue = new JSONObject();
        attendanceValue.put("date_range",dateRangeValue);
        attendanceValue.put("type",1);
        vacationValue.put("attendance",attendanceValue);

        JSONObject value = new JSONObject();
        value.put("vacation",vacationValue);

        return createControl(id,ControlType.vacation,value);
    }

}
package com.XXX.workWechat.dto;
 
public class ControlType {
    //控件类型:Text-文本;Textarea-多行文本;Number-数字;Money-金额;Date-日期/日期+时间;
    // Selector-单选/多选;;Contact-成员/部门;Tips-说明文字;File-附件;Table-明细;
    public static final String text = "Text";
    public static final String textarea = "Textarea";
    public static final String number = "Number";
    public static final String money = "Money";
    public static final String date = "Date";
    public static final String selector = "Selector";
    public static final String contact = "Tips";
    public static final String file = "File";
    public static final String table = "Table";
    public static final String vacation = "Vacation";
}

package com.XXX.workWechat.dto;

import lombok.ToString;

import java.util.List;

 
@ToString
public class WxUserResult {

 

    private int errcode;
    private int isleader;
    private String gender;
    private String mobile;
    private String errmsg;
    private String telephone;
    private String avatar;
    private int hide_mobile;
    private int main_department;
    private String userid;
    private String thumb_avatar;
    private int enable;
    private String name;
    private ExtattrBean extattr;
    private String qr_code;
    private String alias;
    private String position;
    private String email;
    private int status;
    private List<Integer> is_leader_in_dept;
    private List<Integer> department;
    private List<Integer> order;

    public int getErrcode() {
        return errcode;
    }

    public void setErrcode(int errcode) {
        this.errcode = errcode;
    }

    public int getIsleader() {
        return isleader;
    }

    public void setIsleader(int isleader) {
        this.isleader = isleader;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getErrmsg() {
        return errmsg;
    }

    public void setErrmsg(String errmsg) {
        this.errmsg = errmsg;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getAvatar() {
        return avatar;
    }

    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    public int getHide_mobile() {
        return hide_mobile;
    }

    public void setHide_mobile(int hide_mobile) {
        this.hide_mobile = hide_mobile;
    }

    public int getMain_department() {
        return main_department;
    }

    public void setMain_department(int main_department) {
        this.main_department = main_department;
    }

    public String getUserid() {
        return userid;
    }

    public void setUserid(String userid) {
        this.userid = userid;
    }

    public String getThumb_avatar() {
        return thumb_avatar;
    }

    public void setThumb_avatar(String thumb_avatar) {
        this.thumb_avatar = thumb_avatar;
    }

    public int getEnable() {
        return enable;
    }

    public void setEnable(int enable) {
        this.enable = enable;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ExtattrBean getExtattr() {
        return extattr;
    }

    public void setExtattr(ExtattrBean extattr) {
        this.extattr = extattr;
    }

    public String getQr_code() {
        return qr_code;
    }

    public void setQr_code(String qr_code) {
        this.qr_code = qr_code;
    }

    public String getAlias() {
        return alias;
    }

    public void setAlias(String alias) {
        this.alias = alias;
    }

    public String getPosition() {
        return position;
    }

    public void setPosition(String position) {
        this.position = position;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public List<Integer> getIs_leader_in_dept() {
        return is_leader_in_dept;
    }

    public void setIs_leader_in_dept(List<Integer> is_leader_in_dept) {
        this.is_leader_in_dept = is_leader_in_dept;
    }

    public List<Integer> getDepartment() {
        return department;
    }

    public void setDepartment(List<Integer> department) {
        this.department = department;
    }

    public List<Integer> getOrder() {
        return order;
    }

    public void setOrder(List<Integer> order) {
        this.order = order;
    }

    public static class ExtattrBean {
        private List<?> attrs;

        public List<?> getAttrs() {
            return attrs;
        }

        public void setAttrs(List<?> attrs) {
            this.attrs = attrs;
        }
    }
}

4、Service

package com.XXX.workWechat.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.XXX.common.core.domain.entity.SysDictData;
import com.XXX.common.core.redis.RedisCache;
import com.XXX.common.utils.StringUtils;
import com.XXX.common.utils.base.ErrorMessageException;
import com.XXX.employee.mapper.EmployeeMapper;
import com.XXX.leave.domain.GlAskLeave;
import com.XXX.system.service.ISysDictDataService;
import com.XXX.workWechat.dto.AccessTokenResult;
import com.XXX.workWechat.dto.CommitApprovalApplyParam;
import com.XXX.workWechat.dto.ControlType;
import com.XXX.workWechat.dto.WxUserResult;
import com.XXX.workWechat.util.AesException;
import com.XXX.workWechat.util.WXBizMsgCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;

import javax.annotation.Resource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.StringReader;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Service
public class WeChatFlowService {
    @Autowired
    private RedisCache redisCache;
    @Resource
    private ISysDictDataService iSysDictDataService;
    @Resource
    private EmployeeMapper employeeMapper;
    //企业ID
    @Value("${wechat.corpId}")
    private String id;
    //审批应用ID
    @Value("${wechat.agentId}")
    private String agentId;
    //审批应用Secret
    @Value("${wechat.corpSecret}")
    private String secret;
    //意向合同审批流模版ID
    @Value("${wechat.templateId}")
    private String templateId;

    @Value("${wechat.sToken}")
    private String sToken;
    @Value("${wechat.sEncodingAESKey}")
    private String sEncodingAESKey;


    public String getToken() throws ErrorMessageException{
        //获取access_token,存到redis中
        String tokenValue = redisCache.getCacheObject("ACCESS_TOKEN");
        if (StringUtils.isNull(tokenValue)){
            String token = "ACCESS_TOKEN";
            Integer timeOut = 7200;
            tokenValue = getAccessToken();
            redisCache.setCacheObject(token,tokenValue,timeOut, TimeUnit.SECONDS);
        }
        return tokenValue;
    }


    public void getTemplateDetail() throws ErrorMessageException {
        //获取审批模板详情
        String templateDetail = getTemplateDetail(templateId);
        System.out.println(templateDetail);
    }


    public WxUserResult getUserDetail() throws ErrorMessageException {
        //获取用户详情
        String userId = "jack";
        WxUserResult res = getUserDetail(userId);
        System.out.println(res.getUserid());
        System.out.println(res.getName());
//        System.out.println(res.getMobile());
//        System.out.println(res.getEmail());
//        System.out.println("性别。0表示未定义,1表示男性,2表示女性: " + res.getGender());
        return res;
    }


    public void commitApprovalApply(GlAskLeave glAskLeave) throws ErrorMessageException {
        //提交审批申请:请假日期需要加00:00:00,请假天数还是请假小时,审批人、申请人的微信用户ID

        Map<String,String> vacationMap = new HashMap<>();
        vacationMap.put("年假","1");
        vacationMap.put("事假","2");
        vacationMap.put("病假","3");
        vacationMap.put("调休假","4");
        vacationMap.put("婚假","5");
        vacationMap.put("产假","6");
        vacationMap.put("陪产假","7");
        vacationMap.put("其他","8");

        SysDictData sysDictData = iSysDictDataService.selectDictDataById(Long.valueOf(glAskLeave.getLeaveType()));
        String dictText = sysDictData.getDictLabel();

        String key = vacationMap.get(dictText);
        String text = dictText;
        String cont = glAskLeave.getLeaveComment();

        SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String beginDateStr=format2.format(glAskLeave.getLeaveStartDate());
        String endDateStr=format2.format(glAskLeave.getLeaveEndDate());

        Long beginDate = Timestamp.valueOf(beginDateStr).getTime()/1000;
        Long endDate = Timestamp.valueOf(endDateStr).getTime()/1000;
        Long durationTime = (long) (glAskLeave.getLeaveDays()*8*60*60);



//        String creatorUserId = employeeMapper.getWechatId(glAskLeave.getEmployeeId());
        String creatorUserId = "jack";
        String approverUserId = "jack";
        String notifyerUserId = "jack";

        CommitApprovalApplyParam param = new CommitApprovalApplyParam(creatorUserId, templateId);
        //添加审批人
        param.addApprover(2, approverUserId);
        //审批申请数据
        param.setApplyDataContents(
            //以下是contents内容
                param.controlVacation("vacation-1563793073898",key,text,beginDate,endDate,durationTime),
                param.controlText("item-1497581399901",cont)
        );
        //摘要信息
        param.setSummaryInfo("请假类型:"+ text, "开始时间:"+beginDateStr, "结束时间:"+endDateStr);
        //抄送人
        param.setNotifyer(notifyerUserId);
        param.setNotify_type(2);
        String sp_no = commitApprovalApply(param);
        System.out.println(sp_no);
    }

    /**
     * 获取access_token
     *
     * @return token
     */
    public String getAccessToken() throws ErrorMessageException{
        String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET"
                .replace("ID", id).replace("SECRET", secret);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<AccessTokenResult> responseEntity = restTemplate.getForEntity(url, AccessTokenResult.class);
        System.out.println("调用结果:" + responseEntity);
        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            AccessTokenResult ac = responseEntity.getBody();
            if (ac.getErrcode() == 0) {
                return ac.getAccess_token();
            }
            throw new ErrorMessageException("获取微信token失败:" + ac.getErrmsg());
        }
        throw new ErrorMessageException("获取微信token请求访问失败");
    }

    /**
     * 获取审批模板详情
     *
     * @param templateId id
     */
    public String getTemplateDetail(String templateId) throws ErrorMessageException {
        String token = getToken();
        String url = "https://qyapi.weixin.qq.com/cgi-bin/oa/gettemplatedetail?access_token=ACCESS_TOKEN"
                .replace("ACCESS_TOKEN", token);

        RestTemplate restTemplate = new RestTemplate();
        Map<String, String> reqParam = new HashMap<>();
        reqParam.put("template_id", templateId);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, reqParam, String.class);
//        System.out.println("调用结果:" + responseEntity);
        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            return responseEntity.getBody();
        }
        throw new ErrorMessageException("获取审批模板失败!");
    }

    /**
     * 提交审批申请
     *
     * @param param 参数
     * @return 编号
     */
    public String commitApprovalApply(CommitApprovalApplyParam param) throws ErrorMessageException {
        String token = getToken();
        String url = "https://qyapi.weixin.qq.com/cgi-bin/oa/applyevent?access_token=ACCESS_TOKEN"
                .replace("ACCESS_TOKEN", token);

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url, param, JSONObject.class);
        System.out.println("调用结果:" + responseEntity);
        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            JSONObject body = responseEntity.getBody();
            if (body.getInteger("errcode") == 0) {
                return body.getString("sp_no");
            }
            throw new RuntimeException("提交审批流程失败:" + body.getString("errmsg"));
        }
        throw new RuntimeException("提交审批流程请求访问失败");
    }
    /**
     * 读取成员
     *
     * @param userId userId
     * @return 编号
     */
    public WxUserResult getUserDetail(String userId) throws ErrorMessageException {
        String token = getToken();
        System.out.println("token:" + token);
        String url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&userid=USERID"
                .replace("ACCESS_TOKEN", token).replace("USERID", userId);

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<WxUserResult> responseEntity = restTemplate.getForEntity(url, WxUserResult.class);
//        System.out.println("调用结果:" + responseEntity);
        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            WxUserResult body = responseEntity.getBody();
            if (body.getErrcode() == 0) {
                return body;
            }
            throw new RuntimeException("提交审批流程失败:" + body.getErrmsg());
        }
        throw new RuntimeException("读取成员失败请求访问失败");
    }


    public String feedbackFromWxVerifyURL(String msg_signature, String timestamp, String nonce, String echostr) throws AesException {

        System.out.printf("-------feedbackFromWx ------ msg_signature:%s, Long timestamp:%s, String nonce:%s, String echostr:%s%n",
                msg_signature, timestamp, nonce, echostr);

        WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, id);
        String sMsg = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr);
        System.out.printf("sMsg:%s%n", sMsg);
        return sMsg;
    }


    public String feedbackFromWxData(String msg_signature, String timestamp, String nonce, String data)
            throws AesException, ParserConfigurationException, IOException, org.xml.sax.SAXException {
        System.out.println(String.format("-------feedbackFromWx ------ msg_signature:%s, Long timestamp:%s, String nonce:%s, String data:%s",
                msg_signature, timestamp, nonce, data));
        WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, id);
        String sMsg = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, data);
        System.out.println("sMsg:"+sMsg);

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        StringReader sr = new StringReader(sMsg);
        InputSource is = new InputSource(sr);
        Document document = db.parse(is);

        Element root = document.getDocumentElement();

        System.out.println("AgentID:"+root.getElementsByTagName("AgentID").item(0).getTextContent());
        System.out.println("SpNo:"+root.getElementsByTagName("SpNo").item(0).getTextContent());
        System.out.println("SpStatus:"+root.getElementsByTagName("SpStatus").item(0).getTextContent());
        System.out.println("TemplateId:"+root.getElementsByTagName("TemplateId").item(0).getTextContent());
        System.out.println("UserId:"+root.getElementsByTagName("UserId").item(0).getTextContent());

        String fbEncrypt = root.getElementsByTagName("Encrypt").item(0).getTextContent();


        String ss = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, root.getElementsByTagName("Encrypt").item(0).getTextContent());
        System.out.println("=======================ss");
        System.out.println(ss);
        return sMsg;
    }
}

5、上述回调用到的验证Util文件夹,在此处下载,java版

加解密库下载与返回码 - 文档 - 企业微信开发者中心 (qq.com)

6、代码结构图

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ahwangzc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值