1、解决WARN警告: Unable to interpret the implicit parameter configuration

2、修改HttpUtils,sendPostWithRest方法,如果参数为String类型,推送企业微信消息会乱码,因此改为Object类型,直接推送Map<Sring,Object>
3、实现企业微信消息推送
This commit is contained in:
bo.yang 2021-07-30 10:36:14 +08:00
parent 8b515fe0e3
commit e0eac9fe2f
8 changed files with 346 additions and 68 deletions

View File

@ -3,6 +3,7 @@ package com.ruoyi.web.controller.system;
import com.alibaba.fastjson.JSON;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.shiro.util.CustToken;
import com.ruoyi.system.service.IWechatApiService;
@ -21,6 +22,8 @@ import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Controller
@ -78,4 +81,32 @@ public class WechatApiController extends BaseController {
}
@GetMapping("anon/SendTextMessageToWechatUser")
@ResponseBody
public Map<String, String> SendTextMessageToWechatUser() {
List<String> userIdList = new ArrayList<>();
userIdList.add("2342343243");
userIdList.add("erqrqwe");
userIdList.add("359");
Map<String, String> resultMap = wechatApiService.SendTextMessageToWechatUser(userIdList,"<a href=\"www.baidu.com\">哈哈哈!</a>");
return resultMap;
}
@GetMapping("anon/SendTextCardMessageToWechatUser")
@ResponseBody
public Map<String, String> SendTextCardMessageToWechatUser() {
List<String> userIdList = new ArrayList<>();
userIdList.add("23456667");
userIdList.add("355354354");
userIdList.add("359");
userIdList.add("454");
userIdList.add("408");
String title="号外:特大优惠!限时抢购";
String description="今年仅此一次苹果手机1000元起欢迎前来购买走过路过不要错过";
String dtailUrl="https://item.jd.com/100008348530.html";
Map<String, String> resultMap = wechatApiService.SendTextCardMessageToWechatUser(userIdList,title,description,dtailUrl);
return resultMap;
}
}

View File

@ -47,7 +47,7 @@ public class TestController extends BaseController
}
@ApiOperation("获取用户详细")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path",dataTypeClass = Integer.class )
@GetMapping("/{userId}")
public AjaxResult getUser(@PathVariable Integer userId)
{
@ -63,10 +63,10 @@ public class TestController extends BaseController
@ApiOperation("新增用户")
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer"),
@ApiImplicitParam(name = "username", value = "用户名称", dataType = "String"),
@ApiImplicitParam(name = "password", value = "用户密码", dataType = "String"),
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String")
@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class),
@ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class),
@ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class),
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
})
@PostMapping("/save")
public AjaxResult save(UserEntity user)
@ -95,7 +95,7 @@ public class TestController extends BaseController
}
@ApiOperation("删除用户信息")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
@DeleteMapping("/{userId}")
public AjaxResult delete(@PathVariable Integer userId)
{

View File

@ -272,7 +272,9 @@ public class HttpUtils
* @param params 请求参数请求参数为json的形式params="{\"params\":{\"pagesize\":1000}}"
* @return 返回Map Key="statusCode",接口访问返回状态 key="result":接口返回接果
*/
public static Map<String,String> sendPostWithRest(String url, String params){
//public static Map<String,String> sendPostWithRest(String url, String params){
//如果参数为String类型推送企业微信消息会乱码因此改为Object类型直接推送Map<Sring,Object> --yangbo 20210729
public static Map<String,String> sendPostWithRest(String url, Object params){
RestTemplate restTemplate=new RestTemplate();
ResponseEntity<String> result=null;
int statusCode=0;

View File

@ -0,0 +1,111 @@
package com.ruoyi.system.domain;
public class WechatSendMessage {
public String touser;
public String toparty;
public String totag;
public String msgtype;
public Integer agentid;
public String text;
public Integer safe;
public Integer enable_id_trans;
public Integer enable_duplicate_check;
public Integer duplicate_check_interval;
public String getTouser() {
return touser;
}
public void setTouser(String touser) {
this.touser = touser;
}
public String getToparty() {
return toparty;
}
public void setToparty(String toparty) {
this.toparty = toparty;
}
public String getTotag() {
return totag;
}
public void setTotag(String totag) {
this.totag = totag;
}
public Integer getAgentid() {
return agentid;
}
public void setAgentid(Integer agentid) {
this.agentid = agentid;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Integer getSafe() {
return safe;
}
public void setSafe(Integer safe) {
this.safe = safe;
}
public Integer getEnable_id_trans() {
return enable_id_trans;
}
public void setEnable_id_trans(Integer enable_id_trans) {
this.enable_id_trans = enable_id_trans;
}
public Integer getEnable_duplicate_check() {
return enable_duplicate_check;
}
public void setEnable_duplicate_check(Integer enable_duplicate_check) {
this.enable_duplicate_check = enable_duplicate_check;
}
public Integer getDuplicate_check_interval() {
return duplicate_check_interval;
}
public void setDuplicate_check_interval(Integer duplicate_check_interval) {
this.duplicate_check_interval = duplicate_check_interval;
}
public String getMsgtype() {
return msgtype;
}
@Override
public String toString() {
return "WechatSendMessage{" +
"touser='" + touser + '\'' +
", toparty='" + toparty + '\'' +
", totag='" + totag + '\'' +
", msgtype='" + msgtype + '\'' +
", agentid=" + agentid +
", text='" + text + '\'' +
", safe=" + safe +
", enable_id_trans=" + enable_id_trans +
", enable_duplicate_check=" + enable_duplicate_check +
", duplicate_check_interval=" + duplicate_check_interval +
'}';
}
public void setMsgtype(String msgtype) {
this.msgtype = msgtype;
}
}

View File

@ -3,36 +3,36 @@ package com.ruoyi.system.domain;
import java.util.List;
public class WechatUserInfo {
String errocode; //返回码
Integer errcode; //返回码
String errmsg; //返回码描述
String Userid; //成员UserID
String name; //成员名称
String depatrment; //成员所属部门id列表
String order; //部门内的排序值
Object department; //成员所属部门id列表
Object order; //部门内的排序值
String position; //职务信息
String mobile; //手机号码
String gender; //性别0未定义12
String email; //邮箱
String is_leader_in_dept; //在所在的部门内是否为上级
Object is_leader_in_dept; //在所在的部门内是否为上级
String avatar; //头像Url
String thumb_avatar; //头像缩略图Url
String telephone; //座机
String alias; //别名
String address; //地址
String open_userid; //全局唯一id
String main_department; //主部门
String extattr; //扩展属性
String Status; //激活状态: 1=已激活2=已禁用4=未激活5=退出企业
Integer main_department; //主部门
Object extattr; //扩展属性
Integer Status; //激活状态: 1=已激活2=已禁用4=未激活5=退出企业
String qr_code; //员工个人二维码
String external_position; // 对外职务
String external_profile; //成员对外属性
Object external_profile; //成员对外属性
public String getErrocode() {
return errocode;
public Integer getErrcode() {
return errcode;
}
public void setErrocode(String errocode) {
this.errocode = errocode;
public void setErrcode(Integer errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
@ -59,19 +59,19 @@ public class WechatUserInfo {
this.name = name;
}
public String getDepatrment() {
return depatrment;
public Object getdepartment() {
return department;
}
public void setDepatrment(String depatrment) {
this.depatrment = depatrment;
public void setdepartment(Object department) {
this.department = department;
}
public String getOrder() {
public Object getOrder() {
return order;
}
public void setOrder(String order) {
public void setOrder(Object order) {
this.order = order;
}
@ -107,11 +107,11 @@ public class WechatUserInfo {
this.email = email;
}
public String getIs_leader_in_dept() {
public Object getIs_leader_in_dept() {
return is_leader_in_dept;
}
public void setIs_leader_in_dept(String is_leader_in_dept) {
public void setIs_leader_in_dept(Object is_leader_in_dept) {
this.is_leader_in_dept = is_leader_in_dept;
}
@ -163,27 +163,27 @@ public class WechatUserInfo {
this.open_userid = open_userid;
}
public String getMain_department() {
public Integer getMain_department() {
return main_department;
}
public void setMain_department(String main_department) {
public void setMain_department(Integer main_department) {
this.main_department = main_department;
}
public String getExtattr() {
public Object getExtattr() {
return extattr;
}
public void setExtattr(String extattr) {
public void setExtattr(Object extattr) {
this.extattr = extattr;
}
public String getStatus() {
public Integer getStatus() {
return Status;
}
public void setStatus(String status) {
public void setStatus(Integer status) {
Status = status;
}
@ -203,13 +203,11 @@ public class WechatUserInfo {
this.external_position = external_position;
}
public String getExternal_profile() {
public Object getExternal_profile() {
return external_profile;
}
public void setExternal_profile(String external_profile) {
public void setExternal_profile(Object external_profile) {
this.external_profile = external_profile;
}
}

View File

@ -1,9 +1,49 @@
package com.ruoyi.system.service;
import com.ruoyi.system.domain.WechatSendMessage;
import com.ruoyi.system.domain.WechatUserInfo;
import java.util.List;
import java.util.Map;
public interface IWechatApiService {
//获取Access Token
public String GetAccessToken();
//根据企业微信登录身份获取本地LoginName
public String GetLoginNameWithWechatCode(String code);
/**
* 根据企业微信登录链接的code用户获取userid;
* @param code
* @return userid
*/
public String GetUseridByWechatLogin(String code);
/**
* 根据企业微信userid获取用户详细信息
* @param userId
* @return 用户详细信息
*/
public WechatUserInfo GetWechatUserInfoDetailByUserId(String userId);
/**
* 推送text消息到企业微信用户
* @param toUserList 发送的用户列表
* @param message 发送的消息内容
* @return 消息发送结果
*/
public Map<String,String> SendTextMessageToWechatUser(List<String> toUserList, String message);
/**
* 推送文本卡片消息到企业微信用户
* description参数说明支持使用br标签或者空格来进行换行处理也支持使用div标签来使用不同的字体颜色目前内置了3种文字颜色灰色(gray)高亮(highlight)默认黑色(normal)将其作为div标签的class属性即可
* 示例"description" : "<div class=\"gray\">2016年9月26日</div> <div class=\"normal\">恭喜你抽中iPhone 7一台领奖码xxxx</div><div class=\"highlight\">请于2016年10月10日前联系行政同事领取</div>"
* @param toUserList 发送的用户列表
* @param title 标题
* @param description 内容描述
* @param detailUrl 点击详情的Url地址
* @return 消息发送结果
*/
public Map<String,String> SendTextCardMessageToWechatUser(List<String> toUserList, String title, String description, String detailUrl);
}

View File

@ -8,15 +8,17 @@ import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.system.domain.WechatAccessToken;
import com.ruoyi.system.domain.WechatSendMessage;
import com.ruoyi.system.domain.WechatUserInfo;
import com.ruoyi.system.mapper.WechatAccessTokenMapper;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.IWechatApiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Date;
import java.util.List;
import java.util.*;
@Service
public class WechatApiServiceImpl implements IWechatApiService {
@ -111,38 +113,19 @@ public class WechatApiServiceImpl implements IWechatApiService {
public String GetLoginNameWithWechatCode(String code)
{
//获取访问用户身份ID
String url="https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo";
String param = "access_token="+wechatApiService.GetAccessToken()+"&code="+code;
String userInfo = HttpUtils.sendGet(url,param); //测试已能正常返回UserInfo Json,正式使用时打开
//String userInfo = "{\"UserId\":\"359\",\"DeviceId\":\"10000589102865WJ\",\"errcode\":0,\"errmsg\":\"ok\"}"; //为避免去微信获取code麻烦开发调试时打开
JSONObject jsonObjectUserInfo = JSONObject.parseObject(userInfo);
//如果返回码不为0则输出错误信息并返回空值
if ( Integer.parseInt(jsonObjectUserInfo.getString("errcode")) != 0){
System.out.println(jsonObjectUserInfo.getString("errmsg"));
return "";
}
String userId = jsonObjectUserInfo.getString("UserId");
String userId= GetUseridByWechatLogin(code);
//获取用户邮箱与姓名
url="https://qyapi.weixin.qq.com/cgi-bin/user/get";
param="access_token="+wechatApiService.GetAccessToken()+"&userid="+userId;
String userInfoDetail=HttpUtils.sendGet(url,param); //获取成员信息
JSONObject jsonObjectUserInfoDetail=JSONObject.parseObject(userInfoDetail);
//如果返回码不为0则返回错误信息
if(Integer.parseInt(jsonObjectUserInfoDetail.getString("errcode")) != 0)
{
System.out.println(jsonObjectUserInfo.getString("errmsg"));
return "";
}
String userEmail= jsonObjectUserInfoDetail.getString("email");
String userName= jsonObjectUserInfoDetail.getString("name");
WechatUserInfo wechatUserInfo = GetWechatUserInfoDetailByUserId(userId);
//根据邮箱名+用户名匹配本地用户对应的邮箱名与用户名
SysUser sysUser=new SysUser();
sysUser.setUserName(userName);
sysUser.setEmail(userEmail);
sysUser.setUserType("02"); //只获取从OA同步的用户保持与企业微信一致
List<SysUser> userList= userService.selectUserLists(sysUser);
//根据用户id+邮箱名+用户名匹配本地用户对应的userId+邮箱名与用户名
SysUser sysUserWechat=new SysUser();
sysUserWechat.setUserId(Long.parseLong(wechatUserInfo.getUserid()));
sysUserWechat.setUserName(wechatUserInfo.getName());
sysUserWechat.setEmail(wechatUserInfo.getEmail());
sysUserWechat.setUserType("02"); //只获取从OA同步的用户保持与企业微信一致
List<SysUser> userList= userService.selectUserLists(sysUserWechat);
int count= userList.size();
if(count <= 0){
return ""; //系统里没有用户没有从OA同步 处理逻辑待定
@ -155,4 +138,114 @@ public class WechatApiServiceImpl implements IWechatApiService {
}
/**
* 根据企业微信登录链接的code用户获取userid;
*
* @param code
* @return userid
*/
@Override
public String GetUseridByWechatLogin(String code) {
String url="https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo";
String param = "access_token="+wechatApiService.GetAccessToken()+"&code="+code;
//String userInfo = HttpUtils.sendGet(url,param); //测试已能正常返回UserInfo Json,正式使用时打开
String userInfo = "{\"UserId\":\"359\",\"DeviceId\":\"10000589102865WJ\",\"errcode\":0,\"errmsg\":\"ok\"}"; //为避免去微信获取code麻烦开发调试时打开
JSONObject jsonObjectUserInfo = JSONObject.parseObject(userInfo);
//如果返回码不为0则输出错误信息并返回空值
if ( Integer.parseInt(jsonObjectUserInfo.getString("errcode")) != 0){
System.out.println(jsonObjectUserInfo.getString("errmsg"));
return "";
}
return jsonObjectUserInfo.getString("UserId");
}
/**
* 根据企业微信userid获取用户详细信息
*
* @param userId
* @return 用户详细信息
*/
@Override
public WechatUserInfo GetWechatUserInfoDetailByUserId(String userId) {
String url="https://qyapi.weixin.qq.com/cgi-bin/user/get";
String param="access_token="+wechatApiService.GetAccessToken()+"&userid="+userId;
String userInfoDetail=HttpUtils.sendGet(url,param); //获取成员信息
WechatUserInfo wechatUserInfo = JSONObject.parseObject(userInfoDetail,WechatUserInfo.class);
//如果返回码不为0则返回空显示错误信息
if (wechatUserInfo.getErrcode() !=0)
{
System.out.println(wechatUserInfo.getErrmsg());
return null;
}
return wechatUserInfo;
}
private String CovertListToWechatTouserFormat(List<String> toUserList){
StringBuilder toUser = new StringBuilder();
for(String user:toUserList){
toUser.append(user);
if(toUserList.indexOf(user) < toUserList.size()-1){
toUser.append("|");
}
}
return toUser.toString();
}
/**
* 推送text消息到企业微信用户
* @param toUserList 发送的用户列表
* @param message 发送的消息内容
* @return 消息发送结果
*/
@Override
public Map<String,String> SendTextMessageToWechatUser(List<String> toUserList,String message) {
Map<String,String> resultMap;
Map<String, Object> param = new HashMap<>(16);
param.put("touser", CovertListToWechatTouserFormat(toUserList));
param.put("msgtype", "text");
param.put("agentid", agentId);
Map<String, String> text = new HashMap<>(16);
text.put("content", message);
param.put("text", text);
String url="https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="+wechatApiService.GetAccessToken();
//param参数需要直接使用对象而不能转换成json字符串否则推送到企业微信中文消息乱码
resultMap =HttpUtils.sendPostWithRest(url,param);
return resultMap;
}
/**
* 推送文本卡片消息到企业微信用户
* description参数说明支持使用br标签或者空格来进行换行处理也支持使用div标签来使用不同的字体颜色目前内置了3种文字颜色灰色(gray)高亮(highlight)默认黑色(normal)将其作为div标签的class属性即可
* 示例"description" : "<div class=\"gray\">2016年9月26日</div> <div class=\"normal\">恭喜你抽中iPhone 7一台领奖码xxxx</div><div class=\"highlight\">请于2016年10月10日前联系行政同事领取</div>"
*
* @param toUserList 发送的用户列表
* @param title 标题
* @param description 内容描述
* @param detailUrl 点击详情的Url地址
* @return 消息发送结果
*/
@Override
public Map<String, String> SendTextCardMessageToWechatUser(List<String> toUserList, String title, String description, String detailUrl) {
Map<String,String> resultMap;
Map<String, Object> param = new HashMap<>(16);
param.put("touser", CovertListToWechatTouserFormat(toUserList));
param.put("msgtype", "textcard");
param.put("agentid", agentId);
Map<String, Object> textcard=new HashMap<>();
textcard.put("title",title);
textcard.put("description",description);
textcard.put("url",detailUrl);
param.put("textcard",textcard);
String url="https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="+wechatApiService.GetAccessToken();
//param参数需要直接使用对象而不能转换成json字符串否则推送到企业微信中文消息乱码
resultMap =HttpUtils.sendPostWithRest(url,param);
return resultMap;
}
}

View File

@ -231,6 +231,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectUserLists" parameterType="SysUser" resultMap="SysUserResult">
select user_id, dept_id, login_name, user_name, user_type, email, avatar, phonenumber, password, sex, salt, status, del_flag, login_ip, login_date, create_by, create_time, remark from sys_user
where del_flag = '0'
<if test="userId != null and useId != ''">
AND user_id = #{userId}
</if>
<if test="userName != null and userName != ''">
AND user_name = #{userName}
</if>