weixin_rails_middleware_uxinji 1.0.4

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a4f8e4584fbb40a0097d749f8e08b626f10db4cd
4
+ data.tar.gz: d68d4a280935b7796f600b9188b70edbe543989e
5
+ SHA512:
6
+ metadata.gz: ada7e9e76c2adc0ddd1882d233caff70dd83b1c987bb652aceb365860c00d730ec9ffa0f765b861c90559a9fcf80e9ac44b049b6794feea4abb4925e28fa3943
7
+ data.tar.gz: beea4453004e0884e67b6c31d2777f60e0b56d605606da3c72e8c1379f9a9a0c7cb9316bd4fe70a4169a5cf7380c2070d1d1c0207cfdb6a6f4a7bba9b3e4173a
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,90 @@
1
+ # WeixinRailsMiddleware
2
+
3
+ This project rocks and uses MIT-LICENSE.
4
+
5
+ https://rubygems.org/gems/weixin_rails_middleware
6
+
7
+ Example: https://github.com/lanrion/weixin_rails_middleware_example
8
+
9
+ ## Function
10
+
11
+ * 自动验证微信请求。
12
+
13
+ * 无需拼接XML格式,只需要使用 `WeixinMessageHelper` 辅助方法,即可快速回复。
14
+ 使用方法: ` render xml: reply_text_message("Your Message: #{current_message.Content}") `
15
+
16
+ * 支持自定义token,适合一个用户使用。
17
+
18
+ * 支持多用户token: 适合多用户注册网站,每个用户有不同的token,通过 `weixin_rails_middleware.rb` 配置好存储token的Model与字段名,即可。
19
+
20
+ * 文本回复: `reply_text_message(content)`。
21
+
22
+ * 音乐回复: `reply_music_message(music)`, `generate_music(title, desc, music_url, hq_music_url)`。
23
+
24
+ * 图文回复: `reply_news_message(articles)`, `generate_article(title, desc, pic_url, link_url)`。
25
+
26
+ * 视频回复: `replay_video_message(video)`。
27
+
28
+ * 语音回复: `reply_voice_message(voice)`。
29
+
30
+ * 图片回复: `reply_imgage_message(image)`。
31
+
32
+ * 地理位置回复: 自定义需求。
33
+
34
+ ## Install
35
+
36
+ In your `Gemfile`: `gem 'weixin_rails_middleware'`
37
+
38
+ And `bundle intall`
39
+
40
+ ## Init weixin_rails_middleware
41
+
42
+ `rails generate weixin_rails_middleware:install`
43
+
44
+ It will create `config/initializers/weixin_rails_middleware.rb`
45
+
46
+ Note: You need to checkout comments in file
47
+
48
+ And
49
+
50
+ Create `app/decorators/controllers/weixin_rails_middleware/weixin_controller_decorator.rb`
51
+
52
+ Note: You need to overwrite the `reply` method. And there are two instance: `@weixin_message`,
53
+ `@weixin_public_account(token_model instance if you setup, otherwise return nil)`
54
+
55
+ Other
56
+
57
+ Add a line: `WeixinRailsMiddleware::Engine, at: WeixinRailsMiddleware.config.engine_path` in `routes.rb`
58
+
59
+ ## Helpers
60
+
61
+ Please see detail in `weixin_message_helper.rb`
62
+
63
+ ## How to test
64
+ Install `ngrok` and run with `ngrok 4000`, `4000` is your port that Rails Server needed
65
+
66
+ Then, it will generate like this:
67
+
68
+ ```
69
+ Tunnel Status online
70
+ Version 1.6/1.5
71
+ Forwarding http://e0ede89.ngrok.com -> 127.0.0.1:4000
72
+ Forwarding https://e0ede89.ngrok.com -> 127.0.0.1:4000
73
+ Web Interface 127.0.0.1:4040
74
+ # Conn 67
75
+ Avg Conn Time 839.50ms
76
+
77
+ ```
78
+
79
+ Yes, She is `http://e0ede89.ngrok.com`
80
+
81
+ 神器!!
82
+
83
+ ## XML parser
84
+ We use `roxml` to generate XML and use `multi_xml` to parse `XML`, but we let them all use `nokogiri` plugin default.
85
+
86
+ ## TODO
87
+
88
+ * 添加微信自定义菜单
89
+ * 多媒体资料上传
90
+
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'WeixinRailsMiddleware'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,4 @@
1
+ module WeixinRailsMiddleware
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,96 @@
1
+ module WeixinRailsMiddleware
2
+ class WeixinController < ApplicationController
3
+ include WeixinMessageHelper
4
+
5
+ skip_before_filter :verify_authenticity_token
6
+ before_action :check_weixin_params, only: [:index, :reply]
7
+ before_action :set_weixin_public_account, :set_weixin_message, only: :reply
8
+
9
+ def index
10
+ render text: params[:echostr]
11
+ end
12
+
13
+ def reply
14
+ end
15
+
16
+ protected
17
+
18
+ def check_weixin_params
19
+ if check_weixin_token_valid?
20
+ unless is_hexdigest?
21
+ render text: "Forbidden", status: 403
22
+ end
23
+ end
24
+ end
25
+
26
+ # check the token from Weixin Service is exist in local store.
27
+ def check_weixin_token_valid?
28
+ token_string.present? ? check_token_string : check_token_model_instance
29
+ end
30
+
31
+ def token_string
32
+ WeixinRailsMiddleware.config.token_string
33
+ end
34
+
35
+ def check_token_string
36
+ if current_weixin_token != token_string
37
+ render text: "Forbidden", status: 403
38
+ return false
39
+ end
40
+ true
41
+ end
42
+
43
+ def check_token_model_instance
44
+ if token_model_instance.blank?
45
+ render text: "Forbidden", status: 403
46
+ return false
47
+ end
48
+ true
49
+ end
50
+
51
+ def is_hexdigest?
52
+ temp_array = weixin_token, timestamp, nonce
53
+ current_signature = Digest::SHA1.hexdigest(temp_array.sort.join)
54
+ return true if current_signature == signature
55
+ false
56
+ end
57
+
58
+ [:signature, :timestamp, :nonce, :weixin_token].each do |e|
59
+ define_method e do
60
+ params[e]
61
+ end
62
+ end
63
+
64
+ def current_weixin_token
65
+ @current_weixin_token ||= weixin_token
66
+ end
67
+
68
+ def token_model_instance
69
+ token_model = WeixinRailsMiddleware.config.token_model_class
70
+ token_column = WeixinRailsMiddleware.config.token_column
71
+ token_model_instance = token_model.where("#{token_column}" => current_weixin_token).first
72
+ end
73
+
74
+ # e.g. will generate +@weixin_public_account+
75
+ def set_weixin_public_account
76
+ return nil if token_string.present?
77
+ @weixin_public_account ||= token_model_instance
78
+ end
79
+
80
+ def set_weixin_message
81
+ # Get the current_message
82
+ @weixin_message ||= current_weixin_message
83
+ end
84
+
85
+ # take the weixin params
86
+ def current_weixin_params
87
+ @current_weixin_params ||= request.body.read
88
+ end
89
+
90
+ # return a message class with current_weixin_params
91
+ def current_weixin_message
92
+ Message.factory(current_weixin_params)
93
+ end
94
+
95
+ end
96
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ WeixinRailsMiddleware::Engine.routes.draw do
2
+ get 'weixin/:weixin_token', to: 'weixin#index'
3
+ post 'weixin/:weixin_token', to: 'weixin#reply'
4
+ end
@@ -0,0 +1,20 @@
1
+ # Use this hook to configure WeixinRailsMiddleware bahaviors.
2
+ WeixinRailsMiddleware.configure do |config|
3
+
4
+ ## NOTE:
5
+ ## if you config all them, it will use `token_string` default
6
+ ##
7
+ # Th FIRST configure
8
+ # if you config `token_model`, it will use it to find_by_weixin_token
9
+ # you must config a column name, `weixin_token` default
10
+ # config.token_model = "" # ActiveRecord subclass or other ORM subclass
11
+ # config.token_column = "weixin_token"
12
+
13
+ # OR the SECOND configure
14
+ # if you config `token_string`, so it will directly use it
15
+ # config.token_string = "token string"
16
+
17
+ # router
18
+ # config.engine_path = "/"
19
+
20
+ end
@@ -0,0 +1,39 @@
1
+ WeixinRailsMiddleware::WeixinController.class_eval do
2
+
3
+ # There are two instance: @weixin_message,
4
+ # @weixin_public_account(token_model instance if you setup, otherwise return nil)
5
+ def reply
6
+ render xml: send("response_#{@weixin_message.MsgType}_message", {})
7
+ end
8
+
9
+ private
10
+
11
+ def response_text_message(options={})
12
+ reply_text_message("Your Message: #{@weixin_message.Content}")
13
+
14
+ end
15
+
16
+ def response_location_message(options={})
17
+ reply_text_message("Your Location: #{@weixin_message.Location_X}, #{@weixin_message.Location_Y}")
18
+ end
19
+
20
+ def response_image_message(options={})
21
+ # image message handler
22
+ end
23
+
24
+ def response_link_message(options={})
25
+ # link message handler
26
+ end
27
+
28
+ def response_event_message(options={})
29
+ # event messge handler
30
+ end
31
+
32
+ def response_voice_message(options={})
33
+ # voice message handler
34
+ end
35
+
36
+ def response_video_message(options={})
37
+ # video message handler
38
+ end
39
+ end
@@ -0,0 +1,35 @@
1
+ # Rails::Generators::Base dont need a name
2
+ # Rails::Generators::NamedBase need a name
3
+ module WeixinRailsMiddleware
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path('../../templates', __FILE__)
7
+
8
+ desc 'Creates a Dashing initializer for your application.'
9
+
10
+ def install
11
+ route 'mount WeixinRailsMiddleware::Engine, at: WeixinRailsMiddleware.config.engine_path'
12
+ end
13
+
14
+ def copy_initializer
15
+ template 'initializer.rb', 'config/initializers/weixin_rails_middleware.rb'
16
+ end
17
+
18
+ def configure_application
19
+ application <<-APP
20
+ config.to_prepare do
21
+ # Load application's model / class decorators
22
+ Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
23
+ Rails.configuration.cache_classes ? require(c) : load(c)
24
+ end
25
+ end
26
+ APP
27
+ end
28
+
29
+ def copy_decorators
30
+ template 'weixin_controller.rb', 'app/decorators/controllers/weixin_rails_middleware/weixin_controller_decorator.rb'
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :weixin_rails_middleware do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,27 @@
1
+ require "weixin_rails_middleware/engine"
2
+ require "weixin_rails_middleware/configuration"
3
+ require "weixin_rails_middleware/message"
4
+ require "weixin_rails_middleware/reply_message"
5
+ require "weixin_rails_middleware/weixin_message_helper"
6
+
7
+ module WeixinRailsMiddleware
8
+
9
+ DEFAULT_TOKEN_COLUMN_NAME = "weixin_token".freeze
10
+ DEFAULT_ENGINE_PATH = "/".freeze
11
+
12
+ class << self
13
+
14
+ attr_accessor :configuration
15
+
16
+ def config
17
+ self.configuration ||= Configuration.new
18
+ end
19
+
20
+ def configure
21
+ yield config if block_given?
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
@@ -0,0 +1,22 @@
1
+ module WeixinRailsMiddleware
2
+ class Configuration
3
+ # use 'token_model': if the token is saved in SomeModel, then find token by it
4
+ # use 'token_string': if the token is a String, just use it,
5
+ attr_accessor :token_model, :token_column, :token_string, :engine_path
6
+
7
+ def initialize
8
+ @engine_path = DEFAULT_ENGINE_PATH
9
+ @token_column = DEFAULT_TOKEN_COLUMN_NAME
10
+ end
11
+
12
+ def token_model_class
13
+ raise "You need to config `token_model` in config/initializers/weixin_rails_middleware.rb" if token_model.blank?
14
+ token_model_c = token_model.constantize
15
+ unless token_model_c.table_exists?
16
+ raise "You don't have #{token_model_c.table_name} table"
17
+ end
18
+ token_model_c
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ module WeixinRailsMiddleware
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace WeixinRailsMiddleware
4
+ end
5
+ end
@@ -0,0 +1,163 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # ref: https://github.com/wolfg1969/rack-weixin/lib/weixin/model.rb
3
+ require 'roxml'
4
+ require 'multi_xml'
5
+ require 'ostruct'
6
+
7
+ # multi_xml will use Nokogiri if it is available
8
+ MultiXml.parser = :nokogiri
9
+
10
+ module WeixinRailsMiddleware
11
+
12
+ class Message
13
+
14
+ def initialize(hash)
15
+ @source = OpenStruct.new(hash)
16
+ end
17
+
18
+ def method_missing(method, *args, &block)
19
+ @source.send(method, *args, &block)
20
+ end
21
+
22
+ def CreateTime
23
+ @source.CreateTime.to_i
24
+ end
25
+
26
+ def MsgId
27
+ @source.MsgId.to_i
28
+ end
29
+
30
+ def self.factory(xml)
31
+ hash = MultiXml.parse(xml)['xml']
32
+ case hash['MsgType']
33
+ when 'text'
34
+ TextMessage.new(hash)
35
+ when 'image'
36
+ ImageMessage.new(hash)
37
+ when 'location'
38
+ LocationMessage.new(hash)
39
+ when 'link'
40
+ LinkMessage.new(hash)
41
+ when 'event'
42
+ EventMessage.new(hash)
43
+ when 'voice'
44
+ VoiceMessage.new(hash)
45
+ when 'video'
46
+ VideoMessage.new(hash)
47
+ else
48
+ raise ArgumentError, 'Unknown Message'
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ # <xml>
55
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
56
+ # <FromUserName><![CDATA[fromUser]]></FromUserName>
57
+ # <CreateTime>1348831860</CreateTime>
58
+ # <MsgType><![CDATA[text]]></MsgType>
59
+ # <Content><![CDATA[this is a test]]></Content>
60
+ # <MsgId>1234567890123456</MsgId>
61
+ # </xml>
62
+ TextMessage = Class.new(Message)
63
+
64
+ # <xml>
65
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
66
+ # <FromUserName><![CDATA[fromUser]]></FromUserName>
67
+ # <CreateTime>1348831860</CreateTime>
68
+ # <MsgType><![CDATA[image]]></MsgType>
69
+ # <PicUrl><![CDATA[this is a url]]></PicUrl>
70
+ # <MsgId>1234567890123456</MsgId>
71
+ # </xml>
72
+ ImageMessage = Class.new(Message)
73
+
74
+ # <xml>
75
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
76
+ # <FromUserName><![CDATA[fromUser]]></FromUserName>
77
+ # <CreateTime>1351776360</CreateTime>
78
+ # <MsgType><![CDATA[link]]></MsgType>
79
+ # <Title><![CDATA[公众平台官网链接]]></Title>
80
+ # <Description><![CDATA[公众平台官网链接]]></Description>
81
+ # <Url><![CDATA[url]]></Url>
82
+ # <MsgId>1234567890123456</MsgId>
83
+ # </xml>
84
+ LinkMessage = Class.new(Message)
85
+
86
+ # <xml>
87
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
88
+ # <FromUserName><![CDATA[FromUser]]></FromUserName>
89
+ # <CreateTime>123456789</CreateTime>
90
+ # <MsgType><![CDATA[event]]></MsgType>
91
+ # <Event><![CDATA[EVENT]]></Event>
92
+ # <EventKey><![CDATA[EVENTKEY]]></EventKey>
93
+ # </xml>
94
+ EventMessage = Class.new(Message)
95
+
96
+ # <xml>
97
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
98
+ # <FromUserName><![CDATA[fromUser]]></FromUserName>
99
+ # <CreateTime>1351776360</CreateTime>
100
+ # <MsgType><![CDATA[location]]></MsgType>
101
+ # <Location_X>23.134521</Location_X>
102
+ # <Location_Y>113.358803</Location_Y>
103
+ # <Scale>20</Scale>
104
+ # <Label><![CDATA[位置信息]]></Label>
105
+ # <MsgId>1234567890123456</MsgId>
106
+ # </xml>
107
+ class LocationMessage < Message
108
+
109
+ def Location_X
110
+ @source.Location_X.to_f
111
+ end
112
+
113
+ def Location_Y
114
+ @source.Location_Y.to_f
115
+ end
116
+
117
+ def Scale
118
+ @source.Scale.to_i
119
+ end
120
+ end
121
+
122
+ # <xml>
123
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
124
+ # <FromUserName><![CDATA[fromUser]]></FromUserName>
125
+ # <CreateTime>1376632760</CreateTime>
126
+ # <MsgType><![CDATA[voice]]></MsgType>
127
+ # <MediaId><![CDATA[Qyb0tgux6QLjhL6ipvFZJ-kUt2tcQtkn0BU365Vt3wUAtqfGam4QpZU35RXVhv6G]]></MediaId>
128
+ # <Format><![CDATA[amr]]></Format>
129
+ # <MsgId>5912592682802219078</MsgId>
130
+ # <Recognition><![CDATA[]]></Recognition>
131
+ # </xml>
132
+ class VoiceMessage < Message
133
+
134
+ def MediaId
135
+ @source.MediaId
136
+ end
137
+
138
+ def Format
139
+ @source.Format
140
+ end
141
+ end
142
+
143
+ # <xml>
144
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
145
+ # <FromUserName><![CDATA[fromUser]]></FromUserName>
146
+ # <CreateTime>1376632994</CreateTime>
147
+ # <MsgType><![CDATA[video]]></MsgType>
148
+ # <MediaId><![CDATA[TAAGb6iS5LcZR1d5ICiZTWGWi6-Upic9tlWDpAKcNJA]]></MediaId>
149
+ # <ThumbMediaId><![CDATA[U-xulPW4kq6KKMWFNaBSPc65Bcgr7Qopwex0DfCeyQs]]></ThumbMediaId>
150
+ # <MsgId>5912593687824566343</MsgId>
151
+ # </xml>
152
+ class VideoMessage < Message
153
+
154
+ def MediaId
155
+ @source.MediaId
156
+ end
157
+
158
+ def ThumbMediaId
159
+ @source.ThumbMediaId
160
+ end
161
+ end
162
+
163
+ end
@@ -0,0 +1,183 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # ref: https://github.com/wolfg1969/rack-weixin/lib/weixin/model.rb
3
+ require 'roxml'
4
+
5
+ module WeixinRailsMiddleware
6
+
7
+ class ReplyMessage
8
+ include ROXML
9
+ xml_name :xml
10
+ #xml_convention :camelcase
11
+
12
+ xml_accessor :ToUserName, :cdata => true
13
+ xml_accessor :FromUserName, :cdata => true
14
+ xml_reader :CreateTime, :as => Integer
15
+ xml_reader :MsgType, :cdata => true
16
+
17
+ def initialize
18
+ @CreateTime = Time.now.to_i
19
+ end
20
+
21
+ def to_xml
22
+ super.to_xml(:encoding => 'UTF-8', :indent => 0, :save_with => 0)
23
+ end
24
+ end
25
+
26
+ # <xml>
27
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
28
+ # <FromUserName><![CDATA[fromUser]]></FromUserName>
29
+ # <CreateTime>12345678</CreateTime>
30
+ # <MsgType><![CDATA[text]]></MsgType>
31
+ # <Content><![CDATA[Hello]]></Content>
32
+ # </xml>
33
+
34
+ class TextReplyMessage < ReplyMessage
35
+ xml_accessor :Content, :cdata => true
36
+ def initialize
37
+ super
38
+ @MsgType = 'text'
39
+ end
40
+ end
41
+
42
+ class Music
43
+ include ROXML
44
+ xml_accessor :Title, :cdata => true
45
+ xml_accessor :Description, :cdata => true
46
+ xml_accessor :MusicUrl, :cdata => true
47
+ xml_accessor :HQMusicUrl, :cdata => true
48
+ end
49
+
50
+ # <xml>
51
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
52
+ # <FromUserName><![CDATA[fromUser]]></FromUserName>
53
+ # <CreateTime>12345678</CreateTime>
54
+ # <MsgType><![CDATA[music]]></MsgType>
55
+ # <Music>
56
+ # <Title><![CDATA[TITLE]]></Title>
57
+ # <Description><![CDATA[DESCRIPTION]]></Description>
58
+ # <MusicUrl><![CDATA[MUSIC_Url]]></MusicUrl>
59
+ # <HQMusicUrl><![CDATA[HQ_MUSIC_Url]]></HQMusicUrl>
60
+ # <ThumbMediaId><![CDATA[media_id]]></ThumbMediaId>
61
+ # </Music>
62
+ # </xml>
63
+
64
+ class MusicReplyMessage < ReplyMessage
65
+ xml_accessor :Music, :as => Music
66
+ def initialize
67
+ super
68
+ @MsgType = 'music'
69
+ end
70
+ end
71
+
72
+ class Article
73
+ include ROXML
74
+ xml_accessor :Title, :cdata => true
75
+ xml_accessor :Description, :cdata => true
76
+ xml_accessor :PicUrl, :cdata => true
77
+ xml_accessor :Url, :cdata => true
78
+ end
79
+
80
+ # <xml>
81
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
82
+ # <FromUserName><![CDATA[fromUser]]></FromUserName>
83
+ # <CreateTime>12345678</CreateTime>
84
+ # <MsgType><![CDATA[news]]></MsgType>
85
+ # <ArticleCount>2</ArticleCount>
86
+ # <Articles>
87
+ # <item>
88
+ # <Title><![CDATA[title1]]></Title>
89
+ # <Description><![CDATA[description1]]></Description>
90
+ # <PicUrl><![CDATA[picurl]]></PicUrl>
91
+ # <Url><![CDATA[url]]></Url>
92
+ # </item>
93
+ # <item>
94
+ # <Title><![CDATA[title]]></Title>
95
+ # <Description><![CDATA[description]]></Description>
96
+ # <PicUrl><![CDATA[picurl]]></PicUrl>
97
+ # <Url><![CDATA[url]]></Url>
98
+ # </item>
99
+ # </Articles>
100
+ # </xml>
101
+
102
+ class NewsReplyMessage < ReplyMessage
103
+ xml_accessor :ArticleCount, :as => Integer
104
+ xml_accessor :Articles, :as => [Article], :in => 'Articles', :from => 'item'
105
+ def initialize
106
+ super
107
+ @MsgType = 'news'
108
+ end
109
+ end
110
+
111
+ # <xml>
112
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
113
+ # <FromUserName><![CDATA[fromUser]]></FromUserName>
114
+ # <CreateTime>12345678</CreateTime>
115
+ # <MsgType><![CDATA[video]]></MsgType>
116
+ # <Video>
117
+ # <MediaId><![CDATA[media_id]]></MediaId>
118
+ # <Title><![CDATA[title]]></Title>
119
+ # <Description><![CDATA[description]]></Description>
120
+ # </Video>
121
+ # </xml>
122
+
123
+ class Video
124
+ include ROXML
125
+ xml_accessor :MediaId, :cdata => true
126
+ xml_accessor :Description, :cdata => true
127
+ xml_accessor :Title, :cdata => true
128
+ end
129
+
130
+ class VideoReplyMessage < ReplyMessage
131
+ xml_accessor :Video, :as => Video
132
+ def initialize
133
+ super
134
+ @MsgType = 'video'
135
+ end
136
+ end
137
+
138
+ # <xml>
139
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
140
+ # <FromUserName><![CDATA[fromUser]]></FromUserName>
141
+ # <CreateTime>12345678</CreateTime>
142
+ # <MsgType><![CDATA[voice]]></MsgType>
143
+ # <Voice>
144
+ # <MediaId><![CDATA[media_id]]></MediaId>
145
+ # </Voice>
146
+ # </xml>
147
+ class Voice
148
+ include ROXML
149
+ xml_accessor :MediaId, :cdata => true
150
+ end
151
+
152
+ class VoiceReplyMessage < ReplyMessage
153
+ xml_accessor :Voice, :as => Voice
154
+ def initialize
155
+ super
156
+ @MsgType = 'voice'
157
+ end
158
+ end
159
+
160
+ # <xml>
161
+ # <ToUserName><![CDATA[toUser]]></ToUserName>
162
+ # <FromUserName><![CDATA[fromUser]]></FromUserName>
163
+ # <CreateTime>12345678</CreateTime>
164
+ # <MsgType><![CDATA[image]]></MsgType>
165
+ # <Image>
166
+ # <MediaId><![CDATA[media_id]]></MediaId>
167
+ # </Image>
168
+ # </xml>
169
+
170
+ class Image
171
+ include ROXML
172
+ xml_accessor :MediaId, :cdata => true
173
+ end
174
+
175
+ class ImageReplyMessage < ReplyMessage
176
+ xml_accessor :Image, :as => Image
177
+ def initialize
178
+ super
179
+ @MsgType = 'image'
180
+ end
181
+ end
182
+
183
+ end
@@ -0,0 +1,3 @@
1
+ module WeixinRailsMiddleware
2
+ VERSION = "1.0.4"
3
+ end
@@ -0,0 +1,97 @@
1
+ module WeixinRailsMiddleware
2
+ module WeixinMessageHelper
3
+
4
+ # e.g.
5
+ # reply_text_message(@weixin_message.ToUserName, @weixin_message.FromUserName, "Your Message: #{@weixin_message.Content}")
6
+ # Or reply_text_message("Your Message: #{@weixin_message.Content}")
7
+ def reply_text_message(from=nil, to=nil, content)
8
+ message = TextReplyMessage.new
9
+ message.FromUserName = from || @weixin_message.ToUserName
10
+ message.ToUserName = to || @weixin_message.FromUserName
11
+ message.Content = content
12
+ message.to_xml
13
+ end
14
+
15
+ def generate_music(title, desc, music_url, hq_music_url)
16
+ music = Music.new
17
+ music.Title = title
18
+ music.Description = desc
19
+ music.MusicUrl = music_url
20
+ music.HQMusicUrl = hq_music_url
21
+ music
22
+ end
23
+
24
+ # music = generate_music
25
+ def reply_music_message(from=nil, to=nil, music)
26
+ message = MusicReplyMessage.new
27
+ message.FromUserName = from || @weixin_message.ToUserName
28
+ message.ToUserName = to || @weixin_message.FromUserName
29
+ message.Music = music
30
+ message.to_xml
31
+ end
32
+
33
+ def generate_article(title, desc, pic_url, link_url)
34
+ item = Article.new
35
+ item.Title = title
36
+ item.Description = desc
37
+ item.PicUrl = pic_url
38
+ item.Url = link_url
39
+ item
40
+ end
41
+
42
+ # articles = [generate_article]
43
+ def reply_news_message(from=nil, to=nil, articles)
44
+ message = NewsReplyMessage.new
45
+ message.FromUserName = from || @weixin_message.ToUserName
46
+ message.ToUserName = to || @weixin_message.FromUserName
47
+ message.Articles = articles
48
+ message.ArticleCount = articles.count
49
+ message.to_xml
50
+ end
51
+
52
+ def generate_video(media_id, desc, title)
53
+ video = Video.new
54
+ video.MediaId = media_id
55
+ video.Description = desc
56
+ video.Title = title
57
+ vodeo
58
+ end
59
+
60
+ def replay_video_message(from=nil, to=nil, video)
61
+ message = VideoReplyMessage.new
62
+ message.FromUserName = from || @weixin_message.ToUserName
63
+ message.ToUserName = to || @weixin_message.FromUserName
64
+ message.Video = video
65
+ message.to_xml
66
+ end
67
+
68
+ def generate_voice(media_id)
69
+ voice = Voice.new
70
+ voice.MediaId = media_id
71
+ voice
72
+ end
73
+
74
+ def reply_voice_message(from=nil, to=nil, voice)
75
+ message = VoiceReplyMessage.new
76
+ message.FromUserName = from || @weixin_message.ToUserName
77
+ message.ToUserName = to || @weixin_message.FromUserName
78
+ message.Voice = voice
79
+ message.to_xml
80
+ end
81
+
82
+ def generate_image(media_id)
83
+ image = Image.new
84
+ image.MediaId = media_id
85
+ image
86
+ end
87
+
88
+ def reply_imgage_message(from=nil, to=nil, image)
89
+ message = ImageReplyMessage.new
90
+ message.FromUserName = from || @weixin_message.ToUserName
91
+ message.ToUserName = to || @weixin_message.FromUserName
92
+ message.Image = image
93
+ message.to_xml
94
+ end
95
+
96
+ end
97
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: weixin_rails_middleware_uxinji
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.4
5
+ platform: ruby
6
+ authors:
7
+ - lanrion
8
+ - turristan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-02-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: railties
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '>='
19
+ - !ruby/object:Gem::Version
20
+ version: '3.1'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '>='
26
+ - !ruby/object:Gem::Version
27
+ version: '3.1'
28
+ - !ruby/object:Gem::Dependency
29
+ name: nokogiri
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: 1.6.1
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: 1.6.1
42
+ - !ruby/object:Gem::Dependency
43
+ name: rails
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '3.1'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '3.1'
56
+ - !ruby/object:Gem::Dependency
57
+ name: multi_json
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: 1.7.9
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 1.7.9
70
+ - !ruby/object:Gem::Dependency
71
+ name: multi_xml
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: 0.5.2
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: 0.5.2
84
+ - !ruby/object:Gem::Dependency
85
+ name: roxml
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: 3.3.1
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: 3.3.1
98
+ - !ruby/object:Gem::Dependency
99
+ name: rest_client
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: 1.6.7
105
+ type: :runtime
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - '>='
110
+ - !ruby/object:Gem::Version
111
+ version: 1.6.7
112
+ description: weixin_rails_middleware for uxinji weixin public service
113
+ email:
114
+ - huaitao-deng@foxmail.com
115
+ - turristan@gmail.com
116
+ executables: []
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - MIT-LICENSE
121
+ - README.md
122
+ - Rakefile
123
+ - app/controllers/weixin_rails_middleware/application_controller.rb
124
+ - app/controllers/weixin_rails_middleware/weixin_controller.rb
125
+ - config/routes.rb
126
+ - lib/generators/templates/initializer.rb
127
+ - lib/generators/templates/weixin_controller.rb
128
+ - lib/generators/weixin_rails_middleware/install_generator.rb
129
+ - lib/tasks/weixin_rails_middleware_tasks.rake
130
+ - lib/weixin_rails_middleware.rb
131
+ - lib/weixin_rails_middleware/configuration.rb
132
+ - lib/weixin_rails_middleware/engine.rb
133
+ - lib/weixin_rails_middleware/message.rb
134
+ - lib/weixin_rails_middleware/reply_message.rb
135
+ - lib/weixin_rails_middleware/version.rb
136
+ - lib/weixin_rails_middleware/weixin_message_helper.rb
137
+ homepage: https://github.com/turristan/weixin_rails_middleware/tree/uxinji
138
+ licenses: []
139
+ metadata: {}
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - '>='
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project:
156
+ rubygems_version: 2.2.2
157
+ signing_key:
158
+ specification_version: 4
159
+ summary: weixin_rails_middleware specified uxinji
160
+ test_files: []