看别人的一开口就是企业微信文档多坑多坑不知道是不是需求不同,我看的部分还是很不错了的,在这总结一下
需求是在我们系统里面 提交审批申请 在企业微信里审批,同时监控审批流的状态完成时继续后续操作
代码: https://gitee.com/lanyanhua/wechat-flow.git
需要的参数
企业ID,审批应用ID,审批应用Secret,审批流模版ID
模版ID位置比较变态点开审批流在url里
创建流程所需的参数还差三个:token,userid,审批流模版的控件ID
1.获取token
/**
* 获取access_token
*
* @return token
*/
public String getAccessToken() {
//企业ID
String id = "XXXXXXXXXXXXXXXXXX";
//审批应用Secret
String secret = "XXXXXXXXXXXXXXXXXX";
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);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
AccessTokenResult ac = responseEntity.getBody();
if (ac.getErrcode() == 0) {
return ac.getAccess_token();
}
}
throw new BusinessException("获取微信token失败");
}
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;
}
2.获取userid 后台可以更改只能改一次
3.获取审批流里面控件的ID
根据模版ID调用接口获取模版信息 找出需要赋值的 控件id
参数 | 说明 |
template_names | 模板名称,若配置了多语言则会包含中英文的模板名称,默认为zh_CN中文 |
template_content | 模板控件信息 |
└ controls | 模板控件数组。模板详情由多个不同类型的控件组成,控件类型详细说明见附录。 |
└ └ property | 模板控件属性,包含了模板内控件的各种属性信息 |
└ └ └ control | 控件类型:Text-文本;Textarea-多行文本;Number-数字;Money-金额;Date-日期/日期+时间;Selector-单选/多选;Contact-成员/部门;Tips-说明文字;File-附件;Table-明细;Attendance-假勤控件;Vacation-请假控件 |
└ └ └ id | 控件id |
└ └ └ title | 控件名称,若配置了多语言则会包含中英文的控件名称,默认为zh_CN中文 |
└ └ └ placeholder | 控件说明,向申请者展示的控件填写说明,若配置了多语言则会包含中英文的控件说明,默认为zh_CN中文 |
└ └ └ require | 是否必填:1-必填;0-非必填 |
└ └ └ un_print | 是否参与打印:1-不参与打印;0-参与打印 |
└ └ config | 模板控件配置,包含了部分控件类型的附加类型、属性,详见附录说明。目前有配置信息的控件类型有:Date-日期/日期+时间;Selector-单选/多选;Contact-成员/部门;Table-明细;Attendance-假勤组件(请假、外出、出差、加班) |
/**
* 获取审批模板详情
*
* @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", 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);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
return responseEntity.getBody();
}
return "失败";
}
主要的两个接口:提交审批申请、审批申请状态变化回调通知
提交审批申请
调用接口返回流程编号需要存下后面交互时需要用到
/**
* 提交审批申请
*
* @param param 参数
* @return 编号
*/
public String commitApprovalApply(CommitApprovalApplyParam param) {
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);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
JSONObject body = responseEntity.getBody();
if (body.getInteger("errcode") == 0) {
return body.getString("sp_no");
}
}
throw new BusinessException("提交审批流程失败");
}
调用方法代码
@Test
public void testCommitApprovalApply() {
//提交审批申请
String creator_userid = "cab";
String template_id = "XXXXXXXXXXXXXXX";
CommitApprovalApplyParam param = new CommitApprovalApplyParam(creator_userid, template_id);
//添加审批人
param.addApprover(2, "XXXXXXX");
//审批申请数据
param.setApplyDataContents(
param.controlText("Text-1586447955368", "文本1"),
param.controlText("Text-1586447964627", "文本2"),
param.controlText("Text-1586447975810", "文本3")
);
//摘要信息
param.setSummaryInfo("摘要信息1", "摘要信息2", "摘要信息3");
//抄送人
param.setNotifyer("XXX");
param.setNotify_type(2);
System.out.println(JSON.toJSONString(param));
//调用
String sp_no = commitApprovalApply(param);
System.out.println(sp_no);
}
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName: CommitApprovalApplyParam
* @Description:TODO ()
* @author: lanyanhua
* @date: 2020/10/14 2:41 下午
* @Copyright:
*/
@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);
}
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;
}
}
/**
* @ClassName: ControlType
* @Description:TODO ()
* @author: lanyanhua
* @date: 2020/10/14 3:03 下午
* @Copyright:
*/
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";
}
审批申请状态变化回调通知 这个接口看另外一篇