weixin_rails_middleware 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
-