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.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +5 -0
  4. data/CODE_OF_CONDUCT.md +74 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +184 -0
  8. data/Rakefile +10 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/lib/wework/api/agent.rb +39 -0
  12. data/lib/wework/api/base.rb +94 -0
  13. data/lib/wework/api/contact.rb +7 -0
  14. data/lib/wework/api/corp.rb +27 -0
  15. data/lib/wework/api/methods/agent.rb +63 -0
  16. data/lib/wework/api/methods/appchat.rb +62 -0
  17. data/lib/wework/api/methods/approval.rb +16 -0
  18. data/lib/wework/api/methods/batch.rb +38 -0
  19. data/lib/wework/api/methods/checkin.rb +19 -0
  20. data/lib/wework/api/methods/crm.rb +11 -0
  21. data/lib/wework/api/methods/department.rb +36 -0
  22. data/lib/wework/api/methods/media.rb +20 -0
  23. data/lib/wework/api/methods/menu.rb +21 -0
  24. data/lib/wework/api/methods/message.rb +51 -0
  25. data/lib/wework/api/methods/provider.rb +38 -0
  26. data/lib/wework/api/methods/service.rb +53 -0
  27. data/lib/wework/api/methods/tag.rb +37 -0
  28. data/lib/wework/api/methods/user.rb +55 -0
  29. data/lib/wework/api/provider.rb +28 -0
  30. data/lib/wework/api/suite.rb +48 -0
  31. data/lib/wework/cipher.rb +98 -0
  32. data/lib/wework/config.rb +28 -0
  33. data/lib/wework/global_code.rb +327 -0
  34. data/lib/wework/mock_api.rb +34 -0
  35. data/lib/wework/request.rb +117 -0
  36. data/lib/wework/token/app_token.rb +21 -0
  37. data/lib/wework/token/base.rb +59 -0
  38. data/lib/wework/token/corp_token.rb +20 -0
  39. data/lib/wework/token/js_agent_ticket.rb +23 -0
  40. data/lib/wework/token/js_ticket.rb +23 -0
  41. data/lib/wework/token/provider_token.rb +21 -0
  42. data/lib/wework/token/suite_token.rb +21 -0
  43. data/lib/wework/version.rb +3 -0
  44. data/lib/wework.rb +39 -0
  45. data/mock_responses/agent/get.json +29 -0
  46. data/mock_responses/agent/list.json +16 -0
  47. data/mock_responses/agent/set.json +4 -0
  48. data/mock_responses/batch/getresult.json +8 -0
  49. data/mock_responses/department/list.json +24 -0
  50. data/mock_responses/error.json +4 -0
  51. data/mock_responses/files/party.csv +12 -0
  52. data/mock_responses/files/sample.amr +0 -0
  53. data/mock_responses/files/sample.mp4 +0 -0
  54. data/mock_responses/files/sample.txt +1 -0
  55. data/mock_responses/files/user.csv +2 -0
  56. data/mock_responses/files/zhiren.png +0 -0
  57. data/mock_responses/get_jsapi_ticket.json +6 -0
  58. data/mock_responses/gettoken.json +6 -0
  59. data/mock_responses/menu/get.json +24 -0
  60. data/mock_responses/service/get.json +0 -0
  61. data/mock_responses/service/get_corp_token.json +4 -0
  62. data/mock_responses/service/get_login_info.json +34 -0
  63. data/mock_responses/service/get_permanent_code.json +54 -0
  64. data/mock_responses/service/get_pre_auth_code.json +6 -0
  65. data/mock_responses/service/get_provider_token.json +4 -0
  66. data/mock_responses/service/get_suite_token.json +4 -0
  67. data/mock_responses/success.json +4 -0
  68. data/mock_responses/user/convert_to_openid.json +6 -0
  69. data/mock_responses/user/convert_to_userid.json +5 -0
  70. data/mock_responses/user/get.json +18 -0
  71. data/mock_responses/user/getuserdetail.json +10 -0
  72. data/mock_responses/user/getuserinfo.json +8 -0
  73. data/mock_responses/user/list.json +22 -0
  74. data/mock_responses/user/simplelist.json +11 -0
  75. data/wework.gemspec +33 -0
  76. 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,11 @@
1
+ module Wework
2
+ module Api
3
+ module Methods
4
+ module Crm
5
+ def crm_get_external_contact external_userid
6
+ get 'crm/get_external_contact', params: {external_userid: external_userid}
7
+ end
8
+ end
9
+ end
10
+ end
11
+ 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