weixin_rails_middleware 1.2.1 → 1.2.2

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: 4561303d08506a46b5bfe5175b1fb2529e4e7052
4
- data.tar.gz: 4e6aae5db8c81f3ed8ebe0817a1cb2b5e9b662d5
3
+ metadata.gz: 636d0f84432996fd76df3c15716065b775a77379
4
+ data.tar.gz: 6228287ca1e489b6370f95e1a5aa7b5161def9d1
5
5
  SHA512:
6
- metadata.gz: b3f4e2a81e68d03db97d59771a8c95668455d166bb4a512d7fae4bffb2010d5f6fd1f98eef2b576bc90d04d5073e662b07566a54322a168e2d1b2adb30c9bc1d
7
- data.tar.gz: a4b5e171495c7d0524302faed81a58535b58dc130d84e07d9c2c0590cc21889867f83f89803fcdae425a86a5eb0c7ef09df7a44fc41046ceca0aef7af6c46fa0
6
+ metadata.gz: 5f5e0d4d176122697db34adf00a75e228d820eddea54ca11adc881e7bf5c18f284d9ee8e77c628309776c17dc2db67256f61faf9c449075b22c1eb63ba3e8ce0
7
+ data.tar.gz: 8b462a16a5e24a00ba0d0dd3ee7f890d367bd216b85b847b57ab5697cfbd7d185e9fbe7868a61d52457cda788252b4cf275739108c2c013785aa17edfb09aa53
@@ -1,15 +1,12 @@
1
1
  module WeixinRailsMiddleware
2
2
  class WeixinController < ActionController::Base
3
3
  include ReplyWeixinMessageHelper
4
- include ConfigurationHelpers
5
- include WeixinAuthorizeHelper
6
4
 
7
5
  skip_before_filter :verify_authenticity_token
8
- before_filter :check_weixin_params, only: [:index, :reply]
6
+ before_filter :initialize_adapter, :check_weixin_legality, only: [:index, :reply]
9
7
  before_filter :set_weixin_public_account, :set_weixin_message, only: :reply
10
8
 
11
9
  def index
12
- render text: params[:echostr]
13
10
  end
14
11
 
15
12
  def reply
@@ -17,16 +14,26 @@ module WeixinRailsMiddleware
17
14
 
18
15
  protected
19
16
 
17
+ def initialize_adapter
18
+ @weixin_adapter ||= Adapter::WexinAdapter.init_with(params)
19
+ end
20
+
21
+ def check_weixin_legality
22
+ check_result = @weixin_adapter.check_weixin_legality
23
+ valid = check_result.delete(:valid)
24
+ render check_result if action_name == "index"
25
+ return valid
26
+ end
27
+
20
28
  ## Callback
21
29
  # e.g. will generate +@weixin_public_account+
22
30
  def set_weixin_public_account
23
- return nil if weixin_token_string.present?
24
- @weixin_public_account ||= current_weixin_public_account
31
+ @weixin_public_account ||= @weixin_adapter.current_weixin_public_account
25
32
  end
26
33
 
27
34
  def set_weixin_message
28
- # Get the current_message
29
- @weixin_message ||= current_weixin_message
35
+ # Get the current weixin message
36
+ @weixin_message ||= Message.factory(request.body.read)
30
37
  end
31
38
 
32
39
  end
@@ -7,7 +7,7 @@ WeixinRailsMiddleware.configure do |config|
7
7
  ## Config public_account_class if you SAVE public_account into database ##
8
8
  # Th first configure is fit for your weixin public_account is saved in database.
9
9
  # +public_account_class+ The class name that to save your public_account
10
- # config.public_account_class = ""
10
+ # config.public_account_class = "PublicAccount"
11
11
 
12
12
  ## Here configure is for you DON'T WANT TO SAVE your public account into database ##
13
13
  # Or the other configure is fit for only one weixin public_account
@@ -52,7 +52,7 @@ WeixinRailsMiddleware::WeixinController.class_eval do
52
52
  when "subscribe" # 关注公众账号
53
53
  if @keyword.present?
54
54
  # 扫描带参数二维码事件: 1. 用户未关注时,进行关注后的事件推送
55
- reply_text_message("扫描带参数二维码事件: 1. 用户未关注时,进行关注后的事件推送, keyword: #{@keyword}")
55
+ return reply_text_message("扫描带参数二维码事件: 1. 用户未关注时,进行关注后的事件推送, keyword: #{@keyword}")
56
56
  end
57
57
  reply_text_message("关注公众账号")
58
58
  when "unsubscribe" # 取消关注
@@ -78,7 +78,7 @@ WeixinRailsMiddleware::WeixinController.class_eval do
78
78
  # <Format><![CDATA[Format]]></Format>
79
79
  def response_voice_message(options={})
80
80
  @media_id = @weixin_message.MediaId # 可以调用多媒体文件下载接口拉取数据。
81
- @format = @weixin_message.format
81
+ @format = @weixin_message.Format
82
82
  reply_text_message("回复语音信息: #{@keyword}")
83
83
  end
84
84
 
@@ -91,6 +91,7 @@ WeixinRailsMiddleware::WeixinController.class_eval do
91
91
  reply_text_message("回复视频信息")
92
92
  end
93
93
 
94
+ # @weixin_message 在rails 3时如果调用不存在的方法,会出现错误。rails 4好像没有问题。
94
95
  def set_keyword
95
96
  @keyword = @weixin_message.Content || # 文本消息
96
97
  @weixin_message.EventKey || # 事件推送
@@ -4,7 +4,7 @@ require "weixin_rails_middleware/models/message"
4
4
  require "weixin_rails_middleware/models/reply_message"
5
5
  require "weixin_rails_middleware/helpers/reply_weixin_message_helper"
6
6
  require "weixin_rails_middleware/helpers/unique_token_helper"
7
- require "weixin_rails_middleware/helpers/weixin_authorize_helper"
7
+ require "weixin_rails_middleware/adapter"
8
8
  require "weixin_rails_middleware/helpers/auto_generate_weixin_token_secret_key"
9
9
 
10
10
  module WeixinRailsMiddleware
@@ -0,0 +1,3 @@
1
+ require "weixin_rails_middleware/adapter/weixin_adapter"
2
+ require "weixin_rails_middleware/adapter/multiple_public_account"
3
+ require "weixin_rails_middleware/adapter/single_public_account"
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ module WeixinRailsMiddleware
3
+ module Adapter
4
+ class MultiplePublicAccount < WexinAdapter
5
+
6
+ def check_weixin_legality
7
+ return render_authorize_result(404) if !is_weixin_secret_key_valid?
8
+ super
9
+ end
10
+
11
+ # check the token from Weixin Service is exist in local store.
12
+ def is_weixin_secret_key_valid?
13
+ current_weixin_public_account.present?
14
+ end
15
+
16
+ def current_weixin_token
17
+ current_weixin_public_account.try(DEFAULT_TOKEN_COLUMN_NAME)
18
+ end
19
+
20
+ def current_weixin_public_account
21
+ self.class.token_model_class.where("#{DEFAULT_WEIXIN_SECRET_KEY}" => weixin_secret_key).first
22
+ end
23
+
24
+ def error_msg
25
+ "#{__FILE__}:#{__LINE__}: RecordNotFound - Couldn't find #{self.class.token_model} with weixin_secret_key=#{weixin_secret_key}"
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ module WeixinRailsMiddleware
3
+ module Adapter
4
+ class SinglePublicAccount < WexinAdapter
5
+
6
+ def check_weixin_legality
7
+ return render_authorize_result if !is_weixin_secret_key_valid?
8
+ super
9
+ end
10
+
11
+ def is_weixin_secret_key_valid?
12
+ weixin_secret_key == self.class.weixin_secret_string
13
+ end
14
+
15
+ def current_weixin_token
16
+ self.class.weixin_token_string
17
+ end
18
+
19
+ def current_weixin_public_account
20
+ nil
21
+ end
22
+
23
+ def error_msg
24
+ "#{__FILE__}:#{__LINE__}: Weixin secret string NotMatch."
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,74 @@
1
+ # encoding: utf-8
2
+ module WeixinRailsMiddleware
3
+ module Adapter
4
+ class WexinAdapter
5
+ extend ConfigurationHelpers
6
+
7
+ attr_accessor :signature, :timestamp, :nonce, :echostr
8
+ attr_accessor :weixin_secret_key
9
+
10
+ def initialize(weixin_params)
11
+ @weixin_secret_key = weixin_params[:weixin_secret_key]
12
+ # 以下参数为什么加空字符串默认值的原因:
13
+ # SB微信偶尔会再重新发一次get请求,但是不会带上signature,timestamp,nonce的参数
14
+ # 一个预防措施吧。
15
+ @signature = weixin_params[:signature] || ''
16
+ @timestamp = weixin_params[:timestamp] || ''
17
+ @nonce = weixin_params[:nonce] || ''
18
+ @echostr = weixin_params[:echostr] || ''
19
+ end
20
+
21
+ def self.init_with(weixin_params)
22
+ if weixin_token_string.present?
23
+ SinglePublicAccount.new(weixin_params)
24
+ else
25
+ MultiplePublicAccount.new(weixin_params)
26
+ end
27
+ end
28
+
29
+ def check_weixin_legality
30
+ return render_authorize_result(403, self.class.error_msg) if !is_signature_valid?
31
+ render_authorize_result(200, echostr, true)
32
+ end
33
+
34
+ def is_signature_valid?
35
+ sort_params = [current_weixin_token, timestamp, nonce].sort.join
36
+ current_signature = Digest::SHA1.hexdigest(sort_params)
37
+ return true if current_signature == signature
38
+ false
39
+ end
40
+
41
+ def current_weixin_public_account
42
+ raise NotImplementedError, "Subclasses must implement current_weixin_public_account method"
43
+ end
44
+
45
+ def current_weixin_token
46
+ raise NotImplementedError, "Subclasses must implement current_weixin_token method"
47
+ end
48
+
49
+ def is_weixin_secret_key_valid?
50
+ raise NotImplementedError, "Subclasses must implement is_weixin_secret_key_valid? method"
51
+ end
52
+
53
+ class << self
54
+ def error_msg
55
+ "#{__FILE__}:#{__LINE__}: Weixin signature NotMatch"
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ # render weixin server authorize results
62
+ def render_authorize_result(status=403, text=nil, valid=false)
63
+ text = text || error_msg
64
+ Rails.logger.error(text) if status != 200
65
+ {text: text, status: status, valid: valid}
66
+ end
67
+
68
+ def error_msg
69
+ self.class.error_msg
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -15,9 +15,8 @@ module WeixinRailsMiddleware
15
15
  end
16
16
 
17
17
  class Configuration
18
- attr_accessor :public_account_class, :weixin_token_string
19
- attr_accessor :weixin_secret_string
20
-
18
+ attr_accessor :public_account_class
19
+ attr_accessor :weixin_secret_string, :weixin_token_string
21
20
  end
22
21
 
23
22
  module ConfigurationHelpers
@@ -1,6 +1,5 @@
1
1
  module WeixinRailsMiddleware
2
2
  class Engine < ::Rails::Engine
3
- include ConfigurationHelpers
4
3
 
5
4
  isolate_namespace WeixinRailsMiddleware
6
5
  engine_name :weixin_engine
@@ -5,7 +5,6 @@ module WeixinRailsMiddleware
5
5
  included do
6
6
 
7
7
  before_create do
8
- # TODO: refactor
9
8
  self.weixin_secret_key = generate_weixin_secret_key
10
9
  self.weixin_token = WeiXinUniqueToken.generate
11
10
  end
@@ -13,8 +12,8 @@ module WeixinRailsMiddleware
13
12
 
14
13
  private
15
14
 
16
- def generate_weixin_secret_key
17
- WeiXinUniqueToken.generate(generator: :urlsafe_base64, size: 32).downcase
18
- end
15
+ def generate_weixin_secret_key
16
+ WeiXinUniqueToken.generate(generator: :urlsafe_base64, size: 32).downcase
17
+ end
19
18
  end
20
19
  end
@@ -5,11 +5,8 @@ module WeixinRailsMiddleware
5
5
  generator_method_type = options.delete(:generator).try(:to_sym) || :hex
6
6
  generator_method = SecureRandom.method(generator_method_type)
7
7
  token_size = options.delete(:size).try(:to_i) || 12
8
- if generator_method_type != :uuid
9
- generator_method.call(token_size)
10
- else
11
- generator_method.call()
12
- end
8
+ return generator_method.call if generator_method_type == :uuid
9
+ generator_method.call(token_size)
13
10
  end
14
11
  end
15
12
  end
@@ -1,4 +1,4 @@
1
- # -*- encoding : utf-8 -*-
1
+ # encoding: utf-8
2
2
  # ref: https://github.com/wolfg1969/rack-weixin/lib/weixin/model.rb
3
3
  require 'roxml'
4
4
  require 'multi_xml'
@@ -1,4 +1,4 @@
1
- # -*- encoding : utf-8 -*-
1
+ # encoding: utf-8
2
2
  # ref: https://github.com/wolfg1969/rack-weixin/lib/weixin/model.rb
3
3
  require 'roxml'
4
4
 
@@ -7,7 +7,6 @@ module WeixinRailsMiddleware
7
7
  class ReplyMessage
8
8
  include ROXML
9
9
  xml_name :xml
10
- #xml_convention :camelcase
11
10
 
12
11
  xml_accessor :ToUserName, :cdata => true
13
12
  xml_accessor :FromUserName, :cdata => true
@@ -1,3 +1,3 @@
1
1
  module WeixinRailsMiddleware
2
- VERSION = "1.2.1"
2
+ VERSION = "1.2.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: weixin_rails_middleware
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - lanrion
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-01 00:00:00.000000000 Z
11
+ date: 2014-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -111,12 +111,15 @@ files:
111
111
  - lib/generators/weixin_rails_middleware/install_generator.rb
112
112
  - lib/generators/weixin_rails_middleware/migration_generator.rb
113
113
  - lib/weixin_rails_middleware.rb
114
+ - lib/weixin_rails_middleware/adapter.rb
115
+ - lib/weixin_rails_middleware/adapter/multiple_public_account.rb
116
+ - lib/weixin_rails_middleware/adapter/single_public_account.rb
117
+ - lib/weixin_rails_middleware/adapter/weixin_adapter.rb
114
118
  - lib/weixin_rails_middleware/configuration.rb
115
119
  - lib/weixin_rails_middleware/engine.rb
116
120
  - lib/weixin_rails_middleware/helpers/auto_generate_weixin_token_secret_key.rb
117
121
  - lib/weixin_rails_middleware/helpers/reply_weixin_message_helper.rb
118
122
  - lib/weixin_rails_middleware/helpers/unique_token_helper.rb
119
- - lib/weixin_rails_middleware/helpers/weixin_authorize_helper.rb
120
123
  - lib/weixin_rails_middleware/models/message.rb
121
124
  - lib/weixin_rails_middleware/models/reply_message.rb
122
125
  - lib/weixin_rails_middleware/version.rb
@@ -1,74 +0,0 @@
1
- module WeixinRailsMiddleware
2
- module WeixinAuthorizeHelper
3
- extend ActiveSupport::Concern
4
-
5
- protected
6
-
7
- def check_weixin_params
8
-
9
- # if config weixin token string
10
- if weixin_token_string.present?
11
- if !is_weixin_secret_string_valid?
12
- puts "WeixinSecretStringNotMatch"
13
- render text: "WeixinSecretStringNotMatch", status: 403
14
- return false
15
- end
16
- # if use database to store public_account
17
- else
18
- if !is_weixin_secret_key_valid?
19
- puts "RecordNotFound"
20
- render text: "RecordNotFound - Couldn't find #{token_model} with weixin_secret_key=#{current_weixin_secret_key} ", status: 404
21
- return false
22
- end
23
- end
24
-
25
- if !is_signature_valid?
26
- puts "WeixinSignatureNotMatch"
27
- render text: "WeixinSignatureNotMatch", status: 403
28
- return false
29
- end
30
- true
31
- end
32
-
33
- # check the token from Weixin Service is exist in local store.
34
- def is_weixin_secret_key_valid?
35
- if weixin_token_string.blank?
36
- current_weixin_public_account.present?
37
- end
38
- end
39
-
40
- def is_weixin_secret_string_valid?
41
- current_weixin_secret_key == weixin_secret_string
42
- end
43
-
44
- def is_signature_valid?
45
- signature = params[:signature] || ''
46
- timestamp = params[:timestamp] || ''
47
- nonce = params[:nonce] || ''
48
- sort_params = [current_weixin_token, timestamp, nonce].sort.join
49
- current_signature = Digest::SHA1.hexdigest(sort_params)
50
- return true if current_signature == signature
51
- false
52
- end
53
-
54
- def current_weixin_secret_key
55
- @weixin_secret_key = params[:weixin_secret_key]
56
- end
57
-
58
- def current_weixin_token
59
- return weixin_token_string if weixin_token_string.present?
60
- current_weixin_public_account.try(DEFAULT_TOKEN_COLUMN_NAME)
61
- end
62
-
63
- def current_weixin_public_account
64
- @current_weixin_public_account = token_model_class.where("#{DEFAULT_WEIXIN_SECRET_KEY}" => current_weixin_secret_key).first
65
- end
66
-
67
- # return a message class with current_weixin_params
68
- def current_weixin_message
69
- Message.factory(request.body.read)
70
- end
71
-
72
- end
73
- end
74
-