wechat_public_api 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 98dfee4a07d505f15fb5e2b6c8e34d9210f050ee
4
- data.tar.gz: 9866e3df655cb9cdc1e39a7d8ed33922b012bc9f
3
+ metadata.gz: 8a3c096dfbdce45f98fc5f76ea0681506702410a
4
+ data.tar.gz: bdee8fb5d9c08e57c44c724e2a263006a0373bcc
5
5
  SHA512:
6
- metadata.gz: 912aa2de176603be919d491a4453561abb531b9aa937cbd77b417d7104337594a9af642a0dce0ad3711b14a1035606494a384b441c3290fb3221c97597dd6094
7
- data.tar.gz: 7bd5188cc0c6e69832326a5428e3be01afebe1059df2f32738636b4df79880484471409020794c26c4fa8efbcd274a63df0f92097b2f1962152f24bae11d1aef
6
+ metadata.gz: 8d9a56c7272421292cde50c5b703b8bcaa4fc109bb514eb86759e762dc43b9c2abee65cc8fb5ef06d9fcc7c99cf1a74402d466ae72df8576c69477e0805b4e0d
7
+ data.tar.gz: 67511e46afa3b5fdf425a759b33b5db9864e5f2fb33ceb6fcec8b628a2f7802e439ede3c4e332a5fde1948816848e2486fcfcd4f1f11b315a8f991502ea08597
data/README.md CHANGED
@@ -20,170 +20,14 @@ gem 'wechat_public_api'
20
20
 
21
21
  $ gem install wechat_public_api
22
22
 
23
- ## 三行代码获得 access_token
23
+ ## 0.1.4 版本文档
24
24
 
25
- ```ruby
26
- WechatPublicApi.app_id = 'appid'
27
- WechatPublicApi.app_secret = 'secret'
28
- access_token = WechatPublicApi::AccessToken.get() # access_token
29
- ```
30
- ## API文档
31
-
32
- ### WechatPublicApi模块配置,开启你的新项目
33
-
34
- **参数说明**
35
-
36
- * @param <String> app_id     # 公众号后台->开发->基本配置提供的AppID
37
- * @param <String> app_secret # 公众号后台->开发->基本配置提供的AppSecret
38
- * @param <Boolearn> access_token_cache # 默认false,用于标识是否使用redis缓存查询到的access_token
39
-
40
- 使用`WechatPublicApi`模块封装的方法之前,需要配置 app_id、app_secret和access_token_cache(可选),具体如下:
41
-
42
- ```ruby
43
- WechatPublicApi.app_id = 'wx440415e4c3b4b8f9'
44
- WechatPublicApi.app_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
45
- access_token = WechatPublicApi::AccessToken.get() # access_token
46
- ```
47
-
48
- **注意:** access_token_cache是一个布尔值,用于判断是否需要缓存access_token_cache,默认可不填,即默认不缓存access_token,如需缓存,请依照下方代码设置参数:
49
-
50
- ```ruby
51
- WechatPublicApi.access_token_cache = true
52
- ```
53
-
54
- ### API功能概览
55
-
56
- * 菜单栏操作
57
- * 创建菜单栏:`WechatPublicApi::Menu.create(post_data)`
58
- * 查询菜单栏:`WechatPublicApi::Menu.query()`
59
- * 删除菜单栏:`WechatPublicApi::Menu.delete()`
60
- * 客服消息管理
61
- * 发送文字消息:`WechatPublicApi::Kf.text_message(openid, content)`
62
- * 发送图片消息:`WechatPublicApi::Kf.image_message(openid, media_id)`
63
- * 发送图文消息:`WechatPublicApi::Kf.mpnews_message(openid, media_id)`
64
- * 发送图文消息(点击跳转外链): `WechatPublicApi::Kf.news_message(openid, articles)`
65
- * 发送语音消息:`WechatPublicApi::Kf.voice_message(openid, media_id)`
66
- * 模板消息管理
67
- * 获取模板列表:`WechatPublicApi::Tp.get_all()`
68
- * 删除模板:`WechatPublicApi::Tp.delete(templet_id)`
69
- * 发送普通模板消息(不跳转小程序)`WechatPublicApi::Tp.general_message(openid, templet_id, url, data)`
70
- * 发送跳转小程序的模板消息:`WechatPublicApi::Tp.miniprogram_message(openid, templet_id, url, appid, pagepath, data)`
71
- * 用户管理
72
- * 获取用户基本信息: `WechatPublicApi::User.get_userinfo(openid)`
73
- * 帐号管理
74
- * 获取临时带参二维码: `WechatPublicApi::Account.qrscene(sceneid)`
75
- * 获取永久带参二维码: `WechatPublicApi::Account.qrsrtscene(sceneid)`
76
- * 保存带参二维码到本地: `WechatPublicApi::Account.save_qrcode(path, *filename)`
77
- * 生成短链接:`WechatPublicApi::Account.shorturl(longurl)`
78
- * 素材管理
79
- * 获得临时图片素材的 media_id: `WechatPublicApi::Material.upload_image_media(file_path)`
80
- * 获得永久图片素材的 media_id: `WechatPublicApi::Material.upload_image_material(file_path)`
81
- * 消息加密解密
82
- * 加密: `WechatPublicApi::Aes.encrypt(aes_key, text, app_id)`
83
- * 解密: `WechatPublicApi::Aes.decrypt(key, dicrypted_string)`
84
-
85
- ### 菜单栏操作API
25
+ [0.1.4 版本文档][1]
26
+ [1]:https://github.com/Diyilou/wechat_public_api/blob/master/doc/0.1.4.md "版本:0.1.4"
86
27
 
87
- 1. 自定义菜单查询
28
+ ## 两行代码获得 access_token
88
29
 
89
30
  ```ruby
90
- # no params
91
- # @return
92
- # {
93
- # "menu": {
94
- # "button": [
95
- # {
96
- # "type": "view",
97
- # "name": "",
98
- # "url": "",
99
- # "sub_button": []
100
- # },
101
- # {
102
- # "type": "click",
103
- # "name": "",
104
- # "key": "menu_3",
105
- # "sub_button": []
106
- # }
107
- # ]
108
- # }
109
- # }
110
- #
111
- menu_list = WechatPublicApi::Menu.query()
31
+ wechat_api = WechatPublicApi.new appid: 'xx', app_secret: 'xx', access_token_cache: true
32
+ access_token = wechat_api.get_access_token
112
33
  ```
113
-
114
- 2. 自定义菜单创建
115
-
116
- ```ruby
117
- ###
118
- # create wechat public menu
119
- # @param <json> post_data
120
- #
121
- # => post_data example
122
- # {
123
- # "button": [
124
- # {
125
- # "type": "view",
126
- # "name": "",
127
- # "url": "",
128
- # "sub_button": []
129
- # },
130
- # {
131
- # "type": "click",
132
- # "name": "",
133
- # "key": "menu_3",
134
- # "sub_button": []
135
- # }
136
- # ]
137
- # }
138
- #
139
- # if success
140
- # @return <JSON> {"errcode"=>0, "errmsg"=>"ok"}
141
- # if failed
142
- # @return <JSON> {"errcode"=>40166, "errmsg"=>"...."}
143
- #
144
- status = WechatPublicApi::Menu.create(post_data)
145
- ```
146
-
147
- 3. 自定义菜单删除
148
-
149
- ```ruby
150
- # @return <JSON> {"errcode"=>0, "errmsg"=>"ok"}
151
- status = WechatPublicApi::Menu.delete()
152
- ```
153
-
154
- 菜单栏操作API主要包含以上三个方法,接下来看一个完整示例:
155
-
156
- ```ruby
157
- # 创建菜单栏 -> 查询菜单栏列表
158
- # 初始化配置
159
- WechatPublicApi.app_id = 'wx440415e4c3b4b8f9'
160
- WechatPublicApi.app_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
161
- # 创建菜单栏
162
- post_data = {
163
- "button": [
164
- {
165
- "type": "view",
166
- "name": "",
167
- "url": "",
168
- "sub_button": []
169
- },
170
- {
171
- "type": "click",
172
- "name": "",
173
- "key": "menu_3",
174
- "sub_button": []
175
- }
176
- ]
177
- }
178
- status = WechatPublicApi::Menu.create(post_data)
179
- if status.errcode.to_i == 0 && status.errmsg == 'ok'
180
- # 返回菜单栏列表
181
- menu_list = WechatPublicApi::Menu.query()
182
- end
183
- ```
184
-
185
- **注意:** 菜单栏创建和查询的方法包含了查询access_token
186
-
187
- ### 客服消息管理API
188
-
189
- 待更新... 可参考源代码,注释比较详细
@@ -5,43 +5,41 @@
5
5
  # Wechat number: zmx119966
6
6
  ####################################################
7
7
 
8
- module WechatPublicApi
8
+ class WechatPublicApi
9
9
  module AccessToken
10
- class << self
11
-
12
- ###
13
- # 获取 access_token
14
- # 判断access_token_cache,决定是否需要缓存数据
15
- # @return <string> nil or access_token
16
- def get()
17
- appid = WechatPublicApi.app_id
18
- secret = WechatPublicApi.app_secret
19
- access_token_cache = WechatPublicApi.access_token_cache
20
-
21
- unless access_token_cache
22
- response = HTTParty.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=#{appid}&secret=#{secret}").body
23
- response_body = (JSON.parse response)
24
-
25
- # 抛出异常
26
- throw response_body['errmsg'] unless response_body['access_token']
27
-
28
- return response_body['access_token']
29
- end
30
-
31
- _cache_key = "#{appid}_access_token"
32
- _cached_access_token = $redis.get _cache_key
33
- if _cached_access_token == nil or _cached_access_token == ''
34
- response = HTTParty.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=#{appid}&secret=#{secret}").body
35
- response_body = (JSON.parse response)
36
-
37
- # 抛出异常
38
- throw response_body['errmsg'] unless response_body['access_token']
39
-
40
- _cached_access_token = response_body['access_token']
41
- $redis.set _cache_key, _cached_access_token, ex: 2.minutes
42
- end
43
- _cached_access_token
10
+
11
+ ###
12
+ # 获取 access_token
13
+ # 判断access_token_cache,决定是否需要缓存数据
14
+ # @return <string> nil or access_token
15
+ def get_access_token()
16
+ appid = @app_id
17
+ secret = @app_secret
18
+ access_token_cache = @access_token_cache
19
+
20
+ unless access_token_cache
21
+ response = HTTParty.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=#{appid}&secret=#{secret}").body
22
+ response_body = (JSON.parse response)
23
+
24
+ # 抛出异常
25
+ throw response_body['errmsg'] unless response_body['access_token']
26
+
27
+ return response_body['access_token']
28
+ end
29
+
30
+ _cache_key = "#{appid}_access_token"
31
+ _cached_access_token = $redis.get _cache_key
32
+ if _cached_access_token == nil or _cached_access_token == ''
33
+ response = HTTParty.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=#{appid}&secret=#{secret}").body
34
+ response_body = (JSON.parse response)
35
+
36
+ # 抛出异常
37
+ throw response_body['errmsg'] unless response_body['access_token']
38
+
39
+ _cached_access_token = response_body['access_token']
40
+ $redis.set _cache_key, _cached_access_token, ex: 2.minutes
44
41
  end
42
+ _cached_access_token
45
43
  end
46
44
  end
47
45
  end
@@ -5,115 +5,108 @@
5
5
  # Wechat number: zmx119966
6
6
  ####################################################
7
7
 
8
- require "wechat_public_api/access_token"
9
-
10
- module WechatPublicApi
8
+ class WechatPublicApi
11
9
  module Account
12
- class << self
10
+ ###
11
+ # 获取临时场景带惨二维码,30天有效
12
+ # @param <int> sceneid -- 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000)
13
+ # @return <string> url -- 二维码网址
14
+ #
15
+ def get_qrscene(sceneid)
16
+ access_token = get_access_token()
13
17
 
14
- ###
15
- # 获取临时场景带惨二维码,30天有效
16
- # @param <int> sceneid -- 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000)
17
- # @return <string> url -- 二维码网址
18
- #
19
- def qrscene(sceneid)
20
- access_token = AccessToken.get()
18
+ # 获取ticket
19
+ uri = URI.parse("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=#{access_token}")
20
+ post_data = {
21
+ 'expire_seconds' => 2592000,
22
+ 'action_name' => 'QR_SCENE',
23
+ 'action_info' => {'scene' => {'scene_id' => sceneid}}}
24
+ http = Net::HTTP.new(uri.host, uri.port)
25
+ http.use_ssl = true
26
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
27
+ request = Net::HTTP::Post.new("/cgi-bin/qrcode/create?access_token=#{access_token}")
28
+ request.add_field('Content-Type', 'application/json')
29
+ request.body = post_data.to_json
30
+ response = http.request(request)
31
+ content = JSON.parse(response.body)
32
+ ticket = content['ticket']
21
33
 
22
- # 获取ticket
23
- uri = URI.parse("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=#{access_token}")
24
- post_data = {
25
- 'expire_seconds' => 2592000,
26
- 'action_name' => 'QR_SCENE',
27
- 'action_info' => {'scene' => {'scene_id' => sceneid}}}
28
- http = Net::HTTP.new(uri.host, uri.port)
29
- http.use_ssl = true
30
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
31
- request = Net::HTTP::Post.new("/cgi-bin/qrcode/create?access_token=#{access_token}")
32
- request.add_field('Content-Type', 'application/json')
33
- request.body = post_data.to_json
34
- response = http.request(request)
35
- content = JSON.parse(response.body)
36
- ticket = content['ticket']
34
+ # 通过ticket换取二维码
35
+ "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=#{ticket}"
36
+ end
37
37
 
38
- # 通过ticket换取二维码
39
- url = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=' + ticket
40
- url
41
- end
38
+ ###
39
+ # 获取永久二维码
40
+ # @param <int> sceneid -- 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000)
41
+ # @return <string> url -- 二维码网址
42
+ #
43
+ def get_qrsrtscene(sceneid)
44
+ access_token = get_access_token()
42
45
 
43
- ###
44
- # 获取永久二维码
45
- # @param <int> sceneid -- 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000)
46
- # @return <string> url -- 二维码网址
47
- #
48
- def qrsrtscene(sceneid)
49
- access_token = AccessToken.get()
46
+ # 获取ticket
47
+ uri = URI.parse("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=#{access_token}")
48
+ post_data = {
49
+ 'action_name' => 'QR_LIMIT_STR_SCENE',
50
+ 'action_info' => {'scene' => {'scene_id' => sceneid}}}
51
+ http = Net::HTTP.new(uri.host, uri.port)
52
+ http.use_ssl = true
53
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
54
+ request = Net::HTTP::Post.new("/cgi-bin/qrcode/create?access_token=#{access_token}")
55
+ request.add_field('Content-Type', 'application/json')
56
+ request.body = post_data.to_json
57
+ response = http.request(request)
58
+ content = JSON.parse(response.body)
59
+ ticket = content['ticket']
50
60
 
51
- # 获取ticket
52
- uri = URI.parse("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=#{access_token}")
53
- post_data = {
54
- 'action_name' => 'QR_LIMIT_STR_SCENE',
55
- 'action_info' => {'scene' => {'scene_id' => sceneid}}}
56
- http = Net::HTTP.new(uri.host, uri.port)
57
- http.use_ssl = true
58
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
59
- request = Net::HTTP::Post.new("/cgi-bin/qrcode/create?access_token=#{access_token}")
60
- request.add_field('Content-Type', 'application/json')
61
- request.body = post_data.to_json
62
- response = http.request(request)
63
- content = JSON.parse(response.body)
64
- ticket = content['ticket']
61
+ # 通过ticket换取二维码
62
+ "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=#{ticket}"
63
+ end
65
64
 
66
- # 通过ticket换取二维码
67
- url = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=' + ticket
68
- url
65
+ ###
66
+ # 保存带参数二维码到指定位置
67
+ # @param <string> path -- 例如: "#{Rails.root}/public/qrcode"
68
+ # @param <string> filename -- 文件名,可选参数,默认不填写则使用时间戳+随机数的方式命名
69
+ #
70
+ # @return <string> path -- 二维码的保存路径
71
+ def save_qrcode(path, *filename)
72
+ # 判断是否需要新建文件
73
+ unless File.exist?(path)
74
+ FileUtils.makedirs(path)
69
75
  end
70
76
 
71
- ###
72
- # 保存带参数二维码到指定位置
73
- # @param <string> path -- 例如: "#{Rails.root}/public/qrcode"
74
- # @param <string> filename -- 文件名,可选参数,默认不填写则使用时间戳+随机数的方式命名
75
- #
76
- # @return <string> path -- 二维码的保存路径
77
- def save_qrcode(path, *filename)
78
- # 判断是否需要新建文件
79
- unless File.exist?(path)
80
- FileUtils.makedirs(path)
81
- end
82
-
83
- if filename
84
- path = "#{path}/#{filename}"
85
- else
86
- path = "#{path}/#{Time.now.to_i.to_s}_#{rand 1000.9999}"
87
- end
88
-
89
- File.open(path, 'wb') do |f|
90
- f.write(HTTParty.get(url).body)
91
- end
77
+ if filename
78
+ path = "#{path}/#{filename}"
79
+ else
80
+ path = "#{path}/#{Time.now.to_i.to_s}_#{rand 1000.9999}"
81
+ end
92
82
 
93
- path
83
+ File.open(path, 'wb') do |f|
84
+ f.write(HTTParty.get(url).body)
94
85
  end
95
86
 
96
- ###
97
- # @param <string> longurl -- 需要被压缩的url
98
- #
99
- # @return <json> shorturl -- 返回短链接 {"errcode":0,"errmsg":"ok","short_url":"http:\/\/w.url.cn\/s\/AvCo6Ih"}
100
- # if false
101
- # @return {"errcode":40013,"errmsg":"invalid appid"}
102
- #
103
- def shorturl(longurl)
104
- access_token = AccessToken.get()
105
- uri = URI.parse("https://api.weixin.qq.com/cgi-bin/shorturl?access_token=#{access_token}")
106
- post_data = {action: "long2short", long_url: longurl}
107
- http = Net::HTTP.new(uri.host, uri.port)
108
- http.use_ssl = true
109
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
110
- request = Net::HTTP::Post.new("/cgi-bin/shorturl?access_token=#{access_token}")
111
- request.add_field('Content-Type', 'application/json')
112
- request.body = post_data.to_json
113
- response = http.request(request)
87
+ path
88
+ end
114
89
 
115
- JSON.parse(response.body)
116
- end
90
+ ###
91
+ # @param <string> longurl -- 需要被压缩的url
92
+ #
93
+ # @return <json> shorturl -- 返回短链接 {"errcode":0,"errmsg":"ok","short_url":"http:\/\/w.url.cn\/s\/AvCo6Ih"}
94
+ # if false
95
+ # @return {"errcode":40013,"errmsg":"invalid appid"}
96
+ #
97
+ def get_shorturl(longurl)
98
+ access_token = get_access_token()
99
+ uri = URI.parse("https://api.weixin.qq.com/cgi-bin/shorturl?access_token=#{access_token}")
100
+ post_data = {action: "long2short", long_url: longurl}
101
+ http = Net::HTTP.new(uri.host, uri.port)
102
+ http.use_ssl = true
103
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
104
+ request = Net::HTTP::Post.new("/cgi-bin/shorturl?access_token=#{access_token}")
105
+ request.add_field('Content-Type', 'application/json')
106
+ request.body = post_data.to_json
107
+ response = http.request(request)
108
+
109
+ JSON.parse(response.body)
117
110
  end
118
111
  end
119
112
  end
@@ -5,40 +5,37 @@
5
5
  # Wechat number: zmx119966
6
6
  ####################################################
7
7
 
8
- require "wechat_public_api/access_token"
9
- module WechatPublicApi
8
+ class WechatPublicApi
10
9
  module Aes
11
- class << self
12
-
13
- # 解密
14
- def decrypt(key, dicrypted_string)
15
- cipher = OpenSSL::Cipher::AES.new(256, :CBC)
16
- cipher.decrypt
17
- cipher.key = key
18
- cipher.iv = '0000000000000000'
19
- cipher.padding = 0
20
- cipher.update(dicrypted_string) << cipher.final
21
- end
10
+ # 解密
11
+ def decrypt(key, dicrypted_string)
12
+ cipher = OpenSSL::Cipher::AES.new(256, :CBC)
13
+ cipher.decrypt
14
+ cipher.key = key
15
+ cipher.iv = '0000000000000000'
16
+ cipher.padding = 0
17
+ cipher.update(dicrypted_string) << cipher.final
18
+ end
22
19
 
23
- # 加密
24
- def encrypt(aes_key, text, app_id)
25
- text = text.force_encoding("ASCII-8BIT")
26
- random = SecureRandom.hex(8)
27
- msg_len = [text.length].pack("N")
28
- text = "#{random}#{msg_len}#{text}#{app_id}"
29
- text = WxAuth.encode(text)
30
- text = handle_cipher(:encrypt, aes_key, text)
31
- Base64.encode64(text)
32
- end
20
+ # 加密
21
+ def encrypt(aes_key, text, app_id)
22
+ text = text.force_encoding("ASCII-8BIT")
23
+ random = SecureRandom.hex(8)
24
+ msg_len = [text.length].pack("N")
25
+ text = "#{random}#{msg_len}#{text}#{app_id}"
26
+ text = WxAuth.encode(text)
27
+ text = handle_cipher(:encrypt, aes_key, text)
28
+ Base64.encode64(text)
29
+ end
33
30
 
34
- def handle_cipher(action, aes_key, text)
35
- cipher = OpenSSL::Cipher.new('AES-256-CBC')
36
- cipher.send(action)
37
- cipher.padding = 0
38
- cipher.key = aes_key
39
- cipher.iv = aes_key[0...16]
40
- cipher.update(text) + cipher.final
41
- end
31
+ private
32
+ def handle_cipher(action, aes_key, text)
33
+ cipher = OpenSSL::Cipher.new('AES-256-CBC')
34
+ cipher.send(action)
35
+ cipher.padding = 0
36
+ cipher.key = aes_key
37
+ cipher.iv = aes_key[0...16]
38
+ cipher.update(text) + cipher.final
42
39
  end
43
40
  end
44
41
  end