eric_weixin 0.0.1 → 0.0.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/.idea/eric_weixin.iml +2 -2
- data/eric_weixin.gemspec +11 -2
- data/lib/eric_weixin/app/controllers/weixin/weixin_controller.rb +27 -0
- data/lib/eric_weixin/app/model/access_token.rb +45 -0
- data/lib/eric_weixin/app/model/article.rb +17 -0
- data/lib/eric_weixin/app/model/article_news.rb +8 -0
- data/lib/eric_weixin/app/model/news.rb +52 -0
- data/lib/eric_weixin/app/model/public_account.rb +185 -0
- data/lib/eric_weixin/app/model/reply_message_rule.rb +109 -0
- data/lib/eric_weixin/app/model/weixin_user.rb +89 -0
- data/lib/eric_weixin/app/views/eric_weixin/weixin/aa.erb +1 -0
- data/lib/eric_weixin/reply_message.rb +5 -5
- data/lib/eric_weixin/version.rb +1 -1
- data/lib/eric_weixin.rb +14 -1
- metadata +143 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b91a2c0afb290cba50cce75c285a32de4bee430e
|
4
|
+
data.tar.gz: f67c0af9428bb0211ba40747cbc702852d0b4ba8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 023d60c77b3855d6daec7e27d850bf5de60991df7b111af34920b87b06eb437fe6b180cca91767e606b6b8dee0f49e6bc6b76246de9ce4f1ad83714ce653e609
|
7
|
+
data.tar.gz: 884acba9ee05601fdac7d7cd6dc6f59ceb1edeb7bbfef3db0a9f2054b4baf2e6947a89450e8c72a71a578ed32608bd4702c45dbd48b618ac09e2f323a4ea35c4
|
data/.idea/eric_weixin.iml
CHANGED
@@ -14,9 +14,9 @@
|
|
14
14
|
</component>
|
15
15
|
<component name="NewModuleRootManager">
|
16
16
|
<content url="file://$MODULE_DIR$" />
|
17
|
-
<orderEntry type="
|
17
|
+
<orderEntry type="jdk" jdkName="RVM: ruby-2.0.0-p481 [eric_tools]" jdkType="RUBY_SDK" />
|
18
18
|
<orderEntry type="sourceFolder" forTests="false" />
|
19
|
-
<orderEntry type="library" scope="PROVIDED" name="bundler (v1.6.2, RVM: ruby-2.0.0-p481) [gem]" level="application" />
|
19
|
+
<orderEntry type="library" scope="PROVIDED" name="bundler (v1.6.2, RVM: ruby-2.0.0-p481 [eric_tools]) [gem]" level="application" />
|
20
20
|
</component>
|
21
21
|
</module>
|
22
22
|
|
data/eric_weixin.gemspec
CHANGED
@@ -19,6 +19,15 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
-
spec.add_development_dependency "rake"
|
23
|
-
spec.add_development_dependency 'nokogiri'
|
22
|
+
spec.add_development_dependency "rake", '~> 0'
|
23
|
+
spec.add_development_dependency 'nokogiri', '~> 0'
|
24
|
+
spec.add_development_dependency 'rest-client', '~> 0'
|
25
|
+
spec.add_development_dependency 'activerecord', '~> 4.1', '>= 4.1.4'
|
26
|
+
spec.add_development_dependency 'rails', '~> 4.1', '>= 4.1.4'
|
27
|
+
spec.add_development_dependency 'actionpack', '~> 4.1', '>= 4.1.4'
|
28
|
+
spec.add_development_dependency 'activesupport', '~> 4.1', '>= 4.1.4'
|
29
|
+
spec.add_development_dependency 'actionview', '~> 4.1', '>= 4.1.4'
|
30
|
+
|
31
|
+
spec.add_development_dependency 'eric_tools', '~> 0.0.4'
|
32
|
+
|
24
33
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "pp"
|
2
|
+
module EricWeixin
|
3
|
+
class WeixinController < ActionController::Base
|
4
|
+
layout "cms/base"
|
5
|
+
|
6
|
+
# 第一次接入时,用于微信服务器验证开者服务器的真实性。
|
7
|
+
def index
|
8
|
+
render :text => params[:echostr]
|
9
|
+
end
|
10
|
+
|
11
|
+
def reply
|
12
|
+
request_body = request.body.read
|
13
|
+
weixin_secret_key = ::EricWeixin::PublicAccount.get_secret params[:app_id]
|
14
|
+
|
15
|
+
"message from wechat: ".to_logger
|
16
|
+
request_body.to_logger
|
17
|
+
weixin_message = MultiXml.parse(request_body).deep_symbolize_keys[:xml]
|
18
|
+
|
19
|
+
message = ::EricWeixin::ReplyMessageRule.process_rule(weixin_message, weixin_secret_key)
|
20
|
+
render xml: message
|
21
|
+
end
|
22
|
+
|
23
|
+
def aa
|
24
|
+
@ee = 12
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module EricWeixin
|
2
|
+
class AccessToken < ActiveRecord::Base
|
3
|
+
require "rest-client"
|
4
|
+
self.table_name = "weixin_access_tokens"
|
5
|
+
|
6
|
+
|
7
|
+
# 获取有效的Token
|
8
|
+
# 参数为: weixin_secret_key
|
9
|
+
# ::EricWeixin::AccessToken.get_valid_access_token weixin_secret_key: 'bba7ba32bf3e1a60edd8bd8903ce33e5'
|
10
|
+
def self.get_valid_access_token options
|
11
|
+
::EricWeixin::AccessToken.transaction do
|
12
|
+
access_token = ::EricWeixin::AccessToken.where(weixin_secret_key: options[:weixin_secret_key]).first
|
13
|
+
if access_token.blank?
|
14
|
+
public_account = ::EricWeixin::PublicAccount.find_by_weixin_secret_key(options[:weixin_secret_key]).first
|
15
|
+
access_token = ::EricWeixin::AccessToken.new :weixin_secret_key => options[:weixin_secret_key],
|
16
|
+
:access_token => get_new_token(options[:weixin_secret_key]),
|
17
|
+
:expired_at => Time.now.to_i + 2*60*60,
|
18
|
+
:public_account_id => public_account.id
|
19
|
+
access_token.save!
|
20
|
+
end
|
21
|
+
|
22
|
+
if Time.now.to_i > (access_token.expired_at.to_i - 30)
|
23
|
+
access_token.access_token = get_new_token(options[:weixin_secret_key])
|
24
|
+
access_token.expired_at = Time.now.to_i + 2*60*60
|
25
|
+
access_token.save!
|
26
|
+
end
|
27
|
+
access_token.reload
|
28
|
+
access_token.access_token
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
private
|
34
|
+
#::EricWeixin::AccessToken.get_new_token 'bba7ba32bf3e1a60edd8bd8903ce33e5'
|
35
|
+
def self.get_new_token secret_key
|
36
|
+
account = ::EricWeixin::PublicAccount.where(:weixin_secret_key => secret_key).first
|
37
|
+
BusinessException.raise 'account 不存在' if account.blank?
|
38
|
+
response = RestClient.get "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=#{account.weixin_app_id}&secret=#{account.weixin_secret_key}"
|
39
|
+
JSON.parse(response)["access_token"]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class EricWeixin::Article < ActiveRecord::Base
|
2
|
+
self.table_name = "weixin_articles"
|
3
|
+
validates_presence_of :title, :pic_url, :link_url
|
4
|
+
has_many :weixin_article_newses, :class_name => '::EricWeixin::ArticleNews', foreign_key: "weixin_article_id"
|
5
|
+
has_many :weixin_news_datas, :class_name => '::EricWeixin::NewsData', through: :weixin_article_newses
|
6
|
+
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def create_article_data options
|
10
|
+
::EricWeixin::Article.transaction do
|
11
|
+
article = ::EricWeixin::Article.new(options)
|
12
|
+
article.save!
|
13
|
+
article
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class EricWeixin::ArticleNews < ActiveRecord::Base
|
2
|
+
self.table_name = 'weixin_article_news'
|
3
|
+
belongs_to :weixin_article, :class_name => '::EricWeixin::Article', :foreign_key => 'weixin_article_id'
|
4
|
+
belongs_to :weixin_newses, :class_name => '::EricWeixin::News', :foreign_key => 'weixin_news_id'
|
5
|
+
accepts_nested_attributes_for :weixin_newses
|
6
|
+
|
7
|
+
|
8
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class EricWeixin::News < ActiveRecord::Base
|
2
|
+
self.table_name = "weixin_news"
|
3
|
+
has_many :weixin_article_newses, :class_name => '::EricWeixin::ArticleNews', foreign_key: "weixin_news_id"
|
4
|
+
has_many :weixin_articles, -> { order "sort" }, :class_name => '::EricWeixin::Article', through: :weixin_article_newses
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
def generate_news_data
|
9
|
+
articles = []
|
10
|
+
self.weixin_articles.each do |article_data|
|
11
|
+
article = generate_article(article_data.title, article_data.desc, article_data.pic_url, article_data.link_url)
|
12
|
+
articles << article
|
13
|
+
end
|
14
|
+
articles
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def create_news_datas(options, weixin_article_data_ids, weixin_article_data_sort)
|
19
|
+
::EricWeixin::News.transaction do
|
20
|
+
news_data = ::EricWeixin::News.new
|
21
|
+
news_data.update_attributes(options)
|
22
|
+
news_data.weixin_articles.clear
|
23
|
+
weixin_article_data_ids.each do |article_data_id|
|
24
|
+
article_data = ::EricWeixin::Article.find(article_data_id)
|
25
|
+
if (!article_data.blank?) && (!news_data.weixin_articles.include?(article_data))
|
26
|
+
::EricWeixin::ArticleNews.create! weixin_article_id: article_data_id, weixin_news_id: news_data.id, sort: weixin_article_data_sort[article_data_id].first
|
27
|
+
end
|
28
|
+
end
|
29
|
+
news_data.save!
|
30
|
+
news_data
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def update_news_datas(id, options, weixin_article_data_ids, weixin_article_data_sort)
|
36
|
+
::EricWeixin::News.transaction do
|
37
|
+
news_data = ::EricWeixin::News.find(id)
|
38
|
+
news_data.update(options)
|
39
|
+
news_data.weixin_articles.clear
|
40
|
+
weixin_article_data_ids.each do |article_data_id|
|
41
|
+
article_data = ::EricWeixin::Article.find(article_data_id)
|
42
|
+
if (!article_data.blank?) && (!news_data.weixin_articles.include?(article_data))
|
43
|
+
::EricWeixin::ArticleNews.create! weixin_article_id: article_data_id, weixin_news_id: news_data.id, sort: weixin_article_data_sort[article_data_id].first
|
44
|
+
end
|
45
|
+
end
|
46
|
+
news_data.save!
|
47
|
+
news_data
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
module EricWeixin
|
2
|
+
class PublicAccount < ActiveRecord::Base
|
3
|
+
require "rest-client"
|
4
|
+
self.table_name = "weixin_public_accounts"
|
5
|
+
has_many :weixin_users, :class_name => 'WeixinUser', foreign_key: "weixin_public_account_id"
|
6
|
+
|
7
|
+
|
8
|
+
def self.get_secret app_id
|
9
|
+
account = ::EricWeixin::PublicAccount.where(weixin_app_id: app_id).first
|
10
|
+
account.weixin_secret_key
|
11
|
+
end
|
12
|
+
|
13
|
+
#::EricWeixin::PublicAccount.first.get_user_data_from_weixin_api 'osyUtswoeJ9d7p16RdpC5grOeukQ'
|
14
|
+
#返回Hash信息
|
15
|
+
def get_user_data_from_weixin_api openid
|
16
|
+
token = ::EricWeixin::AccessToken.get_valid_access_token weixin_secret_key: self.weixin_secret_key
|
17
|
+
response = RestClient.get "https://api.weixin.qq.com/cgi-bin/user/info?access_token=#{token}&openid=#{openid}&lang=zh_CN"
|
18
|
+
response = JSON.parse response.body
|
19
|
+
response["nickname"] = CGI::escape(response["nickname"]) if not response["nickname"].blank?
|
20
|
+
response
|
21
|
+
end
|
22
|
+
|
23
|
+
#::EricWeixin::PublicAccount.first.weixin_menus
|
24
|
+
def weixin_menus
|
25
|
+
token = ::EricWeixin::AccessToken.get_valid_access_token weixin_secret_key: self.weixin_secret_key
|
26
|
+
response = RestClient.get "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=#{token}"
|
27
|
+
response = JSON.parse response.body
|
28
|
+
response['menu']
|
29
|
+
end
|
30
|
+
#
|
31
|
+
# ::EricWeixin::PublicAccount.first.create_menu '{
|
32
|
+
# "button":[
|
33
|
+
# {
|
34
|
+
# "name":"俱乐部2",
|
35
|
+
# "sub_button":[
|
36
|
+
#
|
37
|
+
# {
|
38
|
+
# "type":"click",
|
39
|
+
# "name":"节目介绍",
|
40
|
+
# "key":"V1001_PROGRAMME_INTRODUCTION"
|
41
|
+
# }]
|
42
|
+
# },
|
43
|
+
# {
|
44
|
+
# "type":"view",
|
45
|
+
# "name":"创意社区",
|
46
|
+
# "url":"http://m.wsq.qq.com/264164362"
|
47
|
+
# },
|
48
|
+
# {
|
49
|
+
# "name":"辣妈奶爸",
|
50
|
+
# "sub_button":[
|
51
|
+
# {
|
52
|
+
# "type":"click",
|
53
|
+
# "name":"百家言",
|
54
|
+
# "key":"V1001_BAIJIAYAN"
|
55
|
+
# },
|
56
|
+
# {
|
57
|
+
# "type":"view",
|
58
|
+
# "name":"辣妈养成记",
|
59
|
+
# "url":"http://m.wsq.qq.com/264164362/t/32"
|
60
|
+
# },
|
61
|
+
# {
|
62
|
+
# "type":"view",
|
63
|
+
# "name":"奶爸集中营4",
|
64
|
+
# "url":"http://m.wsq.qq.com/264164362/t/35"
|
65
|
+
# }]
|
66
|
+
# }]
|
67
|
+
# }'
|
68
|
+
def create_menu menu_json
|
69
|
+
::EricWeixin::PublicAccount.transaction do
|
70
|
+
self.menu_json = menu_json
|
71
|
+
self.save!
|
72
|
+
token = ::EricWeixin::AccessToken.get_valid_access_token weixin_secret_key: self.weixin_secret_key
|
73
|
+
response = RestClient.post "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=#{token}", menu_json
|
74
|
+
response = JSON.parse response.body
|
75
|
+
BusinessException.raise response["errmsg"] if response["errcode"].to_i!=0
|
76
|
+
pp response
|
77
|
+
return 0
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# ::EricWeixin::PublicAccount.first.rebuild_users
|
82
|
+
def rebuild_users next_openid = nil
|
83
|
+
token = ::EricWeixin::AccessToken.get_valid_access_token weixin_secret_key: self.weixin_secret_key
|
84
|
+
response = if next_openid.blank?
|
85
|
+
RestClient.get "https://api.weixin.qq.com/cgi-bin/user/get?access_token=#{token}"
|
86
|
+
else
|
87
|
+
RestClient.get "https://api.weixin.qq.com/cgi-bin/user/get?access_token=#{token}&next_openid=#{next_openid}"
|
88
|
+
end
|
89
|
+
response = JSON.parse response.body
|
90
|
+
if response["count"].to_i > 0
|
91
|
+
response["data"]["openid"].each do |openid|
|
92
|
+
::EricWeixin::WeixinUser.create_weixin_user self.weixin_secret_key, openid
|
93
|
+
end
|
94
|
+
tmp_next_openid = response["next_openid"]
|
95
|
+
self.rebuild_users tmp_next_openid unless tmp_next_openid.blank?
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
GLOBAL_CODES = {
|
101
|
+
-1 => "系统繁忙",
|
102
|
+
0 => "请求成功",
|
103
|
+
40001 => "获取access_token时AppSecret错误,或者access_token无效",
|
104
|
+
40002 => "不合法的凭证类型",
|
105
|
+
40003 => "不合法的OpenID",
|
106
|
+
40004 => "不合法的媒体文件类型",
|
107
|
+
40005 => "不合法的文件类型",
|
108
|
+
40006 => "不合法的文件大小",
|
109
|
+
40007 => "不合法的媒体文件id",
|
110
|
+
40008 => "不合法的消息类型",
|
111
|
+
40009 => "不合法的图片文件大小",
|
112
|
+
40010 => "不合法的语音文件大小",
|
113
|
+
40011 => "不合法的视频文件大小",
|
114
|
+
40012 => "不合法的缩略图文件大小",
|
115
|
+
40013 => "不合法的APPID",
|
116
|
+
40014 => "不合法的access_token",
|
117
|
+
40015 => "不合法的菜单类型",
|
118
|
+
40016 => "不合法的按钮个数",
|
119
|
+
40017 => "不合法的按钮个数",
|
120
|
+
40018 => "不合法的按钮名字长度",
|
121
|
+
40019 => "不合法的按钮KEY长度",
|
122
|
+
40020 => "不合法的按钮URL长度",
|
123
|
+
40021 => "不合法的菜单版本号",
|
124
|
+
40022 => "不合法的子菜单级数",
|
125
|
+
40023 => "不合法的子菜单按钮个数",
|
126
|
+
40024 => "不合法的子菜单按钮类型",
|
127
|
+
40025 => "不合法的子菜单按钮名字长度",
|
128
|
+
40026 => "不合法的子菜单按钮KEY长度",
|
129
|
+
40027 => "不合法的子菜单按钮URL长度",
|
130
|
+
40028 => "不合法的自定义菜单使用用户",
|
131
|
+
40029 => "不合法的oauth_code",
|
132
|
+
40030 => "不合法的refresh_token",
|
133
|
+
40031 => "不合法的openid列表",
|
134
|
+
40032 => "不合法的openid列表长度",
|
135
|
+
40033 => "不合法的请求字符,不能包含xxxx格式的字符",
|
136
|
+
40035 => "不合法的参数",
|
137
|
+
40038 => "不合法的请求格式",
|
138
|
+
40039 => "不合法的URL长度",
|
139
|
+
40050 => "不合法的分组id",
|
140
|
+
40051 => "分组名字不合法",
|
141
|
+
41001 => "缺少access_token参数",
|
142
|
+
41002 => "缺少appid参数",
|
143
|
+
41003 => "缺少refresh_token参数",
|
144
|
+
41004 => "缺少secret参数",
|
145
|
+
41005 => "缺少多媒体文件数据",
|
146
|
+
41006 => "缺少media_id参数",
|
147
|
+
41007 => "缺少子菜单数据",
|
148
|
+
41008 => "缺少oauth code",
|
149
|
+
41009 => "缺少openid",
|
150
|
+
42001 => "access_token超时",
|
151
|
+
42002 => "refresh_token超时",
|
152
|
+
42003 => "oauth_code超时",
|
153
|
+
43001 => "需要GET请求",
|
154
|
+
43002 => "需要POST请求",
|
155
|
+
43003 => "需要HTTPS请求",
|
156
|
+
43004 => "需要接收者关注",
|
157
|
+
43005 => "需要好友关系",
|
158
|
+
44001 => "多媒体文件为空",
|
159
|
+
44002 => "POST的数据包为空",
|
160
|
+
44003 => "图文消息内容为空",
|
161
|
+
44004 => "文本消息内容为空",
|
162
|
+
45001 => "多媒体文件大小超过限制",
|
163
|
+
45002 => "消息内容超过限制",
|
164
|
+
45003 => "标题字段超过限制",
|
165
|
+
45004 => "描述字段超过限制",
|
166
|
+
45005 => "链接字段超过限制",
|
167
|
+
45006 => "图片链接字段超过限制",
|
168
|
+
45007 => "语音播放时间超过限制",
|
169
|
+
45008 => "图文消息超过限制",
|
170
|
+
45009 => "接口调用超过限制",
|
171
|
+
45010 => "创建菜单个数超过限制",
|
172
|
+
45015 => "回复时间超过限制",
|
173
|
+
45016 => "系统分组,不允许修改",
|
174
|
+
45017 => "分组名字过长",
|
175
|
+
45018 => "分组数量超过上限",
|
176
|
+
46001 => "不存在媒体数据",
|
177
|
+
46002 => "不存在的菜单版本",
|
178
|
+
46003 => "不存在的菜单数据",
|
179
|
+
46004 => "不存在的用户",
|
180
|
+
47001 => "解析JSON/XML内容错误",
|
181
|
+
48001 => "api功能未授权",
|
182
|
+
50001 => "用户未授权该api"
|
183
|
+
}
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
class EricWeixin::ReplyMessageRule < ActiveRecord::Base
|
2
|
+
self.table_name = 'weixin_reply_message_rules'
|
3
|
+
scope :valid, -> { where(:is_valid => true) }
|
4
|
+
belongs_to :weixin_public_account, :class_name => '::EricWeixin::PublicAccount', foreign_key: "weixin_public_account_id"
|
5
|
+
delegate :name, to: :weixin_public_account, prefix: true, allow_nil: true
|
6
|
+
|
7
|
+
KEY_WORD_TYPE_LABEL = {"keyword" => '字符', 'regularexpr' => '正则表达式'}
|
8
|
+
REPLY_TYPE_LABEL = {"text" => '静态字符串', 'wx_function' => '动态运行', 'news' => '多图文'}
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def create_reply_message_rule options
|
13
|
+
options = get_arguments_options options, [:weixin_public_account_id, :key_word, :reply_message, :key_word_type, :order, :reply_type], is_valid: true
|
14
|
+
::EricWeixin::ReplyMessageRule.transaction do
|
15
|
+
reply_message_rule = ::EricWeixin::ReplyMessageRule.new options
|
16
|
+
public_account = ::EricWeixin::PublicAccount.find(options[:weixin_public_account_id])
|
17
|
+
reply_message_rule.weixin_app_id = public_account.weixin_app_id
|
18
|
+
reply_message_rule.weixin_secret_key = public_account.weixin_secret_key
|
19
|
+
reply_message_rule.save!
|
20
|
+
reply_message_rule
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def update_reply_message_rule(rule_id, options)
|
25
|
+
options = get_arguments_options options, [:weixin_public_account_id, :key_word, :reply_message, :key_word_type, :order, :reply_type, :is_valid]
|
26
|
+
EricWeixin::ReplyMessageRule.transaction do
|
27
|
+
rule = EricWeixin::ReplyMessageRule.find(rule_id)
|
28
|
+
rule.update_attributes(options)
|
29
|
+
public_account = ::EricWeixin::PublicAccount.find(options[:weixin_public_account_id])
|
30
|
+
rule.weixin_app_id = public_account.weixin_app_id
|
31
|
+
rule.weixin_secret_key = public_account.weixin_secret_key
|
32
|
+
rule.save!
|
33
|
+
rule
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def process_rule(receive_message, secret_key)
|
38
|
+
business_type = "#{receive_message[:MsgType]}~#{receive_message[:Event]}"
|
39
|
+
|
40
|
+
|
41
|
+
reply_message = case business_type
|
42
|
+
#订阅
|
43
|
+
when /event~subscribe/
|
44
|
+
result = ::Weixin::Process.subscribe receive_message
|
45
|
+
if result == true
|
46
|
+
::EricWeixin::WeixinUser.create_weixin_user secret_key, receive_message[:FromUserName]
|
47
|
+
match_key_words 'subscribe', secret_key, receive_message
|
48
|
+
else
|
49
|
+
result
|
50
|
+
end
|
51
|
+
when /event~unsubscribe/
|
52
|
+
result = ::Weixin::Process.unsubscribe receive_message
|
53
|
+
if result == true
|
54
|
+
::EricWeixin::WeixinUser.create_weixin_user secret_key, receive_message[:FromUserName]
|
55
|
+
match_key_words 'unsubscribe', secret_key, receive_message
|
56
|
+
else
|
57
|
+
result
|
58
|
+
end
|
59
|
+
when /event~CLICK/
|
60
|
+
result = ::Weixin::Process.click_event receive_message[:EventKey], receive_message
|
61
|
+
if result == true
|
62
|
+
match_key_words receive_message[:EventKey], secret_key, receive_message
|
63
|
+
else
|
64
|
+
result
|
65
|
+
end
|
66
|
+
when /text~/
|
67
|
+
result = ::Weixin::Process.text_event receive_message[:Content], receive_message
|
68
|
+
if result == true
|
69
|
+
match_key_words receive_message[:Content], secret_key, receive_message
|
70
|
+
else
|
71
|
+
result
|
72
|
+
end
|
73
|
+
else
|
74
|
+
result = ::Weixin::Process.another_event receive_message
|
75
|
+
if result == true
|
76
|
+
match_key_words 'unknow~words', secret_key, receive_message
|
77
|
+
else
|
78
|
+
result
|
79
|
+
end
|
80
|
+
end
|
81
|
+
"message_to_wechat:".to_logger
|
82
|
+
reply_message.to_logger
|
83
|
+
reply_message
|
84
|
+
end
|
85
|
+
|
86
|
+
def match_key_words wx_key_word, secret_key, receive_message
|
87
|
+
matched_rule = EricWeixin::ReplyMessageRule.order(order: :desc).
|
88
|
+
where(:key_word => wx_key_word, :weixin_secret_key => secret_key).first
|
89
|
+
if matched_rule.nil?
|
90
|
+
return EricWeixin::ReplyMessage::transfer_mult_customer_service ToUserName: receive_message[:FromUserName],
|
91
|
+
FromUserName: receive_message[:ToUserName]
|
92
|
+
end
|
93
|
+
reply_msg = case matched_rule.reply_type
|
94
|
+
when "text"
|
95
|
+
EricWeixin::ReplyMessage.get_reply_user_message_text ToUserName: receive_message[:FromUserName],
|
96
|
+
FromUserName: receive_message[:ToUserName],
|
97
|
+
Content: matched_rule.reply_message
|
98
|
+
when "news"
|
99
|
+
weixin_news = ::EricWeixin::News.find_by_match_key matched_rule.reply_message
|
100
|
+
EricWeixin::ReplyMessage::get_reply_user_message_image_text ToUserName: receive_message[:FromUserName],
|
101
|
+
FromUserName: receive_message[:ToUserName],
|
102
|
+
news: weixin_news.weixin_articles
|
103
|
+
when "wx_function"
|
104
|
+
Weixin::WeixinAutoReplyFunctions.send(matched_rule.reply_message, {:key_word => wx_key_word, :receive_message => receive_message})
|
105
|
+
end
|
106
|
+
reply_msg
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class EricWeixin::WeixinUser < ActiveRecord::Base
|
2
|
+
belongs_to :member_info
|
3
|
+
belongs_to :weixin_public_account, :class_name => '::EricWeixin::PublicAccount', :foreign_key => 'weixin_public_account_id'
|
4
|
+
validates_uniqueness_of :openid, scope: :weixin_secret_key
|
5
|
+
validates_presence_of :openid, :weixin_secret_key, :weixin_public_account
|
6
|
+
|
7
|
+
def nickname
|
8
|
+
CGI::unescape(self.attributes["nickname"])
|
9
|
+
end
|
10
|
+
|
11
|
+
def follow_status
|
12
|
+
self.subscribe.to_i == 1
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
|
17
|
+
##
|
18
|
+
# ===业务说明:创建、更新微信用户
|
19
|
+
# * 微信用户在关注、取消关注时更新用户信息。
|
20
|
+
# * 当用户关注微信时,创建用户。
|
21
|
+
# * 当用户取消关注时,把用户标记为取消关注,同时更新用户的最新信息(包含用户名等)
|
22
|
+
# ===参数说明
|
23
|
+
# * secret_key::公众账号的secret_key,其值取决于公众账号的设置。
|
24
|
+
# * openid::用户的openid,微信服务器传送过来。
|
25
|
+
# ===调用方法
|
26
|
+
# EricWeixin::WeixinUser.create_weixin_user 'adsfkj', 'sdfdf'
|
27
|
+
# EricWeixin::WeixinUser.create_weixin_user 'adsfkj', 'sdfdf'
|
28
|
+
# ====返回
|
29
|
+
# 正常情况下返回当前微信用户 <tt>::EricWeixin::WeixinUser</tt>,抛出异常时错误查看异常信息。
|
30
|
+
def create_weixin_user(secret_key, openid)
|
31
|
+
public_account = ::Weixin::PublicAccount.find_by_weixin_secret_key(secret_key)
|
32
|
+
::Weixin::ReplyMessageRule.transaction do
|
33
|
+
weixin_user = ::EricWeixin::WeixinUser.where(openid: openid, weixin_secret_key: secret_key).first
|
34
|
+
if weixin_user.blank?
|
35
|
+
weixin_user = ::EricWeixin::WeixinUser.new openid: openid,
|
36
|
+
weixin_secret_key: secret_key,
|
37
|
+
weixin_public_account_id: public_account.id
|
38
|
+
weixin_user.save!
|
39
|
+
end
|
40
|
+
wx_user_data = public_account.get_user_data_from_weixin_api openid
|
41
|
+
weixin_user.update_attributes(wx_user_data)
|
42
|
+
weixin_user
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def export_users_to_csv(weixin_secret_key)
|
48
|
+
require 'csv'
|
49
|
+
weixin_users = ::EricWeixin::WeixinUser.where(weixin_secret_key: weixin_secret_key)
|
50
|
+
CSV.generate do |csv|
|
51
|
+
csv << ["订阅状态", "openid", "昵称", "性别", "语言", "城市", "省份", "国家", "订阅时间"]
|
52
|
+
weixin_users.each do |weixin_user|
|
53
|
+
user_fields = []
|
54
|
+
user_fields << (weixin_user.follow_status ? '订阅': '取消订阅')
|
55
|
+
user_fields << weixin_user.openid
|
56
|
+
user_fields << weixin_user.nickname
|
57
|
+
user_fields << case weixin_user.sex when 1 then '男' when 2 then '女' else '未知' end
|
58
|
+
user_fields << case weixin_user.language when 'zh_CN' then '简体中文' when 'zh_TW' then '繁体中文' when 'en' then '英文' else '其它' end
|
59
|
+
user_fields << weixin_user.city
|
60
|
+
user_fields << weixin_user.province
|
61
|
+
user_fields << weixin_user.country
|
62
|
+
user_fields << Time.at(weixin_user.subscribe_time.to_i).chinese_format
|
63
|
+
csv << user_fields
|
64
|
+
end
|
65
|
+
csv
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
#绑定会员
|
71
|
+
def connect_member(options)
|
72
|
+
openid = options[:openid]
|
73
|
+
user_name = options[:username]
|
74
|
+
password = options[:password]
|
75
|
+
|
76
|
+
::EricWeixin::WeixinUser.transaction do
|
77
|
+
member_info = MemberInfo.where(user_name: user_name, password: password).first
|
78
|
+
BusinessException.raise '该会员不存在' if member_info.blank?
|
79
|
+
|
80
|
+
weixin_user = ::EricWeixin::WeixinUser.find_by_openid(openid)
|
81
|
+
BusinessException.raise '该微信用户不存在' if weixin_user.blank?
|
82
|
+
|
83
|
+
weixin_user.member_info = member_info
|
84
|
+
weixin_user.save!
|
85
|
+
member_info
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%=@ee%>
|
@@ -13,11 +13,11 @@ module EricWeixin
|
|
13
13
|
# ===参数说明
|
14
14
|
# * ToUserName: 收取方的账号
|
15
15
|
# * FromUserName: 开发者账号
|
16
|
-
# * news: 文章列表,
|
16
|
+
# * news: 文章列表,EricWeixin::Article 的实例数组
|
17
17
|
# ===示例
|
18
|
-
# Tools::
|
18
|
+
# Tools::EricWeixin::ReplyMessage::get_reply_user_message_image_text ToUserName: 'xx',
|
19
19
|
# FromUserName: 'yy',
|
20
|
-
# news:[
|
20
|
+
# news:[EricWeixin::ArticleData.new]
|
21
21
|
def self.get_reply_user_message_image_text options
|
22
22
|
xml = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
|
23
23
|
xml.send(:xml) {
|
@@ -49,7 +49,7 @@ module EricWeixin
|
|
49
49
|
# * FromUserName: 开发者账号
|
50
50
|
# * Content: 回复的消息内容
|
51
51
|
# ===示例
|
52
|
-
# Tools::
|
52
|
+
# Tools::EricWeixin::ReplyMessage.get_reply_user_message_text ToUserName: 'xx',
|
53
53
|
# FromUserName: 'yy',
|
54
54
|
# Content: 'haha'
|
55
55
|
def self.get_reply_user_message_text options
|
@@ -70,7 +70,7 @@ module EricWeixin
|
|
70
70
|
# * ToUserName: 收取方的账号
|
71
71
|
# * FromUserName: 开发者账号
|
72
72
|
# ===示例
|
73
|
-
#
|
73
|
+
# EricWeixin::ReplyMessage::transfer_mult_customer_service ToUserName: 'xxx',
|
74
74
|
# FromUserName: 'yyyy',
|
75
75
|
def self.transfer_mult_customer_service options
|
76
76
|
xml = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
|
data/lib/eric_weixin/version.rb
CHANGED
data/lib/eric_weixin.rb
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
require "eric_weixin/version"
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/eric_weixin/app/model/access_token.rb'
|
4
|
+
require File.dirname(__FILE__) + '/eric_weixin/app/model/article.rb'
|
5
|
+
require File.dirname(__FILE__) + '/eric_weixin/app/model/article_news.rb'
|
6
|
+
require File.dirname(__FILE__) + '/eric_weixin/app/model/news.rb'
|
7
|
+
require File.dirname(__FILE__) + '/eric_weixin/app/model/public_account.rb'
|
8
|
+
require File.dirname(__FILE__) + '/eric_weixin/app/model/reply_message_rule.rb'
|
9
|
+
require File.dirname(__FILE__) + '/eric_weixin/app/model/weixin_user.rb'
|
2
10
|
require File.dirname(__FILE__) + '/eric_weixin/reply_message.rb'
|
3
11
|
|
12
|
+
|
13
|
+
require File.dirname(__FILE__) + '/eric_weixin/app/controllers/weixin/weixin_controller'
|
14
|
+
|
15
|
+
|
4
16
|
module EricWeixin
|
5
|
-
#
|
17
|
+
# 把gem目录放作为视图目录
|
18
|
+
ActionController::Base.append_view_path(File.dirname(__FILE__) + '/eric_weixin/app/views')
|
6
19
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eric_weixin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 刘晓琦
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -28,30 +28,158 @@ dependencies:
|
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: nokogiri
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rest-client
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
53
60
|
- !ruby/object:Gem::Version
|
54
61
|
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activerecord
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4.1'
|
76
|
+
- - '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 4.1.4
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '4.1'
|
86
|
+
- - '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 4.1.4
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rails
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ~>
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '4.1'
|
96
|
+
- - '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 4.1.4
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ~>
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '4.1'
|
106
|
+
- - '>='
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: 4.1.4
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: actionpack
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ~>
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '4.1'
|
116
|
+
- - '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: 4.1.4
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '4.1'
|
126
|
+
- - '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: 4.1.4
|
129
|
+
- !ruby/object:Gem::Dependency
|
130
|
+
name: activesupport
|
131
|
+
requirement: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ~>
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '4.1'
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 4.1.4
|
139
|
+
type: :development
|
140
|
+
prerelease: false
|
141
|
+
version_requirements: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ~>
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '4.1'
|
146
|
+
- - '>='
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: 4.1.4
|
149
|
+
- !ruby/object:Gem::Dependency
|
150
|
+
name: actionview
|
151
|
+
requirement: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - ~>
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '4.1'
|
156
|
+
- - '>='
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: 4.1.4
|
159
|
+
type: :development
|
160
|
+
prerelease: false
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ~>
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '4.1'
|
166
|
+
- - '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: 4.1.4
|
169
|
+
- !ruby/object:Gem::Dependency
|
170
|
+
name: eric_tools
|
171
|
+
requirement: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - ~>
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: 0.0.4
|
176
|
+
type: :development
|
177
|
+
prerelease: false
|
178
|
+
version_requirements: !ruby/object:Gem::Requirement
|
179
|
+
requirements:
|
180
|
+
- - ~>
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: 0.0.4
|
55
183
|
description: 微信插件
|
56
184
|
email:
|
57
185
|
- ericliu@ikidstv.com
|
@@ -72,6 +200,15 @@ files:
|
|
72
200
|
- Rakefile
|
73
201
|
- eric_weixin.gemspec
|
74
202
|
- lib/eric_weixin.rb
|
203
|
+
- lib/eric_weixin/app/controllers/weixin/weixin_controller.rb
|
204
|
+
- lib/eric_weixin/app/model/access_token.rb
|
205
|
+
- lib/eric_weixin/app/model/article.rb
|
206
|
+
- lib/eric_weixin/app/model/article_news.rb
|
207
|
+
- lib/eric_weixin/app/model/news.rb
|
208
|
+
- lib/eric_weixin/app/model/public_account.rb
|
209
|
+
- lib/eric_weixin/app/model/reply_message_rule.rb
|
210
|
+
- lib/eric_weixin/app/model/weixin_user.rb
|
211
|
+
- lib/eric_weixin/app/views/eric_weixin/weixin/aa.erb
|
75
212
|
- lib/eric_weixin/reply_message.rb
|
76
213
|
- lib/eric_weixin/version.rb
|
77
214
|
homepage: ''
|