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、代码结构图