wework-next 1.2.6

Sign up to get free protection for your applications and to get access to all the features.
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