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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 14663e1a3e66b15083a41484dab4a2cef0282d05
4
+ data.tar.gz: 6906d10cfc13429cc508e496022d622524b51c17
5
+ SHA512:
6
+ metadata.gz: de9fe4bdcd7f1ad3c514876da2b746adcf0489f1de3c3ab7ffd3719dc66e7133617f0796cc8210560a8a70a9795be1db2402b269db7a92c2de2a73155d719b27
7
+ data.tar.gz: 99a2f042b72834f8dd5251d97e8f0f27f0d6bafbf8364e7cf63a378b0071f91f15b6b4f0f65e9eff176d0cd6ee0d970a59317c694a53c26365c9fe8bd37b9e4d
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --format documentation --color spec --drb
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :test, :development do
4
+ gem 'rspec', '~> 3.1.0'
5
+ gem "redis-namespace", "~> 1.4.1"
6
+ gem "rake", "~> 0.9.6"
7
+ gem 'simplecov', '~> 0.7.1', :require => false
8
+ gem "codeclimate-test-reporter", require: nil
9
+ gem 'coveralls', require: false
10
+ # For debugger
11
+ gem "pry-rails", "~> 0.3.2"
12
+
13
+ gem "pry-debugger", "~> 0.2.2"
14
+ end
15
+
16
+ # Specify your gem's dependencies in qy_wechat_api.gemspec
17
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 lanrion
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,120 @@
1
+ **企业号对应多个管理组,请前往 `设置` => `权限管理` 任意创建一个管理组,在管理组最下角即可获取 CorpID Secret**
2
+
3
+ **有问题请及时提issue**
4
+
5
+ ```ruby
6
+ gem "qy_wechat_api", git: "https://github.com/lanrion/qy_wechat_api.git"
7
+ ```
8
+
9
+ # token 存储方案
10
+
11
+ ## 对象存储
12
+ 如果你是单个企业号,建议使用这个方案,无需任何配置即可使用。
13
+
14
+ ## Redis 存储
15
+ ```ruby
16
+ redis = Redis.new(host: "127.0.0.1", port: "6379")
17
+
18
+ namespace = "qy_wechat_api:redis_storage"
19
+
20
+ # cleanup keys in the current namespace when restart server everytime.
21
+ exist_keys = redis.keys("#{namespace}:*")
22
+ exist_keys.each{|key|redis.del(key)}
23
+
24
+ redis_with_ns = Redis::Namespace.new("#{namespace}", redis: redis)
25
+
26
+ QyWechatApi.configure do |config|
27
+ config.redis = redis_with_ns
28
+ end
29
+ ```
30
+
31
+ ## 自定义存储方案
32
+ TODO...
33
+
34
+ # API基本用法
35
+
36
+ 请务必结合:http://qydev.weixin.qq.com/wiki/index.php 理解以下API参数使用。
37
+
38
+ ## 初始化
39
+
40
+ ```ruby
41
+ group_client = QyWechatApi::Client.new(corpid, corpsecret)
42
+ # 为了确保用户输入的corpid, corpsecret是准确的,请务必执行:
43
+ group_client.is_valid?
44
+ ```
45
+
46
+ ## 部门
47
+
48
+ ```ruby
49
+ group_client.department.create(name, parent_id, order=nil)
50
+ group_client.department.update(id, name, parent_id, order=nil)
51
+ group_client.department.delete(id)
52
+ group_client.department.list
53
+ ```
54
+
55
+ ## 成员
56
+
57
+ ```ruby
58
+ group_client.user.create(user_id, name, options={})
59
+ group_client.user.update(user_id, options={})
60
+ group_client.user.delete(user_id)
61
+ group_client.user.get(user_id)
62
+ group_client.user.simple_list(department_id, fetch_child=nil, status=nil)
63
+ ```
64
+
65
+ ## 标签
66
+
67
+ ```ruby
68
+ group_client.tag.create(name)
69
+ group_client.tag.update(id, name)
70
+ group_client.tag.delete(id)
71
+ group_client.tag.get(id)
72
+ group_client.tag.add_tag_users(id, user_ids)
73
+ group_client.tag.delete_tag_users(id, user_ids)
74
+ group_client.tag.list
75
+ ```
76
+
77
+ ## 自定义菜单
78
+
79
+ menu_json的生成方法请参考:
80
+ https://github.com/lanrion/weixin_rails_middleware/wiki/DIY-menu
81
+
82
+ ```ruby
83
+ group_client.menu.create(menu_json, app_id)
84
+ group_client.menu.delete(app_id)
85
+ group_client.menu.get(app_id)
86
+ ```
87
+
88
+ ## Oauth2用法
89
+
90
+ 先要配置你应用的 可信域名 `2458023e.ngrok.com`
91
+ state 为开发者自定义参数,可选
92
+
93
+ ```ruby
94
+ # 生成授权url
95
+ group_client.oauth.authorize_url("http://2458023e.ngrok.com", "state")
96
+
97
+ # 获取code后,获取用户信息
98
+ # app_id: 跳转链接时所在的企业应用ID
99
+ group_client.oauth.get_user_info("code", "app_id")
100
+ ```
101
+
102
+ ## 发送消息
103
+
104
+ ```ruby
105
+ # params: (users, parties, tags, agent_id, content, safe=0)
106
+ # users, parties, tags 如果是多个用户,传数组,如果是全部,则直接传 "@all"
107
+ group_client.message.send_text("@all", "@all", "@all", app_id, text_message)
108
+ ```
109
+ **其他发送消息方法请查看 api/message.rb**
110
+
111
+ ## 上传多媒体文件
112
+ ```ruby
113
+ # params: media, media_type
114
+ group_client.media.upload(image_jpg_file, "image")
115
+
116
+ # 获取下载链接
117
+ # 返回一个URL,请开发者自行使用此url下载
118
+ group_client.media.get_media_by_id(media_id)
119
+ ```
120
+
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ require "rest-client"
4
+ require "carrierwave"
5
+ require 'yajl/json_gem'
6
+
7
+ require "qy_wechat_api/carrierwave/qy_wechat_api_uploader"
8
+ require "qy_wechat_api/config"
9
+ require "qy_wechat_api/client"
10
+ require "qy_wechat_api/handler"
11
+ require "qy_wechat_api/api"
12
+
13
+ module QyWechatApi
14
+
15
+ # Storage
16
+ autoload(:Storage, "qy_wechat_api/storage/storage")
17
+ autoload(:ObjectStorage, "qy_wechat_api/storage/object_storage")
18
+ autoload(:RedisStorage, "qy_wechat_api/storage/redis_storage")
19
+
20
+ ENDPOINT_URL = "https://qyapi.weixin.qq.com/cgi-bin"
21
+ OK_MSG = "ok".freeze
22
+ OK_CODE = 0.freeze
23
+
24
+ class << self
25
+
26
+ def http_get_without_token(url, params={})
27
+ get_api_url = ENDPOINT_URL + url
28
+ load_json(RestClient.get(get_api_url, params: params))
29
+ end
30
+
31
+ def http_post_without_token(url, payload={}, params={})
32
+ post_api_url = ENDPOINT_URL + url
33
+ payload = JSON.dump(payload) if !payload[:media].is_a?(File)
34
+ load_json(RestClient.post(post_api_url, payload, params: params))
35
+ end
36
+
37
+ # return hash
38
+ def load_json(string)
39
+ result_hash = JSON.parse(string)
40
+ code = result_hash.delete("errcode")
41
+ en_msg = result_hash.delete("errmsg")
42
+ ResultHandler.new(code, en_msg, result_hash)
43
+ end
44
+
45
+ def open_endpoint(url)
46
+ "https://open.weixin.qq.com#{url}"
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,8 @@
1
+ require "qy_wechat_api/api/base"
2
+ require "qy_wechat_api/api/department"
3
+ require "qy_wechat_api/api/media"
4
+ require "qy_wechat_api/api/message"
5
+ require "qy_wechat_api/api/tag"
6
+ require "qy_wechat_api/api/user"
7
+ require "qy_wechat_api/api/menu"
8
+ require "qy_wechat_api/api/oauth"
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ module QyWechatApi
4
+ module Api
5
+ class Base
6
+ attr_accessor :access_token, :corp_id
7
+
8
+ def initialize(access_token, corp_id=nil)
9
+ @access_token = access_token
10
+ @corp_id = corp_id
11
+ end
12
+
13
+ private
14
+ def http_get(url, params={})
15
+ request_url = "#{base_url}/#{url}"
16
+ params = params.merge({access_token: access_token})
17
+ QyWechatApi.http_get_without_token(request_url, params )
18
+ end
19
+
20
+ def http_post(url, payload={}, params={})
21
+ request_url = "#{base_url}/#{url}"
22
+ params = params.merge({access_token: access_token})
23
+ QyWechatApi.http_post_without_token(request_url, payload, params)
24
+ end
25
+
26
+ def base_url
27
+ ""
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ module QyWechatApi
4
+ module Api
5
+ class Department < Base
6
+
7
+ # name 是 部门名称。长度限制为1~64个字符
8
+ # parentid 是 父亲部门id。根部门id为1
9
+ # order 否 在父部门中的次序。从1开始,数字越大排序越靠后
10
+ def create(name, parent_id, order=nil)
11
+ payload = {name: name}
12
+ payload[:parentid] = parent_id
13
+ payload[:order] = order if not order.nil?
14
+ http_post("create", payload)
15
+ end
16
+
17
+ # id 是 部门id
18
+ # name 否 更新的部门名称。长度限制为0~64个字符。修改部门名称时指定该参数
19
+ # parentid 否 父亲部门id。根部门id为1
20
+ # order 否 在父部门中的次序。从1开始,数字越大排序越靠后
21
+ def update(id, name=nil, parent_id=nil, order=nil)
22
+ payload = {id: id}
23
+ payload[:name] = name if not name.nil?
24
+ payload[:parentid] = parent_id if not parent_id.nil?
25
+ payload[:order] = order if not order.nil?
26
+ http_post("update", payload)
27
+ end
28
+
29
+ def delete(id)
30
+ http_get("delete", id: id)
31
+ end
32
+
33
+ def list
34
+ http_get("list")
35
+ end
36
+
37
+ private
38
+
39
+ def base_url
40
+ "/department"
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+
3
+ module QyWechatApi
4
+ module Api
5
+ class Media < Base
6
+
7
+ # 媒体文件类型,分别有图片(image)、语音(voice)、视频(video),普通文件(file)
8
+ # media: 支持传路径或者文件实例
9
+ def upload(media, media_type)
10
+ file = process_file(media)
11
+ http_post("upload", {media: file}, {type: media_type})
12
+ end
13
+
14
+ # 返回一个URL,请开发者自行使用此url下载
15
+ def get_media_by_id(media_id)
16
+ http_get("get", {media_id: media_id})
17
+ end
18
+
19
+ private
20
+
21
+ def base_url
22
+ "/media"
23
+ end
24
+
25
+ def process_file(media)
26
+ return media if media.is_a?(File) && jpep?(media)
27
+
28
+ media_url = media
29
+ uploader = QyWechatApiUploader.new
30
+
31
+ if http?(media_url) # remote
32
+ uploader.download!(media_url.to_s)
33
+ else # local
34
+ media_file = media.is_a?(File) ? media : File.new(media_url)
35
+ uploader.cache!(media_file)
36
+ end
37
+ file = process_media(uploader)
38
+ CarrierWave.clean_cached_files! # clear last one day cache
39
+ file
40
+ end
41
+
42
+ def process_media(uploader)
43
+ uploader = covert(uploader)
44
+ uploader.file.to_file
45
+ end
46
+
47
+ # JUST ONLY FOR JPG IMAGE
48
+ def covert(uploader)
49
+ # image process
50
+ unless (uploader.file.content_type =~ /image/).nil?
51
+ if !jpep?(uploader.file)
52
+ require "mini_magick"
53
+ # covert to jpeg
54
+ image = MiniMagick::Image.open(uploader.path)
55
+ image.format("jpg")
56
+ uploader.cache!(File.open(image.path))
57
+ image.destroy! # remove /tmp from MinMagick generate
58
+ end
59
+ end
60
+ uploader
61
+ end
62
+
63
+ def http?(uri)
64
+ return false if !uri.is_a?(String)
65
+ uri = URI.parse(uri)
66
+ uri.scheme =~ /^https?$/
67
+ end
68
+
69
+ def jpep?(file)
70
+ content_type = if file.respond_to?(:content_type)
71
+ file.content_type
72
+ else
73
+ content_type(file.path)
74
+ end
75
+ !(content_type =~ /jpeg/).nil?
76
+ end
77
+
78
+ def content_type(media_path)
79
+ MIME::Types.type_for(media_path).first.content_type
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ module QyWechatApi
3
+ module Api
4
+ class Menu < Base
5
+
6
+ def create(menu, agent_id)
7
+ menu = JSON.load(menu) if menu.is_a?(String)
8
+ http_post("create", menu, {agentid: agent_id})
9
+ end
10
+
11
+ def delete(agent_id)
12
+ http_get("delete", {agentid: agent_id})
13
+ end
14
+
15
+ def get(agent_id)
16
+ http_get("get", {agentid: agent_id})
17
+ end
18
+
19
+ private
20
+
21
+ def base_url
22
+ "/menu"
23
+ end
24
+
25
+ end
26
+ end
27
+ end