weixin_authorize 1.6.3 → 1.6.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -1
- data/Gemfile +0 -12
- data/README.md +8 -3
- data/lib/weixin_authorize.rb +22 -10
- data/lib/weixin_authorize/api/custom.rb +37 -0
- data/lib/weixin_authorize/api/groups.rb +11 -0
- data/lib/weixin_authorize/api/mass.rb +18 -16
- data/lib/weixin_authorize/api/media.rb +13 -0
- data/lib/weixin_authorize/api/oauth.rb +15 -3
- data/lib/weixin_authorize/api/user.rb +2 -2
- data/lib/weixin_authorize/client.rb +20 -11
- data/lib/weixin_authorize/handler/exceptions.rb +2 -4
- data/lib/weixin_authorize/handler/global_code.rb +39 -1
- data/lib/weixin_authorize/token/redis_store.rb +5 -2
- data/lib/weixin_authorize/version.rb +1 -1
- data/spec/api/custom_spec.rb +12 -3
- data/spec/api/groups_spec.rb +25 -5
- data/spec/api/media_spec.rb +13 -1
- data/spec/spec_helper.rb +8 -9
- data/weixin_authorize.gemspec +15 -1
- metadata +101 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c62ee0327cea856b56ef05e830a8f86ccf630b7
|
4
|
+
data.tar.gz: fbca80ea0873544e0ec14da9dec434546658cef1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3383868121cf735194d4b19df846f8f421329ddcd9f52ec079c888a1e7e38486e94a60055910f24a6548183ed07b4b0533beb21317a6c95c6e997581a6738d05
|
7
|
+
data.tar.gz: 6efe789d011da30d79986fd8110f93735265ae7897c6a585749e6212f1d29fd2b6026c812a404e3637634641dd0404f8de71ff0be831b94cbf120bbacff20052
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,17 +1,5 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
group :test, :development do
|
4
|
-
gem "rspec"
|
5
|
-
gem 'redis-namespace'
|
6
|
-
gem 'simplecov', '~> 0.7.1', :require => false
|
7
|
-
gem "codeclimate-test-reporter", require: nil
|
8
|
-
gem 'coveralls', require: false
|
9
|
-
# For debugger
|
10
|
-
gem "pry-rails"
|
11
|
-
|
12
|
-
gem "pry-byebug"
|
13
|
-
end
|
14
|
-
|
15
3
|
# Specify your gem's dependencies in weixin_authorize.gemspec
|
16
4
|
gemspec
|
17
5
|
|
data/README.md
CHANGED
@@ -13,6 +13,10 @@ Support using [Redis](http://redis.io) to store `access_token`
|
|
13
13
|
|
14
14
|
[JS SDK](https://github.com/lanrion/weixin_authorize/wiki/js-sdk)
|
15
15
|
|
16
|
+
## 支持自助实现API
|
17
|
+
|
18
|
+
详情见:https://github.com/lanrion/weixin_authorize/wiki/diy-your-api
|
19
|
+
|
16
20
|
## 已经完成API
|
17
21
|
|
18
22
|
* 客服消息
|
@@ -25,8 +29,9 @@ Support using [Redis](http://redis.io) to store `access_token`
|
|
25
29
|
* 群发消息
|
26
30
|
* 多媒体管理
|
27
31
|
* JS SDK(ticket支持缓存)
|
32
|
+
* 更多请查看测试例子
|
28
33
|
|
29
|
-
## V2.0开发中:
|
34
|
+
## V2.0开发中:
|
30
35
|
https://github.com/lanrion/weixin_authorize/milestones/v2.0-dev
|
31
36
|
|
32
37
|
1. 重构API实现,调用方式
|
@@ -42,7 +47,7 @@ Go to https://github.com/lanrion/weixin_authorize/issues/2, apply a weixin sandb
|
|
42
47
|
|
43
48
|
https://github.com/lanrion/weixin_authorize/blob/master/spec/spec_helper.rb
|
44
49
|
|
45
|
-
change your infos:
|
50
|
+
change your infos:
|
46
51
|
|
47
52
|
```ruby
|
48
53
|
ENV["APPID"]="wxe371e0960de5426a"
|
@@ -64,4 +69,4 @@ then run `rspec .`
|
|
64
69
|
|
65
70
|
如果你觉得我的gem对你有帮助,欢迎打赏支持,:smile:
|
66
71
|
|
67
|
-
![](https://raw.githubusercontent.com/lanrion/my_config/master/imagex/
|
72
|
+
![](https://raw.githubusercontent.com/lanrion/my_config/master/imagex/donation_me_wx.jpg)
|
data/lib/weixin_authorize.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
require "rest-client"
|
2
2
|
require "carrierwave"
|
3
|
-
|
3
|
+
if defined? Yajl
|
4
|
+
require 'yajl/json_gem'
|
5
|
+
else
|
6
|
+
require "json"
|
7
|
+
end
|
8
|
+
require "erb"
|
4
9
|
|
5
10
|
require "weixin_authorize/carrierwave/weixin_uploader"
|
6
11
|
require "weixin_authorize/config"
|
@@ -23,21 +28,26 @@ module WeixinAuthorize
|
|
23
28
|
autoload(:RedisStore, "weixin_authorize/js_ticket/redis_store")
|
24
29
|
end
|
25
30
|
|
26
|
-
OK_MSG = "ok"
|
27
|
-
OK_CODE = 0
|
28
|
-
GRANT_TYPE = "client_credential"
|
31
|
+
OK_MSG = "ok".freeze
|
32
|
+
OK_CODE = 0.freeze
|
33
|
+
GRANT_TYPE = "client_credential".freeze
|
34
|
+
# 用于标记endpoint可以直接使用url作为完整请求API
|
35
|
+
CUSTOM_ENDPOINT = "custom_endpoint".freeze
|
29
36
|
|
30
37
|
class << self
|
31
38
|
|
32
|
-
def http_get_without_token(url,
|
39
|
+
def http_get_without_token(url, url_params={}, endpoint="plain")
|
33
40
|
get_api_url = endpoint_url(endpoint, url)
|
34
|
-
load_json(resource(get_api_url).get(params:
|
41
|
+
load_json(resource(get_api_url).get(params: url_params))
|
35
42
|
end
|
36
43
|
|
37
|
-
def http_post_without_token(url,
|
44
|
+
def http_post_without_token(url, post_body={}, url_params={}, endpoint="plain")
|
38
45
|
post_api_url = endpoint_url(endpoint, url)
|
39
|
-
|
40
|
-
|
46
|
+
# to json if invoke "plain"
|
47
|
+
if endpoint == "plain" || endpoint == CUSTOM_ENDPOINT
|
48
|
+
post_body = JSON.dump(post_body)
|
49
|
+
end
|
50
|
+
load_json(resource(post_api_url).post(post_body, params: url_params))
|
41
51
|
end
|
42
52
|
|
43
53
|
def resource(url)
|
@@ -46,13 +56,15 @@ module WeixinAuthorize
|
|
46
56
|
|
47
57
|
# return hash
|
48
58
|
def load_json(string)
|
49
|
-
result_hash = JSON.parse(string)
|
59
|
+
result_hash = JSON.parse(string.force_encoding("UTF-8").gsub(/[\u0011-\u001F]/, ""))
|
50
60
|
code = result_hash.delete("errcode")
|
51
61
|
en_msg = result_hash.delete("errmsg")
|
52
62
|
ResultHandler.new(code, en_msg, result_hash)
|
53
63
|
end
|
54
64
|
|
55
65
|
def endpoint_url(endpoint, url)
|
66
|
+
# 此处为了应对第三方开发者如果自助对接接口时,URL不规范的情况下,可以直接使用URL当为endpoint
|
67
|
+
return url if endpoint == CUSTOM_ENDPOINT
|
56
68
|
send("#{endpoint}_endpoint") + url
|
57
69
|
end
|
58
70
|
|
@@ -3,6 +3,8 @@ module WeixinAuthorize
|
|
3
3
|
module Api
|
4
4
|
module Custom
|
5
5
|
|
6
|
+
CUSTOM_SERVICE = "https://api.weixin.qq.com/customservice".freeze
|
7
|
+
|
6
8
|
# 发送文本消息
|
7
9
|
# {
|
8
10
|
# "touser":"OPENID",
|
@@ -108,6 +110,41 @@ module WeixinAuthorize
|
|
108
110
|
http_post(custom_base_url, message)
|
109
111
|
end
|
110
112
|
|
113
|
+
# 官方示例:{endtime: 1439571890, pageindex: 1, pagesize: 10, starttime: 1438707864}
|
114
|
+
# options:
|
115
|
+
# page_index: 查询第几页,从1开始
|
116
|
+
# page_size: 每页大小,每页最多拉取50条
|
117
|
+
CUSTOM_RECORD_URL = "#{CUSTOM_SERVICE}/msgrecord/getrecord".freeze
|
118
|
+
def get_custom_msg_record(start_time, end_time, options={})
|
119
|
+
start_time, end_time = start_time.to_i, end_time.to_i
|
120
|
+
page_index = options[:page_index] || 1
|
121
|
+
page_size = options[:page_size] || 50
|
122
|
+
option = {
|
123
|
+
endtime: end_time,
|
124
|
+
starttime: start_time,
|
125
|
+
pageindex: page_index,
|
126
|
+
pagesize: page_size
|
127
|
+
}
|
128
|
+
http_post(CUSTOM_RECORD_URL, option, {}, CUSTOM_ENDPOINT)
|
129
|
+
end
|
130
|
+
|
131
|
+
# 客服接口创建会话
|
132
|
+
# POST数据示例如下:
|
133
|
+
# {
|
134
|
+
# "kf_account" : "test1@test",
|
135
|
+
# "openid" : "OPENID",
|
136
|
+
# "text" : "这是一段附加信息"
|
137
|
+
# }
|
138
|
+
KF_SESSION_URL = "#{CUSTOM_SERVICE}/kfsession/create".freeze
|
139
|
+
def create_kf_session(account, open_id, text)
|
140
|
+
post_body = {
|
141
|
+
kf_account: account,
|
142
|
+
openid: open_id,
|
143
|
+
text: text
|
144
|
+
}
|
145
|
+
http_post(KF_SESSION_URL, post_body, {}, CUSTOM_ENDPOINT)
|
146
|
+
end
|
147
|
+
|
111
148
|
private
|
112
149
|
|
113
150
|
# https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
|
@@ -38,6 +38,17 @@ module WeixinAuthorize
|
|
38
38
|
http_post(group_url, {openid: openid, to_groupid: to_groupid})
|
39
39
|
end
|
40
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
|
+
|
41
52
|
private
|
42
53
|
|
43
54
|
def group_base_url
|
@@ -3,12 +3,12 @@ module WeixinAuthorize
|
|
3
3
|
module Api
|
4
4
|
module Mass
|
5
5
|
|
6
|
-
MSG_TYPE = ["mpnews", "image", "text", "voice", "mpvideo"]
|
6
|
+
MSG_TYPE = ["mpnews", "image", "text", "voice", "mpvideo"].freeze
|
7
7
|
|
8
8
|
# media_info= {"media_id" media_id}
|
9
9
|
# https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token=ACCESS_TOKEN
|
10
10
|
def mass_with_group(group_id, media_info, msgtype="mpnews", is_to_all=false)
|
11
|
-
group_option = {
|
11
|
+
group_option = {filter: {group_id: group_id, is_to_all: is_to_all}}
|
12
12
|
media = generate_media(msgtype, media_info, group_option)
|
13
13
|
|
14
14
|
mass_url = "#{mass_base_url}/sendall"
|
@@ -19,7 +19,7 @@ module WeixinAuthorize
|
|
19
19
|
# if mpvideo,
|
20
20
|
# media_info= {"media_id" => media_id, "title" => "title", "description" => "description"}
|
21
21
|
def mass_with_openids(openids, media_info, msgtype="mpnews")
|
22
|
-
openid_option = {
|
22
|
+
openid_option = {touser: openids}
|
23
23
|
media = generate_media(msgtype, media_info, openid_option)
|
24
24
|
mass_url = "#{mass_base_url}/send"
|
25
25
|
http_post(mass_url, media)
|
@@ -29,13 +29,13 @@ module WeixinAuthorize
|
|
29
29
|
# 另外,删除群发消息只能删除图文消息和视频消息,其他类型的消息一经发送,无法删除。
|
30
30
|
def mass_delete_with_msgid(msg_id)
|
31
31
|
mass_url = "#{mass_base_url}/delete"
|
32
|
-
http_post(mass_url, {
|
32
|
+
http_post(mass_url, {msg_id: msg_id})
|
33
33
|
end
|
34
34
|
|
35
35
|
# 预览接口【订阅号与服务号认证后均可用】
|
36
|
-
def mass_preview(openid, media_info,
|
37
|
-
openid_option = {
|
38
|
-
media = generate_media(
|
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
39
|
mass_url = "#{mass_base_url}/preview"
|
40
40
|
http_post(mass_url, media)
|
41
41
|
end
|
@@ -52,22 +52,24 @@ module WeixinAuthorize
|
|
52
52
|
"/message/mass"
|
53
53
|
end
|
54
54
|
|
55
|
-
def generate_media(
|
56
|
-
|
57
|
-
|
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
|
58
60
|
{
|
59
|
-
|
60
|
-
"msgtype" =>
|
61
|
+
msg_type => convert_media_info(msg_type, media_info),
|
62
|
+
"msgtype" => msg_type
|
61
63
|
}.merge(option)
|
62
64
|
end
|
63
65
|
|
64
66
|
# 如果用户填写的media信息,是字符串,则转换来符合的数据结构,如果 是hash,则直接使用用户的结构。
|
65
|
-
def convert_media_info(
|
67
|
+
def convert_media_info(msg_type, media_info)
|
66
68
|
if media_info.is_a?(String)
|
67
|
-
if
|
68
|
-
return {
|
69
|
+
if msg_type == "text"
|
70
|
+
return {content: media_info}
|
69
71
|
else
|
70
|
-
return {
|
72
|
+
return {media_id: media_info}
|
71
73
|
end
|
72
74
|
end
|
73
75
|
media_info
|
@@ -68,6 +68,19 @@ module WeixinAuthorize
|
|
68
68
|
http_post("#{media_base_url}/uploadvideo", video_msg)
|
69
69
|
end
|
70
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
|
+
|
71
84
|
private
|
72
85
|
|
73
86
|
def media_base_url
|
@@ -3,6 +3,13 @@ module WeixinAuthorize
|
|
3
3
|
module Api
|
4
4
|
module Oauth
|
5
5
|
|
6
|
+
# 网站应用微信登录授权URL
|
7
|
+
# 文档:http://t.cn/RyZVWEY
|
8
|
+
def qrcode_authorize_url(redirect_uri, scope="snsapi_login", state="web_wx_login")
|
9
|
+
uri = encode_url(redirect_uri)
|
10
|
+
WeixinAuthorize.open_endpoint("/connect/qrconnect?appid=#{app_id}&redirect_uri=#{uri}&response_type=code&scope=#{scope}&state=#{state}#wechat_redirect")
|
11
|
+
end
|
12
|
+
|
6
13
|
# 应用授权作用域: scope
|
7
14
|
# snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),
|
8
15
|
# snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
|
@@ -11,9 +18,8 @@ module WeixinAuthorize
|
|
11
18
|
|
12
19
|
# 如果用户点击同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE
|
13
20
|
def authorize_url(redirect_uri, scope="snsapi_base", state="weixin")
|
14
|
-
|
15
|
-
|
16
|
-
WeixinAuthorize.open_endpoint("/connect/oauth2/authorize?appid=#{app_id}&redirect_uri=#{redirect_uri}&response_type=code&scope=#{scope}&state=#{state}#wechat_redirect")
|
21
|
+
uri = encode_url(redirect_uri)
|
22
|
+
WeixinAuthorize.open_endpoint("/connect/oauth2/authorize?appid=#{app_id}&redirect_uri=#{uri}&response_type=code&scope=#{scope}&state=#{state}#wechat_redirect")
|
17
23
|
end
|
18
24
|
|
19
25
|
# 首先请注意,这里通过code换取的网页授权access_token,与基础支持中的access_token不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。
|
@@ -33,6 +39,12 @@ module WeixinAuthorize
|
|
33
39
|
WeixinAuthorize.http_get_without_token("/sns/userinfo?access_token=#{oauth_token}&openid=#{openid}&lang=#{lang}", {}, "api")
|
34
40
|
end
|
35
41
|
|
42
|
+
private
|
43
|
+
|
44
|
+
def encode_url(uri)
|
45
|
+
ERB::Util.url_encode(uri)
|
46
|
+
end
|
47
|
+
|
36
48
|
end
|
37
49
|
end
|
38
50
|
end
|
@@ -29,11 +29,11 @@ module WeixinAuthorize
|
|
29
29
|
# }
|
30
30
|
def update_remark(openid, remark)
|
31
31
|
update_url = "/user/info/updateremark"
|
32
|
-
|
32
|
+
post_body = {
|
33
33
|
openid: openid,
|
34
34
|
remark: remark
|
35
35
|
}
|
36
|
-
http_post(update_url,
|
36
|
+
http_post(update_url, post_body)
|
37
37
|
end
|
38
38
|
|
39
39
|
private
|
@@ -1,9 +1,13 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
require "monitor"
|
2
3
|
require "redis"
|
3
4
|
require 'digest/md5'
|
4
5
|
module WeixinAuthorize
|
5
6
|
|
6
7
|
class Client
|
8
|
+
|
9
|
+
include MonitorMixin
|
10
|
+
|
7
11
|
include Api::User
|
8
12
|
include Api::Menu
|
9
13
|
include Api::Custom
|
@@ -15,24 +19,29 @@ module WeixinAuthorize
|
|
15
19
|
include Api::Template
|
16
20
|
|
17
21
|
attr_accessor :app_id, :app_secret, :expired_at # Time.now + expires_in
|
18
|
-
attr_accessor :access_token, :redis_key
|
22
|
+
attr_accessor :access_token, :redis_key, :custom_access_token
|
19
23
|
attr_accessor :jsticket, :jsticket_expired_at, :jsticket_redis_key
|
20
24
|
|
21
|
-
|
22
|
-
|
25
|
+
# options: redis_key, custom_access_token
|
26
|
+
def initialize(app_id, app_secret, options={})
|
27
|
+
@app_id = app_id
|
23
28
|
@app_secret = app_secret
|
24
29
|
@jsticket_expired_at = @expired_at = Time.now.to_i
|
25
|
-
@redis_key
|
30
|
+
@redis_key = security_redis_key(options[:redis_key] || "weixin_#{app_id}")
|
26
31
|
@jsticket_redis_key = security_redis_key("js_sdk_#{app_id}")
|
32
|
+
@custom_access_token = options[:custom_access_token]
|
33
|
+
super() # Monitor#initialize
|
27
34
|
end
|
28
35
|
|
29
36
|
# return token
|
30
37
|
def get_access_token
|
31
|
-
|
38
|
+
return custom_access_token if !custom_access_token.nil?
|
39
|
+
synchronize{ token_store.access_token }
|
32
40
|
end
|
33
41
|
|
34
42
|
# 检查appid和app_secret是否有效。
|
35
43
|
def is_valid?
|
44
|
+
return true if !custom_access_token.nil?
|
36
45
|
token_store.valid?
|
37
46
|
end
|
38
47
|
|
@@ -62,14 +71,14 @@ module WeixinAuthorize
|
|
62
71
|
end
|
63
72
|
|
64
73
|
# 暴露出:http_get,http_post两个方法,方便第三方开发者扩展未开发的微信API。
|
65
|
-
def http_get(url,
|
66
|
-
|
67
|
-
WeixinAuthorize.http_get_without_token(url,
|
74
|
+
def http_get(url, url_params={}, endpoint="plain")
|
75
|
+
url_params = url_params.merge(access_token_param)
|
76
|
+
WeixinAuthorize.http_get_without_token(url, url_params, endpoint)
|
68
77
|
end
|
69
78
|
|
70
|
-
def http_post(url,
|
71
|
-
|
72
|
-
WeixinAuthorize.http_post_without_token(url,
|
79
|
+
def http_post(url, post_body={}, url_params={}, endpoint="plain")
|
80
|
+
url_params = access_token_param.merge(url_params)
|
81
|
+
WeixinAuthorize.http_post_without_token(url, post_body, url_params, endpoint)
|
73
82
|
end
|
74
83
|
|
75
84
|
private
|
@@ -83,7 +83,45 @@ module WeixinAuthorize
|
|
83
83
|
46004 => "不存在的用户",
|
84
84
|
47001 => "解析JSON/XML内容错误",
|
85
85
|
48001 => "api功能未授权",
|
86
|
-
50001 => "用户未授权该api"
|
86
|
+
50001 => "用户未授权该api",
|
87
|
+
50002 => "用户受限,可能是违规后接口被封禁",
|
88
|
+
61451 => "参数错误(invalid parameter)",
|
89
|
+
61452 => "无效客服账号(invalid kf_account)",
|
90
|
+
61453 => "客服帐号已存在(kf_account exsited)",
|
91
|
+
61454 => "客服帐号名长度超过限制(仅允许10个英文字符,不包括@及@后的公众号的微信号)(invalid kf_acount length)",
|
92
|
+
61455 => "客服帐号名包含非法字符(仅允许英文+数字)(illegal character in kf_account)",
|
93
|
+
61456 => "客服帐号个数超过限制(10个客服账号)(kf_account count exceeded)",
|
94
|
+
61457 => "无效头像文件类型(invalid file type)",
|
95
|
+
61450 => "系统错误(system error)",
|
96
|
+
61500 => "日期格式错误",
|
97
|
+
61501 => "日期范围错误",
|
98
|
+
9001001 => "POST数据参数不合法",
|
99
|
+
9001002 => "远端服务不可用",
|
100
|
+
9001003 => "Ticket不合法",
|
101
|
+
9001004 => "获取摇周边用户信息失败",
|
102
|
+
9001005 => "获取商户信息失败",
|
103
|
+
9001006 => "获取OpenID失败",
|
104
|
+
9001007 => "上传文件缺失",
|
105
|
+
9001008 => "上传素材的文件类型不合法",
|
106
|
+
9001009 => "上传素材的文件尺寸不合法",
|
107
|
+
9001010 => "上传失败",
|
108
|
+
9001020 => "帐号不合法",
|
109
|
+
9001021 => "已有设备激活率低于50%,不能新增设备",
|
110
|
+
9001022 => "设备申请数不合法,必须为大于0的数字",
|
111
|
+
9001023 => "已存在审核中的设备ID申请",
|
112
|
+
9001024 => "一次查询设备ID数量不能超过50",
|
113
|
+
9001025 => "设备ID不合法",
|
114
|
+
9001026 => "页面ID不合法",
|
115
|
+
9001027 => "页面参数不合法",
|
116
|
+
9001028 => "一次删除页面ID数量不能超过10",
|
117
|
+
9001029 => "页面已应用在设备中,请先解除应用关系再删除",
|
118
|
+
9001030 => "一次查询页面ID数量不能超过50",
|
119
|
+
9001031 => "时间区间不合法",
|
120
|
+
9001032 => "保存设备与页面的绑定关系参数错误",
|
121
|
+
9001033 => "门店ID不合法",
|
122
|
+
9001034 => "设备备注信息过长",
|
123
|
+
9001035 => "设备申请参数不合法",
|
124
|
+
9001036 => "查询起始值begin不合法"
|
87
125
|
}unless defined?(GLOBAL_CODES)
|
88
126
|
|
89
127
|
end
|
@@ -14,8 +14,11 @@ module WeixinAuthorize
|
|
14
14
|
|
15
15
|
def refresh_token
|
16
16
|
super
|
17
|
-
weixin_redis.hmset(
|
18
|
-
|
17
|
+
weixin_redis.hmset(
|
18
|
+
client.redis_key, "access_token",
|
19
|
+
client.access_token, "expired_at",
|
20
|
+
client.expired_at
|
21
|
+
)
|
19
22
|
weixin_redis.expireat(client.redis_key, client.expired_at.to_i-10) # 提前10秒超时
|
20
23
|
end
|
21
24
|
|
data/spec/api/custom_spec.rb
CHANGED
@@ -42,17 +42,26 @@ describe WeixinAuthorize::Api::Custom do
|
|
42
42
|
|
43
43
|
it "#send_video_custom" do
|
44
44
|
pending("The test must have a media_id")
|
45
|
-
this_should_not_get_executed
|
46
45
|
end
|
47
46
|
|
48
47
|
it "#send_music_custom" do
|
49
48
|
pending("The test must have a media_id")
|
50
|
-
this_should_not_get_executed
|
51
49
|
end
|
52
50
|
|
53
51
|
it "#send_voice_custom" do
|
54
52
|
pending("The test must have a media_id")
|
55
|
-
|
53
|
+
end
|
54
|
+
|
55
|
+
it "#get_custom_msg_record" do
|
56
|
+
option = {pageindex: 1, pagesize: 10}
|
57
|
+
response = $client.get_custom_msg_record(Time.now - 10.days, Time.now, option)
|
58
|
+
expect(response.code).to eq(WeixinAuthorize::OK_CODE)
|
59
|
+
expect(response.result.keys).to eq(["recordlist", "retcode"])
|
60
|
+
end
|
61
|
+
|
62
|
+
it "#create_kf_session" do
|
63
|
+
response = $client.create_kf_session("test1@test", ENV["APPID"], "test kfsession")
|
64
|
+
expect(response.code).to eq(WeixinAuthorize::OK_CODE)
|
56
65
|
end
|
57
66
|
|
58
67
|
end
|
data/spec/api/groups_spec.rb
CHANGED
@@ -8,18 +8,35 @@ describe WeixinAuthorize::Api::Groups do
|
|
8
8
|
"test group_name_2"
|
9
9
|
end
|
10
10
|
|
11
|
+
let(:groups) do
|
12
|
+
$client.groups
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:last_group_id) do
|
16
|
+
groups.result["groups"][-1]["id"]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "#delete all group step by step" do
|
20
|
+
group_ids = groups.result["groups"].collect{|group|group["id"]}
|
21
|
+
group_ids.each do |group_id|
|
22
|
+
res = $client.delete_group(group_id)
|
23
|
+
if res.code.to_s != "45009"
|
24
|
+
expect(res.code).to eq(WeixinAuthorize::OK_CODE)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
11
29
|
it "create a group" do
|
12
30
|
response = $client.create_group(group_name)
|
13
31
|
if response.code == WeixinAuthorize::OK_CODE
|
14
32
|
expect(response.result["group"]["name"]).to eq(group_name)
|
15
33
|
else
|
16
34
|
expect(response.code).to eq(-1)
|
17
|
-
puts "
|
35
|
+
puts "WEIXIN says: system error"
|
18
36
|
end
|
19
37
|
end
|
20
38
|
|
21
39
|
it "get groups" do
|
22
|
-
groups = $client.groups
|
23
40
|
expect(groups.result["groups"][-1]["name"]).to eq(group_name)
|
24
41
|
end
|
25
42
|
|
@@ -32,7 +49,7 @@ describe WeixinAuthorize::Api::Groups do
|
|
32
49
|
response = $client.create_group(group_name)
|
33
50
|
if response.code != WeixinAuthorize::OK_CODE
|
34
51
|
expect(response.code).to eq(-1)
|
35
|
-
puts "
|
52
|
+
puts "WEIXIN says: system error"
|
36
53
|
else
|
37
54
|
expect(response.result["group"]["name"]).to eq(group_name)
|
38
55
|
response = $client.update_group_name(response.result["group"]["id"], group_name_2)
|
@@ -43,12 +60,15 @@ describe WeixinAuthorize::Api::Groups do
|
|
43
60
|
end
|
44
61
|
|
45
62
|
it "#update_group_for_openid" do
|
46
|
-
groups = $client.groups
|
47
|
-
last_group_id = groups.result["groups"][-1]["id"]
|
48
63
|
$client.update_group_for_openid(ENV["OPENID"], last_group_id)
|
49
64
|
group = $client.get_group_for(ENV["OPENID"])
|
50
65
|
expect(group.result["groupid"]).to eq(last_group_id)
|
51
66
|
$client.update_group_for_openid(ENV["OPENID"], 0)
|
52
67
|
end
|
53
68
|
|
69
|
+
it "#batch update group for openids" do
|
70
|
+
res = $client.batch_update_group_for_openids([ENV["OPENID"]], last_group_id)
|
71
|
+
expect(res.code).to eq(WeixinAuthorize::OK_CODE)
|
72
|
+
end
|
73
|
+
|
54
74
|
end
|
data/spec/api/media_spec.rb
CHANGED
@@ -17,13 +17,25 @@ describe WeixinAuthorize::Api::Media do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
let(:remote_png_path) do
|
20
|
-
"https://ruby-china-files.b0.upaiyun.com/
|
20
|
+
"https://ruby-china-files.b0.upaiyun.com/photo/5982eaaa64f467d9dbda03ad4f40ea27.png"
|
21
21
|
end
|
22
22
|
|
23
23
|
let(:remote_jpg_path) do
|
24
24
|
"http://g.hiphotos.baidu.com/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=ce55457e4334970a537e187df4a3baad/03087bf40ad162d99455ef4d13dfa9ec8b13632762d0ed14.jpg"
|
25
25
|
end
|
26
26
|
|
27
|
+
it "can upload a jpg image and get url" do
|
28
|
+
response = $client.upload_image(image_jpg_file)
|
29
|
+
expect(response.code).to eq(WeixinAuthorize::OK_CODE)
|
30
|
+
expect(response.result.keys).to eq(["url"])
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can upload a png image and get url" do
|
34
|
+
response = $client.upload_image(remote_png_path)
|
35
|
+
expect(response.code).to eq(WeixinAuthorize::OK_CODE)
|
36
|
+
expect(response.result.keys).to eq(["url"])
|
37
|
+
end
|
38
|
+
|
27
39
|
it "can upload a jpg File image" do
|
28
40
|
response = $client.upload_media(image_jpg_file, "image")
|
29
41
|
expect(response.code).to eq(WeixinAuthorize::OK_CODE)
|
data/spec/spec_helper.rb
CHANGED
@@ -15,7 +15,6 @@
|
|
15
15
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
16
16
|
require "rspec"
|
17
17
|
require "weixin_authorize"
|
18
|
-
require 'yajl/json_gem'
|
19
18
|
require "redis"
|
20
19
|
require "redis-namespace"
|
21
20
|
|
@@ -25,17 +24,17 @@ require "codeclimate-test-reporter"
|
|
25
24
|
|
26
25
|
require "pry-rails"
|
27
26
|
|
28
|
-
Coveralls.wear!
|
27
|
+
# Coveralls.wear!
|
29
28
|
|
30
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
31
|
-
|
32
|
-
|
33
|
-
]
|
29
|
+
# SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
30
|
+
# SimpleCov::Formatter::HTMLFormatter,
|
31
|
+
# Coveralls::SimpleCov::Formatter
|
32
|
+
# ]
|
34
33
|
|
35
|
-
SimpleCov.start
|
34
|
+
# SimpleCov.start
|
36
35
|
|
37
|
-
ENV['CODECLIMATE_REPO_TOKEN'] = "c91fecbbd9e414e7cc3ad7a7d99207145de0ac65a3368de09e8c19295343d399"
|
38
|
-
CodeClimate::TestReporter.start
|
36
|
+
# ENV['CODECLIMATE_REPO_TOKEN'] = "c91fecbbd9e414e7cc3ad7a7d99207145de0ac65a3368de09e8c19295343d399"
|
37
|
+
# CodeClimate::TestReporter.start
|
39
38
|
|
40
39
|
# If you want test, change your weixin test profile
|
41
40
|
ENV["APPID"]="wx986f04063d341d04"
|
data/weixin_authorize.gemspec
CHANGED
@@ -26,9 +26,23 @@ Gem::Specification.new do |spec|
|
|
26
26
|
|
27
27
|
# A streaming JSON parsing and encoding library for Ruby (C bindings to yajl)
|
28
28
|
# https://github.com/brianmario/yajl-ruby
|
29
|
-
|
29
|
+
# yajl-ruby 不支持 jruby
|
30
|
+
if RUBY_PLATFORM == 'java'
|
31
|
+
spec.add_dependency "json"
|
32
|
+
else
|
33
|
+
spec.add_dependency "yajl-ruby", ">= 1.2.0"
|
34
|
+
end
|
30
35
|
|
31
36
|
spec.add_development_dependency "bundler"
|
32
37
|
spec.add_development_dependency "rake"
|
38
|
+
spec.add_development_dependency "rspec"
|
39
|
+
spec.add_development_dependency "redis-namespace"
|
40
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
41
|
+
spec.add_development_dependency "simplecov", "~> 0.10.0"
|
42
|
+
spec.add_development_dependency 'coveralls', '~> 0.8.2'
|
43
|
+
spec.add_development_dependency 'pry-rails'
|
44
|
+
if RUBY_PLATFORM != 'java'
|
45
|
+
spec.add_development_dependency 'pry-byebug'
|
46
|
+
end
|
33
47
|
|
34
48
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: weixin_authorize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.
|
4
|
+
version: 1.6.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- lanrion
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -108,6 +108,104 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: redis-namespace
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: codeclimate-test-reporter
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: simplecov
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 0.10.0
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 0.10.0
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: coveralls
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 0.8.2
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: 0.8.2
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: pry-rails
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: pry-byebug
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
111
209
|
description: weixin api authorize access_token
|
112
210
|
email:
|
113
211
|
- huaitao-deng@foxmail.com
|
@@ -201,3 +299,4 @@ test_files:
|
|
201
299
|
- spec/api/template_spec.rb
|
202
300
|
- spec/api/user_spec.rb
|
203
301
|
- spec/spec_helper.rb
|
302
|
+
has_rdoc:
|