企业微信登陆地址:https://work.weixin.qq.com(最好是管理员身份,或者自己注册一个自己企业微信)
服务端api:https://work.weixin.qq.com/api/doc#90001/90143/90371
我们找到第三应用消息推动的相关api
应用支持推送文本、图片、视频、文件、图文等类型。
请求方式:POST(HTTPS)
请求地址: https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN
参数说明:
参数 | 是否必须 | 说明 |
---|---|---|
access_token | 是 | 调用接口凭证 |
各个消息类型的具体POST格式参考以下文档。
当应用设置“在微工作台中始终进入主页”后应用在微信端只能接收到文本消息,并且文本消息的长度限制为20字节,超过20字节会被截断。同时其他消息类型也会转换为文本消息,提示用户到企业微信查看。
首先我们需要拿到access_token,但是access_token是什么呢?可以查看开发前必读,有区分三种类型的access_token,
在第三方应用开发提供的接口中,会涉及到三种类型的access_token。下面表格对这三类token的定义及使用场景进行说明,开发者应在不同场景中选择对应的token:
类型 | 说明 | 适用场景 |
---|---|---|
服务商的token | 以corpid(服务商CorpID)、provider_secret(服务商密钥)换取provider_access_token,代表的是服务商的身份 | 用于服务商级别的接口调用,比如登录授权、推广二维码等。说明文档参考 获取服务商凭证 |
第三方应用的token | 以suite_id(第三方应用ID)、suite_secret(第三方应用密钥)换取suite_access_token,代表第三方应用的身份 | 用于获取第三方应用的预授权码,获取授权企业信息等。说明文档参考 获取第三方应用凭证 |
授权企业的token | 企业安装第三方应用后,第三方服务商以企业的corpid、永久授权码来获取access_token | 用于操作授权企业相关接口,如通讯录管理,消息推送等。说明文档参考 获取企业凭证 |
然后第三个“授权企业的token”,可以看到使用场景中有消息推送,点击 获取企业凭证进行查看。
第三方服务商在取得企业的永久授权码后,通过此接口可以获取到企业的access_token。
获取后可通过通讯录、应用、消息等企业接口来运营这些应用。
此处获得的企业access_token与企业获取access_token拿到的token,本质上是一样的,只不过获取方式不同。获取之后,就跟普通企业一样使用token调用API接口
调用企业接口所需的access_token获取方法如下。
请求方式:POST(HTTPS)
请求地址: https://qyapi.weixin.qq.com/cgi-bin/service/get_corp_token?suite_access_token=SUITE_ACCESS_TOKEN
此处获得的企业access_token与企业获取access_token拿到的token,本质上是一样的,所以我选择了第二种方式。
请求方式:GET(HTTPS)
请求URL:https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRECT
注:此处标注大写的单词ID和SECRET,为需要替换的变量,根据实际获取值更新。其它接口也采用相同的标注,不再说明。
若企业安装了第三方应用,该服务商可通过“获取企业access_token”获得此调用凭证。
参数说明:
参数 | 必须 | 说明 |
---|---|---|
corpid | 是 | 企业ID |
corpsecret | 是 | 应用的凭证密钥 |
权限说明:
每个应用有独立的secret,所以每个应用的access_token应该分开来获取
返回结果:
{
"errcode":0,
"errmsg":"",
"access_token": "accesstoken000001",
"expires_in": 7200
}
参数 | 说明 |
---|---|
access_token | 获取到的凭证,最长为512字节 |
expires_in | 凭证的有效时间(秒) |
出错返回示例:
{
"errcode":40091,
"errmsg":"secret is invalid"
}
特别说明:
企业微信所有接口,返回包里都有errcode、errmsg。开发者需根据errcode是否为0判断是否调用成功(errcode意义请见全局错误码)。
而errmsg仅作参考,后续可能会有变动,因此不可作为是否调用成功的判据。
后面不再赘述。
其中企业的id和应用的凭证秘钥可以在术语介绍中找到,但是需要管理员权限
我们拿到access_token之后就可已进行消息的推送了,官方的api给了很多的消息类型,我只是简单的开发了文本卡片消息,
因为官方发送消息的api已经很详细了,上面的都包括了,我只是记录一下自己的思路。所以,下面直接上代码。
@Service
public class QywxSendMessageServiceImpl implements QywxSendMessageService{
private final String agentid="1000003"; //这是企业应用的id
private final String secret="qiyeyingyongmiyao";//这是企业应用的秘钥,自己手动更新
@Override
public String sendMessage(Params param) {
String qywxId = param.getString("qywxId");//获取参数,企业微信的id
String token =getAccessToken(qywxId,secret);//获取token
String userId=param.getString("userId");//推送给具体某个人的userid
String departmentId="";
String content=param.getString("context");
// String msgtype="mytext";
// String agentid="1000002";//WxConstants.AGENTID是应用的agenid
// String content="测试消息推送:你的快递已到,请携带工卡前往邮件中心领取。\n出发前可查看邮件中心视频实况,聪明避开排队。";
Map params = new LinkedHashMap();
params.put("touser", userId);
// params.put("toparty", departmentId);
params.put("agentid", agentid);
JSONObject mytext = new JSONObject();
mytext.put("title","领奖通知");
mytext.put("description","2009年5月10日 恭喜你抽中玛莎拉蒂一辆,领奖码:xxxx请于2009年5月9日前联系行政同事领取");
mytext.put("url","url");
mytext.put("btntxt","更多");
// params.put("msgtype", "text");
params.put("msgtype", "textcard");
params.put("textcard",mytext);
String result="发送失败";
try {
String aa=HttpUtils.httpPostMethod("https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + token, params);
JSONObject parseObject = JSON.parseObject(aa);
String string = parseObject.getString("errcode");
if("0".equals(string)){
result="发送成功";
}else{
result=aa;
}
System.out.println("1.推送消息请求微信接口=="+aa);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private String getAccessToken(String qywxId, String secret2) {
String url="https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid="+qywxId+"&corpsecret="+secret2+"";
String token=null;
try {
token = HttpUtils.httpGetMethod(url);
} catch (Exception e) {
e.printStackTrace();
}
return token;
}
}
public class HttpUtils {
public static String httpPostMethod(String url,
Map params) {
String returnValue = "接口调用失败";
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost post = new HttpPost(url);
post.setHeader("Content-Type","Content-Type");
post.setEntity(new StringEntity(JSON.toJSONString(params), "utf-8"));
CloseableHttpResponse response = null;
try{
response = httpClient.execute(post);
if(response != null && response.getStatusLine().getStatusCode() == 200){
HttpEntity entity = response.getEntity();
returnValue = EntityUtils.toString(entity);
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally {
try {
httpClient.close();
} catch (Exception e) {
//
e.printStackTrace();
}
}
//第五步:处理返回值
return returnValue;
}
public static String httpGetMethod(String url) throws Exception, Exception {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet get = new HttpGet(url);
CloseableHttpResponse response = null;
response = httpClient.execute(get);
HttpEntity entity = response.getEntity();
String returnValue = EntityUtils.toString(entity);
JSONObject jsonObject = JSON.parseObject(returnValue);
String token = jsonObject.getString("access_token");
//建议此处需要将token缓存起来,避免总是调用接口
return token;
}
}