一句话简述就是,后台自动发起员工猪小明的审批申请,领导就可以在企业微信中收到猪小明的审批申请进行审批,可以配置领导审批后企业微信回调我们的服务,我们也可以在后台查询审批流程的详细状态,大体流程就是这样,当然企业微信还提供了其他可能用到的功能,如查询用户信息,用户假期信息等。
可以先大体看下企业微信官方提供的API:企业微信开发API,如下图,比较简单。
代码地址:https://gitee.com/bjzwb/qw_flow
创建一个自定义的模板使用。
设置模板内容,企微提供了文本、多行文本、单选、多选、附件等控件,添加后每个小控件都有一个ID,后续根据这个ID给他赋值。
模板ID在地址栏,这里需要注意下。
/**
* 通过模板ID获取审批模板详情
*
* @param templateId id
*/
public String getTemplateDetail(String templateId) {
String url = "https://qyapi.weixin.qq.com/cgi-bin/oa/gettemplatedetail?access_token=ACCESS_TOKEN"
.replace("ACCESS_TOKEN", getToken());
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();
}
return "失败";
}
//CommitApprovalApplyParam是自定义的一个VO类,即提交申请的内容对象。
public String commitApprovalApply(CommitApprovalApplyParam param) {
String url = "https://qyapi.weixin.qq.com/cgi-bin/oa/applyevent?access_token=ACCESS_TOKEN"
.replace("ACCESS_TOKEN", getToken());
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("提交审批流程请求访问失败");
}
//提交审批申请
@Test
void commitApprovalApply() {
CommitApprovalApplyParam param = new CommitApprovalApplyParam("dzw666", CommonConstant.TEMPLATEID);
//添加审批人
param.addApprover(1, "ZhangSan");
param.addApprover(2, "ZhangSan");
//审批申请数据
param.setApplyDataContents(
param.controlText("Text-1656405646620", "蛋炒饭"),
param.controlText("Textarea-1656411173031", "可乐"),
param.controlSelector("Selector-1656411222519", "multi", "option-1656411222519"),
param.controlTable("Table-1656411291100", param.tableRow(param.controlText("Text-1656411358094", "要"), param.controlText("Text-1656411375322", "不喝")))
);
//摘要信息
param.setSummaryInfo("哈哈哈哈哈哈哈");
//抄送人
param.setNotifyer("ZhangWenBiao");
param.setNotify_type(2);
System.out.println(JSON.toJSONString(param));
System.out.println(sendQwController.commitApprovalApply(param));
}
public JSONObject searchApprovalList(SearchApprovalVo searchApprovalVo) {
String url = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovalinfo?access_token=ACCESS_TOKEN"
.replace("ACCESS_TOKEN", getToken());
ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url, searchApprovalVo, JSONObject.class);
System.out.println("调用结果:" + responseEntity);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
return responseEntity.getBody();
}
throw new RuntimeException("提交审批流程请求访问失败");
}
@Test
void searchApprovalList() throws ParseException {
DateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SearchApprovalVo searchApprovalVo = new SearchApprovalVo();
//审批开始时间
searchApprovalVo.setStarttime(df.parse("2022-06-01 10:00:00").getTime()/1000);
//审批结束时间
searchApprovalVo.setEndtime(df.parse("2022-07-02 10:00:00").getTime()/1000);
//分页参数默认0
searchApprovalVo.setCursor(0);
//数量 默认100
searchApprovalVo.setSize(100);
//筛选条件,支持设置多个条件:template_id - 模板类型/模板id;creator - 申请人;department - 审批单提单者所在部门;sp_status - 审批状态;record_type - 审批单类型属性
searchApprovalVo.setFilters(ListUtil.toList(
new SearchApproveFiltersDTO("template_id",CommonConstant.TEMPLATEID),
new SearchApproveFiltersDTO("creator","dzw666"),
new SearchApproveFiltersDTO("department","1"),
new SearchApproveFiltersDTO("sp_status","1")
));
System.out.println(sendQwController.searchApprovalList(searchApprovalVo));
}
public JSONObject getApprovalDetail(String spNo){
String url = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovaldetail?access_token=ACCESS_TOKEN"
.replace("ACCESS_TOKEN", getToken());
JSONObject jsonObject = new JSONObject();
jsonObject.put("sp_no",spNo);
ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url, jsonObject, JSONObject.class);
System.out.println("调用结果:" + responseEntity);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
return responseEntity.getBody();
}
throw new RuntimeException("提交审批流程请求访问失败");
}
企业微信管理后台配置。
URL:回调的接口,需要提供GET、POST请求方式各一个接口。
Token:自定义的字符串。
EncodingAESKey:秘钥,也可自定义。
开发接口。
下载企业微信的加密解密库,https://open.work.weixin.qq.com/api/doc/90000/90138/90307。
如果缺少依赖,可以引入这个依赖。
<dependency>
<groupId>commons-codecgroupId>
<artifactId>commons-codecartifactId>
<version>1.15version>
dependency>
@GetMapping("/feedbackFromWx")
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);
String sToken = "zwb6666";
String sEncodingAESKey = "9QVSyFkf3IvZrlcV3WVxhLGMWZGMzj3SDmsWDQqYGBL";
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, CommonConstant.CORPID);
String sMsg = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr);
System.out.printf("sMsg:%s%n", sMsg);
return sMsg;
}
@PostMapping("/feedbackFromWx")
public String feedbackFromWxData(String msg_signature, String timestamp, String nonce, @RequestBody String data)
throws AesException, ParserConfigurationException, IOException, SAXException, 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));
String sToken = "zwb6666";
String sEncodingAESKey = "9QVSyFkf3IvZrlcV3WVxhLGMWZGMzj3SDmsWDQqYGBL";
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, CommonConstant.CORPID);
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());
return sMsg;
}
/**
* 读取成员
*
* @param userId userId
* @return 编号
*/
public String getUserDetail(String userId) {
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&userid=USERID"
.replace("ACCESS_TOKEN", getToken()).replace("USERID", userId);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
System.out.println("调用结果:" + responseEntity);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
return responseEntity.getBody();
}
throw new RuntimeException("读取成员失败请求访问失败");
}