Commit e9002507 by lanrion

Merge pull request #15 from lanrion/weixin-error-massage-handler-13

Weixin error massage handler #13
parents 0890bd17 5e179462
...@@ -2,7 +2,8 @@ language: ruby ...@@ -2,7 +2,8 @@ language: ruby
bundler_args: --without development bundler_args: --without development
rvm: rvm:
- 2.0.0 - 2.0.0
script: bundle exec rspec spec script:
- bundle exec rspec spec
services: services:
- redis - redis
addons: addons:
......
...@@ -6,11 +6,19 @@ group :test, :development do ...@@ -6,11 +6,19 @@ group :test, :development do
end end
group :test do group :test do
gem "rake", "~> 0.9.6"
gem 'simplecov', '~> 0.7.1', :require => false gem 'simplecov', '~> 0.7.1', :require => false
gem "codeclimate-test-reporter", require: nil gem "codeclimate-test-reporter", require: nil
gem 'coveralls', require: false gem 'coveralls', require: false
end end
group :development do
# For debugger
gem "pry-rails", "~> 0.3.2"
gem "pry-debugger", "~> 0.2.2"
end
# Specify your gem's dependencies in weixin_authorize.gemspec # Specify your gem's dependencies in weixin_authorize.gemspec
gemspec gemspec
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
[![Gem Version](https://badge.fury.io/rb/weixin_authorize.png)](http://badge.fury.io/rb/weixin_authorize) [![Gem Version](https://badge.fury.io/rb/weixin_authorize.png)](http://badge.fury.io/rb/weixin_authorize)
[![Build Status](https://secure.travis-ci.org/lanrion/weixin_authorize.png?branch=master)](http://travis-ci.org/lanrion/weixin_authorize) [![Build Status](https://secure.travis-ci.org/lanrion/weixin_authorize.png?branch=master)](http://travis-ci.org/lanrion/weixin_authorize)
[![Code Climate](https://codeclimate.com/github/lanrion/weixin_authorize.png)](https://codeclimate.com/github/lanrion/weixin_authorize) [![Code Climate](https://codeclimate.com/github/lanrion/weixin_authorize.png)](https://codeclimate.com/github/lanrion/weixin_authorize)
[![Coverage Status](https://coveralls.io/repos/lanrion/weixin_authorize/badge.png)](https://coveralls.io/r/lanrion/weixin_authorize)
Support using [Redis](http://redis.io) to store `access_token` Support using [Redis](http://redis.io) to store `access_token`
......
require "rest-client" require "rest-client"
require "multi_json" require "multi_json"
require "weixin_authorize/config" require "weixin_authorize/config"
require "weixin_authorize/adapter" require "weixin_authorize/error_handler"
require "weixin_authorize/api" require "weixin_authorize/api"
require "weixin_authorize/client" require "weixin_authorize/client"
module WeixinAuthorize module WeixinAuthorize
# Storage
autoload(:Storage, "weixin_authorize/adapter/storage")
autoload(:ClientStorage, "weixin_authorize/adapter/client_storage")
autoload(:RedisStorage, "weixin_authorize/adapter/redis_storage")
OK_MSG = "ok".freeze
OK_CODE = 0.freeze
class << self class << self
def http_get_without_token(url, headers={}, endpoint="plain") def http_get_without_token(url, headers={}, endpoint="plain")
...@@ -22,7 +30,10 @@ module WeixinAuthorize ...@@ -22,7 +30,10 @@ module WeixinAuthorize
# return hash # return hash
def load_json(string) def load_json(string)
JSON.parse(string) result_hash = JSON.parse(string)
code = result_hash.delete("errcode")
en_msg = result_hash.delete("errmsg")
ResultHandler.new(code, en_msg, result_hash)
end end
def endpoint_url(endpoint, url) def endpoint_url(endpoint, url)
......
require "weixin_authorize/adapter/storage"
require "weixin_authorize/adapter/client_storage"
require "weixin_authorize/adapter/redis_storage"
...@@ -11,7 +11,7 @@ module WeixinAuthorize ...@@ -11,7 +11,7 @@ module WeixinAuthorize
client.expired_at <= Time.now.to_i client.expired_at <= Time.now.to_i
end end
def authenticate def refresh_token
super super
end end
......
...@@ -12,10 +12,10 @@ module WeixinAuthorize ...@@ -12,10 +12,10 @@ module WeixinAuthorize
weixin_redis.hvals(client.redis_key).empty? weixin_redis.hvals(client.redis_key).empty?
end end
def authenticate def refresh_token
super super
weixin_redis.hmset(client.redis_key, :access_token, client.access_token, weixin_redis.hmset(client.redis_key, :access_token, client.access_token,
:expired_at, client.expired_at) :expired_at, client.expired_at)
weixin_redis.expireat(client.redis_key, client.expired_at.to_i-10) # 提前10秒超时 weixin_redis.expireat(client.redis_key, client.expired_at.to_i-10) # 提前10秒超时
end end
......
...@@ -18,29 +18,34 @@ module WeixinAuthorize ...@@ -18,29 +18,34 @@ module WeixinAuthorize
end end
def valid? def valid?
valid_result = http_get_access_token authenticate["valid"]
if valid_result.keys.include?("access_token")
set_access_token_for_client(valid_result)
return true
end
false
end end
def token_expired? def authenticate
raise NotImplementedError, "Subclasses must implement a token_expired? method" auth_result = http_get_access_token
auth = false
if auth_result.is_ok?
set_access_token_for_client(auth_result.result)
auth = true
end
{"valid" => auth, "handler" => auth_result}
end end
def authenticate def refresh_token
raise "APPID or APPSECRET is invalid" if !valid? handle_valid_exception
set_access_token_for_client set_access_token_for_client
end end
def access_token def access_token
authenticate if token_expired? refresh_token if token_expired?
end
def token_expired?
raise NotImplementedError, "Subclasses must implement a token_expired? method"
end end
def set_access_token_for_client(access_token_infos=nil) def set_access_token_for_client(access_token_infos=nil)
token_infos = access_token_infos || http_get_access_token token_infos = access_token_infos || http_get_access_token.result
client.access_token = token_infos["access_token"] client.access_token = token_infos["access_token"]
client.expired_at = Time.now.to_i + token_infos["expires_in"].to_i client.expired_at = Time.now.to_i + token_infos["expires_in"].to_i
end end
...@@ -53,6 +58,16 @@ module WeixinAuthorize ...@@ -53,6 +58,16 @@ module WeixinAuthorize
{grant_type: "client_credential", appid: client.app_id, secret: client.app_secret} {grant_type: "client_credential", appid: client.app_id, secret: client.app_secret}
end end
private
def handle_valid_exception
auth_result = authenticate
if !auth_result["valid"]
result_handler = auth_result["handler"]
raise ValidAccessTokenException, "#{result_handler.code}:#{result_handler.en_msg}(#{result_handler.cn_msg})"
end
end
end end
end end
require "weixin_authorize/error_handler/global_code.rb"
require "weixin_authorize/error_handler/result_handler"
require "weixin_authorize/error_handler/exceptions"
# encoding: utf-8
module WeixinAuthorize
class ValidAccessTokenException < RuntimeError
end
end
# encoding: utf-8
module WeixinAuthorize
GLOBAL_CODES = {
-1 => "系统繁忙",
0 => "请求成功",
40001 => "获取access_token时AppSecret错误,或者access_token无效",
40002 => "不合法的凭证类型",
40003 => "不合法的OpenID",
40004 => "不合法的媒体文件类型",
40005 => "不合法的文件类型",
40006 => "不合法的文件大小",
40007 => "不合法的媒体文件id",
40008 => "不合法的消息类型",
40009 => "不合法的图片文件大小",
40010 => "不合法的语音文件大小",
40011 => "不合法的视频文件大小",
40012 => "不合法的缩略图文件大小",
40013 => "不合法的APPID",
40014 => "不合法的access_token",
40015 => "不合法的菜单类型",
40016 => "不合法的按钮个数",
40017 => "不合法的按钮个数",
40018 => "不合法的按钮名字长度",
40019 => "不合法的按钮KEY长度",
40020 => "不合法的按钮URL长度",
40021 => "不合法的菜单版本号",
40022 => "不合法的子菜单级数",
40023 => "不合法的子菜单按钮个数",
40024 => "不合法的子菜单按钮类型",
40025 => "不合法的子菜单按钮名字长度",
40026 => "不合法的子菜单按钮KEY长度",
40027 => "不合法的子菜单按钮URL长度",
40028 => "不合法的自定义菜单使用用户",
40029 => "不合法的oauth_code",
40030 => "不合法的refresh_token",
40031 => "不合法的openid列表",
40032 => "不合法的openid列表长度",
40033 => "不合法的请求字符,不能包含xxxx格式的字符",
40035 => "不合法的参数",
40038 => "不合法的请求格式",
40039 => "不合法的URL长度",
40050 => "不合法的分组id",
40051 => "分组名字不合法",
41001 => "缺少access_token参数",
41002 => "缺少appid参数",
41003 => "缺少refresh_token参数",
41004 => "缺少secret参数",
41005 => "缺少多媒体文件数据",
41006 => "缺少media_id参数",
41007 => "缺少子菜单数据",
41008 => "缺少oauth code",
41009 => "缺少openid",
42001 => "access_token超时",
42002 => "refresh_token超时",
42003 => "oauth_code超时",
43001 => "需要GET请求",
43002 => "需要POST请求",
43003 => "需要HTTPS请求",
43004 => "需要接收者关注",
43005 => "需要好友关系",
44001 => "多媒体文件为空",
44002 => "POST的数据包为空",
44003 => "图文消息内容为空",
44004 => "文本消息内容为空",
45001 => "多媒体文件大小超过限制",
45002 => "消息内容超过限制",
45003 => "标题字段超过限制",
45004 => "描述字段超过限制",
45005 => "链接字段超过限制",
45006 => "图片链接字段超过限制",
45007 => "语音播放时间超过限制",
45008 => "图文消息超过限制",
45009 => "接口调用超过限制",
45010 => "创建菜单个数超过限制",
45015 => "回复时间超过限制",
45016 => "系统分组,不允许修改",
45017 => "分组名字过长",
45018 => "分组数量超过上限",
46001 => "不存在媒体数据",
46002 => "不存在的菜单版本",
46003 => "不存在的菜单数据",
46004 => "不存在的用户",
47001 => "解析JSON/XML内容错误",
48001 => "api功能未授权",
50001 => "用户未授权该api"
}unless defined?(GLOBAL_CODES)
end
# encoding: utf-8
module WeixinAuthorize
class ResultHandler
attr_accessor :code, :cn_msg, :en_msg, :result
def initialize(code, en_msg, result={})
@code = code || 0
@en_msg = en_msg || "ok"
@cn_msg = GLOBAL_CODES[@code.to_i]
@result = package_result(result)
end
# This method is to valid the current request if is true or is false
def is_ok?
code == OK_CODE
end
# e.g.:
# 45009: api freq out of limit(接口调用超过限制)
def full_message
"#{code}: #{en_msg}(#{cn_msg})."
end
def full_error_message
full_message if !is_ok?
end
private
# if define Rails constant
# result = WeixinAuthorize::ResultHandler.new("0", "success", {:ok => "true"})
# result.result["ok"] #=> true
# result.result[:ok] #=> true
# result.result['ok'] #=> true
def package_result(result)
if defined?(Rails)
ActiveSupport::HashWithIndifferentAccess.new(result)
else
result
end
end
end
end
...@@ -15,7 +15,7 @@ describe WeixinAuthorize::Api::Custom do ...@@ -15,7 +15,7 @@ describe WeixinAuthorize::Api::Custom do
it "#send_text_custom" do it "#send_text_custom" do
response = $client.send_text_custom(ENV["OPENID"], text_message) response = $client.send_text_custom(ENV["OPENID"], text_message)
expect(response["errcode"]).to eq(0) expect(response.code).to eq(WeixinAuthorize::OK_CODE)
end end
it "#send_news_custom" do it "#send_news_custom" do
...@@ -32,14 +32,14 @@ describe WeixinAuthorize::Api::Custom do ...@@ -32,14 +32,14 @@ describe WeixinAuthorize::Api::Custom do
"picurl"=> "http://www.baidu.com/img/bdlogo.gif" "picurl"=> "http://www.baidu.com/img/bdlogo.gif"
}] }]
response = $client.send_news_custom(ENV["OPENID"], articles) response = $client.send_news_custom(ENV["OPENID"], articles)
expect(response["errcode"]).to eq(0) expect(response.code).to eq(WeixinAuthorize::OK_CODE)
end end
it "#send_image_custom" do it "#send_image_custom" do
image = $client.upload_media(image_file, "image") image = $client.upload_media(image_file, "image")
media_id = image["media_id"] media_id = image.result["media_id"]
response = $client.send_image_custom(ENV["OPENID"], media_id) response = $client.send_image_custom(ENV["OPENID"], media_id)
expect(response["errcode"]).to eq(0) expect(response.code).to eq(WeixinAuthorize::OK_CODE)
end end
it "#send_video_custom" do it "#send_video_custom" do
......
...@@ -11,44 +11,44 @@ describe WeixinAuthorize::Api::Groups do ...@@ -11,44 +11,44 @@ describe WeixinAuthorize::Api::Groups do
it "create a group" do it "create a group" do
response = $client.create_group(group_name) response = $client.create_group(group_name)
if !response["errcode"].nil? if response.code == WeixinAuthorize::OK_CODE
expect(response.keys).to eq(["errcode", "errmsg"])
puts "SB WEIXIN says: system error"
else
expect(response["group"]["name"]).to eq(group_name) expect(response["group"]["name"]).to eq(group_name)
else
expect(response.code).to eq(-1)
puts "SB WEIXIN says: system error"
end end
end end
it "get groups" do it "get groups" do
groups = $client.groups groups = $client.groups
expect(groups["groups"][-1]["name"]).to eq(group_name) expect(groups.result["groups"][-1]["name"]).to eq(group_name)
end end
it "#get_group_for ENV['OPENID']" do it "#get_group_for ENV['OPENID']" do
group = $client.get_group_for(ENV["OPENID"]) group = $client.get_group_for(ENV["OPENID"])
expect(group.keys).to eq(["groupid"]) expect(group.result.keys).to eq(["groupid"])
end end
it "#update_group_name" do it "#update_group_name" do
response = $client.create_group(group_name) response = $client.create_group(group_name)
if !response["errcode"].nil? if response.code != WeixinAuthorize::OK_CODE
expect(response.keys).to eq(["errcode", "errmsg"]) expect(response.code).to eq(-1)
puts "SB WEIXIN says: system error" puts "SB WEIXIN says: system error"
else else
expect(response["group"]["name"]).to eq(group_name) expect(response.result["group"]["name"]).to eq(group_name)
response = $client.update_group_name(response["group"]["id"], group_name_2) response = $client.update_group_name(response.result["group"]["id"], group_name_2)
expect(response["errcode"]).to eq(0) expect(response.code).to eq(WeixinAuthorize::OK_CODE)
groups = $client.groups groups = $client.groups
expect(groups["groups"][-1]["name"]).to eq(group_name_2) expect(groups.result["groups"][-1]["name"]).to eq(group_name_2)
end end
end end
it "#update_group_for_openid" do it "#update_group_for_openid" do
groups = $client.groups groups = $client.groups
last_group_id = groups["groups"][-1]["id"] last_group_id = groups.result["groups"][-1]["id"]
$client.update_group_for_openid(ENV["OPENID"], last_group_id) $client.update_group_for_openid(ENV["OPENID"], last_group_id)
group = $client.get_group_for(ENV["OPENID"]) group = $client.get_group_for(ENV["OPENID"])
expect(group["groupid"]).to eq(last_group_id) expect(group.result["groupid"]).to eq(last_group_id)
$client.update_group_for_openid(ENV["OPENID"], 0) $client.update_group_for_openid(ENV["OPENID"], 0)
end end
......
...@@ -12,12 +12,13 @@ describe WeixinAuthorize::Api::Media do ...@@ -12,12 +12,13 @@ describe WeixinAuthorize::Api::Media do
it "can upload a image" do it "can upload a image" do
response = $client.upload_media(image_file, "image") response = $client.upload_media(image_file, "image")
expect(response.keys).to eq(["type", "media_id", "created_at"]) expect(response.code).to eq(WeixinAuthorize::OK_CODE)
expect(response.result.keys).to eq(["type", "media_id", "created_at"])
end end
it "#download_media_url return a String url" do it "#download_media_url return a String url" do
image = $client.upload_media(image_file, "image") image = $client.upload_media(image_file, "image")
media_id = image["media_id"] media_id = image.result["media_id"]
response = $client.download_media_url(media_id) response = $client.download_media_url(media_id)
expect(response.class).to eq(String) expect(response.class).to eq(String)
end end
......
...@@ -6,16 +6,23 @@ describe WeixinAuthorize::Api::Menu do ...@@ -6,16 +6,23 @@ describe WeixinAuthorize::Api::Menu do
it "can create a menu" do it "can create a menu" do
menu = '{"button":[{"type":"click","name":"今日歌曲","key":"V1001_TODAY_MUSIC"},{"type":"click","name":"歌手简介","key":"V1001_TODAY_SINGER"},{"name":"菜单","sub_button":[{"type":"view","name":"搜索","url":"http://www.soso.com/"},{"type":"view","name":"视频","url":"http://v.qq.com/"},{"type":"click","name":"赞一下我们","key":"V1001_GOOD"}]}]}' menu = '{"button":[{"type":"click","name":"今日歌曲","key":"V1001_TODAY_MUSIC"},{"type":"click","name":"歌手简介","key":"V1001_TODAY_SINGER"},{"name":"菜单","sub_button":[{"type":"view","name":"搜索","url":"http://www.soso.com/"},{"type":"view","name":"视频","url":"http://v.qq.com/"},{"type":"click","name":"赞一下我们","key":"V1001_GOOD"}]}]}'
response = $client.create_menu(MultiJson.load(menu)) # or Json string response = $client.create_menu(MultiJson.load(menu)) # or Json string
expect(response["errcode"]).to eq(0) expect(response.code).to eq(WeixinAuthorize::OK_CODE)
end
it "can't create a menu if invalid button size" do
menu = '{"button":[]}'
response = $client.create_menu(menu)
expect(response.code).not_to eq(WeixinAuthorize::OK_CODE)
end end
it "can get a weixin Menu info" do it "can get a weixin Menu info" do
menu_info = $client.menu menu_info = $client.menu
expect(menu_info.keys[0]).to eq("menu") expect(menu_info.result.keys[0]).to eq("menu")
expect(menu_info.code).to eq(WeixinAuthorize::OK_CODE)
end end
it "can delete weixin Menu" do it "can delete weixin Menu" do
response = $client.delete_menu response = $client.delete_menu
expect(response["errcode"]).to eq(0) expect(response.code).to eq(WeixinAuthorize::OK_CODE)
end end
end end
...@@ -4,13 +4,15 @@ describe WeixinAuthorize::Api::Qrcode do ...@@ -4,13 +4,15 @@ describe WeixinAuthorize::Api::Qrcode do
it "#create_qr_scene" do it "#create_qr_scene" do
response = $client.create_qr_scene("123") response = $client.create_qr_scene("123")
expect(response.keys).to eq(["ticket", "expire_seconds"]) expect(response.code).to eq(WeixinAuthorize::OK_CODE)
expect(response["expire_seconds"]).to eq(1800) expect(response.result.keys).to eq(["ticket", "expire_seconds"])
expect(response.result["expire_seconds"]).to eq(1800)
end end
it "#create_qr_limit_scene" do it "#create_qr_limit_scene" do
response = $client.create_qr_limit_scene("1234") response = $client.create_qr_limit_scene("1234")
expect(response.keys).to eq(["ticket"]) expect(response.code).to eq(WeixinAuthorize::OK_CODE)
expect(response.result.keys).to eq(["ticket"])
end end
end end
...@@ -3,18 +3,21 @@ require "spec_helper" ...@@ -3,18 +3,21 @@ require "spec_helper"
describe WeixinAuthorize::Api::User do describe WeixinAuthorize::Api::User do
it "can get a weixin User info" do it "can get a weixin User info" do
user_info = $client.user(ENV["OPENID"]) user_info = $client.user(ENV["OPENID"])
expect(user_info["openid"]).to eq(ENV["OPENID"]) expect(user_info.code).to eq(WeixinAuthorize::OK_CODE)
expect(user_info.result["openid"]).to eq(ENV["OPENID"])
end end
it "can get followers infos" do it "can get followers infos" do
valid_info = $client.is_valid? valid_info = $client.is_valid?
expect(valid_info).to eq(true) expect(valid_info).to eq(true)
followers = $client.followers followers = $client.followers
expect(followers.keys).to eq(["total", "count", "data", "next_openid"]) expect(followers.code).to eq(WeixinAuthorize::OK_CODE)
expect(followers.result.keys).to eq(["total", "count", "data", "next_openid"])
valid_info = $client.is_valid? valid_info = $client.is_valid?
expect(valid_info).to eq(true) expect(valid_info).to eq(true)
followers = $client.followers followers = $client.followers
expect(followers.keys).to eq(["total", "count", "data", "next_openid"]) expect(followers.code).to eq(WeixinAuthorize::OK_CODE)
expect(followers.result.keys).to eq(["total", "count", "data", "next_openid"])
end end
end end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment