一、前言

哈哈,这是我的第一篇博客。

先说一下这个小功能的具体场景:

用户登录钉钉app,点击微应用,获取当前用户的信息,与H5系统的数据库的用户信息对比,如果存在该用户,则点击后直接进入H5系统的首页,否则显示“您无权限”。

补充:又加了一个小需求,就是免登成功,会给该用户发条消息

我是参考钉钉开发文档实现的这个小功能,文档地址:https://ding-doc.dingtalk.com/doc#/serverapi2/clotub

二、准备工作

需要创建一个微应用:https://open-dev.dingtalk.com

1.是在企业内部开发中创建H5微应用,不是第三方企业应用中

企业内部开发:企业内部开发是指“开发企业内部应用”供企业内部的人员使用。企业可以选择由企业内部的开发者进行开发,或者由企业授权定制服务商进行开发。

第三方企业应用:第三方企业应用开发,是指开发者以钉钉、企业之外的第三方身份,基于钉钉的开放能力开发应用,并提供给钉钉上的其他组织使用。(哈哈,这个区别我是直接copy文档中的)

2.H5工程中,创建的一个前端页面ddNoLogin.html(哈哈,这个起名有点中文式英语,因为我没有找到合适的英文单词):

该页面是用来获取免登授权码,然后把该code传递给后台接口的。

3.填写公司服务器的公网IP

可以敲命令查看该ip:curl ifconfig.me

4.微应用创建好,会生成三个参数,

agentId、appKey、appSecret

外加一个corpId(钉钉开发者平台的首页中有显示),这四个参数值是固定的,后续开发需用

5.接口权限

高级权限-企业通讯录中的接口都需要给开通

6.最后发布应用

三、功能开发

哈哈,要开始敲代码了

1.获取免登授权码code

这里调用的是钉钉JS-API中的方法,本功能调用的方法是不需要鉴权的,如果需要鉴权,则还需先dd.config。

关于功能方法是否需要鉴权,可以去查看JSAPI总览

ddNoLogin.html:

<!DOCTYPE html>
<html>
<head>
<title>微应用登陆</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1 user-scalable=0" />
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="http://g.alicdn.com/dingding/open-develop/1.9.0/dingtalk.js"></script>
</head>
<body>
<div id="ddNoLogin"></div>
<script type="text/javascript">
dd.ready(function() {
//1.获取免登授权码code
dd.runtime.permission.requestAuthCode({
corpId : corpId , //企业id
onSuccess : function(result) {
var code = result.code;
getUserInfo(code); //通过该code可以获取用户身份
},
onFail : function(err) {
alert('出错了, ' + err);
}
});
});
function getUserInfo(code) {
$.ajax({
type : "GET",
url : "/xxx/noLogin?code=" + code,
async : false,
dataType : 'json',
contentType : "application/json;charset=utf-8",
success : (function(res) {
if(res.code == "0000"){
window.location.href = '/#/xxxxx';
}else{
$('#ddNoLogin').html(res.msg);
}
}),
});
}
</script>
</body>
</html>

获取code的实现是需要用前端JS去写的

2.获取access_token

钉钉提供了开放的api后台接口,这里通过appkey和appsecret获取token,请求路径:https://oapi.dingtalk.com/gettoken?appkey=key&appsecret=secret

该token有效期是2个小时,有效期内重复获取,会返回相同结果,并自动续期,

故这里我的实现是:定时刷新token,每隔1小时50分钟去获取钉钉的token,并缓存到redis中(我把钉钉的相关配置都放入到application.yml中了)

DdTokenTask.java:

/**
* 定时获取钉钉的token
*/
@Component
@EnableScheduling
public class DdTokenTask { @Autowired
private JedisClient jedisClient; public static final long cacheTime = 1000 * 60 * 55 * 2;//1小时50分钟
@Value("${dtalk.tokenUrl}")
private String tokenUrl;
@Value("${dtalk.app.key}")
private String appKey;
@Value("${dtalk.app.secret}")
private String appSecret;
@Value("${dtalk.redisTokenKey}")
private String tokenKey;
@Value("${dtalk.taskRun}")
private String taskRun; /**
* 每隔1小时50分钟获取钉钉的access_token
*/
@Scheduled(fixedRate = cacheTime)
@Async
public void getDdTokenTask(){
if("true".equals(taskRun)){
//刷新
System.out.println("--->>>>>-------------获取钉钉token的定时任务开始了:"+ DateUtil.formatDateToString(new Date(), "HH:mm:ss")); String accessTokenUrl = tokenUrl + "?appkey=" + appKey + "&appsecret=" + appSecret;
//访问获取access_token 有效期是2小时
String accessToken = JsonUtil.getJsonNode(HttpUtil.doGet(accessTokenUrl)).get("access_token").asText();
//放入到redis中
jedisClient.set(tokenKey, accessToken); System.out.println("--->>>>>-------------获取钉钉token的定时任务结束了,token:"+accessToken);
}
} /*private String getAccessToken(){
//需引入SDK,公司私服没有
DefaultDingTalkClient client = new
DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
OapiGettokenRequest request = new OapiGettokenRequest();
request.setAppkey("appkey");
request.setAppsecret("appsecret");
request.setHttpMethod("GET");
OapiGettokenResponse response = client.execute(request);
return "";
}*/ }

(哈哈,其实文档中提供了钉钉SDK的java写法,不过公司私服没有该SDK,所以我就直接用htttp请求了)

3.获取用户userid

通过免登授权码和access_token获取用户的userid,请求路径:https://oapi.dingtalk.com/user/getuserinfo?access_token=access_token&code=code

4.获取用户详情

请求路径:https://oapi.dingtalk.com/user/get?access_token=ACCESS_TOKEN&userid=shaocui

会返回用户的姓名、手机号等所有信息

DdLoginController.java:

@RestController
@RequestMapping("/ddUser")
@Api(value = "/ddUser", description = "钉钉H5微应用登录", tags = {"DdLoginController"})
public class DdLoginController { @Autowired
private JedisClient jedisClient; @Value("${dtalk.userUrl}")
private String userUrl;
@Value("${dtalk.userDetailUrl}")
private String userDetailUrl;
@Value("${dtalk.redisTokenKey}")
private String tokenKey;
@Value("${dtalk.agentId}")
private Integer agentId; @GetMapping("/noLogin")
@ApiOperation( "钉钉免登")
@ApiImplicitParam(paramType = "query", name = "code", value = "免登授权码", dataType = "String")
public WebResponse noLogin(@RequestParam("code") String code, HttpServletResponse response){
//2.获取access_token
String accessToken = jedisClient.get(tokenKey); //3.获取用户userid
String userIdUrl =userUrl + "?access_token=" + accessToken + "&code=" + code;
//访问获取userid
JsonNode user = JsonUtil.getJsonNode(HttpUtil.doGet(userIdUrl));
if(user.get("errcode").asInt() != 0){
//有些公司的公网ip不固定,导致微应用中设置的不对,这里就会报错
return WebResponse.resFail(user.get("errmsg").asText());
}
String userId = user.get("userid").asText(); //4.获取用户详情 手机号
String userInfoUrl = userDetailUrl + "?access_token=" + accessToken + "&userid=" + userId;
//访问获取mobile
JsonNode userInfo = JsonUtil.getJsonNode(HttpUtil.doGet(userInfoUrl));
String mobile = userInfo.get("mobile").asText(); System.out.println("钉钉用户的手机号:"+mobile); //通过手机号获取该用户
SysUser sysUser = 。。。。。;
if(sysUser == null){
//不存在该用户
return WebResponse.resFail("您无权限访问", null);
} 。。。。。。 //钉钉发送免登成功消息给用户
sendMessage(accessToken, userId, userInfo.get("name").asText()); return WebResponse.resSuccess("免登成功", loginUserInfo);
} //钉钉发送消息给用户
private void sendMessage(String token, String userId, String userName){
String messageUrl = "https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token="+token;
Map<String, Object> map = new HashMap<>();
map.put("agent_id", agentId.longValue());
map.put("userid_list", userId);
map.put("to_all_user", false);
String content = "用户"+userName+"在"+ DateUtil.formatDateToString(new Date(), "yyyy-MM-dd HH:mm:ss")+"时成功登录xxH5端,并进入到xxx页面";
String msg = "{\"msgtype\":\"text\",\"text\":{\"content\":"+"\""+content+"\""+"}}";
JSONObject jsonObj = JSONObject.parseObject(msg);
map.put("msg",jsonObj); HttpUtil.doPost(messageUrl, map, "UTF-8", 20000, null);
}
}

(哈哈,那个。。。。。处的代码是实现系统认证成功后的具体操作,故这里省略)

到此钉钉免登就实现了,然后免登成功后给用户发送消息

5.工作通知消息

POST请求,请求路径:https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token=ACCESS_TOKEN

请求体{agent_id、userid_list、dept_id_list、to_all_user、msg}

注意:

给同一个用户发送相同的内容,一天只能发一次;发送不同的内容,一天可以500次,

故这里我在发送的消息中添加了当前时间。

(哈哈,一些细节的东西我都写在代码的注释里了,最后发现这个小功能好像就一点点代码量)

用java实现“钉钉微应用,免登进入某H5系统首页“功能”的更多相关文章

  1. 钉钉开发第三方H5微应用入门详细教程[ISV][免登流程][授权码][HTTP回调推送][识别用户身份][获取用户信息]

    转载请注明原文地址:https://www.cnblogs.com/applerosa/p/11509512.html (by lnexin@aliyun.com 世间草木) 此教程注意点: 适用于第 ...

  2. .NET平台下,钉钉微应用开发之:获取userid

    工作需求,开发钉钉微应用和小程序,之前有接触过支付宝小程序和生活号的开发,流程没有很大的差别,这里记录下我用ASP.NET MVC实现钉钉微应用的开发,并实现获取用户的userid.小弟我技术有限,本 ...

  3. 钉钉企业内部H5微应用开发

    企业内部H5微应用开发 分为 服务端API和前端API的开发,主要涉及到进入应用免登流程和JSAPI鉴权. JSAPI鉴权开发步骤: 1.创建H5微应用 登入钉钉开放平台(https://open-d ...

  4. Java钉钉开发_02_免登授权(身份验证)(附源码)

    源码已上传GitHub: https://github.com/shirayner/DingTalk_Demo 一.本节要点 1.免登授权的流程 (1)签名校验 (2)获取code,并传到后台 (3) ...

  5. 钉钉开发入门,微应用识别用户身份,获取用户免登授权码code,获取用户userid,获取用户详细信息

    最近有个需求,在钉钉内,点击微应用,获取用户身份,根据获取到的用户身份去企业内部的用户中心做校验,校验通过,相关子系统直接登陆; 就是在获取这个用户身份的时候,网上的资料七零八落的,找的人烦躁的很,所 ...

  6. Java钉钉开发_02_免登授权(身份验证)

    源码已上传GitHub: https://github.com/shirayner/DingTalk_Demo 一.本节要点 1.免登授权的流程 (1)签名校验 (2)获取code,并传到后台 (3) ...

  7. 钉钉微应用接入钉钉免登陆配置记录。NET实现

    在这里记录一下我配置的钉钉接入微应用遇到的坑.搞了我几天天才调通.头皮发麻,现在梳理一下,以免别人也入坑. 1.钉钉接入主要要获取钉钉企业员工的ID,然后去自己的应用的数据库里进行匹配然后实现免登陆的 ...

  8. Java钉钉开发_03_通讯录管理之 人员管理 和 部门管理

    一.本节要点 1.通讯录权限 ISV(应用服务商)默认无管理通讯录的权限,企业应用默认有所有通讯录权限. 2.数据传输格式—JSON 请参见: Java_数据交换_fastJSON_01_用法入门 二 ...

  9. js api 实现钉钉免登

    js api 实现钉钉免登,用于从钉钉微应用跳转到企业内部的oa,erp等,我刚刚实施完了我公司的这个功能,钉钉用起来还不错. 1 js api 实现钉钉免登,页面配置. <title>利 ...

随机推荐

  1. python 可变数量参数 ( 多参数返回求 参数个数,最大值,最大值)

    一. 自定义一串数字求 参数个数,最大值,最大值()---------方法一: def max(*a): m=a[0] p=a[0] n=0 for x in a: if x>m: m=x n+ ...

  2. instruments无法连接,设备查询不到,找不到工程,查询不到对应app

    这种问题真是让人捉急,一定要沐浴更衣,怀着一颗虔诚的心. 1.拔掉设备(iPhone/iPad),关掉设备.(长按电源键) 2.关闭Xcode和Instruments 3.重启设备(iPhone/iP ...

  3. JVM - 复习

    内存模型图 程序计数器(PC) 程序计数器的特点 PC是一小块内存空间,用于记录当前线程执行的字节码指令的地址.如果执行的是本地方法(native),PC里此时显示Undefined 优点: 控制程序 ...

  4. 使用Java8 Stream API对Map按键或值进行排序

    一.什么是Java 8 Stream 使用Java 8 Streams,我们可以按键和按值对映射进行排序.下面是它的工作原理: 将Map或List等集合类对象转换为Stream对象 使用Streams ...

  5. 代码作家Alpha冲刺阶段博客目录

    一.Scrum Meeting 1. [第六周会议记录] 2. [第七周会议记录] 二.测试报告 Alpha阶段测试报告 三.习得的软工原理/方法/技能  1. 在项目前期准备中,我们学会了一些页面设 ...

  6. 路由器配置深入浅出—路由器接口PPP协议封装及PAP和CHAP验证配置

    知识域: 是针对点对点专线连接的接口的二层封装协议配置 PPP的PAP和CHAP验证,cpt支持,不一定要在gns3上做实验. 路由器出厂默认是hdlc封装,修改为ppp封装后,可以采用pap验证或者 ...

  7. Linux之ELF文件初探

    对比windowsPE文件与概述 在windows中可执行文件是pe文件格式,Linux中可执行文件是ELF文件,其文件格式是ELF文件格式,在Linux下的ELF文件除了可执行文件(Excutabl ...

  8. git 的基本使用命令

    1,git 的作用:git是目前世界上最先进的分布式版本控制系统(没有之一) 用在版本控制  和  代码整合 2,git 配置: 1,git init  初始化文件,会在自己的文件夹下创建一个.git ...

  9. 利用python的requests和BeautifulSoup库爬取小说网站内容

    1. 什么是Requests? Requests是用Python语言编写的,基于urllib3来改写的,采用Apache2 Licensed 来源协议的HTTP库. 它比urllib更加方便,可以节约 ...

  10. 命令行代理神器 proxychains

    因为某些原因,我们需要在命令行下载一些国外的资源,这个时候如果使用 wget,curl,或者 aria2c 的时候,往往又没有速度.这个时候我们需要使用代理来进行加速. 我本地搭的有 ss,但 ss ...