功能描述

通过钉钉扫码登录,并且获取到登录的用户信息。这样省去自己开发一套登录系统。相对比较方便。

背景描述

现在钉钉主推E应用,官方的案例也是E应用的,其实这个E应用的后台调用的过程和原来的扫码的登录的已经是不一样了。所以要做这个功能需要查旧的api文档。地址如下:https://open-doc.dingtalk.com/dingdocold

为了兼容性,旧的api以及url应该不会再有改动了。所以现在做一套模板上来,大家可以直接复制代码。修改一些配置就可以运行了。

开发流程

这里根据场景稍微做了一些改变。(sdk的下载自己做)
创建扫码传递的检验信息
在钉钉的开发者平台,扫码登录创建一个授权。主要有如下信息

| 需提交字段 | 说明 | | :- | :- | |名称 |授权微应用的名称| |描述 |扫码登录用于,主要是说明,使用的场景| |授权页面LOGO地址 |这个会显示在授权页面的中间页中,以http或https开头| |回调域名 |回调的URL,以http或https开头|

这里需要注意的是回调域名,就是扫码后跳转的页面,这个后面会用到。创建好以后,我们就可以看到appId及appSecret。
创建二维码
这里主要使用的是跳转,比较方便,一个url解决。

https://oapi.dingtalk.com/connect/qrconnect?appid=APPID&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=REDIRECT_URI

就是上面的url。传递的参数有需要修改的几个地方appid就是第一步获取的id。redirect_uri就是第一步写的跳转页面(跳转页面其实就是要获取具体的信息的请求,扫描只是通过验证了,我们还要记录谁登录等信息,获取具体信息再跳转的页面做)。state这里其实主要是用来禁止缓存的,这是一个get请求,需要做这些操作,其余参数不改。
剩余步骤

后面的步骤比较机械化,如果有兴趣就去看官方文档。这些代码是不需要修改的,我已经抽象成了方法。

重点强调

我们需要获取的一些信息,appid,appSecret,回调的url。

代码

@RestController
@RequestMapping("")
public class DingLoginController {

    private static final String URL = "http://127.0.0.1:8080/loginInfo";
    private static final String DINGDING_URL = "https://oapi.dingtalk.com";
    private static final String METHOD_GET = "GET";
    private static final String APP_ID = "";
    private static final String APP_SECRET = "";

    @RequestMapping("/login")
    public void login(HttpServletResponse response) throws IOException {

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(DINGDING_URL).append("/connect/qrconnect?appid=" + APP_ID + "&")
                .append("response_type=code&scope=snsapi_login&state=")
                .append(System.currentTimeMillis()).append("&redirect_uri=").append(URL);
        response.sendRedirect(stringBuilder.toString());
    }

    @RequestMapping("/loginInfo")
    public JSONResult login(String code) throws ApiException {
        String accessToken = getAccessToken(APP_ID, APP_SECRET);
        String persistentCode = getPersistentCode(accessToken, code);
        JSONObject infos= JSONObject.parseObject(persistentCode);
        String openid = infos.getString("openid");
        String persistent_code = infos.getString("persistent_code");
        String unionid = infos.getString("unionid");
        String snsToken = getSnsToken(accessToken,openid,persistent_code);
        String userInfo = getUserInfo(snsToken);
        return JSONResult.ok(userInfo);


    }


    public String getAccessToken(String appId, String appSecret) throws ApiException {
        OapiSnsGettokenResponse response = null;

        DingTalkClient client = new DefaultDingTalkClient(DINGDING_URL + "/sns/gettoken");
        OapiSnsGettokenRequest request = new OapiSnsGettokenRequest();
        request.setAppid(appId);
        request.setAppsecret(appSecret);
        request.setHttpMethod(METHOD_GET);
        response = client.execute(request);
        String body = response.getBody();
        JSONObject jo = JSON.parseObject(body);
        String errcode = jo.getString("errcode");
        String access_token = null;
        if ("0".equals(errcode)) {
            access_token = (String) jo.get("access_token");
        }
        return access_token;
    }


    public String getPersistentCode(String accessToken, String code) throws ApiException {
        OapiSnsGetPersistentCodeResponse response = null;

        DingTalkClient client = new DefaultDingTalkClient(DINGDING_URL + "/sns/get_persistent_code");
        OapiSnsGetPersistentCodeRequest request = new OapiSnsGetPersistentCodeRequest();
        request.setTmpAuthCode(code);
        response = client.execute(request, accessToken);

        return response.getBody();
    }


    public String getSnsToken(String accessToken,String openId,String persistentCode) throws ApiException {
        OapiSnsGetSnsTokenResponse response = null;
        DingTalkClient client = new DefaultDingTalkClient(DINGDING_URL + "/sns/get_sns_token");
        OapiSnsGetSnsTokenRequest request = new OapiSnsGetSnsTokenRequest();
        request.setPersistentCode(persistentCode);
        request.setOpenid(openId);
        response = client.execute(request, accessToken);
        return response.getSnsToken();
    }


    public String getUserInfo(String snsToken) throws ApiException {
        OapiSnsGetuserinfoResponse response = null;
        DingTalkClient client = new DefaultDingTalkClient(DINGDING_URL + "/sns/getuserinfo");
        OapiSnsGetuserinfoRequest request = new OapiSnsGetuserinfoRequest();
        request.setSnsToken(snsToken);
        request.setHttpMethod(METHOD_GET);
        response = client.execute(request);
        return response.getBody();
    }


}

复制以上代码,然后修改APP_ID ,APP_SECRET ,这里URL = "http://127.0.0.1:8080/loginInfo"是因为我下面的代码写了是访问路径是loginInfo。如果要修改url,记得把下面的代码的url映射也修改掉。

然后就可以发布了,我们访问login就会弹出二维码,用钉钉扫码登录以后,就可以看到返回的扫码的用户信息了。