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 +4 -4
- data/app/controllers/weixin_rails_middleware/weixin_controller.rb +15 -8
- data/lib/generators/templates/install_weixin_rails_middleware.rb +1 -1
- data/lib/generators/templates/weixin_controller.rb +3 -2
- data/lib/weixin_rails_middleware.rb +1 -1
- data/lib/weixin_rails_middleware/adapter.rb +3 -0
- data/lib/weixin_rails_middleware/adapter/multiple_public_account.rb +30 -0
- data/lib/weixin_rails_middleware/adapter/single_public_account.rb +29 -0
- data/lib/weixin_rails_middleware/adapter/weixin_adapter.rb +74 -0
- data/lib/weixin_rails_middleware/configuration.rb +2 -3
- data/lib/weixin_rails_middleware/engine.rb +0 -1
- data/lib/weixin_rails_middleware/helpers/auto_generate_weixin_token_secret_key.rb +3 -4
- data/lib/weixin_rails_middleware/helpers/unique_token_helper.rb +2 -5
- data/lib/weixin_rails_middleware/models/message.rb +1 -1
- data/lib/weixin_rails_middleware/models/reply_message.rb +1 -2
- data/lib/weixin_rails_middleware/version.rb +1 -1
- metadata +6 -3
- data/lib/weixin_rails_middleware/helpers/weixin_authorize_helper.rb +0 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 636d0f84432996fd76df3c15716065b775a77379
|
4
|
+
data.tar.gz: 6228287ca1e489b6370f95e1a5aa7b5161def9d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 :
|
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
|
-
|
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
|
29
|
-
@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.
|
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/
|
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,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
|
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
|
@@ -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
|
-
|
17
|
-
|
18
|
-
|
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
|
9
|
-
|
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
|
-
#
|
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
|
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.
|
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-
|
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
|
-
|