springboot集成微软teams的实例代码
短信预约 -IT技能 免费直播动态提醒
前言
最近做了一个有关微软的平台teams开发,在国内用微软teams聊天工具的少之又少,整个亚洲也没什么开发的实例,官方文档写的有点乱,在没有第三方支持下开发有点头疼。需求是做一个管理后台跟teams打通,支持各种通告发送,以及撤回。没时间具体些,用的东西丢在上面用上的可以参考。
添加依赖
<dependency>
<groupId>com.microsoft.graph</groupId>
<artifactId>microsoft-graph</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>com.microsoft.graph</groupId>
<artifactId>microsoft-graph-core</artifactId>
<version>1.0.5</version>
</dependency>
<dependency>
<groupId>com.microsoft.graph</groupId>
<artifactId>microsoft-graph-auth</artifactId>
<version>0.3.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>msal4j</artifactId>
<version>1.0.0</version>
</dependency>
业务逻辑层
package com.tg.admin.service;
import com.tg.admin.utils.CommonResult;
import java.util.Map;
public interface SplGraphService {
String getToken();
* 获取用户所属团队
* @return 结果
CommonResult<Map<String, Object>> getTeamsInfo();
* 获取用户所属渠道
* @param teamsId 团队ID
CommonResult<Map<String, Object>> getChannel(String teamsId);
* 根据teamsId、channelId获取用户信息
* @param teamsId 团队ID
* @param channelId 渠道ID
CommonResult<Map<String, Object>> getMember(String teamsId, String channelId);
* 发送消息
* @param content 消息内容
* @param teamId 团队ID
CommonResult<Map<String, Object>> sendMs(String content, String teamId, String channelId);
* 添加渠道
* @param displayName 渠道名称
* @param description 渠道备注
* @param teamId 渠道ID
* @return 渠道ID
CommonResult<Map<String, Object>> addChannel(String displayName, String description, String teamId);
* 添加成员
* @param userNum 用户名称
CommonResult<Map<String, Object>> addMembers(String teamId, String channelId, String userNum);
}
业务逻辑实现
package com.tg.admin.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.microsoft.graph.models.extensions.IGraphServiceClient;
import com.microsoft.graph.requests.extensions.GraphServiceClient;
import com.tg.admin.service.ChannelUserLogService;
import com.tg.admin.service.SplGraphService;
import com.tg.admin.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class SplGraphServiceImpl implements SplGraphService {
@Value("#{'${teams.graph.scopes}'.split(',')}")
private List<String> scopes;
@Value("${teams.graph.clientId}")
private String clientId;
@Value("${teams.graph.team.url}")
private String teamsUrl;
@Value("${teams.graph.channel.url}")
private String channelUrl;
@Value("${teams.graph.add.channel.url}")
private String addChannelUrl;
@Value("${teams.graph.ms.url}")
private String msUrl;
@Value("${teams.graph.member.url}")
private String memberUrl;
@Value("${teams.graph.add.channel.members.url}")
private String addChannelMembersUrl;
@Value("${teams.graph.account}")
private String account;
@Value("${teams.graph.password}")
private String password;
private RedisUtil redisUtil;
private RestTemplate restTemplate;
private ChannelUserLogService channelUserLogService;
public SplGraphServiceImpl(RestTemplate restTemplate, RedisUtil redisUtil, @Lazy ChannelUserLogService channelUserLogService) {
this.restTemplate = restTemplate;
this.redisUtil = redisUtil;
this.channelUserLogService = channelUserLogService;
}
@Override
public String getToken() {
Object token = redisUtil.get(Constants.ADMIN_TOKEN_KEY + account);
try {
if (token == null) {
MyAuthenticationProvider authProvider = new MyAuthenticationProvider(clientId, scopes, account, password);
IGraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();
graphClient.me().buildRequest().get();
token = authProvider.getToken();
redisUtil.set(Constants.ADMIN_TOKEN_KEY + account, token, Constants.TOKEN_EXPIRES_TIME);
}
} catch (Exception e) {
log.info("获取teams-graph,获取token接口异常", e);
}
return token.toString();
public CommonResult<Map<String, Object>> getTeamsInfo() {
JSONArray value = null;
Map<String, Object> result = new HashMap<>();
JSONObject jsonObject = new JSONObject();
log.info("调用temas获取团队信息:teamsUrl{}", teamsUrl);
//设置请求头
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", getToken());
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
jsonObject = RestTemplateUtils.requestByGet(teamsUrl, null, restTemplate, headers);
log.info("返回值:jsonObject:{}", jsonObject.toJSONString());
value = jsonObject.getJSONArray("value");
result.put("value", value);
e.printStackTrace();
return CommonResult.ok(result);
public CommonResult<Map<String, Object>> getChannel(String teamId) {
JSONArray array = null;
String url = channelUrl.replace("{team-id}", teamId);
log.info("调用teams获取用户渠道url:{}", url);
jsonObject = RestTemplateUtils.requestByGet(url, null, restTemplate, headers);
log.info("返回结果:jsonObject:{}", jsonObject.toJSONString());
array = jsonObject.getJSONArray("value");
result.put("value", array);
public CommonResult<Map<String, Object>> getMember(String teamsId, String channelId) {
String url = memberUrl.replace("{team-id}", teamsId).replace("{channel-id}", channelId);
log.info("调用teams获取渠道成员:url:{}", url);
public CommonResult<Map<String, Object>> sendMs(String content, String teamId, String channelId) {
String url = msUrl.replace("{team-id}", teamId).replace("{channel-id}", channelId);
log.info("调用teams发送消息:url:{}", url);
Map<String, Object> map = new HashMap<String, Object>();
Map<String, Object> body = new HashMap<>();
map.put("content", content);
map.put("contentType", "html");
body.put("body", map);
jsonObject = RestTemplateUtils.requestByPost(url, body, restTemplate, headers);
log.info("返回结果:jsonObject:{}", jsonObject.toJSONString());
return CommonResult.ok();
public CommonResult<Map<String, Object>> addChannel(String displayName, String description, String teamId) {
String url = addChannelUrl.replace("{id}", teamId);
log.info("调用teams添加渠道:url:{}", url);
map.put("displayName", displayName);
map.put("description", description);
jsonObject = RestTemplateUtils.requestByPost(url, map, restTemplate, headers);
if (jsonObject != null) {
result.put("id", jsonObject.getString("id"));
public CommonResult<Map<String, Object>> addMembers(String teamId, String channelId, String userNum) {
String url = addChannelMembersUrl.replace("{team-id}", teamId).replace("{channel-id}", channelId);
log.info("调用teams添加成员:url:{}", url);
map.put("@odata.type", "#microsoft.graph.aadUserConversationMember");
JSONArray roles = new JSONArray();
roles.add("owner");
map.put("roles", roles);
}
RestTemplateUtils 工具类
package com.tg.admin.utils;
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import java.util.HashMap;
import java.util.Map;
@Component
public class RestTemplateUtils {
public static JSONObject requestByGet(String url, HashMap<String, Object> map, RestTemplate restTemplate, HttpHeaders headers) {
// header填充
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity(null, headers);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
//ResponseEntity responseEntity;
ResponseEntity<JSONObject> responseEntity;
//如果存在參數
if (map != null) {
for (Map.Entry<String, Object> e :
map.entrySet()) {
//构建查询参数
builder.queryParam(e.getKey(), e.getValue());
}
//拼接好参数后的URl//test.com/url?param1={param1}¶m2={param2};
String reallyUrl = builder.build().toString();
responseEntity = restTemplate.exchange(reallyUrl, HttpMethod.GET, request, JSONObject.class);
} else {
responseEntity = restTemplate.exchange(url, HttpMethod.GET, request, JSONObject.class);
}
return responseEntity.getBody();
}
public static JSONObject requestByPost(String url, Map<String, Object> map, RestTemplate restTemplate, HttpHeaders headers) {
// header填充,map填充
HttpEntity<Map<String, Object>> request = new HttpEntity<Map<String, Object>>(map, headers);
ResponseEntity<JSONObject> entity = restTemplate.postForEntity(url, request, JSONObject.class);
return entity.getBody();
}
}
测试接口
package com.tg.admin.controller;
import com.tg.admin.service.SplGraphService;
import com.tg.admin.utils.CommonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
@Api(description = "teams-graph模块(第三方测试接口)")
@RestController
@RequestMapping("/graph")
@RefreshScope
@Slf4j
@Deprecated //添加过期注解,接口保留方便后期异常排查
public class GraphController {
private SplGraphService tgService;
public GraphController(SplGraphService tgService) {
this.tgService = tgService;
}
@ApiOperation("获取所属团队信息")
@GetMapping("/getTeamsInfo")
public CommonResult getTeamsInfo() {
return tgService.getTeamsInfo();
@ApiOperation("获取token")
@GetMapping("/getToken")
public CommonResult getToken() {
return CommonResult.ok(tgService.getToken());
@ApiOperation("获取用户所属渠道")
@ApiImplicitParams({
@ApiImplicitParam(name = "teamId", value = "团队Id", dataType = "string", required = true)
})
@GetMapping("/getChannel")
public CommonResult getChannel(@RequestParam(value = "teamId") String teamId) {
return tgService.getChannel(teamId);
@ApiOperation("获取渠道下的成员")
@ApiImplicitParam(name = "teamId", value = "团队Id", dataType = "string", required = true),
@ApiImplicitParam(name = "channelId", value = "渠道Id", dataType = "string", required = true)
@GetMapping("/getMember")
public CommonResult getMember(@RequestParam(value = "teamId") String teamId,
@RequestParam(value = "channelId") String channelId) {
return tgService.getMember(teamId, channelId);
@ApiOperation("创建团队下的渠道(备用接口)")
@ApiImplicitParam(name = "displayName", value = "渠道名称", dataType = "string", required = true),
@ApiImplicitParam(name = "description", value = "渠道备注", dataType = "string", required = true)
@PostMapping("/addChannel")
public CommonResult addChannel(@RequestParam(value = "teamId") String teamId,
@RequestParam(value = "displayName") String displayName,
@RequestParam(value = "description") String description
) {
return tgService.addChannel(displayName, description, teamId);
@ApiOperation("向渠道里面添加成员(备用接口)")
@ApiImplicitParam(name = "channelId", value = "渠道ID", dataType = "string", required = true),
@ApiImplicitParam(name = "userNum", value = "用户Id", dataType = "string", required = true)
@PostMapping("/addMembers")
public CommonResult addMembers(@RequestParam(value = "teamId") String teamId,
@RequestParam(value = "channelId") String channelId,
@RequestParam(value = "userNum") String userNum
return tgService.addMembers(teamId, channelId, userNum);
@ApiOperation("通过teamId,channelId发送消息")
@PostMapping("/sendMs")
@ApiImplicitParam(name = "content", value = "内容", dataType = "string", required = true),
public CommonResult sendMs(@RequestParam(value = "teamId") String teamId,
@RequestParam(value = "content") String content,
@RequestParam(value = "channelId") String channelId) {
return tgService.sendMs(content, teamId, channelId);
}
yml 配置
teams:
graph:
#微软master账号,密码
account: 管理员账号
password: 管理员密码
add:
channel:
members:
url: https://graph.microsoft.com/v1.0/teams/{team-id}/channels/{channel-id}/members
url: https://graph.microsoft.com/v1.0/teams/{id}/channels
channel:
url: https://graph.microsoft.com/v1.0/teams/{team-id}/channels
clientId: e730901a-8bf3-472b-93dd-afe79713bc5b
member:
url: https://graph.microsoft.com/v1.0/teams/{team-id}/channels/{channel-id}/members
ms:
url: https://graph.microsoft.com/v1.0/teams/{team-id}/channels/{channel-id}/messages
scopes: Group.Read.All,User.Read
team:
url: https://graph.microsoft.com/v1.0/me/joinedTeams
到此这篇关于springboot集成微软teams的文章就介绍到这了,更多相关springboot集成微软teams内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341