qy_wechat_api 1.0.0.beta1

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.
@@ -0,0 +1,123 @@
1
+ # encoding: utf-8
2
+
3
+ module QyWechatApi
4
+ module Api
5
+ class Message < Base
6
+
7
+ # 发送文本
8
+ def send_text(users, parties, tags, agent_id, content, safe=0)
9
+ params = common_params("text", agent_id, users, parties, tags, safe)
10
+ params.merge!({text: {content: content}})
11
+ http_post("send", params)
12
+ end
13
+
14
+ # 发送图片
15
+ def send_image(users, parties, tags, agent_id, media_id, safe=0)
16
+ params = common_params("image", agent_id, users, parties, tags, safe)
17
+ params.merge!({image: {media_id: media_id}})
18
+ http_post("send", params)
19
+ end
20
+
21
+ # 发送语音
22
+ def send_voice(users, parties, tags, agent_id, media_id, safe=0)
23
+ params = common_params("voice", agent_id, users, parties, tags, safe)
24
+ params.merge!({voice: {media_id: media_id}})
25
+ http_post("send", params)
26
+ end
27
+
28
+ # 发送视频
29
+ # media_options: {title: "title", description: "Description"}
30
+ def send_video(users, parties, tags, agent_id, media_id, media_options={}, safe=0)
31
+ params = common_params("video", agent_id, users, parties, tags, safe)
32
+ params.merge!({
33
+ video: {
34
+ media_id: media_id,
35
+ title: media_options["title"],
36
+ description: media_options["description"],
37
+ }
38
+ })
39
+ http_post("send", params)
40
+ end
41
+
42
+ # 文件信息
43
+ def send_file(users, parties, tags, agent_id, media_id, safe=0)
44
+ params = common_params("file", agent_id, users, parties, tags, safe)
45
+ params.merge!({file: {media_id: media_id}})
46
+ http_post("send", params)
47
+ end
48
+
49
+ # news消息
50
+ # "articles":[
51
+ # {
52
+ # "title": "Title",
53
+ # "description": "Description",
54
+ # "url": "URL",
55
+ # "picurl": "PIC_URL"
56
+ # },
57
+ # {
58
+ # "title": "Title",
59
+ # "description": "Description",
60
+ # "url": "URL",
61
+ # "picurl": "PIC_URL"
62
+ # }
63
+ # ]
64
+ def send_news(users, parties, tags, agent_id, articles, safe=0)
65
+ params = common_params("news", agent_id, users, parties, tags, safe)
66
+ params.merge!({news: {articles: articles}})
67
+ http_post("send", params)
68
+ end
69
+
70
+ # mpnews
71
+ # articles":[
72
+ # {
73
+ # "title": "Title",
74
+ # "thumb_media_id": "id",
75
+ # "author": "Author",
76
+ # "content_source_url": "URL",
77
+ # "content": "Content",
78
+ # "digest": "Digest description",
79
+ # "show_cover_pic": "0"
80
+ # },
81
+ # {
82
+ # "title": "Title",
83
+ # "thumb_media_id": "id",
84
+ # "author": "Author",
85
+ # "content_source_url": "URL",
86
+ # "content": "Content",
87
+ # "digest": "Digest description",
88
+ # "show_cover_pic": "0"
89
+ # }
90
+ # ]
91
+ def send_mpnews(users, parties, tags, agent_id, articles, safe=0)
92
+ params = common_params("mpnews", agent_id, users, parties, tags, safe)
93
+ params.merge!({mpnews: {articles: articles}})
94
+ http_post("send", params)
95
+ end
96
+
97
+ private
98
+
99
+ def base_url
100
+ "/message"
101
+ end
102
+
103
+ # 通用函数
104
+ def common_params(msg_type, agent_id, users=[], parties=[], tags=[], safe=0)
105
+ params = {
106
+ touser: join(users),
107
+ toparty: join(parties),
108
+ msgtype: msg_type,
109
+ agentid: agent_id,
110
+ totag: join(tags)
111
+ }
112
+ params.merge!({safe: safe}) if msg_type != "news"
113
+ params
114
+ end
115
+
116
+ def join(array, split="|")
117
+ return array if array.is_a?(String)
118
+ array.join(split)
119
+ end
120
+
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ module QyWechatApi
3
+ module Api
4
+ class Oauth < Base
5
+
6
+ # appid 是 企业的CorpID
7
+ # redirect_uri 是 授权后重定向的回调链接地址,请使用urlencode对链接进行处理
8
+ # response_type 是 返回类型,此时固定为:code
9
+ # scope 是 应用授权作用域,此时固定为:snsapi_base
10
+ # state 否 重定向后会带上state参数,企业可以填写a-zA-Z0-9的参数值
11
+ # #wechat_redirect 是微信终端使用此参数判断是否需要带上身份信息
12
+ # https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
13
+ def authorize_url(redirect_uri, state="qy_wechat")
14
+ require "erb"
15
+ redirect_uri = ERB::Util.url_encode(redirect_uri)
16
+ QyWechatApi.open_endpoint("/connect/oauth2/authorize?appid=#{corp_id}&redirect_uri=#{redirect_uri}&response_type=code&scope=snsapi_base&state=#{state}#wechat_redirect")
17
+ end
18
+
19
+ # 根据code获取成员信息
20
+ # https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE&agentid=AGENTID
21
+ def get_user_info(code, agent_id)
22
+ http_get("user/getuserinfo", {code: code, agentid: agent_id})
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ module QyWechatApi
4
+ module Api
5
+ class Tag < Base
6
+
7
+ def create(name)
8
+ http_post("create", {tagname: name})
9
+ end
10
+
11
+ # tagid 是 标签ID
12
+ # tagname 是
13
+ def update(id, name)
14
+ http_post("update", {tagid: id, tagname: name})
15
+ end
16
+
17
+ def delete(id)
18
+ http_get("delete", {tagid: id})
19
+ end
20
+
21
+ def get(id)
22
+ http_get("get", {tagid: id})
23
+ end
24
+
25
+ # tagid 是 标签ID
26
+ # userlist 是 企业员工ID列表
27
+ def add_tag_users(id, user_ids)
28
+ raise "企业员工ID列表 必须为数组" if !user_ids.is_a?(Array)
29
+ http_post("addtagusers", {tagid: id, userlist: user_ids})
30
+ end
31
+
32
+ # tagid 是 标签ID
33
+ # userlist 是 企业员工ID列表
34
+ def delete_tag_users(id, user_ids)
35
+ raise "企业员工ID列表 必须为数组" if !user_ids.is_a?(Array)
36
+ http_post("deltagusers", {tagid: id, userlist: user_ids})
37
+ end
38
+
39
+ def list
40
+ http_get("list")
41
+ end
42
+
43
+ private
44
+
45
+ def base_url
46
+ "/tag"
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+
3
+ module QyWechatApi
4
+ module Api
5
+ class User < Base
6
+
7
+ # userid 是 员工UserID。对应管理端的帐号,企业内必须唯一。长度为1~64个字符
8
+ # name 是 成员名称。长度为1~64个字符
9
+ # department 否 成员所属部门id列表。注意,每个部门的直属员工上限为1000个
10
+ # position 否 职位信息。长度为0~64个字符
11
+ # mobile 否 手机号码。企业内必须唯一,mobile/weixinid/email三者不能同时为空
12
+ # gender 否 性别。gender=0表示男,=1表示女。默认gender=0
13
+ # tel 否 办公电话。长度为0~64个字符
14
+ # email 否 邮箱。长度为0~64个字符。企业内必须唯一
15
+ # weixinid 否 微信号。企业内必须唯一
16
+ # extattr 否 扩展属性。扩展属性需要在WEB管理端创建后才生效,否则忽略未知属性的赋值
17
+ def create(user_id, name, options={})
18
+ user = {userid: user_id}
19
+ user[:name] = name
20
+ user.merge!(options)
21
+ http_post("create", user)
22
+ end
23
+
24
+ def update(user_id, options={})
25
+ user = {userid: user_id}
26
+ user.merge!(options)
27
+ http_post("update", user)
28
+ end
29
+
30
+ def delete(id)
31
+ http_get("get", {userid: id})
32
+ end
33
+
34
+ def get(id)
35
+ http_get("get", {userid: id})
36
+ end
37
+
38
+ # department_id 是 获取的部门id
39
+ # fetch_child 否 1/0:是否递归获取子部门下面的成员
40
+ # status 否 0获取全部员工,1获取已关注成员列表,2获取禁用成员列表,4获取未关注成员列表。status可叠加
41
+ def simple_list(department_id, fetch_child=nil, status=nil)
42
+ params = {department_id: department_id}
43
+ params[:fetch_child] = fetch_child if not fetch_child.nil?
44
+ params[:status] = status if not status.nil?
45
+ http_get("simplelist", params)
46
+ end
47
+
48
+ private
49
+
50
+ def base_url
51
+ "/user"
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+ module QyWechatApi
3
+ class QyWechatApiUploader < CarrierWave::Uploader::Base
4
+ end
5
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ module QyWechatApi
4
+ class Client
5
+ attr_accessor :corp_id, :group_secret, :expired_at # Time.now + expires_in
6
+ attr_accessor :access_token, :redis_key, :storage
7
+
8
+ def initialize(corp_id, group_secret, redis_key=nil)
9
+ @corp_id = corp_id
10
+ @group_secret = group_secret
11
+ @redis_key = security_redis_key((redis_key || "qy_" + group_secret))
12
+ @storage = Storage.init_with(self)
13
+ end
14
+
15
+ # return token
16
+ def get_access_token
17
+ @storage.access_token
18
+ end
19
+
20
+ # 检查appid和app_secret是否有效。
21
+ def is_valid?
22
+ @storage.valid?
23
+ end
24
+
25
+ # 管理部门API
26
+ def department
27
+ Api::Department.new(get_access_token)
28
+ end
29
+
30
+ # 管理成员API
31
+ def user
32
+ Api::User.new(get_access_token)
33
+ end
34
+
35
+ # 管理标签API
36
+ def tag
37
+ Api::Tag.new(get_access_token)
38
+ end
39
+
40
+ # 管理多媒体文件API
41
+ def media
42
+ Api::Media.new(get_access_token)
43
+ end
44
+
45
+ def message
46
+ Api::Message.new(get_access_token)
47
+ end
48
+
49
+ def menu
50
+ Api::Menu.new(get_access_token)
51
+ end
52
+
53
+ def oauth
54
+ Api::Oauth.new(get_access_token, corp_id)
55
+ end
56
+
57
+ private
58
+
59
+ def security_redis_key(key)
60
+ Digest::MD5.hexdigest(key.to_s).upcase
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,20 @@
1
+ module QyWechatApi
2
+
3
+ class << self
4
+
5
+ attr_accessor :config
6
+
7
+ def configure
8
+ yield self.config ||= Config.new
9
+ end
10
+
11
+ def weixin_redis
12
+ return nil if QyWechatApi.config.nil?
13
+ @redis ||= QyWechatApi.config.redis
14
+ end
15
+ end
16
+
17
+ class Config
18
+ attr_accessor :redis
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ require "qy_wechat_api/handler/errors"
2
+ require "qy_wechat_api/handler/global_code"
3
+ require "qy_wechat_api/handler/result_handler"
@@ -0,0 +1,5 @@
1
+ module QyWechatApi
2
+ module Errors
3
+ class ValidAccessTokenException < RuntimeError;end
4
+ end
5
+ end
@@ -0,0 +1,156 @@
1
+ # encoding: utf-8
2
+ module QyWechatApi
3
+ GLOBAL_CODES = {
4
+ -1 => "系统繁忙",
5
+ 0 => "请求成功",
6
+ 40001 => "获取access_token时Secret错误,或者access_token无效",
7
+ 40002 => "不合法的凭证类型",
8
+ 40003 => "不合法的UserID",
9
+ 40004 => "不合法的媒体文件类型",
10
+ 40005 => "不合法的文件类型",
11
+ 40006 => "不合法的文件大小",
12
+ 40007 => "不合法的媒体文件id",
13
+ 40008 => "不合法的消息类型",
14
+ 40013 => "不合法的corpid",
15
+ 40014 => "不合法的access_token",
16
+ 40015 => "不合法的菜单类型",
17
+ 40016 => "不合法的按钮个数",
18
+ 40017 => "不合法的按钮类型",
19
+ 40018 => "不合法的按钮名字长度",
20
+ 40019 => "不合法的按钮KEY长度",
21
+ 40020 => "不合法的按钮URL长度",
22
+ 40021 => "不合法的菜单版本号",
23
+ 40022 => "不合法的子菜单级数",
24
+ 40023 => "不合法的子菜单按钮个数",
25
+ 40024 => "不合法的子菜单按钮类型",
26
+ 40025 => "不合法的子菜单按钮名字长度",
27
+ 40026 => "不合法的子菜单按钮KEY长度",
28
+ 40027 => "不合法的子菜单按钮URL长度",
29
+ 40028 => "不合法的自定义菜单使用员工",
30
+ 40029 => "不合法的oauth_code",
31
+ 40031 => "不合法的UserID列表",
32
+ 40032 => "不合法的UserID列表长度",
33
+ 40033 => "不合法的请求字符,不能包含xxxx格式的字符",
34
+ 40035 => "不合法的参数",
35
+ 40038 => "不合法的请求格式",
36
+ 40039 => "不合法的URL长度",
37
+ 40040 => "不合法的插件token",
38
+ 40041 => "不合法的插件id",
39
+ 40042 => "不合法的插件会话",
40
+ 40048 => "url中包含不合法domain",
41
+ 40054 => "不合法的子菜单url域名",
42
+ 40055 => "不合法的按钮url域名",
43
+ 40056 => "不合法的agentid",
44
+ 40057 => "不合法的callbackurl",
45
+ 40058 => "不合法的红包参数",
46
+ 40059 => "不合法的上报地理位置标志位",
47
+ 40060 => "设置上报地理位置标志位时没有设置callbackurl",
48
+ 40061 => "设置应用头像失败",
49
+ 40062 => "不合法的应用模式",
50
+ 40063 => "红包参数为空",
51
+ 40064 => "管理组名字已存在",
52
+ 40065 => "不合法的管理组名字长度",
53
+ 40066 => "不合法的部门列表",
54
+ 40067 => "标题长度不合法",
55
+ 40068 => "不合法的标签ID",
56
+ 40069 => "不合法的标签ID列表",
57
+ 40070 => "列表中所有标签(用户)ID都不合法",
58
+ 40071 => "不合法的标签名字,标签名字已经存在",
59
+ 40072 => "不合法的标签名字长度",
60
+ 40073 => "不合法的openid",
61
+ 40074 => "news消息不支持指定为高保密消息",
62
+ 41001 => "缺少access_token参数",
63
+ 41002 => "缺少corpid参数",
64
+ 41003 => "缺少refresh_token参数",
65
+ 41004 => "缺少secret参数",
66
+ 41005 => "缺少多媒体文件数据",
67
+ 41006 => "缺少media_id参数",
68
+ 41007 => "缺少子菜单数据",
69
+ 41008 => "缺少oauth code",
70
+ 41009 => "缺少UserID",
71
+ 41010 => "缺少url",
72
+ 41011 => "缺少agentid",
73
+ 41012 => "缺少应用头像mediaid",
74
+ 41013 => "缺少应用名字",
75
+ 41014 => "缺少应用描述",
76
+ 41015 => "缺少Content",
77
+ 41016 => "缺少标题",
78
+ 41017 => "缺少标签ID",
79
+ 41018 => "缺少标签名字",
80
+ 42001 => "access_token超时",
81
+ 42002 => "refresh_token超时",
82
+ 42003 => "oauth_code超时",
83
+ 42004 => "插件token超时",
84
+ 43001 => "需要GET请求",
85
+ 43002 => "需要POST请求",
86
+ 43003 => "需要HTTPS",
87
+ 43004 => "需要接收者关注",
88
+ 43005 => "需要好友关系",
89
+ 43006 => "需要订阅",
90
+ 43007 => "需要授权",
91
+ 43008 => "需要支付授权",
92
+ 43009 => "需要员工已关注",
93
+ 43010 => "需要处于回调模式",
94
+ 43011 => "需要企业授权",
95
+ 44001 => "多媒体文件为空",
96
+ 44002 => "POST的数据包为空",
97
+ 44003 => "图文消息内容为空",
98
+ 44004 => "文本消息内容为空",
99
+ 45001 => "多媒体文件大小超过限制",
100
+ 45002 => "消息内容超过限制",
101
+ 45003 => "标题字段超过限制",
102
+ 45004 => "描述字段超过限制",
103
+ 45005 => "链接字段超过限制",
104
+ 45006 => "图片链接字段超过限制",
105
+ 45007 => "语音播放时间超过限制",
106
+ 45008 => "图文消息超过限制",
107
+ 45009 => "接口调用超过限制",
108
+ 45010 => "创建菜单个数超过限制",
109
+ 45015 => "回复时间超过限制",
110
+ 45016 => "系统分组,不允许修改",
111
+ 45017 => "分组名字过长",
112
+ 45018 => "分组数量超过上限",
113
+ 45024 => "账号数量超过上限",
114
+ 46001 => "不存在媒体数据",
115
+ 46002 => "不存在的菜单版本",
116
+ 46003 => "不存在的菜单数据",
117
+ 46004 => "不存在的员工",
118
+ 47001 => "解析JSON/XML内容错误",
119
+ 48002 => "Api禁用",
120
+ 50001 => "redirect_uri未授权",
121
+ 50002 => "员工不在权限范围",
122
+ 50003 => "应用已停用",
123
+ 50004 => "员工状态不正确(未关注状态)",
124
+ 50005 => "企业已禁用",
125
+ 60001 => "部门长度不符合限制",
126
+ 60002 => "部门层级深度超过限制",
127
+ 60003 => "部门不存在",
128
+ 60004 => "父亲部门不存在",
129
+ 60005 => "不允许删除有成员的部门",
130
+ 60006 => "不允许删除有子部门的部门",
131
+ 60007 => "不允许删除根部门",
132
+ 60008 => "部门名称已存在",
133
+ 60009 => "部门名称含有非法字符",
134
+ 60010 => "部门存在循环关系",
135
+ 60011 => "管理员权限不足,(user/department/agent)无权限",
136
+ 60012 => "不允许删除默认应用",
137
+ 60013 => "不允许关闭应用",
138
+ 60014 => "不允许开启应用",
139
+ 60015 => "不允许修改默认应用可见范围",
140
+ 60016 => "不允许删除存在成员的标签",
141
+ 60017 => "不允许设置企业",
142
+ 60102 => "UserID已存在",
143
+ 60103 => "手机号码不合法",
144
+ 60104 => "手机号码已存在",
145
+ 60105 => "邮箱不合法",
146
+ 60106 => "邮箱已存在",
147
+ 60107 => "微信号不合法",
148
+ 60108 => "微信号已存在",
149
+ 60109 => "QQ号已存在",
150
+ 60110 => "部门个数超出限制",
151
+ 60111 => "UserID不存在",
152
+ 60112 => "成员姓名不合法",
153
+ 60113 => "身份认证信息(微信号/手机/邮箱)不能同时为空",
154
+ 60114 => "性别不合法"
155
+ } unless defined?(GLOBAL_CODES)
156
+ end