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,327 @@
1
+ module Wework
2
+ GLOBAL_CODES = {
3
+ -1 => "系统繁忙",
4
+ 0 => "请求成功",
5
+ 40001 => "获取access_token时Secret错误,或者access_token无效",
6
+ 40002 => "不合法的凭证类型",
7
+ 40003 => "不合法的UserID",
8
+ 40004 => "不合法的媒体文件类型",
9
+ 40005 => "不合法的文件类型",
10
+ 40006 => "不合法的文件大小",
11
+ 40007 => "不合法的媒体文件id",
12
+ 40008 => "不合法的消息类型",
13
+ 40013 => "不合法的corpid",
14
+ 40014 => "不合法的access_token",
15
+ 40015 => "不合法的菜单类型",
16
+ 40016 => "不合法的按钮个数",
17
+ 40017 => "不合法的按钮类型",
18
+ 40018 => "不合法的按钮名字长度",
19
+ 40019 => "不合法的按钮KEY长度",
20
+ 40020 => "不合法的按钮URL长度",
21
+ 40021 => "不合法的菜单版本号",
22
+ 40022 => "不合法的子菜单级数",
23
+ 40023 => "不合法的子菜单按钮个数",
24
+ 40024 => "不合法的子菜单按钮类型",
25
+ 40025 => "不合法的子菜单按钮名字长度",
26
+ 40026 => "不合法的子菜单按钮KEY长度",
27
+ 40027 => "不合法的子菜单按钮URL长度",
28
+ 40028 => "不合法的自定义菜单使用成员",
29
+ 40029 => "不合法的oauth_code",
30
+ 40031 => "不合法的UserID列表",
31
+ 40032 => "不合法的UserID列表长度",
32
+ 40033 => "不合法的请求字符,不能包含\\uxxxx格式的字符",
33
+ 40035 => "不合法的参数",
34
+ 40038 => "不合法的请求格式",
35
+ 40039 => "不合法的URL长度",
36
+ 40040 => "不合法的插件token",
37
+ 40041 => "不合法的插件id",
38
+ 40042 => "不合法的插件会话",
39
+ 40048 => "url中包含不合法domain",
40
+ 40054 => "不合法的子菜单url域名",
41
+ 40055 => "不合法的按钮url域名",
42
+ 40056 => "不合法的agentid",
43
+ 40057 => "不合法的callbackurl或者callbackurl验证失败",
44
+ 40058 => "不合法的红包参数",
45
+ 40059 => "不合法的上报地理位置标志位",
46
+ 40060 => "设置上报地理位置标志位时没有设置callbackurl",
47
+ 40061 => "设置应用头像失败",
48
+ 40062 => "不合法的应用模式",
49
+ 40063 => "参数为空",
50
+ 40064 => "管理组名字已存在",
51
+ 40065 => "不合法的管理组名字长度",
52
+ 40066 => "不合法的部门列表",
53
+ 40067 => "标题长度不合法",
54
+ 40068 => "不合法的标签ID",
55
+ 40069 => "不合法的标签ID列表",
56
+ 40070 => "列表中所有标签(成员)ID都不合法",
57
+ 40071 => "不合法的标签名字,标签名字已经存在",
58
+ 40072 => "不合法的标签名字长度",
59
+ 40073 => "不合法的openid",
60
+ 40074 => "news消息不支持指定为高保密消息",
61
+ 40077 => "不合法的预授权码",
62
+ 40078 => "不合法的临时授权码",
63
+ 40079 => "不合法的授权信息",
64
+ 40080 => "不合法的suitesecret",
65
+ 40082 => "不合法的suitetoken",
66
+ 40083 => "不合法的suiteid",
67
+ 40084 => "不合法的永久授权码",
68
+ 40085 => "不合法的suiteticket",
69
+ 40086 => "不合法的第三方应用appid",
70
+ 40092 => "导入文件存在不合法的内容",
71
+ 40093 => "不合法的跳转target",
72
+ 40094 => "不合法的URL",
73
+ 40095 => "修改失败,并发冲突",
74
+ 40155 => "请勿添加其他公众号的主页链接",
75
+ 41001 => "缺少access_token参数",
76
+ 41002 => "缺少corpid参数",
77
+ 41003 => "缺少refresh_token参数",
78
+ 41004 => "缺少secret参数",
79
+ 41005 => "缺少多媒体文件数据",
80
+ 41006 => "缺少media_id参数",
81
+ 41007 => "缺少子菜单数据",
82
+ 41008 => "缺少oauth code",
83
+ 41009 => "缺少UserID",
84
+ 41010 => "缺少url",
85
+ 41011 => "缺少agentid",
86
+ 41012 => "缺少应用头像mediaid",
87
+ 41013 => "缺少应用名字",
88
+ 41014 => "缺少应用描述",
89
+ 41015 => "缺少Content",
90
+ 41016 => "缺少标题",
91
+ 41017 => "缺少标签ID",
92
+ 41018 => "缺少标签名字",
93
+ 41021 => "缺少suiteid",
94
+ 41022 => "缺少suitetoken",
95
+ 41023 => "缺少suiteticket",
96
+ 41024 => "缺少suitesecret",
97
+ 41025 => "缺少永久授权码",
98
+ 41034 => "缺少login_ticket",
99
+ 41035 => "缺少跳转target",
100
+ 42001 => "access_token过期",
101
+ 42002 => "refresh_token过期",
102
+ 42003 => "oauth_code过期",
103
+ 42004 => "插件token过期",
104
+ 42007 => "预授权码失效",
105
+ 42008 => "临时授权码失效",
106
+ 42009 => "suitetoken失效",
107
+ 43001 => "需要GET请求",
108
+ 43002 => "需要POST请求",
109
+ 43003 => "需要HTTPS",
110
+ 43004 => "需要成员已关注",
111
+ 43005 => "需要好友关系",
112
+ 43006 => "需要订阅",
113
+ 43007 => "需要授权",
114
+ 43008 => "需要支付授权",
115
+ 43010 => "需要处于回调模式",
116
+ 43011 => "需要企业授权",
117
+ 43013 => "应用对成员不可见",
118
+ 44001 => "多媒体文件为空",
119
+ 44002 => "POST的数据包为空",
120
+ 44003 => "图文消息内容为空",
121
+ 44004 => "文本消息内容为空",
122
+ 45001 => "多媒体文件大小超过限制",
123
+ 45002 => "消息内容大小超过限制",
124
+ 45003 => "标题大小超过限制",
125
+ 45004 => "描述大小超过限制",
126
+ 45005 => "链接长度超过限制",
127
+ 45006 => "图片链接长度超过限制",
128
+ 45007 => "语音播放时间超过限制",
129
+ 45008 => "图文消息的文章数量不能超过10条",
130
+ 45009 => "接口调用超过限制",
131
+ 45010 => "创建菜单个数超过限制",
132
+ 45015 => "回复时间超过限制",
133
+ 45016 => "系统分组,不允许修改",
134
+ 45017 => "分组名字过长",
135
+ 45018 => "分组数量超过上限",
136
+ 45022 => "应用名字长度不合法,合法长度为2-16个字",
137
+ 45024 => "帐号数量超过上限",
138
+ 45025 => "同一个成员每周只能邀请一次",
139
+ 45026 => "触发删除用户数的保护",
140
+ 45027 => "mpnews每天只能发送100次",
141
+ 45028 => "素材数量超过上限",
142
+ 45029 => "media_id对该应用不可见",
143
+ 45032 => "作者名字长度超过限制",
144
+ 46001 => "不存在媒体数据",
145
+ 46002 => "不存在的菜单版本",
146
+ 46003 => "不存在的菜单数据",
147
+ 46004 => "不存在的成员",
148
+ 47001 => "解析JSON/XML内容错误",
149
+ 48001 => "Api未授权",
150
+ 48002 => "Api禁用(一般是管理组类型与Api不匹配,例如普通管理组调用会话服务的Api)",
151
+ 48003 => "suitetoken无效",
152
+ 48004 => "授权关系无效",
153
+ 48005 => "Api已废弃",
154
+ 50001 => "redirect_uri未授权",
155
+ 50002 => "成员不在权限范围",
156
+ 50003 => "应用已停用",
157
+ 50004 => "成员状态不正确,需要成员为企业验证中状态",
158
+ 50005 => "企业已禁用",
159
+ 60001 => "部门长度不符合限制",
160
+ 60002 => "部门层级深度超过限制",
161
+ 60003 => "部门不存在",
162
+ 60004 => "父部门不存在",
163
+ 60005 => "不允许删除有成员的部门",
164
+ 60006 => "不允许删除有子部门的部门",
165
+ 60007 => "不允许删除根部门",
166
+ 60008 => "部门ID或者部门名称已存在",
167
+ 60009 => "部门名称含有非法字符",
168
+ 60010 => "部门存在循环关系",
169
+ 60011 => "权限不足,user/department/agent无权限(1.只有通迅录同步助手才有通迅录写权限。2.自定义的应用,需要确定可见范围是否有此人)",
170
+ 60012 => "不允许删除默认应用",
171
+ 60013 => "不允许关闭应用",
172
+ 60014 => "不允许开启应用",
173
+ 60015 => "不允许修改默认应用可见范围",
174
+ 60016 => "不允许删除存在成员的标签",
175
+ 60017 => "不允许设置企业",
176
+ 60019 => "不允许设置应用地理位置上报开关",
177
+ 60020 => "访问ip不在白名单之中",
178
+ 60023 => "已授权的应用不允许企业管理组调用接口修改菜单",
179
+ 60025 => "主页型应用不支持的消息类型",
180
+ 60027 => "不支持第三方修改主页型应用字段",
181
+ 60028 => "应用已授权予第三方,不允许通过接口修改主页url",
182
+ 60029 => "应用已授权予第三方,不允许通过接口修改可信域名",
183
+ 60031 => "未设置管理组的登录授权域名",
184
+ 60102 => "UserID已存在",
185
+ 60103 => "手机号码不合法",
186
+ 60104 => "手机号码已存在",
187
+ 60105 => "邮箱不合法",
188
+ 60106 => "邮箱已存在",
189
+ 60107 => "微信号不合法",
190
+ 60108 => "微信号已存在",
191
+ 60109 => "QQ号已存在",
192
+ 60110 => "用户同时归属部门超过20个",
193
+ 60111 => "UserID不存在",
194
+ 60112 => "成员姓名不合法",
195
+ 60113 => "身份认证信息(微信号/手机/邮箱)不能同时为空",
196
+ 60114 => "性别不合法",
197
+ 60115 => "已关注成员微信不能修改",
198
+ 60116 => "扩展属性已存在",
199
+ 60118 => "成员无有效邀请字段,详情参考(邀请成员关注)的接口说明",
200
+ 60119 => "成员已关注",
201
+ 60120 => "成员已禁用",
202
+ 60121 => "找不到该成员",
203
+ 60122 => "邮箱已被外部管理员使用",
204
+ 60123 => "无效的部门id",
205
+ 60124 => "无效的父部门id",
206
+ 60125 => "非法部门名字,长度超过限制、重名等,重名包括与csv文件中同级部门重名或者与旧组织架构包含成员的同级部门重名",
207
+ 60126 => "创建部门失败",
208
+ 60127 => "缺少部门id",
209
+ 60128 => "字段不合法,可能存在主键冲突或者格式错误",
210
+ 60129 => "用户设置了拒绝邀请",
211
+ 60131 => "不合法的职位长度",
212
+ 80001 => "可信域名不匹配,或者可信域名没有IPC备案(后续将不能在该域名下正常使用jssdk)",
213
+ 81003 => "邀请额度已用完",
214
+ 81004 => "部门数量超过上限",
215
+ 82001 => "发送消息或者邀请的参数全部为空或者全部不合法",
216
+ 82002 => "不合法的PartyID列表长度",
217
+ 82003 => "不合法的TagID列表长度",
218
+ 82004 => "微信版本号过低",
219
+ 85002 => "包含不合法的词语",
220
+ 86001 => "不合法的会话ID",
221
+ 86003 => "不存在的会话ID",
222
+ 86004 => "不合法的会话名",
223
+ 86005 => "不合法的会话管理员",
224
+ 86006 => "不合法的成员列表大小",
225
+ 86007 => "不存在的成员",
226
+ 86101 => "需要会话管理员权限",
227
+ 86201 => "缺少会话ID",
228
+ 86202 => "缺少会话名",
229
+ 86203 => "缺少会话管理员",
230
+ 86204 => "缺少成员",
231
+ 86205 => "非法的会话ID长度",
232
+ 86206 => "非法的会话ID数值",
233
+ 86207 => "会话管理员不在用户列表中",
234
+ 86208 => "消息服务未开启",
235
+ 86209 => "缺少操作者",
236
+ 86210 => "缺少会话参数",
237
+ 86211 => "缺少会话类型(单聊或者群聊)",
238
+ 86213 => "缺少发件人",
239
+ 86214 => "非法的会话类型",
240
+ 86215 => "会话已存在",
241
+ 86216 => "非法会话成员",
242
+ 86217 => "会话操作者不在成员列表中",
243
+ 86218 => "非法会话发件人",
244
+ 86219 => "非法会话收件人",
245
+ 86220 => "非法会话操作者",
246
+ 86221 => "单聊模式下,发件人与收件人不能为同一人",
247
+ 86222 => "不允许消息服务访问的API",
248
+ 86304 => "不合法的消息类型",
249
+ 86305 => "客服服务未启用",
250
+ 86306 => "缺少发送人",
251
+ 86307 => "缺少发送人类型",
252
+ 86308 => "缺少发送人id",
253
+ 86309 => "缺少接收人",
254
+ 86310 => "缺少接收人类型",
255
+ 86311 => "缺少接收人id",
256
+ 86312 => "缺少消息类型",
257
+ 86313 => "缺少客服,发送人或接收人类型,必须有一个为kf",
258
+ 86314 => "客服不唯一,发送人或接收人类型,必须只有一个为kf",
259
+ 86315 => "不合法的发送人类型",
260
+ 86316 => "不合法的发送人id。Userid不存在、openid不存在、kf不存在",
261
+ 86317 => "不合法的接收人类型",
262
+ 86318 => "不合法的接收人id。Userid不存在、openid不存在、kf不存在",
263
+ 86319 => "不合法的客服,kf不在客服列表中",
264
+ 86320 => "不合法的客服类型",
265
+ 88001 => "缺少seq参数",
266
+ 88002 => "缺少offset参数",
267
+ 88003 => "非法seq",
268
+ 90001 => "未认证摇一摇周边",
269
+ 90002 => "缺少摇一摇周边ticket参数",
270
+ 90003 => "摇一摇周边ticket参数不合法",
271
+ 90004 => "摇一摇周边ticket过期",
272
+ 90005 => "未开启摇一摇周边服务",
273
+ 91004 => "卡券已被核销",
274
+ 91011 => "无效的code",
275
+ 91014 => "缺少卡券详情",
276
+ 91015 => "代金券缺少least_cost或者reduce_cost参数",
277
+ 91016 => "折扣券缺少discount参数",
278
+ 91017 => "礼品券缺少gift参数",
279
+ 91019 => "缺少卡券sku参数",
280
+ 91020 => "缺少卡券有效期",
281
+ 91021 => "缺少卡券有效期类型",
282
+ 91022 => "缺少卡券logo_url",
283
+ 91023 => "缺少卡券code类型",
284
+ 91025 => "缺少卡券title",
285
+ 91026 => "缺少卡券color",
286
+ 91027 => "缺少offset参数",
287
+ 91028 => "缺少count参数",
288
+ 91029 => "缺少card_id",
289
+ 91030 => "缺少卡券code",
290
+ 91031 => "缺少卡券notice",
291
+ 91032 => "缺少卡券description",
292
+ 91033 => "缺少ticket类型",
293
+ 91036 => "不合法的有效期",
294
+ 91038 => "变更库存值不合法",
295
+ 91039 => "不合法的卡券id",
296
+ 91040 => "不合法的ticket type",
297
+ 91041 => "没有创建,上传卡券logo,以及核销卡券的权限",
298
+ 91042 => "没有该卡券投放权限",
299
+ 91043 => "没有修改或者删除该卡券的权限",
300
+ 91044 => "不合法的卡券参数",
301
+ 91045 => "缺少团购券groupon结构",
302
+ 91046 => "缺少现金券cash结构",
303
+ 91047 => "缺少折扣券discount结构",
304
+ 91048 => "缺少礼品券gift结构",
305
+ 91049 => "缺少优惠券coupon结构",
306
+ 91050 => "缺少卡券必填字段",
307
+ 91051 => "商户名称超过12个汉字",
308
+ 91052 => "卡券标题超过9个汉字",
309
+ 91053 => "卡券提醒超过16个汉字",
310
+ 91054 => "卡券描述超过1024个汉字",
311
+ 91055 => "卡券副标题长度超过18个汉字",
312
+ 301001 => "应用id已存在",
313
+ 301002 => "accesstoken不允许操作其它应用。",
314
+ 301004 => "不允许删除超级管理员",
315
+ 301005 => "消息型应用不允许做此操作",
316
+ 301006 => "不允许禁用超级管理员",
317
+ 301008 => "主页型应用不允许做此操作",
318
+ 301009 => "应用发送消息没有接收主体",
319
+ 301010 => "部门名已存在",
320
+ 301013 => "座机不合法",
321
+ 301014 => "英文名称不合法",
322
+ 302001 => "批量同步成员存在userid为空的用户",
323
+ 302002 => "管理员userid不存在",
324
+ 302003 => "存在重复的userid",
325
+ 302004 => "组织架构不合法"
326
+ } unless defined?(GLOBAL_CODES)
327
+ end
@@ -0,0 +1,34 @@
1
+ require 'json'
2
+ require 'sinatra/base'
3
+
4
+ module Wework
5
+ class MockApi < Sinatra::Base
6
+ get '/cgi-bin/media/get' do
7
+ send_file mock_file_path('files/zhiren.png'), :type => :jpg
8
+ end
9
+
10
+ get '/cgi-bin/*' do |api|
11
+ json_response "#{api}.json"
12
+ end
13
+
14
+ %i(get post).each do |http_method|
15
+ send http_method, '/cgi-bin/*/*' do |category, api|
16
+ json_response "#{category}/#{api}.json"
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def json_response file_name
23
+ content_type :json
24
+ status 200
25
+ file_path = mock_file_path(file_name)
26
+ file_path = mock_file_path('success.json') unless File.exist?(file_path)
27
+ File.open(file_path, 'rb').read
28
+ end
29
+
30
+ def mock_file_path path
31
+ File.join(File.expand_path('../../../mock_responses/', __FILE__), path)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,117 @@
1
+ # Reference this: https://github.com/Eric-Guo/wechat/blob/master/lib/wechat/http_client.rb
2
+ require 'http'
3
+ require 'wework/global_code'
4
+
5
+ module Wework
6
+ class Request
7
+ attr_reader :base, :ssl_context, :httprb
8
+
9
+ def initialize(base, skip_verify_ssl)
10
+ @base = base
11
+ @httprb = HTTP.timeout(**Wework.http_timeout_options)
12
+ @ssl_context = OpenSSL::SSL::SSLContext.new
13
+ @ssl_context.ssl_version = :TLSv1_2
14
+ @ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE if skip_verify_ssl
15
+ end
16
+
17
+ def get(path, get_header = {})
18
+ request(path, get_header) do |url, header|
19
+ params = header.delete(:params)
20
+ puts "header:#{header.to_json}"
21
+ puts "params:#{params.to_json}"
22
+ puts "url:#{url}"
23
+ RestClient.get url,{params:params}
24
+ #httprb.headers(header).get(url, params: params, ssl_context: ssl_context)
25
+ end
26
+ end
27
+
28
+
29
+
30
+ def post(path, post_body, post_header = {})
31
+ request(path, post_header) do |url, header|
32
+ params = header.delete(:params)
33
+ RestClient.post url, post_body, {params:params}
34
+ #httprb.headers(header).post(url, params: params, json: post_body, ssl_context: ssl_context)
35
+ end
36
+ end
37
+
38
+ def post_file(path, file, post_header = {})
39
+ request(path, post_header) do |url, header|
40
+ params = header.delete(:params)
41
+ httprb.headers(header)
42
+ .post(url, params: params,
43
+ form: { media: HTTP::FormData::File.new(file),
44
+ hack: 'X' }, # Existing here for http-form_data 1.0.1 handle single param improperly
45
+ ssl_context: ssl_context)
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def request(path, header = {}, &_block)
52
+ url_base = header.delete(:base) || base
53
+ as = header.delete(:as)
54
+ header['Accept'] = 'application/json'
55
+ dup_header = header.dup
56
+ response = yield("#{url_base}#{path}", header)
57
+ raise ResponseError.new(response.code) unless HTTP_OK_STATUS.include?(response.code)
58
+
59
+ parse_response(response, as || :json) do |parse_as, data|
60
+ break data unless parse_as == :json
61
+ result = Wework::Result.new(data)
62
+ if defined?(Rails.logger) && Rails.logger
63
+ Rails.logger.debug "[WEWORK] request path(#{url_base}#{path}); request params: #{dup_header.inspect}; response: #{result.inspect}"
64
+ end
65
+ raise AccessTokenExpiredError if result.token_expired?
66
+ result
67
+ end
68
+ end
69
+
70
+ def parse_response(response, as)
71
+ content_type = response.headers[:content_type]
72
+ parse_as = {
73
+ %r{^application\/json} => :json,
74
+ %r{^image\/.*} => :file
75
+ }.each_with_object([]) { |match, memo| memo << match[1] if content_type =~ match[0] }.first || as || :text
76
+
77
+ case parse_as
78
+ when :file
79
+ file = Tempfile.new('tmp')
80
+ file.binmode
81
+ file.write(response.body)
82
+ file.close
83
+ data = file
84
+
85
+ when :json
86
+ data = JSON.parse response.body.to_s
87
+ else
88
+ data = response.body
89
+ end
90
+
91
+ yield(parse_as, data)
92
+ end
93
+ end
94
+
95
+ class Result < OpenStruct
96
+ def initialize(data)
97
+ data['message'] = GLOBAL_CODES[data['errcode'].to_i]
98
+ data['full_message'] = "#{data['errcode']}:#{data['errmsg']}(#{data['message']})"
99
+ super data
100
+ end
101
+
102
+ def token_expired?
103
+ # 42001: access_token timeout
104
+ # 40014: invalid access_token
105
+ # 40001, invalid credential, access_token is invalid or not latest hint
106
+ [42001, 40014, 40001].include?(errcode)
107
+ end
108
+
109
+ def throw_error
110
+ raise ResultErrorException.new(full_message) unless success?
111
+ end
112
+
113
+ def success?
114
+ errcode == SUCCESS_CODE
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,21 @@
1
+ require 'wework/token/base'
2
+
3
+ module Wework
4
+ module Token
5
+ class AppToken < Base
6
+
7
+ def redis_key
8
+ @redis_key ||= Digest::MD5.hexdigest "WX_APP_TOKEN_#{client.corp_id}_#{client.secret}"
9
+ end
10
+
11
+ def token_key
12
+ 'access_token'
13
+ end
14
+
15
+ def refresh_token
16
+ client.request.get 'gettoken', params: {corpid: client.corp_id, corpsecret: client.secret}
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,59 @@
1
+ module Wework
2
+ module Token
3
+ class Base
4
+ attr_accessor :client
5
+
6
+ def initialize(client)
7
+ @client = client
8
+ raise RedisNotConfigException if redis.nil?
9
+ end
10
+
11
+ def token
12
+ update_token if expired?
13
+ redis.hget(redis_key, token_key)
14
+ end
15
+
16
+ def update_token
17
+ result = refresh_token
18
+ value = result.send(token_key)
19
+ if value.nil?
20
+ puts "#{self.class.name} refresh token error: #{result.inspect}"
21
+ else
22
+ expires_at = Time.now.to_i + result.expires_in.to_i - Wework.expired_shift_seconds
23
+
24
+ redis.hmset(
25
+ redis_key,
26
+ token_key, value,
27
+ "expires_at", expires_at
28
+ )
29
+
30
+ redis.expireat(redis_key, expires_at)
31
+ end
32
+
33
+ value
34
+ end
35
+
36
+ private
37
+
38
+ def redis
39
+ Wework.redis
40
+ end
41
+
42
+ def redis_key
43
+ raise NotImplementedError
44
+ end
45
+
46
+ def token_key
47
+ raise NotImplementedError
48
+ end
49
+
50
+ def refresh_token
51
+ raise NotImplementedError
52
+ end
53
+
54
+ def expired?
55
+ redis.hvals(redis_key).empty? || redis.hget(redis_key, 'expires_at').to_i <= Time.now.to_i
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,20 @@
1
+ require 'wework/token/base'
2
+
3
+ module Wework
4
+ module Token
5
+ class CorpToken < Base
6
+
7
+ def redis_key
8
+ @redis_key ||= Digest::MD5.hexdigest "WX_CORP_TOKEN_#{client.corp_id}_#{client.permanent_code}"
9
+ end
10
+
11
+ def token_key
12
+ 'access_token'
13
+ end
14
+
15
+ def refresh_token
16
+ client.suite.get_corp_token(client.corp_id, client.permanent_code)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ require 'wework/token/base'
2
+
3
+ module Wework
4
+ module Token
5
+ class JsAgentTicket < Base
6
+
7
+ alias_method :ticket, :token
8
+
9
+ def redis_key
10
+ @redis_key ||= Digest::MD5.hexdigest "WX_JS_AGENT_TICKET_#{client.corp_id}_#{client.agent_id}"
11
+ end
12
+
13
+ def token_key
14
+ 'ticket'
15
+ end
16
+
17
+ def refresh_token
18
+ client.get 'ticket/get', params: { type: 'agent_config' }
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'wework/token/base'
2
+
3
+ module Wework
4
+ module Token
5
+ class JsTicket < Base
6
+
7
+ alias_method :ticket, :token
8
+
9
+ def redis_key
10
+ @redis_key ||= Digest::MD5.hexdigest "WX_JS_TICKET_#{client.corp_id}_#{client.agent_id}"
11
+ end
12
+
13
+ def token_key
14
+ 'ticket'
15
+ end
16
+
17
+ def refresh_token
18
+ client.get 'get_jsapi_ticket'
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ require 'wework/token/base'
2
+
3
+ module Wework
4
+ module Token
5
+ class ProviderToken < Base
6
+
7
+ def redis_key
8
+ @redis_key ||= Digest::MD5.hexdigest "WX_PROVIDER_TOKEN_#{client.corp_id}_#{client.secret}"
9
+ end
10
+
11
+ def token_key
12
+ 'provider_access_token'
13
+ end
14
+
15
+ def refresh_token
16
+ client.request.post 'service/get_provider_token', {corpid: client.corp_id, provider_secret: client.secret}
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ require 'wework/token/base'
2
+
3
+ module Wework
4
+ module Token
5
+ class SuiteToken < Base
6
+
7
+ def redis_key
8
+ @redis_key ||= Digest::MD5.hexdigest "WX_SUITE_TOKEN_#{client.suite_id}_#{client.suite_secret}_#{client.suite_token}"
9
+ end
10
+
11
+ def token_key
12
+ 'suite_access_token'
13
+ end
14
+
15
+ def refresh_token
16
+ client.request.post 'service/get_suite_token', {suite_id: client.suite_id, suite_secret: client.suite_secret, suite_ticket: client.suite_ticket}
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module Wework
2
+ VERSION = '1.2.6'.freeze
3
+ end