weixin_authorize_superayi 1.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +19 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +11 -0
  6. data/Gemfile +5 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +72 -0
  9. data/Rakefile +1 -0
  10. data/lib/weixin_authorize/api/custom.rb +176 -0
  11. data/lib/weixin_authorize/api/data_cube.rb +8 -0
  12. data/lib/weixin_authorize/api/groups.rb +60 -0
  13. data/lib/weixin_authorize/api/mass.rb +80 -0
  14. data/lib/weixin_authorize/api/media.rb +149 -0
  15. data/lib/weixin_authorize/api/menu.rb +36 -0
  16. data/lib/weixin_authorize/api/oauth.rb +50 -0
  17. data/lib/weixin_authorize/api/qrcode.rb +53 -0
  18. data/lib/weixin_authorize/api/template.rb +43 -0
  19. data/lib/weixin_authorize/api/user.rb +69 -0
  20. data/lib/weixin_authorize/api.rb +3 -0
  21. data/lib/weixin_authorize/carrierwave/weixin_uploader.rb +4 -0
  22. data/lib/weixin_authorize/client.rb +95 -0
  23. data/lib/weixin_authorize/config.rb +35 -0
  24. data/lib/weixin_authorize/handler/exceptions.rb +5 -0
  25. data/lib/weixin_authorize/handler/global_code.rb +127 -0
  26. data/lib/weixin_authorize/handler/result_handler.rb +52 -0
  27. data/lib/weixin_authorize/handler.rb +3 -0
  28. data/lib/weixin_authorize/js_ticket/object_store.rb +21 -0
  29. data/lib/weixin_authorize/js_ticket/redis_store.rb +41 -0
  30. data/lib/weixin_authorize/js_ticket/store.rb +40 -0
  31. data/lib/weixin_authorize/token/object_store.rb +25 -0
  32. data/lib/weixin_authorize/token/redis_store.rb +38 -0
  33. data/lib/weixin_authorize/token/store.rb +72 -0
  34. data/lib/weixin_authorize/version.rb +3 -0
  35. data/lib/weixin_authorize.rb +97 -0
  36. data/spec/1_fetch_access_token_spec.rb +43 -0
  37. data/spec/2_fetch_jsticket_spec.rb +10 -0
  38. data/spec/api/custom_spec.rb +71 -0
  39. data/spec/api/groups_spec.rb +74 -0
  40. data/spec/api/mass_spec.rb +70 -0
  41. data/spec/api/media_spec.rb +82 -0
  42. data/spec/api/medias/favicon.ico +0 -0
  43. data/spec/api/medias/ruby-logo.jpg +0 -0
  44. data/spec/api/menu_spec.rb +26 -0
  45. data/spec/api/qrcode_spec.rb +22 -0
  46. data/spec/api/template_spec.rb +40 -0
  47. data/spec/api/user_spec.rb +26 -0
  48. data/spec/spec_helper.rb +130 -0
  49. data/weixin_authorize_superayi.gemspec +48 -0
  50. metadata +301 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cfb6ac26947ce643a231765a9a4bf51de165c8b0
4
+ data.tar.gz: 7acc0f884b76bfdaaae49843de26848721489c15
5
+ SHA512:
6
+ metadata.gz: b63888e6c550d4272e5f8460775026e0b7688045c48bf47b6531d57eba2af00740a9db02b93025245e867179f1489ee369b1c422bf4bdb192784e815367bb2d5
7
+ data.tar.gz: 214a03e2f36e22ef82aebe3f4b369b32b191024de04b02ecf331bab56474e0b3816261b5d9f6d725050cc249755be43f76c09383fed86e07f9575743b57f8db9
data/.coveralls.yml ADDED
@@ -0,0 +1,2 @@
1
+ service_name: travis-pro
2
+ repo_token: aAaaYkiZrS6MHUIbKFdM1b5EnevvVZ4MQ
data/.gitignore ADDED
@@ -0,0 +1,19 @@
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
+ *DS_Store
19
+ .ruby-version
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation --color spec --drb
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ bundler_args:
3
+ rvm:
4
+ - 2.0.0
5
+ script:
6
+ - bundle exec rspec spec
7
+ services:
8
+ - redis
9
+ addons:
10
+ code_climate:
11
+ repo_token: c91fecbbd9e414e7cc3ad7a7d99207145de0ac65a3368de09e8c19295343d399
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in weixin_authorize.gemspec
4
+ gemspec
5
+
data/LICENSE.txt ADDED
@@ -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.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # WeixinAuthorize
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/weixin_authorize.png)](http://badge.fury.io/rb/weixin_authorize)
4
+ [![Build Status](https://secure.travis-ci.org/lanrion/weixin_authorize.png?branch=master)](http://travis-ci.org/lanrion/weixin_authorize)
5
+ [![Code Climate](https://codeclimate.com/github/lanrion/weixin_authorize.png)](https://codeclimate.com/github/lanrion/weixin_authorize)
6
+ [![Coverage Status](https://codeclimate.com/github/lanrion/weixin_authorize/coverage.png)](https://codeclimate.com/github/lanrion/weixin_authorize)
7
+
8
+ Support using [Redis](http://redis.io) to store `access_token`
9
+
10
+ [Wiki](https://github.com/lanrion/weixin_authorize/wiki)
11
+
12
+ [Getting-Started](https://github.com/lanrion/weixin_authorize/wiki/Getting-Started)
13
+
14
+ [JS SDK](https://github.com/lanrion/weixin_authorize/wiki/js-sdk)
15
+
16
+ ## 支持自助实现API
17
+
18
+ 详情见:https://github.com/lanrion/weixin_authorize/wiki/diy-your-api
19
+
20
+ ## 已经完成API
21
+
22
+ * 客服消息
23
+ * 模板消息
24
+ * 用户分组管理
25
+ * 用户信息管理
26
+ * Oauth 2授权
27
+ * 二维码生成
28
+ * 自定义菜单
29
+ * 群发消息
30
+ * 多媒体管理
31
+ * JS SDK(ticket支持缓存)
32
+ * 更多请查看测试例子
33
+
34
+ ## V2.0开发中:
35
+ https://github.com/lanrion/weixin_authorize/milestones/v2.0-dev
36
+
37
+ 1. 重构API实现,调用方式
38
+ 2. 对token,ticket的管理,提供第三方开发灵活者自助化
39
+ 3. 尝试RestClient的弃用,选择更高效的HTTP client包
40
+ 4. 支持更多的异常处理机制
41
+
42
+ 注意:查看Wiki或者源代码时,请切换对应的版本来查看。Master处于不断更新完善分支。
43
+
44
+ ## How to test
45
+
46
+ Go to https://github.com/lanrion/weixin_authorize/issues/2, apply a weixin sandbox test account and follow this account
47
+
48
+ https://github.com/lanrion/weixin_authorize/blob/master/spec/spec_helper.rb
49
+
50
+ change your infos:
51
+
52
+ ```ruby
53
+ ENV["APPID"]="wxe371e0960de5426a"
54
+ ENV["APPSECRET"]="572b93d3d20aea242692a804243a141b"
55
+ ENV["OPENID"]="oEEoyuEasxionjR5HygmEOQGwRcw"
56
+ ```
57
+
58
+ then run `rspec .`
59
+
60
+ ## Contributing
61
+
62
+ 1. Fork it
63
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
64
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
65
+ 4. Push to the branch (`git push origin my-new-feature`)
66
+ 5. Create new Pull Request
67
+
68
+ ## 捐赠支持
69
+
70
+ 如果你觉得我的gem对你有帮助,欢迎打赏支持,:smile:
71
+
72
+ ![](https://raw.githubusercontent.com/lanrion/my_config/master/imagex/donation_me_wx.jpg)
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,176 @@
1
+ # encoding: utf-8
2
+ module WeixinAuthorize
3
+ module Api
4
+ module Custom
5
+
6
+ CUSTOM_SERVICE = "https://api.weixin.qq.com/customservice".freeze
7
+
8
+ # 发送文本消息
9
+ # {
10
+ # "touser":"OPENID",
11
+ # "msgtype":"text",
12
+ # "text":
13
+ # {
14
+ # "content":"Hello World"
15
+ # }
16
+ # }
17
+ def send_text_custom(to_user, content)
18
+ message = default_options(to_user).merge({text: {content: content}})
19
+ http_post(custom_base_url, message)
20
+ end
21
+
22
+ # 发送图片消息
23
+ # {
24
+ # "touser":"OPENID",
25
+ # "msgtype":"image",
26
+ # "image":
27
+ # {
28
+ # "media_id":"MEDIA_ID"
29
+ # }
30
+ # }
31
+ def send_image_custom(to_user, media_id)
32
+ message = default_options(to_user, "image").merge({image: {media_id: media_id}})
33
+ http_post(custom_base_url, message)
34
+ end
35
+
36
+ # 发送语音消息
37
+ # {
38
+ # "touser":"OPENID",
39
+ # "msgtype":"voice",
40
+ # "voice":
41
+ # {
42
+ # "media_id":"MEDIA_ID"
43
+ # }
44
+ # }
45
+ def send_voice_custom(to_user, media_id)
46
+ message = default_options(to_user, "voice").merge({voice: {media_id: media_id}})
47
+ http_post(custom_base_url, message)
48
+ end
49
+
50
+ # 发送视频消息
51
+ # {
52
+ # "touser":"OPENID",
53
+ # "msgtype":"video",
54
+ # "video":
55
+ # {
56
+ # "media_id":"MEDIA_ID"
57
+ # }
58
+ # }
59
+ def send_video_custom(to_user, media_id, options={})
60
+ video_options = {media_id: media_id}.merge(options)
61
+ message = default_options(to_user, "video").merge({video: video_options})
62
+ http_post(custom_base_url, message)
63
+ end
64
+
65
+ # 根据media_id发送图文消息
66
+ # {
67
+ # "touser":"OPENID",
68
+ # "msgtype":"mpnews",
69
+ # "mpnews":
70
+ # {
71
+ # "media_id":"MEDIA_ID"
72
+ # }
73
+ # }
74
+ def send_mpnews_custom(to_user, media_id, options={})
75
+ mpnews_options = {media_id: media_id}.merge(options)
76
+ message = default_options(to_user, "mpnews").merge({mpnews: mpnews_options})
77
+ http_post(custom_base_url, message)
78
+ end
79
+
80
+ # 发送音乐消息
81
+ # {
82
+ # "touser":"OPENID",
83
+ # "msgtype":"music",
84
+ # "music":
85
+ # {
86
+ # "title":"MUSIC_TITLE",
87
+ # "description":"MUSIC_DESCRIPTION",
88
+ # "musicurl":"MUSIC_URL",
89
+ # "hqmusicurl":"HQ_MUSIC_URL",
90
+ # "thumb_media_id":"THUMB_MEDIA_ID"
91
+ # }
92
+ # }
93
+ def send_music_custom(to_user, media_id, musicurl, hqmusicurl, options={})
94
+ music_options = { thumb_media_id: media_id,
95
+ musicurl: musicurl,
96
+ hqmusicurl: hqmusicurl
97
+ }.merge(options)
98
+ message = default_options(to_user, "music").merge({music: music_options})
99
+ http_post(custom_base_url, message)
100
+ end
101
+
102
+ # 发送图文消息
103
+ # {
104
+ # "touser":"OPENID",
105
+ # "msgtype":"news",
106
+ # "news":{
107
+ # "articles": [
108
+ # {
109
+ # "title":"Happy Day",
110
+ # "description":"Is Really A Happy Day",
111
+ # "url":"URL",
112
+ # "picurl":"PIC_URL"
113
+ # },
114
+ # {
115
+ # "title":"Happy Day",
116
+ # "description":"Is Really A Happy Day",
117
+ # "url":"URL",
118
+ # "picurl":"PIC_URL"
119
+ # }
120
+ # ]
121
+ # }
122
+ # }
123
+ def send_news_custom(to_user, articles=[])
124
+ message = default_options(to_user, "news").merge({news: {articles: articles}})
125
+ http_post(custom_base_url, message)
126
+ end
127
+
128
+ # 官方示例:{endtime: 1439571890, pageindex: 1, pagesize: 10, starttime: 1438707864}
129
+ # options:
130
+ # page_index: 查询第几页,从1开始
131
+ # page_size: 每页大小,每页最多拉取50条
132
+ CUSTOM_RECORD_URL = "#{CUSTOM_SERVICE}/msgrecord/getrecord".freeze
133
+ def get_custom_msg_record(start_time, end_time, options={})
134
+ start_time, end_time = start_time.to_i, end_time.to_i
135
+ page_index = options[:page_index] || 1
136
+ page_size = options[:page_size] || 50
137
+ option = {
138
+ endtime: end_time,
139
+ starttime: start_time,
140
+ pageindex: page_index,
141
+ pagesize: page_size
142
+ }
143
+ http_post(CUSTOM_RECORD_URL, option, {}, CUSTOM_ENDPOINT)
144
+ end
145
+
146
+ # 客服接口创建会话
147
+ # POST数据示例如下:
148
+ # {
149
+ # "kf_account" : "test1@test",
150
+ # "openid" : "OPENID",
151
+ # "text" : "这是一段附加信息"
152
+ # }
153
+ KF_SESSION_URL = "#{CUSTOM_SERVICE}/kfsession/create".freeze
154
+ def create_kf_session(account, open_id, text)
155
+ post_body = {
156
+ kf_account: account,
157
+ openid: open_id,
158
+ text: text
159
+ }
160
+ http_post(KF_SESSION_URL, post_body, {}, CUSTOM_ENDPOINT)
161
+ end
162
+
163
+ private
164
+
165
+ # https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
166
+ def custom_base_url
167
+ "/message/custom/send"
168
+ end
169
+
170
+ def default_options(to_user, msgtype="text")
171
+ {touser: to_user, msgtype: msgtype}
172
+ end
173
+
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ module WeixinAuthorize
3
+ module Api
4
+ module DataCube
5
+
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+ module WeixinAuthorize
3
+ module Api
4
+ module Groups
5
+
6
+ # 创建分组
7
+ # https://api.weixin.qq.com/cgi-bin/groups/create?access_token=ACCESS_TOKEN
8
+ def create_group(group_name)
9
+ create_url = "#{group_base_url}/create"
10
+ http_post(create_url, {group: {name: group_name}})
11
+ end
12
+
13
+ # 查询所有分组
14
+ # https://api.weixin.qq.com/cgi-bin/groups/get?access_token=ACCESS_TOKEN
15
+ def groups
16
+ groups_url = "#{group_base_url}/get"
17
+ http_get(groups_url)
18
+ end
19
+
20
+ # 查询用户所在分组
21
+ # https://api.weixin.qq.com/cgi-bin/groups/getid?access_token=ACCESS_TOKEN
22
+ def get_group_for(openid)
23
+ group_url = "#{group_base_url}/getid"
24
+ http_post(group_url, {openid: openid})
25
+ end
26
+
27
+ # 修改分组名
28
+ # https://api.weixin.qq.com/cgi-bin/groups/update?access_token=ACCESS_TOKEN
29
+ def update_group_name(group_id, new_group_name)
30
+ group_url = "#{group_base_url}/update"
31
+ http_post(group_url, {group: {id: group_id, name: new_group_name}})
32
+ end
33
+
34
+ # 移动用户分组
35
+ # https://api.weixin.qq.com/cgi-bin/groups/members/update?access_token=ACCESS_TOKEN
36
+ def update_group_for_openid(openid, to_groupid)
37
+ group_url = "#{group_base_url}/members/update"
38
+ http_post(group_url, {openid: openid, to_groupid: to_groupid})
39
+ end
40
+
41
+ # 批量移动用户分组
42
+ def batch_update_group_for_openids(openids, group_id)
43
+ group_url = "#{group_base_url}/members/batchupdate"
44
+ http_post(group_url, {openid_list: openids, to_groupid: group_id})
45
+ end
46
+
47
+ def delete_group(group_id)
48
+ group_url = "#{group_base_url}/delete"
49
+ http_post(group_url, {group: {id: group_id}})
50
+ end
51
+
52
+ private
53
+
54
+ def group_base_url
55
+ "/groups"
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,80 @@
1
+ # encoding: utf-8
2
+ module WeixinAuthorize
3
+ module Api
4
+ module Mass
5
+
6
+ MSG_TYPE = ["mpnews", "image", "text", "voice", "mpvideo"].freeze
7
+
8
+ # media_info= {"media_id" media_id}
9
+ # https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token=ACCESS_TOKEN
10
+ def mass_with_group(group_id, media_info, msgtype="mpnews", is_to_all=false)
11
+ group_option = {filter: {group_id: group_id, is_to_all: is_to_all}}
12
+ media = generate_media(msgtype, media_info, group_option)
13
+
14
+ mass_url = "#{mass_base_url}/sendall"
15
+ http_post(mass_url, media)
16
+ end
17
+
18
+ # https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token=ACCESS_TOKEN
19
+ # if mpvideo,
20
+ # media_info= {"media_id" => media_id, "title" => "title", "description" => "description"}
21
+ def mass_with_openids(openids, media_info, msgtype="mpnews")
22
+ openid_option = {touser: openids}
23
+ media = generate_media(msgtype, media_info, openid_option)
24
+ mass_url = "#{mass_base_url}/send"
25
+ http_post(mass_url, media)
26
+ end
27
+
28
+ # 请注意,只有已经发送成功的消息才能删除删除消息只是将消息的图文详情页失效,已经收到的用户,还是能在其本地看到消息卡片。
29
+ # 另外,删除群发消息只能删除图文消息和视频消息,其他类型的消息一经发送,无法删除。
30
+ def mass_delete_with_msgid(msg_id)
31
+ mass_url = "#{mass_base_url}/delete"
32
+ http_post(mass_url, {msg_id: msg_id})
33
+ end
34
+
35
+ # 预览接口【订阅号与服务号认证后均可用】
36
+ def mass_preview(openid, media_info, msg_type="mpnews")
37
+ openid_option = {touser: openid}
38
+ media = generate_media(msg_type, media_info, openid_option)
39
+ mass_url = "#{mass_base_url}/preview"
40
+ http_post(mass_url, media)
41
+ end
42
+
43
+ # 查询群发消息发送状态【订阅号与服务号认证后均可用】
44
+ def mass_get_status(msg_id)
45
+ mass_url = "#{mass_base_url}/get"
46
+ http_post(mass_url, {"msg_id" => msg_id})
47
+ end
48
+
49
+ private
50
+
51
+ def mass_base_url
52
+ "/message/mass"
53
+ end
54
+
55
+ def generate_media(msg_type, media_info, option)
56
+ msg_type = msg_type.to_s
57
+ if not MSG_TYPE.include?(msg_type)
58
+ raise MediaTypeException, "#{msg_type} is a invalid msg_type"
59
+ end
60
+ {
61
+ msg_type => convert_media_info(msg_type, media_info),
62
+ "msgtype" => msg_type
63
+ }.merge(option)
64
+ end
65
+
66
+ # 如果用户填写的media信息,是字符串,则转换来符合的数据结构,如果 是hash,则直接使用用户的结构。
67
+ def convert_media_info(msg_type, media_info)
68
+ if media_info.is_a?(String)
69
+ if msg_type == "text"
70
+ return {content: media_info}
71
+ else
72
+ return {media_id: media_info}
73
+ end
74
+ end
75
+ media_info
76
+ end
77
+
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,149 @@
1
+ # encoding: utf-8
2
+
3
+ module WeixinAuthorize
4
+ module Api
5
+ module Media
6
+ # 上传多媒体文件
7
+ # http请求方式: POST/FORM
8
+ # http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
9
+ # 支持传路径或者文件类型
10
+ def upload_media(media, media_type)
11
+ file = process_file(media)
12
+ upload_media_url = "#{media_base_url}/upload"
13
+ http_post(upload_media_url, {media: file}, {type: media_type}, "file")
14
+ end
15
+
16
+ # 目前仅仅把下载链接返回给第三方开发者,由第三方开发者处理下载
17
+ def download_media_url(media_id)
18
+ download_media_url = WeixinAuthorize.endpoint_url("file", "#{media_base_url}/get")
19
+ params = URI.encode_www_form("access_token" => get_access_token,
20
+ "media_id" => media_id)
21
+ download_media_url += "?#{params}"
22
+ download_media_url
23
+ end
24
+
25
+ # 上传图文消息素材, 主要用于群发消息接口
26
+ # {
27
+ # "articles": [
28
+ # {
29
+ # "thumb_media_id":"mwvBelOXCFZiq2OsIU-p",
30
+ # "author":"xxx",
31
+ # "title":"Happy Day",
32
+ # "content_source_url":"www.qq.com",
33
+ # "content":"content",
34
+ # "digest":"digest"
35
+ # },
36
+ # {
37
+ # "thumb_media_id":"mwvBelOXCFZiq2OsIU-p",
38
+ # "author":"xxx",
39
+ # "title":"Happy Day",
40
+ # "content_source_url":"www.qq.com",
41
+ # "content":"content",
42
+ # "digest":"digest"
43
+ # }
44
+ # ]
45
+ # }
46
+ # Option: author, content_source_url
47
+ def upload_mass_news(news=[])
48
+ upload_news_url = "#{media_base_url}/uploadnews"
49
+ http_post(upload_news_url, {articles: news})
50
+ end
51
+
52
+ # media_id: 需通过基础支持中的上传下载多媒体文件来得到
53
+ # https://file.api.weixin.qq.com/cgi-bin/media/uploadvideo?access_token=ACCESS_TOKEN
54
+
55
+ # return:
56
+ # {
57
+ # "type":"video",
58
+ # "media_id":"IhdaAQXuvJtGzwwc0abfXnzeezfO0NgPK6AQYShD8RQYMTtfzbLdBIQkQziv2XJc",
59
+ # "created_at":1398848981
60
+ # }
61
+ def upload_mass_video(media_id, title="", desc="")
62
+ video_msg = {
63
+ "media_id" => media_id,
64
+ "title" => title,
65
+ "description" => desc
66
+ }
67
+
68
+ http_post("#{media_base_url}/uploadvideo", video_msg)
69
+ end
70
+
71
+ # 上传图文消息内的图片获取URL
72
+ # https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN
73
+ #
74
+ # return:
75
+ # {
76
+ # "url": "http://mmbiz.qpic.cn/mmbiz/gLO17UPS6FS2xsypf378iaNhWacZ1G1UplZYWEYfwvuU6Ont96b1roYs CNFwaRrSaKTPCUdBK9DgEHicsKwWCBRQ/0"
77
+ # }
78
+ def upload_image(image)
79
+ file = process_file(image)
80
+ upload_image_url = "#{media_base_url}/uploadimg"
81
+ http_post(upload_image_url, {media: file}, {type: 'image'}, 'file')
82
+ end
83
+
84
+ private
85
+
86
+ def media_base_url
87
+ "/media"
88
+ end
89
+
90
+ def process_file(media)
91
+ return media if media.is_a?(File) && jpep?(media)
92
+
93
+ media_url = media
94
+ uploader = WeixinUploader.new
95
+
96
+ if http?(media_url) # remote
97
+ uploader.download!(media_url.to_s)
98
+ else # local
99
+ media_file = media.is_a?(File) ? media : File.new(media_url)
100
+ uploader.cache!(media_file)
101
+ end
102
+ file = process_media(uploader)
103
+ CarrierWave.clean_cached_files! # clear last one day cache
104
+ file
105
+ end
106
+
107
+ def process_media(uploader)
108
+ uploader = covert(uploader)
109
+ uploader.file.to_file
110
+ end
111
+
112
+ # JUST ONLY FOR JPG IMAGE
113
+ def covert(uploader)
114
+ # image process
115
+ unless (uploader.file.content_type =~ /image/).nil?
116
+ if !jpep?(uploader.file)
117
+ require "mini_magick"
118
+ # covert to jpeg
119
+ image = MiniMagick::Image.open(uploader.path)
120
+ image.format("jpg")
121
+ uploader.cache!(File.open(image.path))
122
+ image.destroy! # remove /tmp from MinMagick generate
123
+ end
124
+ end
125
+ uploader
126
+ end
127
+
128
+ def http?(uri)
129
+ return false if !uri.is_a?(String)
130
+ uri = URI.parse(uri)
131
+ uri.scheme =~ /^https?$/
132
+ end
133
+
134
+ def jpep?(file)
135
+ content_type = if file.respond_to?(:content_type)
136
+ file.content_type
137
+ else
138
+ content_type(file.path)
139
+ end
140
+ !(content_type =~ /jpeg/).nil?
141
+ end
142
+
143
+ def content_type(media_path)
144
+ MIME::Types.type_for(media_path).first.content_type
145
+ end
146
+
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+ module WeixinAuthorize
3
+ module Api
4
+ module Menu
5
+
6
+ # 自定义菜单查询接口
7
+ # https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
8
+ def menu
9
+ get_menu_url = "#{menu_base_url}/get"
10
+ http_get(get_menu_url)
11
+ end
12
+
13
+ # 自定义菜单删除接口
14
+ # https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN
15
+ def delete_menu
16
+ delete_menu_url = "#{menu_base_url}/delete"
17
+ http_get(delete_menu_url)
18
+ end
19
+
20
+ # 自定义菜单创建接口
21
+ # https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
22
+ def create_menu(menu)
23
+ menu = JSON.load(menu) if menu.is_a?(String)
24
+ create_menu_url = "#{menu_base_url}/create"
25
+ http_post(create_menu_url, menu)
26
+ end
27
+
28
+ private
29
+
30
+ def menu_base_url
31
+ "/menu"
32
+ end
33
+
34
+ end
35
+ end
36
+ end