wework-next 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|