Apex对接钉钉免登

前提

  1. 打通数据库服务器访问钉钉的网络

  2. Oracle ACL是否放行

  3. Wallet 是否添加钉钉证书

  4. Apex INTERNAL 工作区是否添加 Wallet 路径

  5. 测试请求

    1
    2
    3
    4
    select   APEX_WEB_SERVICE.make_rest_request(
    p_url => 'https://developers.dingtalk.com/',
    p_http_method => 'GET')
    from dual;
  6. 钉钉关键信息APPKEY,APPSECRET,AGENT_ID,corpId (向本公司钉钉管理员建H5应用索要)

  7. 钉钉JS dingtalk.open.js

步骤

  1. 新建应用

  2. 将 dingtalk.open.js 导入应用的静态文件中得到 #WORKSPACE_IMAGES#dingtalk.open.js

  3. 新建全局页项 DINGDING_CODE,DINGDING_ACCESS_TOKEN 权限都是设置为 无限制

  4. 共享组件>>应用程序处理中创建一个全局的Ajax回调 名字GET_DINGDING_PD_ACCESS_TOKEN 权限设置为不需要授权

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    Declare
    l_code varchar2(100) := apex_application.g_x01;
    l_appkey varchar2(30) := 'din0'; -- 前提6中的 APPKEY
    l_appsecret varchar2(70) := 'O5Gg5P'; -- 前提6中的 APPSECRET
    l_email varchar2(100) := null ;
    l_clob clob;
    Begin
    if l_code is not null then
    :DINGDING_CODE := l_code; --
    apex_web_service.g_request_headers(1).name := 'Content-Type';
    apex_web_service.g_request_headers(1).VALUE := 'application/json';
    l_clob := APEX_WEB_SERVICE.make_rest_request(
    p_url => 'https://oapi.dingtalk.com/gettoken',
    p_http_method => 'GET',
    p_parm_name =>apex_util.string_to_table('appkey:appsecret'),
    p_parm_value =>apex_util.string_to_table(l_appkey || ';' || l_appsecret, p_separator=>';')
    );
    apex_json.parse(l_clob);
    if apex_json.does_exist(p_path => 'access_token') then
    :DINGDING_ACCESS_TOKEN := apex_json.get_varchar2(p_path => 'access_token');
    apex_json.open_object();
    apex_json.close_object();
    end if;
    apex_json.open_object();
    apex_json.close_object();
    end if;
    End;
  5. 新建钉钉登录中转页(page_id 9990)

  6. 将默认登录页9999中的页别名 剪切 到中转页

  7. 在中转页 JavaScript 区域文件URL填充 #WORKSPACE_IMAGES#dingtalk.open.js 函数和全局变量声明

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    if (dd.env.platform === "notInDingTalk") {
    alert('抱歉请在钉钉登录');
    } else {
    dd.ready(function () {
    // dd.ready参数为回调函数,在环境准备就绪时触发,jsapi的调用需要保证在该回调函数触发后调用,否则无效。
    dd.runtime.permission.requestAuthCode({

    corpId:"ding46", // 前提 6中的corpId
    onSuccess: function (result) {
    apex.server.process(

    "GET_DINGDING_PD_ACCESS_TOKEN", // 保持和3中的名字一致
    { 'x01': result.code },
    {
    success: function (data) {
    // alert(data)
    window.location ='f?p='+&APP_ID.+':1:'+&APP_SESSION.
    }
    }
    );
    },
    onFail: function (err) {
    alert('抱歉钉钉登录失败');
    }

    });
    });
    }

  8. 自定义认证方案pl/sql 会话过程名无效 TOKEN_INVALID_SESSION_DINGDING_1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    PROCEDURE TOKEN_INVALID_SESSION_DINGDING_1
    IS
    l_access_token varchar2(50) := :DINGDING_ACCESS_TOKEN ;
    l_userid varchar2(50) := null ;
    l_email varchar2(100) := null ;
    l_clob clob;

    BEGIN
    -- get code
    -- 获取access_token
    -- 通过免登授权码和access_token获取用户的userid

    apex_debug.warn('+++++++++++l_access_token+++++++++++>');
    apex_debug.warn(l_access_token);
    apex_debug.warn('<+++++++++++');

    if l_access_token is not null then
    l_clob := APEX_WEB_SERVICE.make_rest_request(
    p_url => 'https://oapi.dingtalk.com/user/getuserinfo',
    p_http_method => 'GET',
    p_parm_name =>apex_util.string_to_table('access_token:code'),
    p_parm_value =>apex_util.string_to_table(l_access_token || ';' || :DINGDING_CODE, p_separator=>';')
    );
    apex_debug.warn('------------->');
    apex_debug.warn(l_clob);
    apex_debug.warn('<-------------');
    apex_json.parse(l_clob);
    apex_debug.warn('+++++++++++l_code+++++++++++>');
    apex_debug.warn(l_clob);
    apex_debug.warn('<+++++++++++');
    if apex_json.does_exist(p_path => 'userid') then
    l_userid := apex_json.get_varchar2(p_path => 'userid');
    -- :CREATED_BY_NAME :=apex_json.get_varchar2(p_path => 'name'); --取姓名
    -- :DINGDING_USERID := l_userid;
    sys.dbms_output.put_line('l_userid' || ' - ' || l_userid);
    APEX_DEBUG.WARN('l_userid' || ' - ' || l_userid);
    else
    apex_json.open_object();

    apex_json.write('l_clob', l_clob);
    apex_json.close_object();
    end if;
    end if;
    /*
    -- 用户8位工号
    if l_userid is not null then
    l_clob := APEX_WEB_SERVICE.make_rest_request(
    p_url => 'https://oapi.dingtalk.com/user/get',
    p_http_method => 'GET',
    p_parm_name =>apex_util.string_to_table('access_token:userid'),
    p_parm_value =>apex_util.string_to_table(l_access_token || ';' || l_userid, p_separator=>';')
    );
    apex_json.parse(l_clob);
    if apex_json.does_exist(p_path => 'jobnumber') then
    l_email := apex_json.get_varchar2(p_path => 'jobnumber');
    sys.dbms_output.put_line('l_email' || ' - ' || l_clob);
    APEX_DEBUG.WARN('l_email' || ' - ' || l_clob);
    end if;
    end if;

    */

    if l_userid is not null then
    -- login
    if l_userid='03' then l_userid:='02'; end if; -- 模拟账号
    apex_authentication.post_login(l_userid,
    null, true);
    end if;
    End;