wework 0.3.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +0 -1
- data/README.md +7 -0
- data/lib/wework.rb +15 -10
- data/lib/wework/api/agent.rb +15 -79
- data/lib/wework/api/base.rb +24 -32
- data/lib/wework/api/contact.rb +1 -75
- data/lib/wework/api/corp.rb +29 -0
- data/lib/wework/api/methods/agent.rb +49 -0
- data/lib/wework/api/methods/approval.rb +16 -0
- data/lib/wework/api/methods/batch.rb +34 -0
- data/lib/wework/api/methods/checkin.rb +19 -0
- data/lib/wework/api/methods/department.rb +27 -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 +52 -0
- data/lib/wework/api/methods/provider.rb +16 -0
- data/lib/wework/api/methods/suite.rb +53 -0
- data/lib/wework/api/methods/user.rb +35 -0
- data/lib/wework/api/provider.rb +13 -0
- data/lib/wework/api/suite.rb +72 -0
- data/lib/wework/cipher.rb +3 -0
- data/lib/wework/mock_api.rb +34 -0
- data/lib/wework/request.rb +3 -1
- 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_ticket.rb +25 -0
- data/lib/wework/token/provider_token.rb +21 -0
- data/lib/wework/token/suite_token.rb +21 -0
- data/lib/wework/version.rb +1 -1
- 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 +6 -2
- metadata +114 -19
- data/lib/wework/engine.rb +0 -31
- data/lib/wework/js_ticket/redis_store.rb +0 -41
- data/lib/wework/js_ticket/store.rb +0 -36
- data/lib/wework/provider.rb +0 -39
- data/lib/wework/token/redis_store.rb +0 -41
- data/lib/wework/token/store.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9599e4575016ec45c4efe18b2e9d80cb27873f3cb8675ff379e7a1f9da774954
|
4
|
+
data.tar.gz: fc49b09c054faecde4feb2e9eab2754e39b6340b1a1be78b6ab81c3bc1260679
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 54a4da5b3fcd4f14c58ecb1f95e44348b95f80b970fc4ddf9b15491e80db824bcf39763ecce2473379c41500f308c8b51056120a26c8a1b9ba51b4dd74245859
|
7
|
+
data.tar.gz: 557479ed57faeae92f92f9633ca3a68fa0584a8529e2cc1a54afa273f1fb64a2f3fdf66a4e79692c5aa0e34d7080979487ecf36c0985cda26758fb881e5816d6
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
Wework is a ruby API wrapper for work wechat.
|
4
4
|
|
5
|
+
[![CircleCI](https://circleci.com/gh/mycolorway/wework/tree/suite.svg?style=svg)](https://circleci.com/gh/mycolorway/wework/tree/suite)
|
6
|
+
|
7
|
+
## Version 1.1.0
|
8
|
+
* 支持第三方应用接口
|
9
|
+
* 支持小程序接口
|
10
|
+
|
11
|
+
|
5
12
|
## Version 0.1.4
|
6
13
|
* 异步任务接口 [doc](https://work.weixin.qq.com/api/doc#10138)
|
7
14
|
|
data/lib/wework.rb
CHANGED
@@ -2,22 +2,27 @@ require 'redis'
|
|
2
2
|
require 'active_support/all'
|
3
3
|
#require 'active_support/core_ext/object/blank'
|
4
4
|
|
5
|
-
|
6
|
-
require path
|
7
|
-
end
|
5
|
+
LIB_PATH = "#{File.dirname(__FILE__)}/wework"
|
6
|
+
Dir["#{LIB_PATH}/api/methods/*.rb", "#{LIB_PATH}/token/*.rb"].each { |path| require path }
|
8
7
|
|
8
|
+
require 'wework/version'
|
9
|
+
require 'wework/cipher'
|
10
|
+
require 'wework/config'
|
9
11
|
require 'wework/api/base'
|
10
12
|
require 'wework/api/agent'
|
11
13
|
require 'wework/api/contact'
|
14
|
+
require 'wework/api/suite'
|
15
|
+
require 'wework/api/corp'
|
16
|
+
require 'wework/api/provider'
|
17
|
+
|
12
18
|
|
13
19
|
module Wework
|
14
|
-
API_ENDPOINT
|
15
|
-
AUTHORIZE_ENDPOINT
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
SUCCESS_CODE = 0
|
20
|
+
API_ENDPOINT = 'https://qyapi.weixin.qq.com/cgi-bin/'.freeze
|
21
|
+
AUTHORIZE_ENDPOINT = 'https://open.weixin.qq.com/connect/oauth2/authorize'.freeze
|
22
|
+
SSO_AUTHORIZE_ENDPOINT = 'https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect'.freeze
|
23
|
+
APP_AUTHORIZE_ENDPOINT = 'https://open.work.weixin.qq.com/3rdapp/install'.freeze
|
24
|
+
HTTP_OK_STATUS = [200, 201].freeze
|
25
|
+
SUCCESS_CODE = 0
|
21
26
|
|
22
27
|
# Exceptions
|
23
28
|
class RedisNotConfigException < RuntimeError; end
|
data/lib/wework/api/agent.rb
CHANGED
@@ -1,94 +1,30 @@
|
|
1
|
-
require "erb"
|
2
|
-
|
3
1
|
module Wework
|
4
2
|
module Api
|
5
3
|
class Agent < Base
|
6
|
-
# user agent: UA is mozilla/5.0 (iphone; cpu iphone os 10_2 like mac os x) applewebkit/602.3.12 (khtml, like gecko) mobile/14c92 wxwork/1.3.2 micromessenger/6.2
|
7
|
-
|
8
|
-
def authorize_url(redirect_uri, scope="snsapi_base", state="wxwork")
|
9
|
-
uri = ERB::Util.url_encode(redirect_uri)
|
10
|
-
"#{AUTHORIZE_ENDPOINT}?appid=#{corp_id}&redirect_uri=#{uri}&response_type=code&scope=#{scope}&agentid=#{app_id}&state=#{state}#wechat_redirect"
|
11
|
-
end
|
12
|
-
|
13
|
-
def get_oauth_userinfo code
|
14
|
-
get 'user/getuserinfo', params: {code: code}
|
15
|
-
end
|
16
|
-
|
17
|
-
def get_jssign_package url
|
18
|
-
timestamp = Time.now.to_i
|
19
|
-
noncestr = SecureRandom.hex(8)
|
20
|
-
str = "jsapi_ticket=#{jsapi_ticket}&noncestr=#{noncestr}×tamp=#{timestamp}&url=#{url}"
|
21
|
-
{
|
22
|
-
"appId" => corp_id,
|
23
|
-
"nonceStr" => noncestr,
|
24
|
-
"timestamp" => timestamp,
|
25
|
-
"url" => url,
|
26
|
-
"signature" => Digest::SHA1.hexdigest(str),
|
27
|
-
"rawString" => str
|
28
|
-
}
|
29
|
-
end
|
30
|
-
|
31
|
-
def get_info
|
32
|
-
get 'agent/get', params: {agentid: agent_id}
|
33
|
-
end
|
34
|
-
|
35
|
-
def set_info data={}
|
36
|
-
post 'agent/set', data.merge(agentid: agent_id)
|
37
|
-
end
|
38
|
-
|
39
|
-
def menu_create menu
|
40
|
-
post 'menu/create', menu, params: {agentid: agent_id}
|
41
|
-
end
|
42
|
-
|
43
|
-
def menu_get
|
44
|
-
get 'menu/get', params: {agentid: agent_id}
|
45
|
-
end
|
46
|
-
|
47
|
-
def menu_delete
|
48
|
-
get 'menu/delete', params: {agentid: agent_id}
|
49
|
-
end
|
50
|
-
|
51
|
-
def message_send user_ids, department_ids, payload={}
|
52
|
-
payload[:agentid] = agent_id
|
53
|
-
payload[:touser] = Array.wrap(user_ids).join('|') if user_ids.present?
|
54
|
-
payload[:toparty] = Array.wrap(department_ids).join('|') if department_ids.present?
|
55
|
-
post 'message/send', payload
|
56
|
-
end
|
57
|
-
|
58
|
-
def text_message_send user_ids, department_ids, content
|
59
|
-
message_send user_ids, department_ids, {text: {content: content}, msgtype: 'text'}
|
60
|
-
end
|
61
4
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
message_send user_ids, department_ids, {voice: {media_id: media_id}, msgtype: 'voice'}
|
68
|
-
end
|
5
|
+
include Methods::Agent
|
6
|
+
include Methods::Message
|
7
|
+
include Methods::Menu
|
8
|
+
include Methods::Checkin
|
9
|
+
include Methods::Approval
|
69
10
|
|
70
|
-
|
71
|
-
message_send user_ids, department_ids, {file: {media_id: media_id}, msgtype: 'file'}
|
72
|
-
end
|
11
|
+
attr_reader :agent_id
|
73
12
|
|
74
|
-
def
|
75
|
-
|
13
|
+
def initialize(options={})
|
14
|
+
@agent_id = options.delete(:agent_id)
|
15
|
+
@agent_id = @agent_id.to_i if @agent_id && @agent_id.match?(/\A\d+\Z/)
|
16
|
+
super(options)
|
76
17
|
end
|
77
18
|
|
78
|
-
def
|
79
|
-
|
80
|
-
end
|
81
|
-
|
82
|
-
def news_message_send user_ids, department_ids, news=[]
|
83
|
-
message_send user_ids, department_ids, {news: {articles: news}, msgtype: 'news'}
|
19
|
+
def jsapi_ticket
|
20
|
+
jsticket_store.ticket
|
84
21
|
end
|
85
22
|
|
86
23
|
private
|
87
24
|
|
88
|
-
def
|
89
|
-
@
|
25
|
+
def jsticket_store
|
26
|
+
@jsticket_store ||= Token::JsTicket.new self
|
90
27
|
end
|
91
|
-
|
92
28
|
end
|
93
29
|
end
|
94
|
-
end
|
30
|
+
end
|
data/lib/wework/api/base.rb
CHANGED
@@ -1,24 +1,19 @@
|
|
1
|
-
require 'wework/
|
2
|
-
require 'wework/token/redis_store'
|
3
|
-
|
4
|
-
require 'wework/js_ticket/store'
|
5
|
-
require 'wework/js_ticket/redis_store'
|
1
|
+
require 'wework/request'
|
6
2
|
|
7
3
|
module Wework
|
8
4
|
module Api
|
9
5
|
class Base
|
10
|
-
include Wework::Cipher
|
11
6
|
|
12
|
-
|
13
|
-
|
7
|
+
include Methods::Media
|
8
|
+
include Methods::User
|
9
|
+
include Methods::Department
|
14
10
|
|
15
|
-
|
16
|
-
delegate :jsapi_ticket, to: :jsticket_store
|
11
|
+
attr_accessor :corp_id, :secret, :options
|
17
12
|
|
18
|
-
def initialize
|
19
|
-
@corp_id = corp_id
|
20
|
-
@
|
21
|
-
@
|
13
|
+
def initialize options={}
|
14
|
+
@corp_id = options.delete(:corp_id)
|
15
|
+
@secret = options.delete(:secret)
|
16
|
+
@token_store = options.delete(:token_store)
|
22
17
|
@options = options
|
23
18
|
end
|
24
19
|
|
@@ -27,58 +22,55 @@ module Wework
|
|
27
22
|
end
|
28
23
|
|
29
24
|
def valid?
|
30
|
-
|
25
|
+
return false if corp_id.nil?
|
26
|
+
token_store.token.present?
|
31
27
|
rescue AccessTokenExpiredError
|
32
28
|
false
|
33
29
|
rescue => e
|
34
|
-
Rails.logger.error "[WEWORK] (valid?) fetch access token error(#{corp_id}
|
30
|
+
Rails.logger.error "[WEWORK] (valid?) fetch access token error(#{corp_id}): #{e.inspect}" if defined?(Rails)
|
35
31
|
false
|
36
32
|
end
|
37
33
|
|
38
34
|
def get(path, headers = {})
|
39
|
-
|
35
|
+
with_token(headers[:params]) do |params|
|
40
36
|
request.get path, headers.merge(params: params)
|
41
37
|
end
|
42
38
|
end
|
43
39
|
|
44
40
|
def post(path, payload, headers = {})
|
45
|
-
|
41
|
+
with_token(headers[:params]) do |params|
|
46
42
|
request.post path, payload, headers.merge(params: params)
|
47
43
|
end
|
48
44
|
end
|
49
45
|
|
50
46
|
def post_file(path, file, headers = {})
|
51
|
-
|
47
|
+
with_token(headers[:params]) do |params|
|
52
48
|
request.post_file path, file, headers.merge(params: params)
|
53
49
|
end
|
54
50
|
end
|
55
51
|
|
56
|
-
|
57
|
-
|
58
|
-
post_file 'media/upload', file, params: { type: type }
|
59
|
-
end
|
60
|
-
|
61
|
-
def media_get(media_id)
|
62
|
-
get 'media/get', params: { media_id: media_id }, as: :file
|
52
|
+
def access_token
|
53
|
+
token_store.token
|
63
54
|
end
|
64
55
|
|
65
56
|
private
|
66
57
|
|
67
|
-
def
|
58
|
+
def with_token(params = {}, tries = 2)
|
68
59
|
params ||= {}
|
69
|
-
yield(params.merge(
|
60
|
+
yield(params.merge(token_params))
|
70
61
|
rescue AccessTokenExpiredError
|
71
|
-
token_store.
|
62
|
+
token_store.update_token
|
72
63
|
retry unless (tries -= 1).zero?
|
73
64
|
end
|
74
65
|
|
75
66
|
def token_store
|
76
|
-
@token_store ||= Token::
|
67
|
+
@token_store ||= Token::AppToken.new self
|
77
68
|
end
|
78
69
|
|
79
|
-
def
|
80
|
-
|
70
|
+
def token_params
|
71
|
+
{access_token: access_token}
|
81
72
|
end
|
73
|
+
|
82
74
|
end
|
83
75
|
end
|
84
76
|
end
|
data/lib/wework/api/contact.rb
CHANGED
@@ -1,81 +1,7 @@
|
|
1
1
|
module Wework
|
2
2
|
module Api
|
3
3
|
class Contact < Base
|
4
|
-
|
5
|
-
def initialize(corp_id, corp_secret)
|
6
|
-
super(corp_id, CONTACT_AGENT_ID, corp_secret)
|
7
|
-
end
|
8
|
-
|
9
|
-
def user_create data={}
|
10
|
-
post 'user/create', data
|
11
|
-
end
|
12
|
-
|
13
|
-
def user_get userid
|
14
|
-
get 'user/get', params: {userid: userid}
|
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 department_create data={}
|
38
|
-
post 'department/create', data
|
39
|
-
end
|
40
|
-
|
41
|
-
def department_update department_id, data={}
|
42
|
-
post 'department/update', data.merge(id: department_id)
|
43
|
-
end
|
44
|
-
|
45
|
-
def department_delete department_id
|
46
|
-
get 'department/delete', params: {id: department_id}
|
47
|
-
end
|
48
|
-
|
49
|
-
def department_list department_id=0
|
50
|
-
get 'department/list', params: {id: department_id}
|
51
|
-
end
|
52
|
-
|
53
|
-
def batch_syncuser media_id, callback_url=nil, token=nil, encodingaeskey=nil
|
54
|
-
post 'batch/syncuser', batch_params(media_id, callback_url, token, encodingaeskey)
|
55
|
-
end
|
56
|
-
|
57
|
-
def batch_replaceuser media_id, callback_url=nil, token=nil, encodingaeskey=nil
|
58
|
-
post 'batch/replaceuser', batch_params(media_id, callback_url, token, encodingaeskey)
|
59
|
-
end
|
60
|
-
|
61
|
-
def batch_replaceparty media_id, callback_url=nil, token=nil, encodingaeskey=nil
|
62
|
-
post 'batch/replaceparty', batch_params(media_id, callback_url, token, encodingaeskey)
|
63
|
-
end
|
64
|
-
|
65
|
-
def batch_getresult job_id
|
66
|
-
get 'batch/getresult', params: {jobid: job_id}
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
def batch_params media_id, callback_url, token, encodingaeskey
|
72
|
-
params = {media_id: media_id}
|
73
|
-
if callback_url.present? && token.present? && encodingaeskey.present?
|
74
|
-
params[:callback] = {url: callback_url, token: token, encodingaeskey: encodingaeskey}
|
75
|
-
end
|
76
|
-
|
77
|
-
params
|
78
|
-
end
|
4
|
+
include Methods::Batch
|
79
5
|
end
|
80
6
|
end
|
81
7
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Wework
|
2
|
+
module Api
|
3
|
+
class Corp < Base
|
4
|
+
|
5
|
+
include Wework::Cipher
|
6
|
+
include Methods::User
|
7
|
+
include Methods::Department
|
8
|
+
|
9
|
+
attr_reader :suite, :permanent_code
|
10
|
+
|
11
|
+
def initialize(options={})
|
12
|
+
@suite = options.delete(:suite)
|
13
|
+
@permanent_code = options.delete(:permanent_code)
|
14
|
+
super(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def agent(agent_id)
|
18
|
+
Wework::Api::Agent.new(corp_id: corp_id, agent_id: agent_id, token_store: token_store)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def token_store
|
24
|
+
@token_store ||= Token::CorpToken.new self
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "erb"
|
2
|
+
|
3
|
+
module Wework
|
4
|
+
module Api
|
5
|
+
module Methods
|
6
|
+
module Agent
|
7
|
+
def authorize_url(redirect_uri, scope="snsapi_base", state="wxwork")
|
8
|
+
# user agent: UA is mozilla/5.0 (iphone; cpu iphone os 10_2 like mac os x) applewebkit/602.3.12 (khtml, like gecko) mobile/14c92 wxwork/1.3.2 micromessenger/6.2
|
9
|
+
uri = ERB::Util.url_encode(redirect_uri)
|
10
|
+
"#{AUTHORIZE_ENDPOINT}?appid=#{corp_id}&redirect_uri=#{uri}&response_type=code&scope=#{scope}&agentid=#{agent_id}&state=#{state}#wechat_redirect"
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_oauth_userinfo code
|
14
|
+
get 'user/getuserinfo', params: {code: code}
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_user_detail user_ticket
|
18
|
+
post 'user/getuserdetail', {user_ticket: user_ticket}
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_jssign_package url
|
22
|
+
timestamp = Time.now.to_i
|
23
|
+
noncestr = SecureRandom.hex(8)
|
24
|
+
str = "jsapi_ticket=#{jsapi_ticket}&noncestr=#{noncestr}×tamp=#{timestamp}&url=#{url}"
|
25
|
+
{
|
26
|
+
"appId" => corp_id,
|
27
|
+
"nonceStr" => noncestr,
|
28
|
+
"timestamp" => timestamp,
|
29
|
+
"url" => url,
|
30
|
+
"signature" => Digest::SHA1.hexdigest(str),
|
31
|
+
"rawString" => str
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_session_with_jscode(js_code, grant_type='authorization_code')
|
36
|
+
post 'miniprogram/jscode2session', {}, params: {js_code: js_code, grant_type: grant_type}
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_agent
|
40
|
+
get 'agent/get', params: {agentid: agent_id}
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_agent data={}
|
44
|
+
post 'agent/set', data.merge(agentid: agent_id)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|