钉钉小程序入门3—钉钉扫码登录PC端网站

news2024/12/23 18:54:18

第一部分、准备材料🌲

公网环境

老版钉钉扫码中必须要配置一个域名才可以调试,新版支持IP配置调了。我是手机打开热点,电脑连接热点进行调试的,比老版要方便了不少。

查看本机IP地址方法:
如果使用的Windows,执行命令:ipconfig

如果使用的Mac,执行命令:ifconfig en0

创建一个小程序(企业内应用即可)

这个小程序可以是H5微应用也可以是小程序,但需要是企业内应用。
将创建后的小程序appKey和appSecret

在这里插入图片描述

搭建SpringBoot项目

目录结构如下:
在这里插入图片描述

注意:resources中的目录结构和文件名一定要和我的一致,不能多不能少,否则会出现启动报错或者找不到文件的问题。

第二部分、环境配置⚙

SpringBoot项目pom.xml

这里我引入了VM模板用来放置扫码页与首页的html代码,引入DingTalk调用三方接口获取扫码用户的基本信息。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>SpringBoot-DDScan</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringBoot-DDScan</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- dingding -->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>alibaba-dingtalk-service-sdk</artifactId>
            <version>1.1.1</version>
            <exclusions>
                <exclusion>
                    <artifactId>log4j</artifactId>
                    <groupId>log4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>dingtalk</artifactId>
            <version>1.2.5</version>
        </dependency>


        <!-- VM 模板 -->
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>velocity-spring-boot-starter</artifactId>
            <version>1.0.4.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

SpringBoot项目application.properties

spring.application.name=dd-scan
server.port=8080

## 小程序AppID和AppSecret(此处填入自己复制的)
qr.appId=xxxx
qr.appSerret=xxxx

# Velocity\u914D\u7F6E\uFF0C\u8BE6\u89C1 http://gitlab.alibaba-inc.com/middleware-container/pandora-boot/wikis/spring-boot-velocity
spring.velocity.resource-loader-path=classpath:/velocity/templates
spring.velocity.toolbox-config-location=/velocity/toolbox.xml
spring.velocity.layout-url=/velocity/layout/default.vm

钉钉开放平台-登录与分享配置回调域名

这里的回调地址就是扫码后跳转的地址。这里的地址与下面login.vm中的window.url 一定要一模一样,否则会扫码会弹出”回调域名配置错误“的提示。
在这里插入图片描述

钉钉开放平台-权限管理授权

选择:个人手机号信息、成员信息读权限权限即可
在这里插入图片描述

第三部分、代码📚

后端代码

SpringBootDdScanApplication.java

package com.example.springbootddscan;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootDdScanApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDdScanApplication.class, args);
    }

}

MainController.java

package com.example.springbootddscan.controller;

import com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders;
import com.aliyun.dingtalkcontact_1_0.models.GetUserResponse;
import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenRequest;
import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenResponse;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/login")
public class MainController {

    @Value("${qr.appId}")
    private String qrAppId;

    @Value("${qr.appSerret}")
    private String qrAppSecret;

    @GetMapping("/toLoginPage")
    public ModelAndView toLoginPage() {
        return new ModelAndView("login");
    }

    @GetMapping("/scanLogin")
    public ModelAndView scanLogin(@RequestParam String authCode) throws Exception {
        //获取当前小程序的accesstoken
        GetUserTokenResponse userTokenResponse = getUserAccessToken(qrAppId, qrAppSecret, authCode, "authorization_code");
        //查询当前用户信息
        GetUserResponse me = getUserWithOptions(userTokenResponse.getBody().getAccessToken(), "me");
        //获取首页模板
        ModelAndView modelAndView = new ModelAndView("index");
        modelAndView.addObject("userid",me.getBody().getOpenId());
        modelAndView.addObject("userName",me.getBody().getNick());
        modelAndView.addObject("userPhone",me.getBody().getMobile());
        return modelAndView;
    }

    public GetUserResponse getUserWithOptions(String accessToken, String unionId) throws Exception {
        // 准备请求配置参数
        Config config = new Config();
        // 设置请求协议
        config.protocol = "https";
        // 设置请求区域
        config.regionId = "central";
        // 初始化账号Client
        com.aliyun.dingtalkcontact_1_0.Client client = new com.aliyun.dingtalkcontact_1_0.Client(config);
        GetUserHeaders getUserHeaders = new GetUserHeaders();
        getUserHeaders.xAcsDingtalkAccessToken = accessToken;
        return client.getUserWithOptions(unionId, getUserHeaders, new RuntimeOptions());
    }

    public GetUserTokenResponse getUserAccessToken(String suiteKey, String suiteSecret, String authCode, String grantType) throws Exception {
        // 准备请求配置参数
        Config config = new Config();
        // 设置请求协议
        config.protocol = "https";
        // 设置请求区域
        config.regionId = "central";
        // 初始化账号Client
        com.aliyun.dingtalkoauth2_1_0.Client client = new com.aliyun.dingtalkoauth2_1_0.Client(config);
        GetUserTokenRequest getUserTokenRequest = new GetUserTokenRequest()
                .setClientId(suiteKey)
                .setClientSecret(suiteSecret)
                .setCode(authCode)
                .setGrantType(grantType);
        return client.getUserToken(getUserTokenRequest);
    }
}

前端代码

login.vm

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>钉钉扫码登录</title>
</head>
<body>
<!-- 方案二 ,该方法依赖jquery库-->
<script src="https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js"></script>
<script>
    <!-- 获取到的IP地址 -->
    window.url = 'http://xxx.xx.xxx.xx:8080/login/scanLogin'
    <!-- 小程序的appId -->
    window.appid = 'xxxx'
</script>
<!-- STEP1:在HTML中添加包裹容器元素 -->
<div id="self_defined_element" class="self-defined-classname"></div>
<style>
    /* STEP2:指定这个包裹容器元素的CSS样式,尤其注意宽高的设置 */
    .self-defined-classname {
        width: 300px;
        height: 300px;
    }
</style>
<script>
    // STEP3:在需要的时候,调用 window.DTFrameLogin 方法构造登录二维码,并处理登录成功或失败的回调。
    window.DTFrameLogin(
            {
                id: 'self_defined_element',
                width: 300,
                height: 300,
            },
            {
                redirect_uri: encodeURIComponent(window.url),
                client_id: window.appid,
                scope: 'openid',
                response_type: 'code',
                state: 'test',
                prompt: 'consent',
            },
            (loginResult) => {
                console.log(loginResult)
                const {redirectUrl, authCode, state} = loginResult;
                // 这里可以直接进行重定向
                window.location.href = redirectUrl;
                // 也可以在不跳转页面的情况下,使用code进行授权
                console.log(authCode);
            },
            (errorMsg) => {
                // 这里一般需要展示登录失败的具体原因
                alert(`Login Error: ${errorMsg}`);
            },
    );
</script>
</body>
</html>

index.vm

<h1>首页</h1>
<h2>userid: ${userid}</h2>
<h2>用户名: ${userName}</h2>
<h2>手机号码:${userPhone}</h2>

其他文件

toolbox.xml

<?xml version="1.0" encoding="UTF-8"?>

<tools>
    <data type="number" key="TOOLS_VERSION" value="2.0"/>
    <data type="boolean" key="GENERIC_TOOLS_AVAILABLE" value="true"/>
    <toolbox scope="application">
        <tool class="org.apache.velocity.tools.generic.AlternatorTool"/>
        <tool class="org.apache.velocity.tools.generic.ClassTool"/>
        <tool class="org.apache.velocity.tools.generic.ComparisonDateTool"/>
        <tool class="org.apache.velocity.tools.generic.ConversionTool"/>
        <tool class="org.apache.velocity.tools.generic.DisplayTool"/>
        <tool class="org.apache.velocity.tools.generic.EscapeTool"/>
        <tool class="org.apache.velocity.tools.generic.FieldTool"/>
        <tool class="org.apache.velocity.tools.generic.MathTool"/>
        <tool class="org.apache.velocity.tools.generic.NumberTool"/>
        <tool class="org.apache.velocity.tools.generic.ResourceTool"/>
        <tool class="org.apache.velocity.tools.generic.SortTool"/>
        <tool class="org.apache.velocity.tools.generic.XmlTool"/>
    </toolbox>
    <toolbox scope="request">
        <tool class="org.apache.velocity.tools.generic.ContextTool"/>
        <tool class="org.apache.velocity.tools.generic.LinkTool"/>
        <tool class="org.apache.velocity.tools.generic.LoopTool"/>
        <tool class="org.apache.velocity.tools.generic.RenderTool"/>
        <tool class="org.apache.velocity.tools.view.CookieTool"/>
        <tool class="org.apache.velocity.tools.view.ImportTool"/>
        <tool class="org.apache.velocity.tools.view.IncludeTool"/>
        <tool class="org.apache.velocity.tools.view.PagerTool"/>
        <tool class="org.apache.velocity.tools.view.ParameterTool"/>
        <tool class="org.apache.velocity.tools.view.ViewContextTool"/>
        <!--
        This is not directly useable.
        <tool class="org.apache.velocity.tools.view.AbstractSearchTool"/>
        -->
        <!-- move this to request scope -->
        <tool class="org.apache.velocity.tools.generic.ResourceTool"/>
        <!--
        This is not useful in its default form.
        But, if it were, it'd be request-scoped.
        <tool class="org.apache.velocity.tools.generic.ValueParser"/>
        -->
    </toolbox>
</tools>

default.vm

$!{screen_content}

第四部分、演示🍓

输入登录地址

http://xxx.xxx.xxx.xxx:8080/login/toLoginPage

这里记住一定要用IP,不能使用localhost或者127.0.0.1,否则即使二维码能出现,扫码完也不会有反应。
在这里插入图片描述

使用钉钉扫码

扫完码后钉钉会弹出一个授权页,点击同意即可。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RC5ajAZU-1670244714399)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d636a914a6144afc965d47a2aa50b409~tplv-k3u1fbpfcp-watermark.image?)]

钉钉回调地址进入首页

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-llcMLSRh-1670244714400)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bbbfd463657841febc7bed7e481ce3b5~tplv-k3u1fbpfcp-watermark.image?)]

第五部分、原理解释

钉钉文档链接:https://open.dingtalk.com/document/orgapp-server/tutorial-obtaining-user-personal-information

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/64154.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL高可用复制管理工具 —— Orchestrator使用

Orchestrator介绍 Orchestrator&#xff08;orch&#xff09;&#xff1a;go编写的MySQL高可用性和复制拓扑管理工具&#xff0c;支持复制拓扑结构的调整&#xff0c;自动故障转移和手动主从切换等。后端数据库用MySQL或SQLite存储元数据&#xff0c;并提供Web界面展示MySQL复…

docker学习笔记2(狂神)

Docker的常用命令 然后我们来学我们最重要的镜像命令&#xff1a; docker images 查看所有本地的主机上的镜像 docker search搜索镜像&#xff1a; docker pull下载镜像&#xff1a; docker pull 镜像名[:tag] 指定版本下载&#xff1a; docker rmi删除镜像&#xff1a; 批量…

[附源码]Python计算机毕业设计Django市场摊位管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

m基于遗传优化的不同等级电动汽车充电站的选址方案matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 作为电动汽车的普及与推广&#xff0c;必要的基础配套服务设施、充电站的建设位置和选址规划对整体行业的发展起着重要的意义&#xff0c;本文中提出了一个不同等级电动汽车充电站的选址与求解算…

Zebec联合Visa推出实体借记卡持续利好生态,$ZBC表现强劲

Zebec生态从今年年初开始&#xff0c;持续的释放利好提振市场信心。此前&#xff0c;Zebec曾以 10 亿美元的完全稀释估值筹集了 850 万美元&#xff0c;该轮融资投资者包括 Circle Ventures、Shima 和 Resolute等知名 Web3 投资机构。这是 Zebec Protocol 继今年年初获得 2800 …

计算机系统基本概念

1.计算机的硬件结构 早期的计算机没有很复杂的图形功能&#xff0c;CPU的核心频率也不高&#xff0c;跟内存的频率一样&#xff0c;它们都是直接连接在同一个总线&#xff08;Bus&#xff09; 上的。由于IO设备诸如显示设备、键盘、软盘和磁盘等速度与CPU和内存相比还是慢很多…

QT:布局管理器消息盒子对话框

让组件在水平和垂直方向对齐 有三种常用布局管理器&#xff1a; 水平&#xff0c;QHBoxLayout 垂直&#xff0c;QVBoxLayout 网格&#xff0c;QGridLayout(使布局好的界面嵌套到主窗口) 1.让组件大小固定 修改属性&#xff1a;minimusize&#xff0c;maxmumsize 最小和最大组件…

使用setuptools构建python包

python包分发方式 源码包分发&#xff1a; 源码包安装过程是先解压&#xff0c;再编译。最后才安装&#xff0c;所以其是跨平台的&#xff0c;由于每次安装都需要进行编译&#xff0c;相对于二进制包安装方式来说安装速度较慢。 解压——编译——安装 源码包本质上是一个压缩…

CDGA|2023年数据治理发展前景预测步骤

CDGA|2023年数据治理发展前景预测步骤 数据治理发展前景预测&#xff0c;就是在数据治理市场调查获得的各种信息和资料的基础上&#xff0c;运用科学的预测技术和方法&#xff0c;对影响数据治理市场供求变化的诸因素进行调查研究&#xff0c;分析和预见数据治理发展趋势&…

《解构领域驱动设计》读书笔记

文章目录书籍信息开篇软件复杂度剖析复杂系统理解能力预测能力领域驱动设计概览基本概念控制软件复杂度领域驱动设计统一过程现存的不足领域驱动设计统一过程全局分析问题空间探索全局分析的 5W 模型高效沟通高效协作商业模式画布业务流程图服务蓝图用例图事件风暴学习循环价值…

windows系统下mysql的主从复制

使用一台物理机实现mysql的主从复制功能。 准备&#xff1a; 1、操作系统&#xff1a;Windows Server 2016 Standard 2、下载mysql免安装包&#xff1a; https://downloads.mysql.com/archives/get/p/23/file/mysql-5.6.17-winx64.zip 安装maser 1、解压mysql压缩包&…

Windows下安装hadoop2.7.4

Windows下安装hadoop 案例环境 该压缩包是已经简化配置后的 hadoop2.7.4下载地址文件分享 (weiyun.com) 安装步骤 解压压缩包 配置环境变量 在系统变量中添加 在path中添加 拷贝hadoop2.7.4\bin\hadoop.dll到目录C:\Windows\System32 配置文件 把/etc/hadoop/ 下目录的相…

玩以太坊链上项目的必备技能(初识智能合约语言-Solidity之旅一)

前面一篇关于智能合约翻译文讲到了&#xff0c;是一种计算机程序&#xff0c;既然是程序&#xff0c;那就可以使用程序语言去编写智能合约了。 而若想玩区块链上的项目&#xff0c;大部分区块链项目都是开源的&#xff0c;能看得懂智能合约代码&#xff0c;或找出其中的漏洞&a…

管理RMAN备份_维护RMAN备份和仓库记录

1&#xff0e;RMAN备份和仓库维护概述 1.1&#xff0e;备份和仓库维护的目的 建议的维护策略是配置一个快速恢复区域&#xff0c;一个备份保留策略和一个归档 redo日志删除策略。在这种情况中&#xff0c;数据库按需要自动维护和删除备份与归档redo日志。然而&#xff0c;有时…

[附源码]Python计算机毕业设计Django水果管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

阿里P8专家爆出:入职阿里必备的598道java面试题,内含算法

前言 之前也给大家分享过很多的面试题和大佬的面试经验&#xff0c;相信大家也已经利用到了&#xff0c;也顺利找到了工作&#xff0c;并拿到了高薪。 今天就给大家分享阿里P8专家长期以来面试所问到的java面试题&#xff0c;总共有598道&#xff08;含算法&#xff09;&…

PCL 使用MLS 上采样

移动最小二乘法MLS&#xff08;Moving Lest Squares&#xff09;简要介绍_Figure 09的博客-CSDN博客_移动最小二乘法 深入理解移动最小二乘法曲面拟合代码&#xff08;MLS2D.m&#xff09;_残影丶的博客-CSDN博客_mls2d PCL 点云采样_Σίσυφος1900的博客-CSDN博客 上采样…

和数集团浅谈区块链技术如何赋能数字政务?

在“十四五”提高数字政府建设水平的大环境下,构建数字政务发展体系是国家治理现代化的必然选择。2021年是2035远景目标的开局之年&#xff0c;《十四五规划纲要》中明确将区块链列为“十四五”七大数字经济重点产业之一。数字政务的体系架构和创新机理,离不开新兴技术融合互通…

移动通信:分集技术(时间分集,频率分集,空间分集,SC,MRC,EGC)学习笔记

文章目录Micro diversityTime DiversityFrequency DiversitySpatial DiversityCombination of signalsSelection CombiningMaximal Ratio CombiningEqual Gain CombiningReferences分集技术是用来补偿衰落信道损耗的&#xff0c;它通常通过两个或更多的接收天线来实现。同均衡器…

越早越好,突破职业瓶颈,2023年考PMP项目管理有何好处?

考PMP没有行业和职业的限制&#xff0c;只要是需要感兴趣的人就可以报考。 适合任何领域行业的项目。 是通用的项目管理理念。 那么 # 考了PMP会有什么益处呢&#xff1f;# ---带你30秒看完&#xff0c;从六个方面讲 01 职场加分项 目前国内很多的大型企业在招聘的时候会有…