Commit 9432c4cb by lanrion

Merge pull request #11 from lanrion/fixed-#10-refactor-with-Adapter

Fixed #10 refactor with adapter
parents 54121afb 36a4c5ec
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/api" require "weixin_authorize/api"
require "weixin_authorize/client" require "weixin_authorize/client"
module WeixinAuthorize module WeixinAuthorize
class << self
def http_get_without_token(url, headers={}, endpoint="plain")
get_api_url = endpoint_url(endpoint, url)
json_parse(RestClient.get(get_api_url, :params => headers))
end
def http_post_without_token(url, payload={}, headers={}, endpoint="plain")
post_api_url = endpoint_url(endpoint, url)
payload = MultiJson.dump(payload) if endpoint == "plain" # to json
json_parse(RestClient.post(post_api_url, payload, headers))
end
# return hash
def json_parse(json)
JSON.parse(json)
end
def endpoint_url(endpoint, url)
send("#{endpoint}_endpoint") + url
end
def plain_endpoint
"https://api.weixin.qq.com/cgi-bin"
end
def file_endpoint
"http://file.api.weixin.qq.com/cgi-bin"
end
def mp_endpoint
"https://mp.weixin.qq.com/cgi-bin"
end
end
end end
require "weixin_authorize/adapter/storage"
require "weixin_authorize/adapter/client_storage"
require "weixin_authorize/adapter/redis_storage"
# encoding: utf-8
module WeixinAuthorize
class ClientStorage < Storage
def valid?
super
end
def token_expired?
# 如果当前token过期时间小于现在的时间,则重新获取一次
client.expired_at <= Time.now.to_i
end
def authenticate
super
end
def access_token
super
client.access_token
end
end
end
# encoding: utf-8
module WeixinAuthorize
class RedisStorage < Storage
def valid?
weixin_redis.del(client.redis_key)
super
end
def token_expired?
weixin_redis.hvals(client.redis_key).empty?
end
def authenticate
super
weixin_redis.hmset(client.redis_key, :access_token, client.access_token,
:expired_at, client.expired_at)
weixin_redis.expireat(client.redis_key, client.expired_at.to_i-10) # 提前10秒超时
end
def access_token
super
client.access_token = weixin_redis.hget(client.redis_key, "access_token")
client.expired_at = weixin_redis.hget(client.redis_key, "expired_at")
client.access_token
end
def weixin_redis
WeixinAuthorize.config.redis
end
end
end
# encoding: utf-8
module WeixinAuthorize
class Storage
attr_accessor :client
def initialize(client)
@client = client
end
def self.init_with(client)
if WeixinAuthorize.config.redis.nil?
ClientStorage.new(client)
else
RedisStorage.new(client)
end
end
def valid?
valid_result = http_get_access_token
if valid_result.keys.include?("access_token")
set_access_token_for_client(valid_result)
return true
end
false
end
def token_expired?
raise NotImplementedError, "Subclasses must implement a token_expired? method"
end
def authenticate
raise "APPID or APPSECRET is invalid" if !valid?
set_access_token_for_client
end
def access_token
authenticate if token_expired?
end
def set_access_token_for_client(access_token_infos=nil)
token_infos = access_token_infos || http_get_access_token
client.access_token = token_infos["access_token"]
client.expired_at = Time.now.to_i + token_infos["expires_in"].to_i
end
def http_get_access_token
WeixinAuthorize.http_get_without_token("/token", authenticate_headers)
end
def authenticate_headers
{grant_type: "client_credential", appid: client.app_id, secret: client.app_secret}
end
end
end
...@@ -15,7 +15,7 @@ module WeixinAuthorize ...@@ -15,7 +15,7 @@ module WeixinAuthorize
# 目前仅仅把下载链接返回给第三方开发者,由第三方开发者处理下载 # 目前仅仅把下载链接返回给第三方开发者,由第三方开发者处理下载
def download_media_url(media_id) def download_media_url(media_id)
download_media_url = file_endpoint + "#{media_base_url}/get" download_media_url = WeixinAuthorize.endpoint_url("file", "#{media_base_url}/get")
params = URI.encode_www_form("access_token" => get_access_token, params = URI.encode_www_form("access_token" => get_access_token,
"media_id" => media_id) "media_id" => media_id)
download_media_url += "?#{params}" download_media_url += "?#{params}"
......
...@@ -6,7 +6,7 @@ module WeixinAuthorize ...@@ -6,7 +6,7 @@ module WeixinAuthorize
# 临时二维码 # 临时二维码
def create_qr_scene(scene_id, expire_seconds=1800) def create_qr_scene(scene_id, expire_seconds=1800)
post_url = "#{qrcode_base_url}/create" post_url = "#{qrcode_base_url}/create"
qrcode_infos = {action_name: "QR_SCENE", expire_seconds: expire_seconds} qrcode_infos = {action_name: "QR_SCENE", expire_seconds: expire_seconds}
qrcode_infos = qrcode_infos.merge(action_info(scene_id)) qrcode_infos = qrcode_infos.merge(action_info(scene_id))
http_post(post_url, qrcode_infos) http_post(post_url, qrcode_infos)
...@@ -14,7 +14,7 @@ module WeixinAuthorize ...@@ -14,7 +14,7 @@ module WeixinAuthorize
# 永久二维码 # 永久二维码
def create_qr_limit_scene(scene_id) def create_qr_limit_scene(scene_id)
post_url = "#{qrcode_base_url}/create" post_url = "#{qrcode_base_url}/create"
qrcode_infos = {action_name: "QR_LIMIT_SCENE"} qrcode_infos = {action_name: "QR_LIMIT_SCENE"}
qrcode_infos = qrcode_infos.merge(action_info(scene_id)) qrcode_infos = qrcode_infos.merge(action_info(scene_id))
http_post(post_url, qrcode_infos) http_post(post_url, qrcode_infos)
...@@ -22,7 +22,7 @@ module WeixinAuthorize ...@@ -22,7 +22,7 @@ module WeixinAuthorize
# 通过ticket换取二维码, 直接访问即可显示! # 通过ticket换取二维码, 直接访问即可显示!
def qr_code_url(ticket) def qr_code_url(ticket)
"https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=#{ticket}" WeixinAuthorize.mp_endpoint("/showqrcode?ticket=#{ticket}")
end end
private private
......
...@@ -13,117 +13,40 @@ module WeixinAuthorize ...@@ -13,117 +13,40 @@ module WeixinAuthorize
attr_accessor :app_id, :app_secret, :expired_at # Time.now + expires_in attr_accessor :app_id, :app_secret, :expired_at # Time.now + expires_in
attr_accessor :access_token, :redis_key attr_accessor :access_token, :redis_key
attr_accessor :storage
def initialize(app_id, app_secret, redis_key=nil) def initialize(app_id, app_secret, redis_key=nil)
@app_id = app_id @app_id = app_id
@app_secret = app_secret @app_secret = app_secret
@expired_at = Time.now.to_i @expired_at = Time.now.to_i
@redis_key = security_redis_key((redis_key || "weixin_" + app_id)) @redis_key = security_redis_key((redis_key || "weixin_" + app_id))
@storage = Storage.init_with(self)
end end
# return token # return token
def get_access_token def get_access_token
authenticate if token_expired? @storage.access_token
if !is_weixin_redis_blank?
self.access_token = weixin_redis.hget(redis_key, "access_token")
self.expired_at = weixin_redis.hget(redis_key, "expired_at")
end
@access_token
end end
# 检查appid和app_secret是否有效。 # 检查appid和app_secret是否有效。
def is_valid? def is_valid?
# 重新验证,清除存储在Redis的access_token @storage.valid?
weixin_redis.del(redis_key) if !is_weixin_redis_blank?
valid_result = http_get_access_token
if valid_result.keys.include?("access_token")
set_access_token_for_client(valid_result)
return true
end
false
end
def token_expired?
if is_weixin_redis_blank?
# 如果当前token过期时间小于现在的时间,则重新获取一次
@expired_at <= Time.now.to_i
else
weixin_redis.hvals(redis_key).empty?
end
end end
private private
# authenticate access_token
def authenticate
raise "APPID or APPSECRET is invalid" if !is_valid?
set_access_token_for_client
if !is_weixin_redis_blank?
authenticate_with_redis
end
end
def authenticate_with_redis
weixin_redis.hmset(redis_key, :access_token, access_token, :expired_at, expired_at)
weixin_redis.expireat(redis_key, expired_at.to_i-10) # 提前10秒超时
end
def set_access_token_for_client(access_token_infos=nil)
token_infos = access_token_infos || http_get_access_token
self.access_token = token_infos["access_token"]
self.expired_at = Time.now.to_i + token_infos["expires_in"].to_i
end
def http_get_access_token
hash_infos = http_get_without_token("/token", authenticate_options)
hash_infos
end
def authenticate_options
{grant_type: "client_credential", appid: app_id, secret: app_secret}
end
def access_token_param def access_token_param
{access_token: get_access_token} {access_token: get_access_token}
end end
def http_get_without_token(url, options={}, endpoint="plain") def http_get(url, headers={}, endpoint="plain")
get_api_url = endpoint_url(endpoint) + url headers = headers.merge(access_token_param)
JSON.parse(RestClient.get(get_api_url, :params => options)) WeixinAuthorize.http_get_without_token(url, headers, endpoint)
end
def http_get(url, options={})
options = options.merge(access_token_param)
http_get_without_token(url, options)
end end
# Refactor
def http_post(url, payload={}, headers={}, endpoint="plain") def http_post(url, payload={}, headers={}, endpoint="plain")
post_api_url = endpoint_url(endpoint) + url headers = {:params => access_token_param.merge(headers)}
payload = MultiJson.dump(payload) if endpoint == "plain" # to json WeixinAuthorize.http_post_without_token(url, payload, headers, endpoint)
post_params = {:params => access_token_param.merge(headers)}
JSON.parse(RestClient.post(post_api_url, payload, post_params))
end
def endpoint_url(endpoint)
send("#{endpoint}_endpoint")
end
def plain_endpoint
"https://api.weixin.qq.com/cgi-bin"
end
def file_endpoint
"http://file.api.weixin.qq.com/cgi-bin"
end
def weixin_redis
return nil if WeixinAuthorize.config.nil?
@redis ||= WeixinAuthorize.config.redis
end
def is_weixin_redis_blank?
weixin_redis.nil?
end end
def security_redis_key(key) def security_redis_key(key)
......
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