Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
dingtalk-sdk
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open-source
dingtalk-sdk
Commits
15cb4dfb
Commit
15cb4dfb
authored
Sep 02, 2020
by
Francis Zhou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
增加 get_3rd_login_free_user_profile 方法
parent
dee88453
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
136 additions
and
29 deletions
+136
-29
dingtalk.rb
lib/dingtalk.rb
+26
-6
auth.rb
lib/dingtalk/auth.rb
+14
-2
core.rb
lib/dingtalk/core.rb
+33
-11
request_url.rb
lib/dingtalk/request_url.rb
+11
-4
auth_spec.rb
spec/dingtalk/auth_spec.rb
+49
-4
dingtalk_spec.rb
spec/dingtalk_spec.rb
+3
-2
No files found.
lib/dingtalk.rb
View file @
15cb4dfb
...
@@ -3,10 +3,35 @@ require 'base64'
...
@@ -3,10 +3,35 @@ require 'base64'
require
'openssl'
require
'openssl'
require
"dingtalk/version"
require
"dingtalk/version"
require
"dingtalk/auth"
require
"dingtalk/access_token"
module
Dingtalk
module
Dingtalk
class
Error
<
StandardError
class
Error
<
StandardError
end
end
class
Signature
def
initialize
(
s
)
@signature
=
s
end
def
to_s
@signature
end
def
url_encoded
URI
.
encode_www_form_component
@signature
end
end
class
Request
include
Auth
def
initialize
(
app_key
:,
app_secret
:)
@app_key
,
@app_secret
=
app_key
,
app_secret
end
end
class
<<
self
class
<<
self
# 个人免登录场景的签名计算
# 个人免登录场景的签名计算
# @url https://ding-doc.dingtalk.com/doc#/faquestions/hxs5v9
# @url https://ding-doc.dingtalk.com/doc#/faquestions/hxs5v9
...
@@ -29,12 +54,7 @@ module Dingtalk
...
@@ -29,12 +54,7 @@ module Dingtalk
signature_str
=
OpenSSL
::
HMAC
.
digest
(
"SHA256"
,
app_secret
,
timestamp
.
to_s
)
signature_str
=
OpenSSL
::
HMAC
.
digest
(
"SHA256"
,
app_secret
,
timestamp
.
to_s
)
signature_str_base64
=
Base64
.
encode64
(
signature_str
).
strip
signature_str_base64
=
Base64
.
encode64
(
signature_str
).
strip
if
options
[
:url_encode
]
Signature
.
new
(
signature_str_base64
)
# 不知道为什么 URI.encode 方法不行
return
URI
.
encode_www_form_component
(
signature_str_base64
)
end
signature_str_base64
end
end
end
end
end
end
lib/dingtalk/auth.rb
View file @
15cb4dfb
...
@@ -6,13 +6,24 @@ module Dingtalk
...
@@ -6,13 +6,24 @@ module Dingtalk
class
<<
self
class
<<
self
extend
Dingtalk
::
Core
extend
Dingtalk
::
Core
# 企业内部应用免登
# 企业内部应用免登
录 用户ID获取
# @url https://ding-doc.dingtalk.com/doc#/serverapi2/clotub
# @url https://ding-doc.dingtalk.com/doc#/serverapi2/clotub
add_request
:get_int_login_free_user_id
,
:get
,
Dingtalk
::
RequestUrl
::
GET_USER_INFO
do
|
request
|
add_request
:get_int_login_free_user_id
,
:get
,
Dingtalk
::
RequestUrl
::
INT_LOGIN_FREE_
GET_USER_INFO
do
|
request
|
request
.
add_arg
:code
,
required:
true
,
in: :query
request
.
add_arg
:code
,
required:
true
,
in: :query
request
.
add_arg
:access_token
,
required:
true
,
in: :query
request
.
add_arg
:access_token
,
required:
true
,
in: :query
end
end
# 钉钉内免登录第三方网站 个人信息获取
# @url https://ding-doc.dingtalk.com/doc#/serverapi2/etaarr
add_request
:get_3rd_login_free_user_profile
,
:post
,
Dingtalk
::
RequestUrl
::
GET_USER_INFO_SNS
do
|
request
|
request
.
is_json
=
true
request
.
add_arg
:accessKey
,
required:
true
,
in: :query
request
.
add_arg
:timestamp
,
required:
true
,
in: :query
request
.
add_arg
:signature
,
required:
true
,
in: :query
request
.
add_arg
:tmp_auth_code
,
required:
true
,
in: :body
end
end
end
end
end
end
end
\ No newline at end of file
lib/dingtalk/core.rb
View file @
15cb4dfb
...
@@ -8,25 +8,43 @@ require "dingtalk"
...
@@ -8,25 +8,43 @@ require "dingtalk"
module
Dingtalk
module
Dingtalk
module
Core
module
Core
class
RequestBuilder
class
RequestBuilder
attr_reader
:query_args
,
:
payload
_args
,
:required_args
attr_reader
:query_args
,
:
body
_args
,
:required_args
def
initialize
def
initialize
@is_json
=
false
@body_args
=
[]
@query_args
=
[]
@query_args
=
[]
@payload_args
=
[]
@required_args
=
[]
@required_args
=
[]
@with_key_and_secret
=
false
@with_key_and_secret
=
false
end
end
def
is_json?
@is_json
end
def
is_arg_required?
(
arg_name
)
def
is_arg_required?
(
arg_name
)
@required_args
.
include?
arg_name
@required_args
.
include?
arg_name
end
end
def
has_body_args?
!
@body_args
.
empty?
end
def
has_query_args?
!
@query_args
.
empty?
end
def
is_json
=
(
b
)
@is_json
=
b
end
def
add_arg
(
arg_name
,
option
)
def
add_arg
(
arg_name
,
option
)
case
option
[
:in
]
case
option
[
:in
]
when
:body
@body_args
<<
arg_name
when
:query
when
:query
@query_args
<<
arg_name
@query_args
<<
arg_name
when
:payload
@payload_args
<<
arg_name
else
else
raise
Dingtalk
::
Error
.
new
(
"unknown argument position"
)
raise
Dingtalk
::
Error
.
new
(
"unknown argument position"
)
end
end
...
@@ -40,22 +58,26 @@ module Dingtalk
...
@@ -40,22 +58,26 @@ module Dingtalk
yield
builder
if
block_given?
yield
builder
if
block_given?
define_method
request_name
do
|
method_args
=
{}
|
define_method
request_name
do
|
method_args
=
{}
|
default_options
=
{
request_options
=
{}.
tap
do
|
h
|
query:
{}
}
request_options
=
default_options
.
tap
do
|
h
|
builder
.
required_args
.
each
do
|
arg
|
builder
.
required_args
.
each
do
|
arg
|
raise
Dingtalk
::
Error
.
new
(
"missing required argument '
#{
arg
}
' when invoke request
#{
request_name
}
"
)
\
raise
Dingtalk
::
Error
.
new
(
"missing required argument '
#{
arg
}
' when invoke request
#{
request_name
}
"
)
\
if
method_args
[
arg
].
nil?
if
method_args
[
arg
].
nil?
end
end
h
[
:body
]
=
{}
if
builder
.
has_body_args?
h
[
:query
]
=
{}
if
builder
.
has_query_args?
builder
.
body_args
.
each
do
|
arg
|
h
[
:body
][
arg
]
=
method_args
[
arg
]
end
builder
.
query_args
.
each
do
|
arg
|
builder
.
query_args
.
each
do
|
arg
|
h
[
:query
][
arg
]
=
method_args
[
arg
]
unless
method_args
[
arg
].
nil?
h
[
:query
][
arg
]
=
method_args
[
arg
]
unless
method_args
[
arg
].
nil?
end
end
builder
.
payload_args
.
each
do
|
arg
|
if
builder
.
is_json?
h
[
:body
][
arg
]
=
method_args
[
arg
]
h
[
:body
]
=
h
[
:body
].
to_json
h
[
:headers
]
=
{
:"Content-Type"
=>
"application/json"
}
if
builder
.
is_json?
end
end
end
end
...
...
lib/dingtalk/request_url.rb
View file @
15cb4dfb
# frozen_string_literal: true
module
Dingtalk
module
Dingtalk
module
RequestUrl
module
RequestUrl
# 获取 AccessToken
# 获取 AccessToken
ACCESS_TOKEN
=
"https://oapi.dingtalk.com/gettoken"
.
freeze
ACCESS_TOKEN
=
"https://oapi.dingtalk.com/gettoken"
# 扫码登录第三方网站 OAuth 跳转地址
# @url https://ding-doc.dingtalk.com/doc#/serverapi2/kymkv6
CONNECT_QR_REDIRECT
=
"https://oapi.dingtalk.com/connect/qrconnect"
# 企业内应用免登录获取用户ID
# 企业内应用免登录获取用户ID
# https://ding-doc.dingtalk.com/doc#/serverapi2/clotub
#
@url
https://ding-doc.dingtalk.com/doc#/serverapi2/clotub
GET_USER_INFO
=
"https://oapi.dingtalk.com/user/getuserinfo"
.
freeze
INT_LOGIN_FREE_GET_USER_INFO
=
"https://oapi.dingtalk.com/user/getuserinfo"
# 服务端通过临时授权码获取授权用户的个人信息
# 服务端通过临时授权码获取授权用户的个人信息
# @url https://ding-doc.dingtalk.com/doc#/serverapi2/etaarr
# @url https://ding-doc.dingtalk.com/doc#/serverapi2/etaarr
GET_USER_INFO_SNS
=
"https://oapi.dingtalk.com/sns/getuserinfo_bycode"
.
freeze
GET_USER_INFO_SNS
=
"https://oapi.dingtalk.com/sns/getuserinfo_bycode"
end
end
end
end
\ No newline at end of file
spec/dingtalk/auth_spec.rb
View file @
15cb4dfb
...
@@ -3,26 +3,70 @@ require "dingtalk/auth"
...
@@ -3,26 +3,70 @@ require "dingtalk/auth"
RSpec
.
describe
Dingtalk
::
Auth
do
RSpec
.
describe
Dingtalk
::
Auth
do
before
:each
do
before
:each
do
@app_key
=
"mocked_app_key"
@app_secret
=
"mocked_app_secret"
@int_user_id
=
100
@int_user_id
=
100
@access_token
=
"mocked_access_token"
@access_token
=
"mocked_access_token"
@int_login_code
=
"mocked_int_login_code"
@int_login_code
=
"mocked_int_login_code"
@timestamp
=
(
Time
.
now
.
localtime
(
"+08:00"
).
to_f
*
1000
).
to_i
@signature
=
Dingtalk
.
login_free_signature
(
@app_secret
,
timestamp:
@timestamp
)
response_body
=
{}.
tap
do
|
h
|
# 企业内部免登 响应结果
get_user_info_response_body
=
{}.
tap
do
|
h
|
h
[
:userid
]
=
@int_user_id
h
[
:userid
]
=
@int_user_id
h
[
:is_sys
]
=
false
h
[
:is_sys
]
=
false
h
[
:sys_level
]
=
0
h
[
:sys_level
]
=
0
end
end
# 钉钉内免登第三方网站 响应结果
get_user_info_by_code_response_body
=
{}.
tap
do
|
h
|
h
[
:errcode
]
=
0
h
[
:errmsg
]
=
"ok"
h
[
:user_info
]
=
{
nick:
"张三"
,
openid:
"liSii8KCxxxxx"
,
unionid:
"7Huu46kk"
}
end
stub_request
(
:get
,
/oapi.dingtalk.com\/user\/getuserinfo/
)
stub_request
(
:get
,
/oapi.dingtalk.com\/user\/getuserinfo/
)
.
with
(
query:
{
code:
@int_login_code
,
access_token:
@access_token
})
.
with
(
query:
{
code:
@int_login_code
,
access_token:
@access_token
})
.
to_return
(
status:
200
,
body:
response_body
.
to_json
)
.
to_return
(
status:
200
,
body:
get_user_info_response_body
.
to_json
)
stub_request
(
:post
,
/oapi.dingtalk.com\/sns\/getuserinfo_bycode/
)
.
with
(
query:
{
accessKey:
@app_key
,
timestamp:
@timestamp
.
to_s
,
signature:
@signature
.
to_s
},
body:
{
tmp_auth_code:
"23152698ea18304da4d0ce1xxxxx"
}.
to_json
,
headers:
{
:"Content-Type"
=>
"application/json"
}
)
.
to_return
(
status:
200
,
body:
get_user_info_by_code_response_body
.
to_json
)
end
end
it
'should get internal app user id in login-free scenario'
do
it
'should get user id in internal app login-free scenario'
do
response
=
Dingtalk
::
Auth
.
get_int_login_free_user_id
code:
@int_login_code
,
access_token:
@access_token
response
=
Dingtalk
::
Auth
.
get_int_login_free_user_id
(
code:
@int_login_code
,
access_token:
@access_token
,
)
expect
(
response
[
:userid
]).
to
eq
(
@int_user_id
)
expect
(
response
[
:userid
]).
to
eq
(
@int_user_id
)
expect
(
response
[
:is_sys
]).
to
eq
(
false
)
expect
(
response
[
:is_sys
]).
to
eq
(
false
)
expect
(
response
[
:sys_level
]).
to
eq
(
0
)
expect
(
response
[
:sys_level
]).
to
eq
(
0
)
end
end
# 详情见 https://ding-doc.dingtalk.com/doc#/serverapi2/etaarr
it
'should get user profile through temp auth code in login-free scenario'
do
response
=
Dingtalk
::
Auth
.
get_3rd_login_free_user_profile
(
accessKey:
@app_key
,
timestamp:
@timestamp
,
signature:
@signature
.
to_s
,
tmp_auth_code:
"23152698ea18304da4d0ce1xxxxx"
)
expect
(
response
[
:user_info
]).
to
be_a
(
Hash
)
expect
(
response
[
:user_info
][
:nick
]).
to
eq
(
"张三"
)
expect
(
response
[
:user_info
][
:openid
]).
to
eq
(
"liSii8KCxxxxx"
)
expect
(
response
[
:user_info
][
:unionid
]).
to
eq
(
"7Huu46kk"
)
end
end
end
\ No newline at end of file
spec/dingtalk_spec.rb
View file @
15cb4dfb
...
@@ -4,12 +4,13 @@ RSpec.describe Dingtalk do
...
@@ -4,12 +4,13 @@ RSpec.describe Dingtalk do
end
end
# 测试样本见 https://ding-doc.dingtalk.com/doc#/faquestions/hxs5v9 底部
# 测试样本见 https://ding-doc.dingtalk.com/doc#/faquestions/hxs5v9 底部
it
"sign
ature
correct timestamp with app_secret in personal login-free scenario"
do
it
"sign correct timestamp with app_secret in personal login-free scenario"
do
timestamp
=
1546084445901
timestamp
=
1546084445901
app_secret
=
"testappSecret"
app_secret
=
"testappSecret"
signature
=
Dingtalk
.
login_free_signature
(
app_secret
,
timestamp:
timestamp
)
signature
=
Dingtalk
.
login_free_signature
(
app_secret
,
timestamp:
timestamp
)
expect
(
signature
).
to
eq
(
"HCbG3xNE3vzhO%2Bu7qCUL1jS5hsu2n5r2cFhnTrtyDAE%3D"
)
expect
(
signature
).
to
be_a
(
Dingtalk
::
Signature
)
expect
(
signature
.
url_encoded
).
to
eq
(
"HCbG3xNE3vzhO%2Bu7qCUL1jS5hsu2n5r2cFhnTrtyDAE%3D"
)
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment