第一步,看官方文档
如果你想要通过用户扫码获取到他的个人信息,那么你需要完成全部的交互,如果你只是想为你的网站做一个免登录处理,其实只要拿到用户的
第三步,创建一个用户扫码界面并获取临时code
官网一共给大家提供了两种方式,第一种就是直接跳转到钉钉的二维码扫描;第二种是嵌入到自己的网页显示二维码。
因为我用的是第一种,并且这篇博客也仅仅是建立在初步实现,所以这里就不为大家介绍第二种嵌入方式了。
将自己的appid填写在APPID处,将自己希望扫码后跳转到的地址填写在REDIRECT_URI,比如可以填写为http://google.com/dingtalkLogin或者http://google.com/dingtalkLogin.action等等,大家可以根据自己的实际情况填写。
- 获取临时code和参数state,首先再看一次官网说明文档:
所以你在REDIRECT_URI跳转回去的方法中,需要获取到code和state两个参数。而关于state,参数其实就是你在之前拼接URL的时候中的STATE,这里建议大家可以使用时间戳(当用户访问的时候,因为URL不同,所以浏览器会重新获取,避免浏览器因缓存而导致二维码无法使用等问题);
代码:
- 拼接URL:
/**
*
* 描述:后台默认跳转到二维码登录界面
* 开发人员:暴沸
* 开发时间: 2017年2月23日 下午9:09:57
* 联系方式:[email protected]
*
* @param request
*/
@RequestMapping(value="login")
public void toALiDingDing(HttpServletResponse response){ //这是我自己写的一个获取时间戳的Util,前期大家可以不管这个STATE TimeUtil timeUtil = new TimeUtil(); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("https://oapi.dingtalk.com/connect/qrconnect?appid=APPID&") .append("response_type=code&scope=snsapi_login&state=") .append(timeUtil.getNow())
.append("&redirect_uri=")openid就可以了。当然我会在这篇博客中贴出全部步骤的代码。
第二步,获取appId和appSecret
- 登录/注册到钉钉开发者官网:新版开发者平台:http://open-dev.dingtalk.com
- 在左侧的五个菜单中点击自助工具,然后在右侧的菜单中创建扫码登录应用授权,然后依次输入名称、描述、授权页面logo地址(这个图片最后会出现在用户扫码设备中,建议使用压缩图片减少用户加载时间)、回调域名(一般都是写一个子域名,比如http://oa.dingtalk.com),保存之后便可以看到对应的appId以及appSecret了。
.append("REDIRECT_URI"); try { response.sendRedirect(stringBuilder.toString()); } catch (IOException e1) { } }
第四步,获取access_token
- 首先我们还是看一下官方说明文档:
获取钉钉开放应用的ACCESS_TOKEN(钉钉官网)
所以我们需要使用java代码向钉钉服务器端发送一个GET请求
关于Java如何封装get和post请求可以参考一下我自己写的博客:
【JavaWeb开发】用Apache的HttpClient4.5完成HttpGet请求
【JavaWeb开发】用Apache的HttpClient4.5完成HttpPost请求
//获取accesstoken
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
HttpClient httpClient = httpClientBuilder.build();
HttpResponse httpResponse = null;
String url = "https://oapi.dingtalk.com/sns/gettoken?appid=APPID&appsecret=APPSECRET";
HttpGet httpGet = new HttpGet(url); try { httpResponse = httpClient.execute(httpGet); } catch (Exception e) { } BufferedReader bufferedReader = null; StringBuilder entityStringBuilder=new StringBuilder(); //得到httpResponse的状态响应码 int statusCode=httpResponse.getStatusLine().getStatusCode(); if (statusCode==HttpStatus.SC_OK) { //得到httpResponse的实体数据 HttpEntity httpEntity=httpResponse.getEntity(); if (httpEntity!=null) { try { bufferedReader=new BufferedReader (new InputStreamReader(httpEntity.getContent(), "UTF-8"), 8*1024); String line=null; while ((line=bufferedReader.readLine())!=null) { entityStringBuilder.append(line+"/n"); } } catch (Exception e) { } } } JSONObject jsonObject = new JSONObject(entityStringBuilder.toString()); String access_token = jsonObject.getString("access_token");
第五步,获取持久授权码persistent_code
在官网文档中指出,需要使用之前获取到的临时code以及access_token两个参数来发送一个POST请求:
//获取用户授权的持久授权码
String url3 = "https://oapi.dingtalk.com/sns/get_persistent_code?access_token="+access_token;
System.out.println("url3="+url3);
HttpPost httpPost3 = new HttpPost(url3); //封装临时授权码 JSONObject jsonObject3_1 = new JSONObject(); jsonObject3_1.put("tmp_auth_code", code); HttpEntity httpEntity3 = null; httpEntity3 = new StringEntity(jsonObject3_1.toString(),"UTF-8"); httpPost3.setEntity(httpEntity3); HttpResponse httpResponse3 = null; try { httpResponse3 = httpClient.execute(httpPost3); } catch (Exception e) { // TODO: handle exception } StringBuilder entityStringBuilder3=new StringBuilder(); //得到httpResponse的状态响应码 int statusCode3=httpResponse3.getStatusLine().getStatusCode(); if (statusCode3==HttpStatus.SC_OK) { //得到httpResponse的实体数据 HttpEntity httpEntity3_2=httpResponse3.getEntity(); if (httpEntity3!=null) { try { bufferedReader=new BufferedReader (new InputStreamReader(httpEntity3_2.getContent(), "UTF-8"), 8*1024); String line=null; while ((line=bufferedReader.readLine())!=null) { entityStringBuilder3.append(line+"/n"); } } catch (Exception e) { e.printStackTrace(); } } } JSONObject jsonObject3_2 = new JSONObject(entityStringBuilder3.toString()); String persistent_code = jsonObject3_2.getString("persistent_code"); String openid = jsonObject3_2.getString("openid");
如果你自习看代码,在这一步中我们已经拿到了用户在这个网页应用中的唯一标识openid了,其实到这里就可以实现网站的免登录扫码了哦!
第六步,获取SNS_TOKEN
文档指出,我们需要在POST请求中封装之前获取到的access_token、openid以及persistent_code
//获取用户授权的SNS_TOKEN
String url4 = "https://oapi.dingtalk.com/sns/get_sns_token?access_token="+access_token;
HttpPost httpPost4 = new HttpPost(url4);
JSONObject jsonObject4 = new JSONObject(); jsonObject4.put("openid", openid); jsonObject4.put("persistent_code", persistent_code); HttpEntity httpEntity4 = null; httpEntity4 = new StringEntity(jsonObject4.toString(),"UTF-8"); httpPost4.setEntity(httpEntity4); HttpResponse httpResponse4 = null; //重新获取一个新的httpClient HttpClientBuilder httpClientBuilder2 = HttpClientBuilder.create(); HttpClient httpClient2 = httpClientBuilder2.build(); try { httpResponse4 = httpClient2.execute(httpPost4); } catch (Exception e) { // TODO: handle exception } StringBuilder entityStringBuilder4=new StringBuilder(); //得到httpResponse的状态响应码 int statusCode4=httpResponse4.getStatusLine().getStatusCode(); if (statusCode4==HttpStatus.SC_OK) { //得到httpResponse的实体数据 HttpEntity httpEntity4_1=httpResponse4.getEntity(); if (httpEntity4_1!=null) { try { bufferedReader=new BufferedReader (new InputStreamReader(httpEntity4_1.getContent(), "UTF-8"), 8*1024); String line=null; while ((line=bufferedReader.readLine())!=null) { entityStringBuilder4.append(line+"/n"); } } catch (Exception e) { e.printStackTrace(); } } } // JSONObject jsonObject4_1 = new JSONObject(entityStringBuilder4.toString()); String sns_token = jsonObject4_1.getString("sns_token");
胜利就在眼前了!
第七步,获取用户信息
直接发送GET请求即可!
//获取用户授权的个人信息
String url5 = "https://oapi.dingtalk.com/sns/getuserinfo?sns_token="+sns_token;
HttpGet httpGet5 = new HttpGet(url5);
HttpResponse httpResponse5 = null; try { HttpClient httpClient3 = httpClientBuilder.build(); httpResponse5 = httpClient3.execute(httpGet5); } catch (Exception e) { // TODO: handle exception } StringBuilder entityStringBuilder5=new StringBuilder(); //得到httpResponse的状态响应码 int statusCode5=httpResponse5.getStatusLine().getStatusCode(); if (statusCode5==HttpStatus.SC_OK) { //得到httpResponse的实体数据 HttpEntity httpEntity5=httpResponse5.getEntity(); if (httpEntity5!=null) { try { bufferedReader=new BufferedReader (new InputStreamReader(httpEntity5.getContent(), "UTF-8"), 8*1024); String line=null; while ((line=bufferedReader.readLine())!=null) { entityStringBuilder5.append(line+"/n"); } } catch (Exception e) { e.printStackTrace(); } } } JSONObject jsonObject5_1 = new JSONObject(entityStringBuilder5.toString()); JSONObject jsonObject5 = jsonObject5_1.getJSONObject("user_info"); String nick = jsonObject5.getString("nick"); String unionid = jsonObject5.getString("unionid"); String dingId = jsonObject5.getString("dingId");
//-----------------------------------------以下为博主(Happy王子乐)代码原创,最后会贴出完成代码 ------------//
第八步:
根据unionid获取用户userId (以下代码和上述代码不配套,最后贴出完整配套代码;PS:钉钉官方文档比较坑,其中有两个access_token,以下接口是使用的另一个access_token)
String appAccessToken = getAppAccesstoken();
String userId = getUserId(appAccessToken, unionId);
public String getAppAccesstoken() { String url = "https://oapi.dingtalk.com/gettoken?corpid=dingbbe74ca7c844b45f35c2f4657eb6378f&corpsecret=MERA4ADae_62lU05Y9fbU9Z43NZBoIBTHnam1SGiKgblcO_NKIzEts-2G3Ji5njw"; JSONObject json = ossHttpGetUtil(url); if(null!=json){ if (Integer.parseInt(json.get("errcode").toString()) == 0) { String appAccessToken = json.getString("access_token"); return appAccessToken; } } return ""; } public JSONObject getPersistentCode(String accessToken,String code) { String url = "https://oapi.dingtalk.com/sns/get_persistent_code?access_token=" + accessToken; JSONObject jsonData = new JSONObject(); jsonData.put("tmp_auth_code", code); JSONObject json = ossHttpPostUtil(url, jsonData); if(null!=json){ if (Integer.parseInt(json.get("errcode").toString()) == 0) { return json; } } return null; }
第九步: 根据userId获取用户详细数据
JSONObject userData = getUserData(appAccessToken, userId);
public JSONObject getUserData(String accessToken, String userId) { String url = "https://oapi.dingtalk.com/user/get?access_token="+accessToken+"&userid="+userId; JSONObject json = ossHttpGetUtil(url); if(null!=json){ if (Integer.parseInt(json.get("errcode").toString()) == 0) { return json; } } return null; }
//-----------------------以下是从回掉地址传入code,到查询用户详细信息,完成代码,个人原创(Happy王子乐)
package com.hqq.api.staff.services.impl; import com.alibaba.fastjson.JSONObject; import com.hqq.api.staff.entitis.Staff; import com.hqq.api.staff.repos.StaffRepo; import com.hqq.api.staff.services.StaffService; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Example; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import java.io.BufferedReader; import java.util.List; /** * Created by kevinzou on 30/07/2017. * StaffServiceImpl */ @Service public class StaffServiceImpl implements StaffService { @Autowired private StaffRepo repo; @Override public Staff save(Staff entity) { return repo.save(entity); } @Override public void delete(Long id) { repo.delete(id); } @Override public void delete(Staff entity) { repo.delete(entity); } @Override public Staff findById(Long id) { return repo.findOne(id); } @Override public Staff findBySample(Staff sample) { return repo.findOne(Example.of(sample)); } @Override public List<Staff> findAll() { return repo.findAll(); } @Override public List<Staff> findAll(Sort sort) { return repo.findAll(sort); } @Override public List<Staff> findBySamples(Staff sample) { return repo.findAll(Example.of(sample)); } @Override public List<Staff> findBySamples(Staff sample, Sort sort) { return repo.findAll(Example.of(sample), sort); } @Override public Page<Staff> findBySamples(Staff sample, PageRequest pageRequest) { return repo.findAll(Example.of(sample), pageRequest); } @Override public Page<Staff> findBySamples(PageRequest pageRequest) { return repo.findAll(pageRequest); } @Override public JSONObject goDingLogin(String code) { try{ //获取accesstoken String accessToken = getAccesstoken(); //获取用户授权的持久授权码 JSONObject json = getPersistentCode(accessToken, code); String openId = ""; String persistentCode = ""; if(null!=json){ openId = json.getString("openid"); persistentCode = json.getString("persistent_code"); } //获取用户授权的SNS_TOKEN String snsToken = getSnsToken(accessToken, openId, persistentCode); //获取用户unionid String unionId = getUnionId(snsToken); //根据unionid获取用户userId String appAccessToken = getAppAccesstoken(); String userId = getUserId(appAccessToken, unionId); //获取用户详细数据 JSONObject userData = getUserData(appAccessToken, userId); return userData; }catch (Exception e){ } return null; } public String getAccesstoken() { String url = "https://oapi.dingtalk.com/sns/gettoken?appid=dingoap77h68gih6szglb4&appsecret=ZUGaKf3pvd6DDtVEpjdISmjCv_Sq1VNH0Oe8v_nfockMKIQth03KWwSS5fzRIM5o"; JSONObject json = ossHttpGetUtil(url); if(null!=json){ if (Integer.parseInt(json.get("errcode").toString()) == 0) { String accessToken = json.getString("access_token"); return accessToken; } } return ""; } public String getAppAccesstoken() { String url = "https://oapi.dingtalk.com/gettoken?corpid=dingbbe74ca7c844b45f35c2f4657eb6378f&corpsecret=MERA4ADae_62lU05Y9fbU9Z43NZBoIBTHnam1SGiKgblcO_NKIzEts-2G3Ji5njw"; JSONObject json = ossHttpGetUtil(url); if(null!=json){ if (Integer.parseInt(json.get("errcode").toString()) == 0) { String appAccessToken = json.getString("access_token"); return appAccessToken; } } return ""; } public JSONObject getPersistentCode(String accessToken,String code) { String url = "https://oapi.dingtalk.com/sns/get_persistent_code?access_token=" + accessToken; JSONObject jsonData = new JSONObject(); jsonData.put("tmp_auth_code", code); JSONObject json = ossHttpPostUtil(url, jsonData); if(null!=json){ if (Integer.parseInt(json.get("errcode").toString()) == 0) { return json; } } return null; } public String getSnsToken(String accesstoken, String openid, String persistent_code) { String url = "https://oapi.dingtalk.com/sns/get_sns_token?access_token="+accesstoken; HttpPost httpPost = new HttpPost(url); JSONObject jsonData = new JSONObject(); jsonData.put("openid", openid); jsonData.put("persistent_code", persistent_code); JSONObject json = ossHttpPostUtil(url, jsonData); if(null!=json){ if (Integer.parseInt(json.get("errcode").toString()) == 0) { String snsToken = json.getString("sns_token"); return snsToken; } } return null; } public String getUnionId(String snsToken) { String url = "https://oapi.dingtalk.com/sns/getuserinfo?sns_token="+snsToken; JSONObject json = ossHttpGetUtil(url); if(null!=json){ if (Integer.parseInt(json.get("errcode").toString()) == 0) { JSONObject jsonUser = json.getJSONObject("user_info"); String unionid = jsonUser.getString("unionid"); return unionid; } } return ""; } public String getUserId(String accessToken, String unionId) { String url = "https://oapi.dingtalk.com/user/getUseridByUnionid?unionid="+unionId+"&access_token="+accessToken; JSONObject json = ossHttpGetUtil(url); if(null!=json){ if (Integer.parseInt(json.get("errcode").toString()) == 0) { String userId = json.getString("userid"); return userId; } } return ""; } public JSONObject getUserData(String accessToken, String userId) { String url = "https://oapi.dingtalk.com/user/get?access_token="+accessToken+"&userid="+userId; JSONObject json = ossHttpGetUtil(url); if(null!=json){ if (Integer.parseInt(json.get("errcode").toString()) == 0) { return json; } } return null; } private JSONObject ossHttpGetUtil(String url){ HttpGet httpGet = new HttpGet(url); HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); HttpClient httpClient = httpClientBuilder.build(); HttpResponse httpResponse = null; try { httpResponse = httpClient.execute(httpGet); } catch (Exception e) { } BufferedReader bufferedReader = null; StringBuilder entityStringBuilder = new StringBuilder(); //得到httpResponse的状态响应码 int statusCode = httpResponse.getStatusLine().getStatusCode(); JSONObject jsonObject = null; String access_token = ""; if (statusCode == HttpStatus.SC_OK) { //得到httpResponse的实体数据 HttpEntity httpEntity = httpResponse.getEntity(); if (httpEntity != null) { try { return jsonObject = JSONObject.parseObject(EntityUtils.toString(httpEntity)); } catch (Exception e) { } } } return null; } private JSONObject ossHttpPostUtil(String url, JSONObject json){ HttpPost httpPost = new HttpPost(url); HttpEntity httpEntity = null; httpEntity = new StringEntity(json.toString(), "UTF-8"); httpPost.setEntity(httpEntity); HttpResponse httpResponse = null; HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); HttpClient httpClient = httpClientBuilder.build(); try { httpResponse = httpClient.execute(httpPost); } catch (Exception e) { } StringBuilder entityStringBuilder = new StringBuilder(); //得到httpResponse的状态响应码 int statusCode = httpResponse.getStatusLine().getStatusCode(); if (statusCode == HttpStatus.SC_OK) { //得到httpResponse的实体数据 HttpEntity httpEntity2 = httpResponse.getEntity(); JSONObject jsonObject = null; if (httpEntity2 != null) { try { return jsonObject = jsonObject.parseObject(EntityUtils.toString(httpEntity2)); } catch (Exception e) { } } } return null; } }
- 第顶顶顶顶