qy_wechat_api 1.0.0.beta1

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