wework-next 1.2.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +184 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/wework/api/agent.rb +39 -0
- data/lib/wework/api/base.rb +94 -0
- data/lib/wework/api/contact.rb +7 -0
- data/lib/wework/api/corp.rb +27 -0
- data/lib/wework/api/methods/agent.rb +63 -0
- data/lib/wework/api/methods/appchat.rb +62 -0
- data/lib/wework/api/methods/approval.rb +16 -0
- data/lib/wework/api/methods/batch.rb +38 -0
- data/lib/wework/api/methods/checkin.rb +19 -0
- data/lib/wework/api/methods/crm.rb +11 -0
- data/lib/wework/api/methods/department.rb +36 -0
- data/lib/wework/api/methods/media.rb +20 -0
- data/lib/wework/api/methods/menu.rb +21 -0
- data/lib/wework/api/methods/message.rb +51 -0
- data/lib/wework/api/methods/provider.rb +38 -0
- data/lib/wework/api/methods/service.rb +53 -0
- data/lib/wework/api/methods/tag.rb +37 -0
- data/lib/wework/api/methods/user.rb +55 -0
- data/lib/wework/api/provider.rb +28 -0
- data/lib/wework/api/suite.rb +48 -0
- data/lib/wework/cipher.rb +98 -0
- data/lib/wework/config.rb +28 -0
- data/lib/wework/global_code.rb +327 -0
- data/lib/wework/mock_api.rb +34 -0
- data/lib/wework/request.rb +117 -0
- data/lib/wework/token/app_token.rb +21 -0
- data/lib/wework/token/base.rb +59 -0
- data/lib/wework/token/corp_token.rb +20 -0
- data/lib/wework/token/js_agent_ticket.rb +23 -0
- data/lib/wework/token/js_ticket.rb +23 -0
- data/lib/wework/token/provider_token.rb +21 -0
- data/lib/wework/token/suite_token.rb +21 -0
- data/lib/wework/version.rb +3 -0
- data/lib/wework.rb +39 -0
- data/mock_responses/agent/get.json +29 -0
- data/mock_responses/agent/list.json +16 -0
- data/mock_responses/agent/set.json +4 -0
- data/mock_responses/batch/getresult.json +8 -0
- data/mock_responses/department/list.json +24 -0
- data/mock_responses/error.json +4 -0
- data/mock_responses/files/party.csv +12 -0
- data/mock_responses/files/sample.amr +0 -0
- data/mock_responses/files/sample.mp4 +0 -0
- data/mock_responses/files/sample.txt +1 -0
- data/mock_responses/files/user.csv +2 -0
- data/mock_responses/files/zhiren.png +0 -0
- data/mock_responses/get_jsapi_ticket.json +6 -0
- data/mock_responses/gettoken.json +6 -0
- data/mock_responses/menu/get.json +24 -0
- data/mock_responses/service/get.json +0 -0
- data/mock_responses/service/get_corp_token.json +4 -0
- data/mock_responses/service/get_login_info.json +34 -0
- data/mock_responses/service/get_permanent_code.json +54 -0
- data/mock_responses/service/get_pre_auth_code.json +6 -0
- data/mock_responses/service/get_provider_token.json +4 -0
- data/mock_responses/service/get_suite_token.json +4 -0
- data/mock_responses/success.json +4 -0
- data/mock_responses/user/convert_to_openid.json +6 -0
- data/mock_responses/user/convert_to_userid.json +5 -0
- data/mock_responses/user/get.json +18 -0
- data/mock_responses/user/getuserdetail.json +10 -0
- data/mock_responses/user/getuserinfo.json +8 -0
- data/mock_responses/user/list.json +22 -0
- data/mock_responses/user/simplelist.json +11 -0
- data/wework.gemspec +33 -0
- metadata +243 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
module Wework
|
2
|
+
module Api
|
3
|
+
module Methods
|
4
|
+
module Batch
|
5
|
+
def batch_syncuser media_id, callback_url=nil, token=nil, encodingaeskey=nil
|
6
|
+
post 'batch/syncuser', batch_params(media_id, callback_url, token, encodingaeskey)
|
7
|
+
end
|
8
|
+
|
9
|
+
def batch_replaceuser media_id, callback_url=nil, token=nil, encodingaeskey=nil
|
10
|
+
post 'batch/replaceuser', batch_params(media_id, callback_url, token, encodingaeskey)
|
11
|
+
end
|
12
|
+
|
13
|
+
def batch_replaceparty media_id, callback_url=nil, token=nil, encodingaeskey=nil
|
14
|
+
post 'batch/replaceparty', batch_params(media_id, callback_url, token, encodingaeskey)
|
15
|
+
end
|
16
|
+
|
17
|
+
def batch_getresult job_id
|
18
|
+
get 'batch/getresult', params: {jobid: job_id}
|
19
|
+
end
|
20
|
+
|
21
|
+
def batch_invite user=[], party=[], tag=[]
|
22
|
+
post 'batch/invite', {user: user, party: party, tag: tag}
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def batch_params media_id, callback_url, token, encodingaeskey
|
28
|
+
params = {media_id: media_id}
|
29
|
+
if callback_url.present? && token.present? && encodingaeskey.present?
|
30
|
+
params[:callback] = {url: callback_url, token: token, encodingaeskey: encodingaeskey}
|
31
|
+
end
|
32
|
+
|
33
|
+
params
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "erb"
|
2
|
+
|
3
|
+
module Wework
|
4
|
+
module Api
|
5
|
+
module Methods
|
6
|
+
module Checkin
|
7
|
+
def get_checkin_data start_time, end_time, userid_list=[], checkin_type=3
|
8
|
+
# https://work.weixin.qq.com/api/doc#11196
|
9
|
+
post 'checkin/getcheckindata', {
|
10
|
+
opencheckindatatype: checkin_type,
|
11
|
+
starttime: start_time,
|
12
|
+
endtime: end_time,
|
13
|
+
useridlist: userid_list,
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Wework
|
2
|
+
module Api
|
3
|
+
module Methods
|
4
|
+
module Department
|
5
|
+
def department_create(data = {})
|
6
|
+
post 'department/create', data
|
7
|
+
end
|
8
|
+
|
9
|
+
def department_update(department_id, data = {})
|
10
|
+
post 'department/update', data.merge(id: department_id)
|
11
|
+
end
|
12
|
+
|
13
|
+
def department_delete(department_id)
|
14
|
+
get 'department/delete', params: { id: department_id }
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param [nil] department_id
|
18
|
+
def simple_list(department_id = nil)
|
19
|
+
if department_id.nil?
|
20
|
+
get 'department/simplelist', params: {}
|
21
|
+
else
|
22
|
+
get 'department/simplelist', params: { id: department_id }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def department_list(department_id = nil)
|
27
|
+
if department_id.nil?
|
28
|
+
get 'department/list'
|
29
|
+
else
|
30
|
+
get 'department/list', params: { id: department_id }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Wework
|
2
|
+
module Api
|
3
|
+
module Methods
|
4
|
+
module Media
|
5
|
+
# public API
|
6
|
+
def media_upload(type, file)
|
7
|
+
post_file 'media/upload', file, params: { type: type }
|
8
|
+
end
|
9
|
+
|
10
|
+
def media_get(media_id)
|
11
|
+
get 'media/get', params: { media_id: media_id }, as: :file
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_media_url(media_id)
|
15
|
+
"#{API_ENDPOINT}media/get?access_token=#{access_token}&media_id=#{media_id}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "erb"
|
2
|
+
|
3
|
+
module Wework
|
4
|
+
module Api
|
5
|
+
module Methods
|
6
|
+
module Menu
|
7
|
+
def menu_create menu
|
8
|
+
post 'menu/create', menu, params: {agentid: agent_id}
|
9
|
+
end
|
10
|
+
|
11
|
+
def menu_get
|
12
|
+
get 'menu/get', params: {agentid: agent_id}
|
13
|
+
end
|
14
|
+
|
15
|
+
def menu_delete
|
16
|
+
get 'menu/delete', params: {agentid: agent_id}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "erb"
|
2
|
+
|
3
|
+
module Wework
|
4
|
+
module Api
|
5
|
+
module Methods
|
6
|
+
module Message
|
7
|
+
def miniprogram_message_send user_id, miniprogram_notice={}, options={}
|
8
|
+
post 'message/send', { touser: user_id, msgtype: 'miniprogram_notice', miniprogram_notice: miniprogram_notice, **options }
|
9
|
+
end
|
10
|
+
|
11
|
+
def text_message_send user_ids, department_ids, content
|
12
|
+
message_send user_ids, department_ids, {text: {content: content}, msgtype: 'text'}
|
13
|
+
end
|
14
|
+
|
15
|
+
def image_message_send user_ids, department_ids, media_id
|
16
|
+
message_send user_ids, department_ids, {image: {media_id: media_id}, msgtype: 'image'}
|
17
|
+
end
|
18
|
+
|
19
|
+
def voice_message_send user_ids, department_ids, media_id
|
20
|
+
message_send user_ids, department_ids, {voice: {media_id: media_id}, msgtype: 'voice'}
|
21
|
+
end
|
22
|
+
|
23
|
+
def file_message_send user_ids, department_ids, media_id
|
24
|
+
message_send user_ids, department_ids, {file: {media_id: media_id}, msgtype: 'file'}
|
25
|
+
end
|
26
|
+
|
27
|
+
def video_message_send user_ids, department_ids, video={}
|
28
|
+
message_send user_ids, department_ids, {video: video, msgtype: 'video'}
|
29
|
+
end
|
30
|
+
|
31
|
+
def textcard_message_send user_ids, department_ids, textcard={}
|
32
|
+
message_send user_ids, department_ids, {textcard: textcard, msgtype: 'textcard'}
|
33
|
+
end
|
34
|
+
|
35
|
+
def news_message_send user_ids, department_ids, news=[]
|
36
|
+
message_send user_ids, department_ids, {news: {articles: news}, msgtype: 'news'}
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def message_send user_ids, department_ids, payload={}
|
42
|
+
payload[:agentid] = agent_id
|
43
|
+
payload[:touser] = Array.wrap(user_ids).join('|') if user_ids.present?
|
44
|
+
payload[:toparty] = Array.wrap(department_ids).join('|') if department_ids.present?
|
45
|
+
|
46
|
+
post 'message/send', payload
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Wework
|
2
|
+
module Api
|
3
|
+
module Methods
|
4
|
+
module Provider
|
5
|
+
def sso_authorize_url(redirect_uri, user_type='admin', state='qywxlogin')
|
6
|
+
uri = ERB::Util.url_encode(redirect_uri)
|
7
|
+
"#{SSO_AUTHORIZE_ENDPOINT}?appid=#{corp_id}&redirect_uri=#{uri}&state=#{state}&usertype=#{user_type}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_login_info auth_code
|
11
|
+
post 'service/get_login_info', {auth_code: auth_code, access_token: access_token}
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_register_code template_id, options={}
|
15
|
+
params = {template_id: template_id}
|
16
|
+
post 'service/get_register_code', params.merge(options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_register_url template_id, options={}
|
20
|
+
register_code = get_register_code(template_id, options).register_code
|
21
|
+
"#{REGISTER_ENDPOINT}?register_code=#{register_code}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def service_media_upload(type, file)
|
25
|
+
post_file 'service/media/upload', file, params: { type: type }
|
26
|
+
end
|
27
|
+
|
28
|
+
def id_translate auth_corpid, media_id
|
29
|
+
post 'service/contact/id_translate', { auth_corpid: auth_corpid, media_id_list: [ media_id ] }
|
30
|
+
end
|
31
|
+
|
32
|
+
def service_batch_getresult job_id
|
33
|
+
get 'service/batch/getresult', params: { jobid: job_id }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Wework
|
2
|
+
module Api
|
3
|
+
module Methods
|
4
|
+
module Service
|
5
|
+
def corp_authorize_url(redirect_uri, state="corp_authorize")
|
6
|
+
"#{APP_AUTHORIZE_ENDPOINT}?suite_id=#{suite_id}&pre_auth_code=#{get_pre_auth_code}&redirect_uri=#{redirect_uri}&state=#{state}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def get_pre_auth_code
|
10
|
+
result = get 'service/get_pre_auth_code'
|
11
|
+
return result.pre_auth_code if result.success?
|
12
|
+
end
|
13
|
+
|
14
|
+
def set_session_info pre_auth_code, session_info={}
|
15
|
+
post 'service/set_session_info', {pre_auth_code: pre_auth_code, session_info: session_info}
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_permanent_code auth_code
|
19
|
+
post 'service/get_permanent_code', {auth_code: auth_code}
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_auth_info auth_corpid, permanent_code
|
23
|
+
post 'service/get_auth_info', {auth_corpid: auth_corpid, permanent_code: permanent_code}
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_corp_token auth_corpid, permanent_code
|
27
|
+
post 'service/get_corp_token', {suite_id: suite_id, auth_corpid: auth_corpid, permanent_code: permanent_code}
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_admin_list auth_corpid, agentid
|
31
|
+
post 'service/get_admin_list', {auth_corpid: auth_corpid, agentid: agentid}
|
32
|
+
end
|
33
|
+
|
34
|
+
def authorize_url(redirect_uri, scope="snsapi_base", state="wxwork")
|
35
|
+
uri = ERB::Util.url_encode(redirect_uri)
|
36
|
+
"#{AUTHORIZE_ENDPOINT}?appid=#{suite_id}&redirect_uri=#{uri}&response_type=code&scope=#{scope}&state=#{state}#wechat_redirect"
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_oauth_userinfo(code)
|
40
|
+
get 'service/getuserinfo3rd', params: {access_token: access_token, code: code}
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_user_detail(user_ticket)
|
44
|
+
post "service/getuserdetail3rd?access_token=#{access_token}", {user_ticket: user_ticket}
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_session_with_jscode(js_code, grant_type='authorization_code')
|
48
|
+
post 'service/miniprogram/jscode2session', {}, params: {js_code: js_code, grant_type: grant_type}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Wework
|
2
|
+
module Api
|
3
|
+
module Methods
|
4
|
+
module Tag
|
5
|
+
def tag_create(tagname, tagid=nil)
|
6
|
+
data = {tagname: tagname}
|
7
|
+
data[:tagid] = tagid unless tagid.nil?
|
8
|
+
post 'tag/create', data
|
9
|
+
end
|
10
|
+
|
11
|
+
def tag_update(tagid, tagname)
|
12
|
+
post 'tag/update', {tagid: tagid, tagname: tagname}
|
13
|
+
end
|
14
|
+
|
15
|
+
def tag_delete tagid
|
16
|
+
get 'user/delete', params: {tagid: tagid}
|
17
|
+
end
|
18
|
+
|
19
|
+
def tag_get tagid
|
20
|
+
get 'user/get', params: {tagid: tagid}
|
21
|
+
end
|
22
|
+
|
23
|
+
def tag_addtagusers tagid, userlist=[], partylist=[]
|
24
|
+
post 'tag/addtagusers', {tagid: tagid, userlist: userlist, partylist: partylist}
|
25
|
+
end
|
26
|
+
|
27
|
+
def tag_deltagusers tagid, userlist=[], partylist=[]
|
28
|
+
post 'tag/deltagusers', {tagid: tagid, userlist: userlist, partylist: partylist}
|
29
|
+
end
|
30
|
+
|
31
|
+
def tag_list
|
32
|
+
get 'user/list'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Wework
|
2
|
+
module Api
|
3
|
+
module Methods
|
4
|
+
module User
|
5
|
+
def user_create data={}
|
6
|
+
post 'user/create', data
|
7
|
+
end
|
8
|
+
|
9
|
+
def user_get userid
|
10
|
+
get 'user/get', params: {userid: userid}
|
11
|
+
end
|
12
|
+
|
13
|
+
def user_getuserid mobile
|
14
|
+
post 'user/getuserid', {mobile: mobile}
|
15
|
+
end
|
16
|
+
|
17
|
+
def user_update userid, data={}
|
18
|
+
post 'user/update', data.merge(userid: userid)
|
19
|
+
end
|
20
|
+
|
21
|
+
def user_delete userid
|
22
|
+
get 'user/delete', params: {userid: userid}
|
23
|
+
end
|
24
|
+
|
25
|
+
def user_batchdelete useridlist=[]
|
26
|
+
post 'user/batchdelete', {useridlist: useridlist}
|
27
|
+
end
|
28
|
+
|
29
|
+
def user_simplelist department_id, fetch_child=0
|
30
|
+
get 'user/simplelist', params: {department_id: department_id, fetch_child: fetch_child}
|
31
|
+
end
|
32
|
+
|
33
|
+
def user_list department_id, fetch_child=0
|
34
|
+
get 'user/list', params: {department_id: department_id, fetch_child: fetch_child}
|
35
|
+
end
|
36
|
+
|
37
|
+
def user_list_id
|
38
|
+
get 'user/list_id',params:{limit:10000}
|
39
|
+
end
|
40
|
+
def convert_to_openid userid
|
41
|
+
post 'user/convert_to_openid', {userid: userid}
|
42
|
+
end
|
43
|
+
|
44
|
+
def convert_to_userid openid
|
45
|
+
post 'user/convert_to_userid', {openid: openid}
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def authsucc userid
|
50
|
+
get 'user/authsucc', params: {userid: userid}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Wework
|
2
|
+
module Api
|
3
|
+
class Provider < Base
|
4
|
+
include Methods::Provider
|
5
|
+
include Wework::Cipher
|
6
|
+
|
7
|
+
attr_reader :encoding_aes_key, :token
|
8
|
+
|
9
|
+
def initialize(options={})
|
10
|
+
@token = options.delete(:token)
|
11
|
+
@encoding_aes_key = options.delete(:encoding_aes_key)
|
12
|
+
super(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def token_store
|
18
|
+
@token_store ||= Token::ProviderToken.new self
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def token_params
|
24
|
+
{provider_access_token: access_token}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'builder'
|
2
|
+
|
3
|
+
module Wework
|
4
|
+
module Api
|
5
|
+
class Suite < Base
|
6
|
+
|
7
|
+
include Wework::Cipher
|
8
|
+
include Methods::Service
|
9
|
+
|
10
|
+
attr_reader :encoding_aes_key, :suite_id, :suite_secret, :suite_token, :token
|
11
|
+
|
12
|
+
def initialize(options={})
|
13
|
+
@suite_id = options.delete(:suite_id)
|
14
|
+
@suite_secret = options.delete(:suite_secret)
|
15
|
+
@token = @suite_token = options.delete(:suite_token)
|
16
|
+
@encoding_aes_key = options.delete(:encoding_aes_key)
|
17
|
+
super(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def suite_ticket= ticket
|
21
|
+
Wework.redis.set ticket_key, ticket
|
22
|
+
end
|
23
|
+
|
24
|
+
def suite_ticket
|
25
|
+
Wework.redis.get ticket_key
|
26
|
+
end
|
27
|
+
|
28
|
+
def corp(corp_id, permanent_code)
|
29
|
+
Wework::Api::Corp.new(suite: self, corp_id: corp_id, permanent_code: permanent_code)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def token_params
|
35
|
+
{suite_access_token: access_token}
|
36
|
+
end
|
37
|
+
|
38
|
+
def ticket_key
|
39
|
+
"SUITE_TICKET_#{suite_id}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def token_store
|
43
|
+
@token_store ||= Token::SuiteToken.new self
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'openssl/cipher'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
# the file copy from here
|
5
|
+
# https://github.com/Eric-Guo/wechat/blob/master/lib/wechat/cipher.rb
|
6
|
+
|
7
|
+
module Wework
|
8
|
+
module Cipher
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
BLOCK_SIZE = 32
|
12
|
+
CIPHER = 'AES-256-CBC'.freeze
|
13
|
+
|
14
|
+
def encrypt(plain, encoding_aes_key)
|
15
|
+
cipher = OpenSSL::Cipher.new(CIPHER)
|
16
|
+
cipher.encrypt
|
17
|
+
|
18
|
+
cipher.padding = 0
|
19
|
+
key_data = Base64.decode64(encoding_aes_key + '=')
|
20
|
+
cipher.key = key_data
|
21
|
+
cipher.iv = [key_data].pack('H*')
|
22
|
+
|
23
|
+
cipher.update(plain) + cipher.final
|
24
|
+
end
|
25
|
+
|
26
|
+
def decrypt(msg, encoding_aes_key)
|
27
|
+
cipher = OpenSSL::Cipher.new(CIPHER)
|
28
|
+
cipher.decrypt
|
29
|
+
|
30
|
+
cipher.padding = 0
|
31
|
+
key_data = Base64.decode64(encoding_aes_key + '=')
|
32
|
+
cipher.key = key_data
|
33
|
+
cipher.iv = [key_data].pack('H*')
|
34
|
+
|
35
|
+
plain = cipher.update(msg) + cipher.final
|
36
|
+
decode_padding(plain)
|
37
|
+
end
|
38
|
+
|
39
|
+
# app_id or corp_id
|
40
|
+
def pack(content, app_id)
|
41
|
+
random = SecureRandom.hex(8)
|
42
|
+
text = content.force_encoding('ASCII-8BIT')
|
43
|
+
msg_len = [text.length].pack('N')
|
44
|
+
|
45
|
+
encode_padding("#{random}#{msg_len}#{text}#{app_id}")
|
46
|
+
end
|
47
|
+
|
48
|
+
def unpack(msg)
|
49
|
+
msg = decode_padding(msg)
|
50
|
+
msg_len = msg[16, 4].reverse.unpack('V')[0]
|
51
|
+
content = msg[20, msg_len]
|
52
|
+
app_id = msg[(20 + msg_len)..-1]
|
53
|
+
|
54
|
+
[content, app_id]
|
55
|
+
end
|
56
|
+
|
57
|
+
def msg_decrypt message
|
58
|
+
unpack(decrypt(Base64.decode64(message), encoding_aes_key))[0]
|
59
|
+
end
|
60
|
+
|
61
|
+
def msg_encrypt message
|
62
|
+
Base64.strict_encode64(encrypt(pack(message, corp_id), encoding_aes_key))
|
63
|
+
end
|
64
|
+
|
65
|
+
def signature(timestamp, nonce, encrypt)
|
66
|
+
array = [token, timestamp, nonce]
|
67
|
+
array << encrypt unless encrypt.nil?
|
68
|
+
Digest::SHA1.hexdigest array.compact.collect(&:to_s).sort.join
|
69
|
+
end
|
70
|
+
|
71
|
+
def generate_xml(msg, timestamp, nonce)
|
72
|
+
encrypt = msg_encrypt(msg)
|
73
|
+
{
|
74
|
+
Encrypt: encrypt,
|
75
|
+
MsgSignature: signature(timestamp, nonce, encrypt),
|
76
|
+
TimeStamp: timestamp,
|
77
|
+
Nonce: nonce
|
78
|
+
}.to_xml(root: 'xml', children: 'item', skip_instruct: true, skip_types: true)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def encode_padding(data)
|
84
|
+
length = data.bytes.length
|
85
|
+
amount_to_pad = BLOCK_SIZE - (length % BLOCK_SIZE)
|
86
|
+
amount_to_pad = BLOCK_SIZE if amount_to_pad == 0
|
87
|
+
padding = ([amount_to_pad].pack('c') * amount_to_pad)
|
88
|
+
data + padding
|
89
|
+
end
|
90
|
+
|
91
|
+
def decode_padding(plain)
|
92
|
+
pad = plain.bytes[-1]
|
93
|
+
# no padding
|
94
|
+
pad = 0 if pad < 1 || pad > BLOCK_SIZE
|
95
|
+
plain[0...(plain.length - pad)]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Wework
|
2
|
+
|
3
|
+
class << self
|
4
|
+
def configure
|
5
|
+
yield config
|
6
|
+
end
|
7
|
+
|
8
|
+
def config
|
9
|
+
@config ||= Config.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def redis
|
13
|
+
config.redis
|
14
|
+
end
|
15
|
+
|
16
|
+
def http_timeout_options
|
17
|
+
config.http_timeout_options || {write: 2, connect: 5, read: 10}
|
18
|
+
end
|
19
|
+
|
20
|
+
def expired_shift_seconds
|
21
|
+
config.expired_shift_seconds || 100
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Config
|
26
|
+
attr_accessor :redis, :http_timeout_options, :expired_shift_seconds
|
27
|
+
end
|
28
|
+
end
|