Springboot+浙政钉 扫码免登 集成

初次编写博客 有不到之处 请指出 谢谢

应用上架

第一步申请isv入驻

第二步用isv账号添加用户和机构
专有钉下载地址
第三步用isv账号在团队管理授权普通用户管理员权限,在工作台中的权限管理中的权限角色管理授权开放平台管理员权限和用户工作台管理权限

第四步在开发者后台-我的应用-组织内部应用中创建应用,创建成功后进入详情这里就鞥拿到ak和as

第五步应用配置如配置移动端地址,服务器出口之类的,这一步如移动端地址h5需要一个能连接外网的地址

第六步应用权限配置,如果不知道建议先全部开启,知道的按需开启,应用访问范围也需要配置,如果应用需要跳转到其他应用需要允许跳转的第三方应用配置

第七步在应用发布中将应用上架

第八步进入工作台管理,这时候如果是普通用户那第三步的配置可能可能极为关键,点击用户工作台,新增一个用户工作台,之后配置页面应用,配置应用分组列表,将你的h5或app加入分组列表,在页面应用这个分组,之后发布工作站

第九步进入手机版工作台能看见配置好的应用就ok了
ps:如果看不到可能是应用配置的问题,可以去看一下控制台的应用管理看一下应用归属,登录手机的用户是否属于这个组织等等

免登扫码前端

避免误导各位大佬 就引用专有钉的链接
h5以及小程序 获取免登授权码
扫码登录部分

免登扫码后端代码

数据库就不展示啦 如需要请联系
maven 需要 下载jdk
然后打到本地maven 仓库 可以参考

首先定义扫码和免登的key等

#aliyunoss.domainName= openplatform-pro.ding.zj.gov.cn  正式浙政钉接口
aliyunoss.domainName= openplatform.dg-work.cn 专有钉的域名
aliyunoss.appKey= XXXXX
aliyunoss.appSecret= XXXXX
aliyunoss.tenantId= XXXXXaliyunoss.canCodeAppKey= XXXXX
aliyunoss.canCodeAppSecret= XXXXX

然后注入浙政钉的参数到系统


import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public  class UserDtalkConfig {//域名 (免登和扫码 一样)public static String domainName;//appKey 免登的public static String appKey;//appKey 租户ID  在获取通讯录 和组织需要 (免登和扫码 一样)public static String  tenantId;//appSecret 免登的public static String appSecret;//AppKey 扫码的public static String canCodeAppKey;//AppSecret 扫码的public static String canCodeAppSecret;public static String getDomainName() {return domainName;}@Value("${aliyunoss.domainName}")public  void setDomainName(String domainName) {UserDtalkConfig.domainName = domainName;}public static String getAppKey() {return appKey;}@Value("${aliyunoss.appKey}")public  void setAppKey(String appKey) {UserDtalkConfig.appKey = appKey;}public static String getAppSecret() {return appSecret;}@Value("${aliyunoss.appSecret}") public  void setAppSecret(String appSecret) {UserDtalkConfig.appSecret = appSecret;}public static String getCanCodeAppKey() {return canCodeAppKey;}@Value("${aliyunoss.canCodeAppKey}")public  void setCanCodeAppKey(String canCodeAppKey) {UserDtalkConfig.canCodeAppKey = canCodeAppKey;}public static String getCanCodeAppSecret() {return canCodeAppSecret;}@Value("${aliyunoss.canCodeAppSecret}")public  void setCanCodeAppSecret(String canCodeAppSecret) {UserDtalkConfig.canCodeAppSecret = canCodeAppSecret;}public static String getTenantId() {return tenantId;}@Value("${aliyunoss.tenantId}")public  void setTenantId(String tenantId) {UserDtalkConfig.tenantId = tenantId;}
}

@Value 这些是静态注入参数哦


import com.alibaba.xxpt.gateway.shared.client.http.ExecutableClient;
import com.zysj.zzding.ZhejiangPoliticalNail.config.UserDtalkConfig;
import org.springframework.beans.BeanUtils;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
//声明一个单例 用来调用浙政钉的接口
public enum EnumSingleton {INSTANCE;//扩展,实际的单例对象 这个对象是免登的private ExecutableClient executableClient;//扩展,实际的单例对象 这个对象是扫码的private ExecutableClient executableScanCodeClient;public ExecutableClient getIntance(){return executableClient;}public ExecutableClient getScanCodeReInit() {return executableScanCodeClient;}EnumSingleton()  {try {init();} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {e.printStackTrace();}}private void init() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {executableClient = ExecutableClient.getInstance();executableClient.setAccessKey(UserDtalkConfig.getAppKey());executableClient.setSecretKey(UserDtalkConfig.getAppSecret());executableClient.setDomainName(UserDtalkConfig.getDomainName());executableClient.setProtocal("https");executableClient.init();//画重点 深入查看发现 ExecutableClient 这个对象是单例 而我们需要二个不同的对象 通过反射方式 拷贝出来一个新的 ExecutableClient 对象Class<ExecutableClient> c = ExecutableClient.class;Constructor<ExecutableClient> cc = c.getDeclaredConstructor();//未添加会出现 private 权限问题cc.setAccessible(true);executableScanCodeClient = cc.newInstance();executableScanCodeClient.setAccessKey(UserDtalkConfig.getCanCodeAppKey());executableScanCodeClient.setSecretKey(UserDtalkConfig.getCanCodeAppSecret());executableScanCodeClient.setDomainName(UserDtalkConfig.getDomainName());executableScanCodeClient.setProtocal("https");executableScanCodeClient.init();}
}

展示一下控制层

import com.alibaba.fastjson.JSONObject;
import com.zysj.zzding.ZhejiangPoliticalNail.service.sys_user.SysUserService;
import com.zysj.zzding.ZhejiangPoliticalNail.util.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.ExecutionException;/*** <p>*  前端控制器* </p>** @since 2021-07-14*/
@RestController
@RequestMapping("zzd-sys-user")
@Api(tags = "浙政钉部分API")
public class SysUserController {finalSysUserService userService;public SysUserController(SysUserService userService) {this.userService = userService;}@ApiOperation(value = "浙政钉 免登录接口")@RequestMapping(value = {"/getExclusiveRegistrationFree"}, method = RequestMethod.POST)@ApiImplicitParams({@ApiImplicitParam(name = "params", value = "传参 {\"auth_code\" : auth_code 以json方式存储}",  dataType = "json", paramType = "body"),})public R getExclusiveRegistrationFree(@RequestBody Map<String,Object> params, HttpServletRequest req, HttpServletResponse resp) throws ClassNotFoundException, InstantiationException, IllegalAccessException {return userService.getExclusiveRegistrationFreeScanCodeType(params.get("auth_code").toString(),req,resp,0);}@ApiOperation(value = "浙政钉扫码登录 接口")@RequestMapping(value = {"/getExclusiveRegistrationFreeScanCode"}, method = RequestMethod.POST)@ApiImplicitParams({@ApiImplicitParam(name = "params", value = "传参 {\"auth_code\" : auth_code 以json方式存储}",  dataType = "json", paramType = "body"),})public R getExclusiveRegistrationFreeScanCode(@RequestBody Map<String,Object> params,HttpServletRequest req, HttpServletResponse resp) throws ClassNotFoundException, InstantiationException, IllegalAccessException {return userService.getExclusiveRegistrationFreeScanCodeType(params.get("auth_code").toString(),req,resp,1);}@ApiOperation(value = "批量添加用户操作")@RequestMapping(value = {"/addMobilesUser"}, method = RequestMethod.POST)@ApiImplicitParams({@ApiImplicitParam(name = "mobiles", value = "手机号 逗号分割",  dataType = "String[]", paramType = "query"),})public R addMobilesUser(@RequestParam(value = "mobiles") String mobiles,  HttpServletRequest req, HttpServletResponse resp) throws ClassNotFoundException, InstantiationException, IllegalAccessException, ExecutionException, InterruptedException {return userService.addMobilesUser(mobiles,req,resp);}@ApiOperation(value = "获取到应用权限下的所有部门和人员 树形结构")//这部分就不展示啦 因为用到啦 ForkJoinPool 和 ForkJoinTask 以及二分查找 等优化 因为部门只能一层一层拿 所以比较复杂 篇幅有限 需要啦 再单独联系@RequestMapping(value = {"/getDeptScopes"}, method = RequestMethod.POST)public void getDeptScopes( ) throws ClassNotFoundException, InstantiationException, IllegalAccessException {userService.getDeptScopes();}

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zysj.zzding.ZhejiangPoliticalNail.util.R;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;/*** <p>*  服务类* </p>** @since 2021-07-14*/
public interface SysUserService  {//根据手机号批量获取用户R addMobilesUser(String mobiles, HttpServletRequest req, HttpServletResponse resp) throws ClassNotFoundException, InstantiationException, IllegalAccessException, ExecutionException, InterruptedException;//扫码 和免登的入口 免登 为0 扫码为 1 R getExclusiveRegistrationFreeScanCodeType(String auth_code, HttpServletRequest req, HttpServletResponse resp, int i) throws ClassNotFoundException, InstantiationException, IllegalAccessException;//下面的接口都与 同步 部门和员工有关就 不多说啦哦void getDeptScopes() throws ClassNotFoundException, InstantiationException, IllegalAccessException;JSONObject getPageSubOrganizationCodes(String organizationCode,Integer pageSize,Integer pageNo);JSONObject getPageOrganizationEmployeeCodes(String organizationCode,Integer pageSize,Integer pageNo);Map<String,Object> getOrganizationByCode(String organizationCode);Map<String,Object> getDeptEmployeeByCode(String employeeCode, JSONObject userE);}

实现类

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.xxpt.gateway.shared.client.http.PostClient;
import com.zysj.zzding.ZhejiangPoliticalNail.config.UserDtalkConfig;
import com.zysj.zzding.ZhejiangPoliticalNail.dao.sys_user.ZzdSysUserMapper;
import com.zysj.zzding.ZhejiangPoliticalNail.entity.sys_user.EnumSingleton;
import com.zysj.zzding.ZhejiangPoliticalNail.service.sys_user.SysUserService;
import com.zysj.zzding.ZhejiangPoliticalNail.service.task.ZzdingSyncTaskService;
import com.zysj.zzding.ZhejiangPoliticalNail.util.R;
import com.zysj.zzding.ZhejiangPoliticalNail.util.RSAUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;/*** <p>*  服务实现类* </p>** @author 尚帅* @since 2021-07-14*/
@Service
public class SysUserServiceImpls implements SysUserService   {private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpls.class);//请忽略 这个是定义用 浙政钉的 哪个用户信息登录 默认accountId@Value("${zzdUser.UserName:accountId}")private String zzdUserName;@Overridepublic  R  getExclusiveRegistrationFreeScanCodeType(String auth_code, HttpServletRequest req, HttpServletResponse resp, int i)  {JSONObject userData;if (i==0){//应用免登userData = this.getDingtalkAppUser(auth_code);}else {//扫码登录userData = this.getDingtalkAppUserScanCode(auth_code);}//userData 这个里面就是用户的详细信息
//      String userName =String.valueOf(userData.get(zzdUserName));
//       int ss = sysUserMapper.getByUserName(userName);
//        if (ss==0){                                              这部分需根据自己的业务来做登录操作
//            return R.error(404,"请联系管理员添加账户");
//        }
//     return   sysUserMapper.loginUserName(passWordRas)return R.ok().put("list",userData);}//应用免登 获取用户详情public JSONObject getDingtalkAppUser(String authCode) {try {String api = "/rpc/oauth2/dingtalk_app_user.json";String apiResult;PostClient postClient = EnumSingleton.INSTANCE.getIntance().newPostClient(api);postClient.addParameter("access_token", this.getAccessToken());postClient.addParameter("auth_code", authCode);apiResult = postClient.post();log.info("getDingtalkAppUser返回结果打印:" + apiResult);JSONObject jsonObject = JSONObject.parseObject(apiResult);if (jsonObject != null && jsonObject.getBoolean("success")) {JSONObject contentObj = jsonObject.getJSONObject("content");JSONObject dataObj = contentObj.getJSONObject("data");return dataObj;}} catch (Exception e) {log.error("浙政钉-根据authCode换取用户信息异常", e);}return null;}//应用免登 获取tokenpublic String getAccessToken() {//判断缓存中accessToken是否存在
//        String redisAccessToken = redisService.getCacheObject(GOV_DTALK_ACCESS_TOKEN);
//        if (StringUtils.isNotBlank(redisAccessToken)) {//            return redisAccessToken;
//        }try {//缓存中不存在,则重新获取String api = "/gettoken.json";PostClient client = EnumSingleton.INSTANCE.getIntance().newPostClient(api);client.addParameter("appkey", UserDtalkConfig.getAppKey());client.addParameter("appsecret", UserDtalkConfig.getAppSecret());//调用APIString apiResult = client.post();System.out.println("getAccessToken返回结果打印:" + apiResult);JSONObject jsonObject = JSONObject.parseObject(apiResult);if (jsonObject != null && jsonObject.getBoolean("success")) {JSONObject contentObj = jsonObject.getJSONObject("content");JSONObject dataObj = contentObj.getJSONObject("data");String accessToken = dataObj.getString("accessToken");long expiresIn = dataObj.getLong("expiresIn");//                redisService.setCacheObject(GOV_DTALK_ACCESS_TOKEN, accessToken, expiresIn, TimeUnit.SECONDS);   可以把token 保存在redis 但是 浙政钉的 token有效为 60sreturn accessToken;}else{throw new RuntimeException(apiResult);}} catch (Exception e) {System.out.println("浙政钉-获取accessToken异常");}return null;}public JSONObject getDingtalkAppUserScanCode(String authCode) {try {String apiResult;String api = "/rpc/oauth2/getuserinfo_bycode.json";PostClient postClient = EnumSingleton.INSTANCE.getScanCodeReInit().newPostClient(api);System.out.println("+++++++++++++++++++++++" + postClient.toString());postClient.addParameter("code", authCode);postClient.addParameter("access_token", this.getAccessTokenScanCode());apiResult= postClient.post();System.out.println("getDingtalkAppUserScanCode返回结果打印:" + apiResult);JSONObject jsonObject = JSONObject.parseObject(apiResult);if (jsonObject != null && jsonObject.getBoolean("success")) {JSONObject contentObj = jsonObject.getJSONObject("content");JSONObject dataObj = contentObj.getJSONObject("data");return dataObj;}} catch (Exception e) {log.error("浙政钉-根据authCode换取用户信息异常", e);}return null;}public String getAccessTokenScanCode() {//判断缓存中accessToken是否存在
//        String redisAccessToken = redisService.getCacheObject(GOV_DTALK_ACCESS_TOKEN);
//        if (StringUtils.isNotBlank(redisAccessToken)) {//            return redisAccessToken;
//        }try {//缓存中不存在,则重新获取String api = "/gettoken.json";PostClient client = EnumSingleton.INSTANCE.getScanCodeReInit().newPostClient(api);log.info(UserDtalkConfig.getCanCodeAppKey()+"UserDtalkConfig.getCanCodeAppKey");client.addParameter("appkey", UserDtalkConfig.getCanCodeAppKey());log.info(UserDtalkConfig.getCanCodeAppSecret()+"UserDtalkConfig.getCanCodeAppSecret");client.addParameter("appsecret", UserDtalkConfig.getCanCodeAppSecret());//调用APIString apiResult = client.post();log.info("getAccessToken返回结果打印:" + apiResult);JSONObject jsonObject = JSONObject.parseObject(apiResult);if (jsonObject != null && jsonObject.getBoolean("success")) {JSONObject contentObj = jsonObject.getJSONObject("content");JSONObject dataObj = contentObj.getJSONObject("data");String accessToken = dataObj.getString("accessToken");long expiresIn = dataObj.getLong("expiresIn");
//                redisService.setCacheObject(GOV_DTALK_ACCESS_TOKEN, accessToken, expiresIn, TimeUnit.SECONDS);   可以把token 保存在redis 但是 浙政钉的 token有效为 60sreturn accessToken;}} catch (Exception e) {System.out.println("浙政钉-获取accessToken异常");}return null;}@Override//获取应用权限下的所有部门和 用户 树形结构保存到数据库 比较 复杂 就不列入啦public void getDeptScopes() {//        List<Map<String,Object>> returnList=new ArrayList<>();
//        String apis = "/auth/scopesV2";
//        PostClient postClients = EnumSingleton.INSTANCE.getIntance().newPostClient(apis);
//        postClients.addParameter("tenantId", UserDtalkConfig.getTenantId());
//        String apisResult = postClients.post();
//        JSONObject detailsJsonObject = JSONObject.parseObject(apisResult);
//        if (detailsJsonObject != null && detailsJsonObject.getBoolean("success")) {//            JSONObject scopes= detailsJsonObject.getJSONObject("content");
//          JSONArray sst=  scopes.getJSONArray("deptVisibleScopes");
//            sst.forEach(e->{//              Map map= getOrganizationByCode(String.valueOf(e));
//                if(!Boolean.parseBoolean(map.get("successful").toString())){//                    System.out.println("获取失败");
//                }else {//                    returnList.add((Map<String, Object>) map.get("data"));
//                }
                sysUserMapper.addUpdateDeptList(returnList);
                zzdingSyncTaskService.runSync(String.valueOf(e));  批量任务处理 就不展示啦
//            });
//        }}@Overridepublic JSONObject getPageSubOrganizationCodes(String organizationCode,Integer pageSize,Integer pageNo) {String apis = "/mozi/organization/pageSubOrganizationCodes";PostClient postClients = EnumSingleton.INSTANCE.getIntance().newPostClient(apis);postClients.addParameter("status", "TOTAL");return getJsonObjectPage(organizationCode, pageSize, pageNo, postClients);}@Overridepublic JSONObject getPageOrganizationEmployeeCodes(String organizationCode, Integer pageSize, Integer pageNo) {String apis = "/mozi/organization/pageOrganizationEmployeePositions";PostClient postClients = EnumSingleton.INSTANCE.getIntance().newPostClient(apis);return getJsonObjectPage(organizationCode, pageSize, pageNo, postClients);}@Overridepublic Map getOrganizationByCode(String organizationCode) {String apis = "/mozi/organization/getOrganizationByCode";PostClient postClients = EnumSingleton.INSTANCE.getIntance().newPostClient(apis);postClients.addParameter("tenantId", UserDtalkConfig.getTenantId());postClients.addParameter("organizationCode", organizationCode);String apisResult = postClients.post();JSONObject detailsJsonObject = JSONObject.parseObject(apisResult);return getJudgeSuccess(detailsJsonObject);}@Overridepublic Map getDeptEmployeeByCode(String employeeCode,JSONObject userE) {String apis = "/mozi/employee/listEmployeeAccountIds";PostClient postClients = EnumSingleton.INSTANCE.getIntance().newPostClient(apis);postClients.addParameter("employeeCodes",employeeCode);postClients.addParameter("tenantId", UserDtalkConfig.getTenantId());String apisResult = postClients.post();System.out.println("getDingtalkAppUser返回结果打印:" + apisResult);JSONObject detailsJsonObject = JSONObject.parseObject(apisResult);return getJudgeSuccessInfo(detailsJsonObject,userE);}private JSONObject getJsonObjectPage(String organizationCode, Integer pageSize, Integer pageNo, PostClient postClients) {postClients.addParameter("tenantId", UserDtalkConfig.getTenantId());postClients.addParameter("organizationCode", organizationCode);postClients.addParameter("pageSize", String.valueOf(pageSize));postClients.addParameter("pageNo", String.valueOf(pageNo));postClients.addParameter("returnTotalSize","true");String apisResult = postClients.post();JSONObject detailsJsonObject = JSONObject.parseObject(apisResult);if (detailsJsonObject != null && detailsJsonObject.getBoolean("success")) {return detailsJsonObject.getJSONObject("content");}return null;}@Override// 根据手机号批量同步 用户信息 因为 浙政钉 批量的时候 有一个错误就返回错误 所有这边采用 多线程单个去跑的方法public R addMobilesUser(String mobiles, HttpServletRequest req, HttpServletResponse resp) throws ExecutionException, InterruptedException {String[] mobileList = mobiles.split(",");Map<String, Object> returnMap= new HashMap<String, Object>();Map returnErrorMap= new HashMap();List<Future<Map<String,Object>>>  MobilesUserList =  new ArrayList<>();for (String s : mobileList) {Future<Map<String,Object>> MobilesUser =  getMobilesUser(s);MobilesUserList.add(MobilesUser);}System.out.println(new Date());for (Future<Map<String,Object>> future : MobilesUserList) {while (true) {//CPU高速轮询:每个future都并发轮循,判断完成状态然后获取结果,这一行,是本实现方案的精髓所在。即有10个future在高速轮询,完成一个future的获取结果,就关闭一个轮询if (future.isDone() && !future.isCancelled()) {//获取future成功完成状态,如果想要限制每个任务的超时时间,取消本行的状态判断+future.get(1000*1, TimeUnit.MILLISECONDS)+catch超时异常使用即可。Map<String,Object> result = future.get();//获取结果if (result.get("code").toString().equals("0")){returnMap.putAll((Map<String, Object>)result.get("list"));}else {returnErrorMap.putAll((Map) result.get("list"));}System.out.println("任务i=" + future.get() + "获取完成!" + new Date());break;//当前future获取结果完毕,跳出while} else {//每次轮询休息1毫秒(CPU纳秒级),避免CPU高速轮循耗空CPU---》新手别忘记这个Thread.sleep(1);}System.out.println(new Date());}}
//        sysUserMapper.addUpdateUserList(returnMap);if (returnErrorMap.isEmpty()){return R.ok("添加成功");}else {return R.error(305,"部分用户添加失败 具体请参考后续名单").put("list",returnErrorMap).put("mobileCount",mobileList.length).put("errorCount",returnErrorMap.size());}}//线程执行方法@Async("threadPoolTaskExecutor")public Future<Map<String,Object>> getMobilesUser(String mobile){JSONObject apiResult = getByMobile(mobile);Map<String,Object> map =new HashMap<>();Map<String, java.io.Serializable> apiResultMap =getJudgeSuccess(apiResult);if(!Boolean.parseBoolean(apiResultMap.get("successful").toString())){map.put(mobile,apiResult);return new AsyncResult<>(R.error(406,"获取信息失败").put("list",map));}JSONObject Employee =getEmployeeByCode(JSONObject.parseObject(apiResultMap.get("data").toString()));Map<String, java.io.Serializable> EmployeeMap =getJudgeSuccess(Employee);if(!Boolean.parseBoolean(EmployeeMap.get("successful").toString())){map.put(mobile,Employee);return new AsyncResult<>(R.error(406,"获取信息失败").put("list",map));}else {JSONObject maps = JSONObject.parseObject(EmployeeMap.get("data").toString());JSONObject jsonObject= JSONObject.parseObject(apiResultMap.get("data").toString());maps.put("accountId",jsonObject.get("accountId"));map.put(mobile,maps);return new AsyncResult<>(R.ok().put("list",map));}}private Map<String, java.io.Serializable> getJudgeSuccess(JSONObject apiResult) {Map<String, java.io.Serializable> map =new HashMap<String, java.io.Serializable>();if (apiResult != null && apiResult.getBoolean("success")) {JSONObject contentObj = apiResult.getJSONObject("content");JSONObject o = contentObj.getJSONObject("data");if (o==null||o.isEmpty()){map.put("successful",false);return map;}map.put("successful",true);map.put("data",o);return map;}else {map.put("successful",false);return map;}}private Map<String, Object> getJudgeSuccessInfo(JSONObject apiResult, JSONObject userE) {Map<String, Object> map =new HashMap<>();if (apiResult != null && apiResult.getBoolean("success")) {JSONObject contentObj = apiResult.getJSONObject("content");JSONArray o = contentObj.getJSONArray("data");if (o==null||o.isEmpty()){map.put("successful",false);return map;}map.put("successful",true);JSONObject maps = JSONObject.parseObject(JSONObject.toJSONString(o.get(0)));map.put("accountId",maps.get("accountId"));map.put("accountCode",maps.get("accountCode"));map.put("accountNamespace",maps.get("accountNamespace"));map.put("data",userE);return map;}else {map.put("successful",false);return map;}}private JSONObject getEmployeeByCode(JSONObject o) {Map<String,Object> map = JSONObject.parseObject(JSONObject.toJSONString(o), Map.class);String apis = "/mozi/employee/getEmployeeByCode";PostClient postClients = EnumSingleton.INSTANCE.getIntance().newPostClient(apis);postClients.addParameter("employeeCode",map.get("employeeCode").toString());postClients.addParameter("tenantId", UserDtalkConfig.getTenantId());String apisResult = postClients.post();System.out.println("getDingtalkAppUser返回结果打印:" + apisResult);return JSONObject.parseObject(apisResult);}private JSONObject getByMobile(String mobile) {String api = "/mozi/employee/get_by_mobile";PostClient postClient = EnumSingleton.INSTANCE.getIntance().newPostClient(api);postClient.addParameter("areaCode", "86");postClient.addParameter("tenantId", UserDtalkConfig.getTenantId());postClient.addParameter("namespace", "local");postClient.addParameter("mobile", mobile);String apiResult = postClient.post();return JSONObject.parseObject(apiResult);}
}

R 这个工具类是 自己定义的 最后也会贴上去


import java.util.HashMap;
import java.util.Map;/*** 返回数据*/
public class R extends HashMap<String, Object> {private static final long serialVersionUID = 1L;public R() {put("code", 0);put("msg", "success");}public static R error() {return error(500, "未知异常,请联系管理员");}public static R error(String msg) {return error(500, msg);}public static R error(int code, String msg) {R r = new R();r.put("code", code);r.put("msg", msg);return r;}public static R ok(String msg) {R r = new R();r.put("msg", msg);return r;}public static R ok(Map<String, Object> map) {R r = new R();r.putAll(map);return r;}public static R ok() {return new R();}@Overridepublic R put(String key, Object value) {super.put(key, value);return this;}
}

还有线程池

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.ThreadPoolExecutor;@Configuration
public class ThreadPoolConfig
{/***   默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,*  当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;*  当队列满了,就继续创建线程,当线程数量大于等于maxPoolSize后,开始使用拒绝策略拒绝*//*** 获得Java虚拟机可用的处理器个数 + 1*/private static final int THREADS = Runtime.getRuntime().availableProcessors() + 1;@Value("${async.executor.thread.core_pool_size:0}")public static int corePoolSizeConfig;// 核心线程池大小public static int corePoolSize = corePoolSizeConfig ==0 ? THREADS : corePoolSizeConfig;// 最大可创建的线程数//@Value("${async.executor.thread.max_pool_size}")private int maxPoolSize = 2 * THREADS;;// 队列最大长度//@Value("${async.executor.thread.queue_capacity}")private int queueCapacity = 1024;// 线程池维护线程所允许的空闲时间//@Value("${async.executor.thread.keep_alive_seconds}")private int keepAliveSeconds = 300;//线程池名前缀 //@Value("${async.executor.thread.threadNamePrefix}")private static final String threadNamePrefix = "Async-Service-";@Bean(name = "threadPoolTaskExecutor")public ThreadPoolTaskExecutor threadPoolTaskExecutor(){ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setMaxPoolSize(maxPoolSize);executor.setCorePoolSize(corePoolSize);executor.setQueueCapacity(queueCapacity);executor.setKeepAliveSeconds(keepAliveSeconds);executor.setThreadNamePrefix(threadNamePrefix);// 线程池对拒绝任务(无线程可用)的处理策略// CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 初始化executor.initialize();return executor;}}

免登 和扫码 到这里就结束啦 上面的部分 浙政钉的url 请到文档中心查看 当然 如需要 同步应用的所有部门和用户 可以留言

浙政钉 扫码 免登集成相关推荐

  1. 钉钉扫码免登-钉钉应用内免登的实现(附仓库及Demo)

    新版钉钉扫码免登及钉钉应用内免登的一次实现 (附仓库及Demo) Vue2, JDK1.8, SpringBoot2.x.x, 钉钉模块, 钉钉模块Demo, 钉钉开放平台 目录 新版钉钉扫码免登及钉 ...

  2. 浙政钉扫一扫获取用户信息

    浙政钉的开发文档和专有钉钉一样:但想通过浙政钉扫一扫需向发浙政钉起申请获取应用信息 这里以专有钉钉为例 1.首先先注册一个专有钉钉账户 专有钉钉开放平台开发文档:https://dg-work.cn/ ...

  3. 前端Vue项目实现钉钉扫码免登录

    从前端实现的原理是引入二维码后,拿到返回页面的code,将code传到服务器获取数据库里的用户信息,匹配进行放行 第一步:在钉钉开发者平台创建一个应用,拿到相对应的appId ,测试时回调地址可以直接 ...

  4. keycloak单点登录(浙政钉2.0扫码、手机号验证码登录)

    写在前面:本篇博客只针对前端代码实现,keycloak配置什么的,自己和后端或者运维联调吧.说实在的,因为不熟悉keycloak代码的逻辑,再加上时间紧,所以搞了一些很多骚操作. 登录这些前端代码是写 ...

  5. 专有钉钉 浙政钉 前端 对接流程(小程序)

    主要开发流程 本公司专有钉钉开发平台账号(公司钉钉超管注册 给开发人员权限) 超管按照文档给予开发人员权限 创建项目 下载开发工具 配置专有钉钉开发环境 免登录(用户不用输入账号密码直接登录) 根据业 ...

  6. 浙政钉(专有钉钉)门户免登(超详细)

    钉钉家族 介绍浙政钉门户免登之前,首先搞清楚几个软件的关系,软件分别是:钉钉,专有钉钉,浙政钉 钉钉 是阿里巴巴集团专为中小企业打造的沟通和协同的多端平台. 专有钉钉 原名 政务钉钉,有更开放的设计能 ...

  7. 钉钉扫码登录第三方_在钉钉发布公司重要文件,真的安全吗?

    钉钉以疫情在家办公为契机,加上"幸运地"被教育部"选中",在2月5日,钉钉下载量首次超过微信,跃居苹果App Store排行榜第一,并打破App Store记录 ...

  8. python钉钉扫码登录程序_钉钉扫码登录网站(两种方式实现)

    钉钉扫码登录网站(两种方式实现) 效果: 动手敲代码! 第一步,钉钉后台配置 点击进入钉钉开发者平台 的页面,点击左侧菜单的[移动接入应用-登录],然后点击右上角的[创建扫码登录应用授权],创建用于免 ...

  9. 【浙政钉】第四篇:浙政钉创建群聊、消息接入、发送

    背景 浙政钉上架应用可创建群聊,和用户单聊等. 版权 本文允许转载,转载请写上原文地址,谢谢!作者:曹震 目录 一.准备工作 二.浙政钉系列 三.接口开发 1.特别说明 1.1访问IP不在白名单中,r ...

最新文章

  1. 我把 Spring Boot 的 banner 换成了美女,老板说工作不饱和,建议安排加班
  2. sketch如何做设计稿交互_交互设计师是做什么的——交互设计的历史、现状和未来...
  3. puppet安装与配置
  4. 李永乐线性代数手写笔记-行列式与矩阵
  5. 运行程序时java后面跟的是文件名对吗_运行程序时java命令后面跟的是文件名。...
  6. github 码云 获取_开发记录篇使用VS2019管理github项目
  7. java循环打印三角形_Java for循环打印三角形(基础)
  8. python从入门到精通pdf-跟老齐学Python从入门到精通完整版PDF_Python教程
  9. ASP.NET Web API 路由 (上)
  10. restful 风格api
  11. mysql cmd定时_windows下定时执行mysql冷备份
  12. 学成在线 网页前端(源码DIV+CSS)
  13. APP隐私合规检测工具Camille环境搭建
  14. C语言吸引人眼球的题目,公众号文章标题如何吸引用户眼球,12个写出好标题的技巧...
  15. 英科学家用扫描技术成功读取大脑记忆
  16. 用不同的QR Code识别库实现二维码的识别(第一篇:opencv 和BoofCV)
  17. visual studio 中鼠标光标的切换(或鼠标光标变成阴影方块)
  18. 高通骁龙765/骁龙765G芯片参数分析介绍
  19. 机器学习教程 三.回归理论及代码实现
  20. [GBase 8s 教程]GBase 8s 分页语法

热门文章

  1. php require的用法,php require的用法是什么
  2. TVS瞬态电压抑制二极管,用什么替代比较好?
  3. python,按自然数排序
  4. 优秀的DCIM系统具备哪些特征
  5. 鼠标经过时,地图上的每个城市变颜色并且有提示框
  6. DBeaver配置ODBC
  7. 淘宝618每日一猜答案(6月8日)明星孙怡最喜欢的显瘦单品?
  8. 【数据库课程】研讨04
  9. n个小球放入m个盒子中_M个球放入N个盒子的放法
  10. UE4 添加多人联机功能