eric_weixin 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/eric_weixin/cms/weixin/customs_service_records_controller.rb +1 -1
- data/app/controllers/eric_weixin/cms/weixin/weixin_users_controller.rb +3 -1
- data/app/controllers/eric_weixin/wz/pays_controller.rb +24 -0
- data/app/models/eric_weixin/access_token.rb +1 -1
- data/app/models/eric_weixin/customs_service_record.rb +4 -0
- data/app/models/eric_weixin/jsapi_ticket.rb +67 -0
- data/app/models/eric_weixin/media_news.rb +26 -1
- data/app/models/eric_weixin/media_news_sent_record.rb +6 -0
- data/app/models/eric_weixin/public_account.rb +28 -0
- data/app/models/eric_weixin/redpack.rb +30 -0
- data/app/models/eric_weixin/redpack_order.rb +92 -0
- data/app/models/eric_weixin/reply_message_rule.rb +136 -34
- data/app/models/eric_weixin/weixin_user.rb +9 -3
- data/app/views/eric_weixin/cms/weixin/customs_service_records/index.html.erb +2 -1
- data/app/views/eric_weixin/cms/weixin/media_news/_select_article.html.erb +1 -1
- data/app/views/eric_weixin/cms/weixin/media_news/new.html.erb +2 -2
- data/app/views/eric_weixin/cms/weixin/reply_message_rules/index.html.erb +2 -2
- data/app/views/eric_weixin/cms/weixin/two_dimension_codes/_two_dimension_code_form.html.erb +1 -1
- data/app/views/eric_weixin/cms/weixin/weixin_users/index.html.erb +14 -1
- data/db/migrate/20150906064203_add_error_count_to_weixin_media_news.rb +5 -0
- data/db/migrate/20150906072855_create_weixin_media_news_sent_records.rb +15 -0
- data/db/migrate/20150908023239_add_phone_to_weixin_users.rb +5 -0
- data/db/migrate/20150910024059_create_weixin_customs_service_records.rb +16 -0
- data/db/migrate/20150911023948_create_weixin_redpack_orders.rb +21 -0
- data/db/migrate/20150911062057_create_weixin_redpacks.rb +13 -0
- data/db/migrate/20150914061051_create_jsapi_tickets.rb +10 -0
- data/lib/eric_weixin/modules/mult_customer.rb +6 -4
- data/lib/eric_weixin/modules/pay.rb +84 -0
- data/lib/eric_weixin/version.rb +1 -1
- metadata +15 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f051bb6d4db95b0b0dc05755a37b0cb58cac07ec
|
4
|
+
data.tar.gz: e7d315eb8728a9e5b76dffa7f1b88e381f0ddf80
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bcbd2c1d0bbf1de98ecaa786e0e5ee495aacbc25712d8577061e608e79c756501183b5a565f79b4187dca1a883bb1b9d559503f57dbfe354815a3ca615a8cc1
|
7
|
+
data.tar.gz: 7ff65051d3508cd2632e26972e94017180610045656c2e054d6a8efaf4f68a8f447183a8622ff45905ccc1b6df45b3c88ca6b3753fefb4ea65ceeeabc8732083
|
@@ -3,6 +3,6 @@ class EricWeixin::Cms::Weixin::CustomsServiceRecordsController < EricWeixin::Cms
|
|
3
3
|
def index
|
4
4
|
options = params.permit(:public_account_id, :opercode, :chat_date, :chat_content, :worker, :nick_name)
|
5
5
|
@customs_service_records = ::EricWeixin::CustomsServiceRecord.common_query options
|
6
|
-
@customs_service_records = @customs_service_records.paginate(page: params[:page], per_page:20)
|
6
|
+
@customs_service_records = @customs_service_records.order(:time).paginate(page: params[:page], per_page:20)
|
7
7
|
end
|
8
8
|
end
|
@@ -9,7 +9,9 @@ class EricWeixin::Cms::Weixin::WeixinUsersController < EricWeixin::Cms::BaseCont
|
|
9
9
|
:province,
|
10
10
|
:weixin_public_account_id,
|
11
11
|
:start_date,
|
12
|
-
:end_date
|
12
|
+
:end_date,
|
13
|
+
:first_register_channel,
|
14
|
+
:last_register_channel)).
|
13
15
|
order(id: :desc).
|
14
16
|
paginate(page: params[:page]||1, per_page: params[:per_page]||10) unless public_account.blank?
|
15
17
|
end
|
@@ -12,4 +12,28 @@ class EricWeixin::Wz::PaysController < ApplicationController
|
|
12
12
|
render text: '您支付失败,请返回重新尝试,谢谢。'
|
13
13
|
end
|
14
14
|
|
15
|
+
# wxappid
|
16
|
+
# re_openid
|
17
|
+
# total_amount
|
18
|
+
# wishing
|
19
|
+
# client_ip
|
20
|
+
# act_name
|
21
|
+
# remark
|
22
|
+
# def sendredpack
|
23
|
+
# pp "******************* params *********************"
|
24
|
+
# pp params
|
25
|
+
# weixin_user = ::Weixin::WeixinUser.find_by_openid(params[:openid])
|
26
|
+
# public_account = weixin_user.weixin_public_account
|
27
|
+
# options = {}
|
28
|
+
# options[:wxappid] = public_account.weixin_app_id
|
29
|
+
# options[:re_openid] = params[:openid]
|
30
|
+
# options[:total_amount] = params[:total_fee]
|
31
|
+
# options[:wishing] = "恭喜发财"
|
32
|
+
# options[:client_ip] = get_ip
|
33
|
+
# options[:act_name] = "送福利"
|
34
|
+
# options[:remark] = "第一次送"
|
35
|
+
# EricWeixin::Pay.sendredpack options
|
36
|
+
# render text: 'ok'
|
37
|
+
# end
|
38
|
+
|
15
39
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module EricWeixin
|
2
2
|
class AccessToken < ActiveRecord::Base
|
3
3
|
|
4
|
-
belongs_to :public_account, :class_name => '::EricWeixin::PublicAccount', foreign_key: :
|
4
|
+
belongs_to :public_account, :class_name => '::EricWeixin::PublicAccount', foreign_key: :public_account_id
|
5
5
|
|
6
6
|
self.table_name = "weixin_access_tokens"
|
7
7
|
|
@@ -71,6 +71,10 @@ class EricWeixin::CustomsServiceRecord < ActiveRecord::Base
|
|
71
71
|
::EricWeixin::WeixinUser.find_by_openid(self.openid).nickname rescue ''
|
72
72
|
end
|
73
73
|
|
74
|
+
def wixin_user
|
75
|
+
::EricWeixin::WeixinUser.find_by_openid(self.openid)
|
76
|
+
end
|
77
|
+
|
74
78
|
def self.common_query options
|
75
79
|
records = self.all
|
76
80
|
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module EricWeixin
|
2
|
+
class JsapiTicket < ActiveRecord::Base
|
3
|
+
|
4
|
+
belongs_to :public_account, :class_name => '::EricWeixin::PublicAccount', foreign_key: :public_account_id
|
5
|
+
|
6
|
+
self.table_name = "weixin_jsapi_tickets"
|
7
|
+
|
8
|
+
|
9
|
+
# 获取 jsapi ticket 方法一。根据 APPID 查到微信公众号 PublicAccount.id ,然后
|
10
|
+
# 调用 ::EricWeixin::JsapiTicket.get_valid_ticket 获取 jsapi ticket 并作为返回值返回.
|
11
|
+
# ===参数说明
|
12
|
+
# * app_id #微信公众号的 app_id
|
13
|
+
# ===调用示例
|
14
|
+
# ::EricWeixin::JsapiTicket.get_valid_jsapi_ticket_by_app_id app_id: 'wx51729870d9012531'
|
15
|
+
def self.get_valid_jsapi_ticket_by_app_id options
|
16
|
+
pa = ::EricWeixin::PublicAccount.find_by_weixin_app_id options[:app_id]
|
17
|
+
::EricWeixin::JsapiTicket.get_valid_ticket public_account_id: pa.id
|
18
|
+
end
|
19
|
+
|
20
|
+
# 获取 jsapi ticket 方法二。根据微信公众号 PublicAccount.id 获取 jsapi ticket .
|
21
|
+
# 若微信公众号未存在 jsapi ticket 或者 jsapi ticket 过期都立即获取新的并返回。
|
22
|
+
# ===参数说明
|
23
|
+
# * public_account_id #公众账号 ID
|
24
|
+
# ===调用示例
|
25
|
+
# ::EricWeixin::JsapiTicket.get_valid_ticket public_account_id: 1
|
26
|
+
def self.get_valid_ticket options
|
27
|
+
self.transaction do
|
28
|
+
ticket = ::EricWeixin::JsapiTicket.find_by_public_account_id options[:public_account_id]
|
29
|
+
if ticket.blank?
|
30
|
+
public_account = ::EricWeixin::PublicAccount.find_by_id options[:public_account_id]
|
31
|
+
ticket = ::EricWeixin::JsapiTicket.new jsapi_ticket: get_new_ticket(public_account.id),
|
32
|
+
expired_at: Time.now.to_i + 2*60*60,
|
33
|
+
public_account_id: public_account.id
|
34
|
+
ticket.save!
|
35
|
+
end
|
36
|
+
|
37
|
+
if Time.now.to_i > (ticket.expired_at.to_i - 30)
|
38
|
+
ticket.jsapi_ticket = get_new_ticket options[:public_account_id]
|
39
|
+
ticket.expired_at = Time.now.to_i + 2*60*60
|
40
|
+
ticket.save!
|
41
|
+
end
|
42
|
+
ticket.reload
|
43
|
+
ticket.jsapi_ticket
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# 根据微信公众号从微信服务器获取最新的 AccessToken.
|
48
|
+
# ===参数说明
|
49
|
+
# * public_account_id #公众账号 ID
|
50
|
+
# ===调用示例
|
51
|
+
# ::EricWeixin::AccessToken.get_new_token '5e3b98ca0000959946657212739fd535'
|
52
|
+
# https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=12&secret=23
|
53
|
+
def self.get_new_ticket public_account_id
|
54
|
+
account = ::EricWeixin::PublicAccount.find_by_id public_account_id
|
55
|
+
BusinessException.raise 'account 不存在' if account.blank?
|
56
|
+
# url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=#{account.weixin_app_id}&secret=#{account.weixin_secret_key}"
|
57
|
+
access_token = ::EricWeixin::AccessToken.get_valid_access_token public_account_id: account.id
|
58
|
+
url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=#{access_token}&type=jsapi"
|
59
|
+
response = RestClient.get url
|
60
|
+
pp response
|
61
|
+
JSON.parse(response)["ticket"]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
|
@@ -2,6 +2,7 @@ class EricWeixin::MediaNews < ActiveRecord::Base
|
|
2
2
|
self.table_name = 'weixin_media_news'
|
3
3
|
has_many :media_article_news, foreign_key: 'weixin_media_news_id'
|
4
4
|
has_many :media_articles, through: :media_article_news
|
5
|
+
has_many :media_messages, foreign_key: 'media_news_id'
|
5
6
|
# def upload_news_old
|
6
7
|
#
|
7
8
|
# EricWeixin::MediaNews.transaction do
|
@@ -77,6 +78,7 @@ class EricWeixin::MediaNews < ActiveRecord::Base
|
|
77
78
|
|
78
79
|
def delete_server_news
|
79
80
|
EricWeixin::MediaNews.transaction do
|
81
|
+
BusinessException.raise '该图文已经发送出去,不可以删除。' if self.status == 1
|
80
82
|
token = ::EricWeixin::AccessToken.get_valid_access_token public_account_id: self.public_account_id
|
81
83
|
url = "https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=#{token}"
|
82
84
|
|
@@ -101,7 +103,7 @@ class EricWeixin::MediaNews < ActiveRecord::Base
|
|
101
103
|
end
|
102
104
|
|
103
105
|
def send_to_openids
|
104
|
-
BusinessException.raise '' if self.media_id.blank?
|
106
|
+
BusinessException.raise 'media_id不可以为空。' if self.media_id.blank?
|
105
107
|
EricWeixin::MediaNews.transaction do
|
106
108
|
openids = ::Weixin::Process.__send__ self.user_group_name
|
107
109
|
pp "****************** 将要发送的openids *********************"
|
@@ -125,7 +127,12 @@ class EricWeixin::MediaNews < ActiveRecord::Base
|
|
125
127
|
pp response
|
126
128
|
response_json = JSON.parse(response)
|
127
129
|
BusinessException.raise response_json["errmsg"] unless response_json["errcode"] == 0
|
130
|
+
media_message = ::EricWeixin::MediaNewsSentRecord.new
|
131
|
+
media_message.msg_id = response_json["msg_id"]
|
132
|
+
media_message.media_news = self
|
133
|
+
media_message.save!
|
128
134
|
end
|
135
|
+
self.send_time = Time.now
|
129
136
|
self.status = 1
|
130
137
|
self.save!
|
131
138
|
self.reload
|
@@ -213,4 +220,22 @@ class EricWeixin::MediaNews < ActiveRecord::Base
|
|
213
220
|
end
|
214
221
|
end
|
215
222
|
|
223
|
+
def self.update_media_news_after_sending receive_message
|
224
|
+
self.transaction do
|
225
|
+
msg = EricWeixin::MediaNewsSentRecord.find_by_msg_id(receive_message[:MsgID]||receive_message[:MsgId])
|
226
|
+
return if msg.blank?
|
227
|
+
msg.update sent_count: receive_message[:SentCount],
|
228
|
+
total_count: receive_message[:TotalCount],
|
229
|
+
filter_count: receive_message[:FilterCount],
|
230
|
+
error_count: receive_message[:ErrorCount],
|
231
|
+
status: receive_message[:Status]
|
232
|
+
news = msg.media_news
|
233
|
+
news.filter_count = (news.filter_count.blank? ? 0 : news.filter_count) + msg.filter_count
|
234
|
+
news.total_count = (news.total_count.blank? ? 0 : news.total_count) + msg.total_count
|
235
|
+
news.sent_count = (news.sent_count.blank? ? 0 : news.sent_count) + msg.sent_count
|
236
|
+
news.error_count = (news.error_count.blank? ? 0 : news.error_count) + msg.error_count
|
237
|
+
news.save!
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
216
241
|
end
|
@@ -6,6 +6,7 @@ class EricWeixin::PublicAccount < ActiveRecord::Base
|
|
6
6
|
has_many :two_dimension_codes, :class_name => 'TwoDimensionCode', foreign_key: "weixin_public_account_id"
|
7
7
|
has_one :access_token, :class_name => 'AccessToken', foreign_key: "public_account_id"
|
8
8
|
has_many :customs_service_records, class_name: 'CustomsServiceRecord', foreign_key: "weixin_public_account_id"
|
9
|
+
has_many :redpacks, foreign_key: "weixin_public_account_id"
|
9
10
|
|
10
11
|
#根据微信号名称获取微信账号相关信息
|
11
12
|
# ::EricWeixin::PublicAccount.get_public_account_by_name 'dfxt'
|
@@ -118,6 +119,33 @@ class EricWeixin::PublicAccount < ActiveRecord::Base
|
|
118
119
|
end
|
119
120
|
end
|
120
121
|
|
122
|
+
# 获取用户列表,并把最新的用户信息存到数据库.
|
123
|
+
# ===参数说明
|
124
|
+
# * next_openid #拉取列表的后一个用户的 next_openid,用户列表未拉取完时存在。
|
125
|
+
# ===调用示例
|
126
|
+
# ::EricWeixin::PublicAccount.first.rebuild_users_simple
|
127
|
+
def rebuild_users_simple next_openid = nil
|
128
|
+
token = ::EricWeixin::AccessToken.get_valid_access_token public_account_id: self.id
|
129
|
+
response = if next_openid.blank?
|
130
|
+
RestClient.get "https://api.weixin.qq.com/cgi-bin/user/get?access_token=#{token}"
|
131
|
+
else
|
132
|
+
RestClient.get "https://api.weixin.qq.com/cgi-bin/user/get?access_token=#{token}&next_openid=#{next_openid}"
|
133
|
+
end
|
134
|
+
response = JSON.parse response.body
|
135
|
+
if response["count"].to_i > 0
|
136
|
+
response["data"]["openid"].each do |openid|
|
137
|
+
users = ::EricWeixin::WeixinUser.where openid: openid
|
138
|
+
if users.blank?
|
139
|
+
|
140
|
+
::EricWeixin::WeixinUser.create_weixin_user self.id, openid
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
tmp_next_openid = response["next_openid"]
|
145
|
+
self.rebuild_users tmp_next_openid unless tmp_next_openid.blank?
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
121
149
|
|
122
150
|
GLOBAL_CODES = {
|
123
151
|
-1 => "系统繁忙",
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class EricWeixin::Redpack < ActiveRecord::Base
|
2
|
+
self.table_name = 'weixin_redpacks'
|
3
|
+
|
4
|
+
belongs_to :redpack_order, foreign_key: 'weixin_redpack_order_id'
|
5
|
+
|
6
|
+
STATUS = {
|
7
|
+
"SENDING" => "发放中",
|
8
|
+
"SENT" => "已发放待领取",
|
9
|
+
"FAILED" => "发放失败",
|
10
|
+
"RECEIVED" => "已领取",
|
11
|
+
"REFUND" => "已退款"
|
12
|
+
}
|
13
|
+
|
14
|
+
def self.create_redpack options
|
15
|
+
self.transaction do
|
16
|
+
packs = EricWeixin::Redpack.where weixin_redpack_order_id: options[:weixin_redpack_order_id],
|
17
|
+
openid: options[:openid]
|
18
|
+
return packs[0] unless packs.blank?
|
19
|
+
|
20
|
+
redpack = self.new status: options[:status],
|
21
|
+
openid: options[:openid],
|
22
|
+
amount: options[:amount],
|
23
|
+
rcv_time: options[:rcv_time],
|
24
|
+
weixin_redpack_order_id: options[:weixin_redpack_order_id]
|
25
|
+
redpack.save!
|
26
|
+
redpack
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
class EricWeixin::RedpackOrder < ActiveRecord::Base
|
2
|
+
self.table_name = 'weixin_redpack_orders'
|
3
|
+
belongs_to :public_account, foreign_key: "weixin_public_account_id"
|
4
|
+
has_many :redpacks, foreign_key: 'weixin_redpack_order_id'
|
5
|
+
|
6
|
+
SENDTYPE = {
|
7
|
+
"API" => "通过API接口发放",
|
8
|
+
"UPLOAD" => "通过上传文件方式发放",
|
9
|
+
"ACTIVITY" => "通过活动方式发放"
|
10
|
+
}
|
11
|
+
HBTYPE = {
|
12
|
+
"GROUP" => "裂变红包",
|
13
|
+
"NORMAL" => "普通红包"
|
14
|
+
}
|
15
|
+
|
16
|
+
validates_presence_of :mch_billno, message: '商户订单号必填。'
|
17
|
+
|
18
|
+
# ================必填参数===================
|
19
|
+
# re_openid
|
20
|
+
# total_amount
|
21
|
+
# wishing
|
22
|
+
# client_ip
|
23
|
+
# act_name
|
24
|
+
# remark
|
25
|
+
# send_name
|
26
|
+
# ================选填参数===================
|
27
|
+
# wxappid
|
28
|
+
# mch_id
|
29
|
+
# mch_key
|
30
|
+
# total_num
|
31
|
+
def self.create_redpack_order options
|
32
|
+
self.transaction do
|
33
|
+
weixin_user = ::Weixin::WeixinUser.find_by_openid(options[:re_openid])
|
34
|
+
public_account = weixin_user.weixin_public_account||EricWeixin::PublicAccount.find_by_weixin_app_id(params[:wxappid])
|
35
|
+
BusinessException.raise '查找不到对应的公众号。' if public_account.blank?
|
36
|
+
options[:wxappid] = options[:wxappid]||public_account.weixin_app_id
|
37
|
+
options[:mch_id] = options[:mch_id]||public_account.mch_id
|
38
|
+
options[:total_num] ||= 1
|
39
|
+
options[:mch_key] = options[:mch_key]||public_account.mch_key
|
40
|
+
result = EricWeixin::Pay.sendredpack options
|
41
|
+
pp "*********************** 发红包结果 **************************"
|
42
|
+
pp result
|
43
|
+
return result['err_code'] if result['return_code'] == 'FAIL'
|
44
|
+
redpack_order = self.new
|
45
|
+
redpack_order.mch_billno = result['mch_billno']
|
46
|
+
redpack_order.weixin_public_account_id = public_account.id
|
47
|
+
redpack_order.save!
|
48
|
+
redpack_order
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_info
|
53
|
+
return unless self.redpacks.blank?
|
54
|
+
EricWeixin::RedpackOrder.transaction do
|
55
|
+
options = {}
|
56
|
+
options[:mch_billno] = self.mch_billno
|
57
|
+
options[:mch_id] = self.public_account.mch_id
|
58
|
+
options[:appid] = self.public_account.weixin_app_id
|
59
|
+
options[:mch_key] = self.public_account.mch_key
|
60
|
+
result = EricWeixin::Pay.gethbinfo options
|
61
|
+
pp "************************ 查询红包结果 *****************************"
|
62
|
+
pp result
|
63
|
+
return result['err_code'] if result['return_code'] == 'FAIL'
|
64
|
+
self.detail_id = result['detail_id']
|
65
|
+
self.send_type = result['send_type']
|
66
|
+
self.hb_type = result['hb_type']
|
67
|
+
self.total_num = result['total_num']
|
68
|
+
self.total_amount = result['total_amount']
|
69
|
+
self.reason = result['reason']
|
70
|
+
self.send_time = result['send_time']
|
71
|
+
self.refund_time = result['refund_time']
|
72
|
+
self.refund_amount = result['refund_amount']
|
73
|
+
self.wishing = result['wishing']
|
74
|
+
self.remark = result['emark']
|
75
|
+
self.act_name = result['act_name']
|
76
|
+
self.save!
|
77
|
+
hbinfo = (result['hblist']['hbinfo'] rescue '')
|
78
|
+
|
79
|
+
unless hbinfo.blank?
|
80
|
+
options[:status] = hbinfo['status']
|
81
|
+
options[:openid] = hbinfo['openid']
|
82
|
+
options[:amount] = hbinfo['amount']
|
83
|
+
options[:rcv_time] = hbinfo['rcv_time']
|
84
|
+
options[:weixin_redpack_order_id] = self.id
|
85
|
+
EricWeixin::Redpack.create_redpack options
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -10,13 +10,13 @@ class EricWeixin::ReplyMessageRule < ActiveRecord::Base
|
|
10
10
|
validates_presence_of :key_word, message: "关键词不能为空。"
|
11
11
|
validates_presence_of :reply_message, message: "回复信息不能为空。"
|
12
12
|
validates_presence_of :weixin_public_account, message: "对应的微信公众账号不能为空。"
|
13
|
-
validates_inclusion_of :reply_type, in: REPLY_TYPE_LABEL.collect{|r| r.first}, message: "不正确的回复类型。"
|
14
|
-
validates_inclusion_of :key_word_type, in: KEY_WORD_TYPE_LABEL.collect{|r| r.first}, message: "不正确的关键词类型。"
|
15
|
-
|
13
|
+
validates_inclusion_of :reply_type, in: REPLY_TYPE_LABEL.collect { |r| r.first }, message: "不正确的回复类型。"
|
14
|
+
validates_inclusion_of :key_word_type, in: KEY_WORD_TYPE_LABEL.collect { |r| r.first }, message: "不正确的关键词类型。"
|
16
15
|
|
17
16
|
|
18
17
|
class << self
|
19
18
|
|
19
|
+
#创建匹配规则
|
20
20
|
def create_reply_message_rule options
|
21
21
|
options = get_arguments_options options, [:weixin_public_account_id, :key_word, :reply_message, :key_word_type, :order, :reply_type], is_valid: true
|
22
22
|
::EricWeixin::ReplyMessageRule.transaction do
|
@@ -26,6 +26,7 @@ class EricWeixin::ReplyMessageRule < ActiveRecord::Base
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
# 更新匹配规则
|
29
30
|
def update_reply_message_rule(rule_id, options)
|
30
31
|
options = get_arguments_options options, [:weixin_public_account_id, :key_word, :reply_message, :key_word_type, :order, :reply_type, :is_valid]
|
31
32
|
::EricWeixin::ReplyMessageRule.transaction do
|
@@ -37,8 +38,10 @@ class EricWeixin::ReplyMessageRule < ActiveRecord::Base
|
|
37
38
|
end
|
38
39
|
|
39
40
|
|
40
|
-
|
41
|
+
#处理来自微信端客户所有的处理。
|
41
42
|
def process_rule(receive_message, public_account)
|
43
|
+
receive_message_log = receive_message.clone
|
44
|
+
receive_message_log[:Content] = CGI::escape(receive_message_log[:Content]) if not receive_message_log[:Content].blank?
|
42
45
|
business_type = "#{receive_message[:MsgType]}~#{receive_message[:Event]}"
|
43
46
|
|
44
47
|
#兼容腾讯的一个坑....有的是MsgId, 有的是MsgID
|
@@ -49,7 +52,7 @@ class EricWeixin::ReplyMessageRule < ActiveRecord::Base
|
|
49
52
|
weixin_public_account_id: public_account.id,
|
50
53
|
message_type: receive_message[:MsgType],
|
51
54
|
message_id: receive_message[:MsgId] || receive_message[:MsgID],
|
52
|
-
data:
|
55
|
+
data: receive_message_log.to_json,
|
53
56
|
process_status: 0, #在这里假设都处理完毕,由业务引起的更新请在工程的Process中进行修改。
|
54
57
|
event_name: receive_message[:Event],
|
55
58
|
event_key: receive_message[:EventKey], #事件值
|
@@ -59,10 +62,10 @@ class EricWeixin::ReplyMessageRule < ActiveRecord::Base
|
|
59
62
|
reply_message = case business_type
|
60
63
|
#订阅
|
61
64
|
when /event~subscribe/
|
62
|
-
::EricWeixin::WeixinUser.create_weixin_user public_account.id, receive_message[:FromUserName],receive_message[:EventKey]
|
63
|
-
result = ::Weixin::Process.subscribe receive_message
|
65
|
+
user, is_new = ::EricWeixin::WeixinUser.create_weixin_user public_account.id, receive_message[:FromUserName], receive_message[:EventKey]
|
66
|
+
result = ::Weixin::Process.subscribe receive_message, is_new
|
64
67
|
if result == true
|
65
|
-
match_key_words 'subscribe', public_account.id, receive_message
|
68
|
+
match_key_words 'subscribe', public_account.id, receive_message, false
|
66
69
|
else
|
67
70
|
result
|
68
71
|
end
|
@@ -77,16 +80,18 @@ class EricWeixin::ReplyMessageRule < ActiveRecord::Base
|
|
77
80
|
result
|
78
81
|
end
|
79
82
|
|
80
|
-
|
83
|
+
#点击消息,点击菜单时响应。
|
81
84
|
when /event~CLICK/
|
82
85
|
result = ::Weixin::Process.click_event receive_message[:EventKey], receive_message
|
83
86
|
if result == true
|
84
|
-
match_key_words receive_message[:EventKey], public_account.id, receive_message
|
87
|
+
match_key_words receive_message[:EventKey], public_account.id, receive_message, false
|
85
88
|
else
|
86
89
|
result
|
87
90
|
end
|
88
91
|
|
89
|
-
|
92
|
+
#扫描带参数二维码
|
93
|
+
|
94
|
+
|
90
95
|
when /event~SCAN/
|
91
96
|
result = ::Weixin::Process.scan_event receive_message[:EventKey], receive_message
|
92
97
|
if result == true
|
@@ -151,11 +156,21 @@ class EricWeixin::ReplyMessageRule < ActiveRecord::Base
|
|
151
156
|
when /text~/
|
152
157
|
result = ::Weixin::Process.text_event receive_message[:Content], receive_message
|
153
158
|
if result == true
|
159
|
+
# if receive_message[:Content] == "我要找客服"
|
160
|
+
# ::EricWeixin::ReplyMessage::transfer_mult_customer_service ToUserName: receive_message[:FromUserName],
|
161
|
+
# FromUserName: receive_message[:ToUserName]
|
162
|
+
# else
|
154
163
|
match_key_words receive_message[:Content], public_account.id, receive_message
|
164
|
+
# end
|
155
165
|
else
|
156
166
|
result
|
157
167
|
end
|
158
168
|
|
169
|
+
when /image~/
|
170
|
+
result = ::Weixin::Process.image_event receive_message[:Content], receive_message
|
171
|
+
if result == true
|
172
|
+
''
|
173
|
+
end
|
159
174
|
when /link~/
|
160
175
|
result = ::Weixin::Process.link_event receive_message
|
161
176
|
if result == true
|
@@ -164,6 +179,11 @@ class EricWeixin::ReplyMessageRule < ActiveRecord::Base
|
|
164
179
|
result
|
165
180
|
end
|
166
181
|
|
182
|
+
# 群发发送图文推送后,微信服务器返回的结果
|
183
|
+
when /event~MASSSENDJOBFINISH/
|
184
|
+
::EricWeixin::MediaNews.update_media_news_after_sending receive_message
|
185
|
+
::Weixin::Process.message_send_job_finish receive_message
|
186
|
+
''
|
167
187
|
#暂时识别不了的消息
|
168
188
|
else
|
169
189
|
"暂时未处理的场景".to_logger
|
@@ -186,34 +206,116 @@ class EricWeixin::ReplyMessageRule < ActiveRecord::Base
|
|
186
206
|
reply_message
|
187
207
|
end
|
188
208
|
|
189
|
-
def match_key_words wx_key_word, public_account_id, receive_message,need_to_mult_service=true
|
190
|
-
matched_rule = ::EricWeixin::ReplyMessageRule.order(order: :desc).
|
191
|
-
where(:key_word => wx_key_word, :weixin_public_account_id => public_account_id, :key_word_type=>(receive_message[:MsgType]||"text")).first
|
192
|
-
if matched_rule.nil?
|
193
|
-
# todo 处理正则表达式
|
194
209
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
210
|
+
# 用户发送的关键字、 事件关键字匹配处理。
|
211
|
+
# 关键字处理分三类: 事件关键字、 正则表达式关键字、 文本严格匹配关键字
|
212
|
+
# 关键字匹配好以后,返回类型有三种: 文本、 图文、以及动态运行。
|
213
|
+
#
|
214
|
+
# need_to_mult_service 如果匹配不到,是否提示转客服。
|
215
|
+
def match_key_words wx_key_word, public_account_id, receive_message, need_to_mult_service=true
|
201
216
|
|
217
|
+
message_type = receive_message[:MsgType]||"text"
|
218
|
+
reply_message_rule = nil
|
219
|
+
case message_type
|
220
|
+
when 'event'
|
221
|
+
# event类型关键字 event类型关键字不需要匹配正则表达式。
|
222
|
+
reply_message_rule = ::EricWeixin::ReplyMessageRule.order(order: :desc).valid.
|
223
|
+
where(weixin_public_account_id: public_account_id, key_word_type: 'event', key_word: wx_key_word).first
|
224
|
+
else
|
225
|
+
# 对于非event类型的关键字, 按照order 的优先级,逐条比对。 如果order相同,文本类型优先。 匹配成功就停止。
|
226
|
+
rules = ::EricWeixin::ReplyMessageRule.order(order: :desc).valid.
|
227
|
+
where(weixin_public_account_id: public_account_id, key_word_type: ['regularexpr', 'text'])
|
228
|
+
rules.each do |rule|
|
229
|
+
if rule.key_word_type == 'text'
|
230
|
+
if wx_key_word == rule.key_word
|
231
|
+
reply_message_rule = rule
|
232
|
+
break
|
233
|
+
end
|
234
|
+
end
|
235
|
+
if rule.key_word_type = 'regularexpr'
|
236
|
+
regexp = Regexp.new rule.key_word
|
237
|
+
result = regexp.match wx_key_word
|
238
|
+
unless result.blank?
|
239
|
+
reply_message_rule = rule
|
240
|
+
break
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
202
244
|
end
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
245
|
+
|
246
|
+
|
247
|
+
# if need_to_mult_service
|
248
|
+
# return ::EricWeixin::ReplyMessage::transfer_mult_customer_service ToUserName: receive_message[:FromUserName],
|
249
|
+
# FromUserName: receive_message[:ToUserName]
|
250
|
+
# else
|
251
|
+
# return '' #当匹配不上,也不需要去多客服的时候,就直接返回。
|
252
|
+
# end
|
253
|
+
|
254
|
+
|
255
|
+
reply_msg = if reply_message_rule.blank?
|
256
|
+
if need_to_mult_service
|
257
|
+
# 返回给用户,如何唤醒客服。
|
258
|
+
message = ::EricWeixin::ReplyMessageRule.get_contact_customer_notice public_account_id
|
259
|
+
if message.blank?
|
260
|
+
''
|
261
|
+
else
|
262
|
+
::EricWeixin::ReplyMessage.get_reply_user_message_text ToUserName: receive_message[:FromUserName],
|
263
|
+
FromUserName: receive_message[:ToUserName],
|
264
|
+
Content: message
|
265
|
+
end
|
266
|
+
else
|
267
|
+
''
|
268
|
+
end
|
269
|
+
|
270
|
+
else
|
271
|
+
|
272
|
+
if reply_message_rule.reply_message == 'CONTACT_CUSTOMER_NOTICE'
|
273
|
+
::EricWeixin::ReplyMessage::transfer_mult_customer_service ToUserName: receive_message[:FromUserName],
|
274
|
+
FromUserName: receive_message[:ToUserName]
|
275
|
+
else
|
276
|
+
case reply_message_rule.reply_type
|
277
|
+
when "text"
|
278
|
+
::EricWeixin::ReplyMessage.get_reply_user_message_text ToUserName: receive_message[:FromUserName],
|
279
|
+
FromUserName: receive_message[:ToUserName],
|
280
|
+
Content: reply_message_rule.reply_message
|
281
|
+
when "news"
|
282
|
+
weixin_news = ::EricWeixin::News.find_by_match_key reply_message_rule.reply_message
|
283
|
+
::EricWeixin::ReplyMessage::get_reply_user_message_image_text ToUserName: receive_message[:FromUserName],
|
284
|
+
FromUserName: receive_message[:ToUserName],
|
285
|
+
news: weixin_news.weixin_articles
|
286
|
+
when "wx_function"
|
287
|
+
::Weixin::WeixinAutoReplyFunctions.send(reply_message_rule.reply_message, ({:key_word => wx_key_word, :receive_message => receive_message}))
|
288
|
+
end
|
289
|
+
end
|
215
290
|
end
|
216
291
|
reply_msg
|
217
292
|
end
|
293
|
+
|
294
|
+
|
295
|
+
# 获取提示找客服的语句。
|
296
|
+
def get_contact_customer_notice public_account_id
|
297
|
+
rules = ::EricWeixin::ReplyMessageRule.valid.where weixin_public_account_id: public_account_id,
|
298
|
+
key_word_type: 'text',
|
299
|
+
key_word: 'CONTACT_CUSTOMER_NOTICE'
|
300
|
+
if rules.blank?
|
301
|
+
::EricWeixin::ReplyMessageRule.create_reply_message_rule weixin_public_account_id: public_account_id,
|
302
|
+
key_word: 'CONTACT_CUSTOMER_NOTICE',
|
303
|
+
reply_message: '请发送:"芝麻开门"来联系客服',
|
304
|
+
key_word_type: 'text',
|
305
|
+
order: 1,
|
306
|
+
reply_type: "text"
|
307
|
+
|
308
|
+
::EricWeixin::ReplyMessageRule.create_reply_message_rule weixin_public_account_id: public_account_id,
|
309
|
+
key_word: '芝麻开门',
|
310
|
+
reply_message: 'CONTACT_CUSTOMER_NOTICE',
|
311
|
+
key_word_type: 'text',
|
312
|
+
order: 1,
|
313
|
+
reply_type: "text"
|
314
|
+
|
315
|
+
return ::EricWeixin::ReplyMessageRule.get_contact_customer_notice public_account_id
|
316
|
+
else
|
317
|
+
rules.first.reply_message
|
318
|
+
end
|
319
|
+
end
|
218
320
|
end
|
219
321
|
end
|
@@ -37,7 +37,7 @@ class EricWeixin::WeixinUser < ActiveRecord::Base
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def nickname
|
40
|
-
CGI::unescape(self.attributes["nickname"])
|
40
|
+
CGI::unescape(self.attributes["nickname"]) rescue '无法正常显示'
|
41
41
|
end
|
42
42
|
|
43
43
|
##
|
@@ -54,7 +54,7 @@ class EricWeixin::WeixinUser < ActiveRecord::Base
|
|
54
54
|
response.to_debug
|
55
55
|
response = JSON.parse response.body
|
56
56
|
if response["errcode"].to_i == 0
|
57
|
-
|
57
|
+
::EricWeixin::WeixinUser.create_weixin_user self.weixin_public_account_id, self.openid
|
58
58
|
|
59
59
|
else
|
60
60
|
BusinessException.raise "设置备注名报错,错误代码为#{response["errcode"]}"
|
@@ -76,13 +76,17 @@ class EricWeixin::WeixinUser < ActiveRecord::Base
|
|
76
76
|
# ====返回
|
77
77
|
# 正常情况下返回当前微信用户 <tt>::EricWeixin::WeixinUser</tt>,抛出异常时错误查看异常信息。
|
78
78
|
def create_weixin_user(public_account_id, openid, channel=nil)
|
79
|
+
is_new = false
|
79
80
|
public_account = ::EricWeixin::PublicAccount.find_by_id(public_account_id)
|
80
81
|
::EricWeixin::ReplyMessageRule.transaction do
|
82
|
+
is_new = false
|
81
83
|
weixin_user = ::EricWeixin::WeixinUser.where(openid: openid, weixin_public_account_id: public_account.id).first
|
82
84
|
if weixin_user.blank?
|
85
|
+
is_new = true
|
83
86
|
weixin_user = ::EricWeixin::WeixinUser.new openid: openid,
|
84
87
|
weixin_public_account_id: public_account.id
|
85
88
|
weixin_user.save!
|
89
|
+
is_new = true
|
86
90
|
end
|
87
91
|
wx_user_data = public_account.get_user_data_from_weixin_api openid
|
88
92
|
weixin_user.update_attributes(wx_user_data.select{|k,v| ["subscribe", "openid", "nickname", "sex", "language", "city", "province", "country", "headimgurl", "subscribe_time", "remark"].include? k })
|
@@ -91,7 +95,7 @@ class EricWeixin::WeixinUser < ActiveRecord::Base
|
|
91
95
|
weixin_user.last_register_channel = channel
|
92
96
|
weixin_user.save!
|
93
97
|
end
|
94
|
-
weixin_user
|
98
|
+
return weixin_user, is_new
|
95
99
|
end
|
96
100
|
end
|
97
101
|
|
@@ -162,6 +166,8 @@ class EricWeixin::WeixinUser < ActiveRecord::Base
|
|
162
166
|
users = users.where(weixin_public_account_id: options[:weixin_public_account_id]) unless options[:weixin_public_account_id].blank?
|
163
167
|
users = users.where("subscribe_time >= ?", options[:start_date].to_date.to_time.to_i) unless options[:start_date].blank?
|
164
168
|
users = users.where("subscribe_time <= ?", (options[:end_date].to_date+1.day).to_time.to_i) unless options[:end_date].blank?
|
169
|
+
users = users.where("last_register_channel = ?", options[:last_register_channel]) unless options[:last_register_channel].blank?
|
170
|
+
users = users.where("first_register_channel = ?", options[:first_register_channel]) unless options[:first_register_channel].blank?
|
165
171
|
users
|
166
172
|
end
|
167
173
|
end
|
@@ -47,12 +47,13 @@
|
|
47
47
|
<% end %>
|
48
48
|
<table>
|
49
49
|
<thead>
|
50
|
-
<th width="100">用户</th><th>客服</th><th>聊天类型</th><th>日期时间</th><th>公众号</th><th>聊天内容</th>
|
50
|
+
<th width="100">用户</th><th>头像</th><th>客服</th><th>聊天类型</th><th>日期时间</th><th>公众号</th><th>聊天内容</th>
|
51
51
|
</thead>
|
52
52
|
<tbody>
|
53
53
|
<% @customs_service_records.each do |record| %>
|
54
54
|
<tr>
|
55
55
|
<td><%= record.nick_name %></td>
|
56
|
+
<td><%= image_tag((record.weixin_user.headimgurl rescue ''), height: '32', width: '32') %></td>
|
56
57
|
<td><%= record.worker %></td>
|
57
58
|
<td><%= ::EricWeixin::CustomsServiceRecord::OPERCODE[record.opercode.to_i] %></td>
|
58
59
|
<td><%= Time.at( record.time.to_i ).chinese_format %></td>
|
@@ -5,7 +5,7 @@
|
|
5
5
|
<td><%= media_article.title %></td>
|
6
6
|
<td><img src="<%= media_article.media_resource.local_link %>" width="20" height="20"></td>
|
7
7
|
<td><%= media_article.is_first_article ? '首图文' : '' %></td>
|
8
|
-
<td><%= link_to '
|
8
|
+
<td><%= link_to '选中', "javascript:select_this_to_target_news(#{media_article.id})" %></td>
|
9
9
|
</tr>
|
10
10
|
<% end %>
|
11
11
|
</table>
|
@@ -80,14 +80,14 @@
|
|
80
80
|
<label class="inline">其他</label>
|
81
81
|
</div>
|
82
82
|
<div class="columns small-6 text-left">
|
83
|
-
<%= check_box_tag 'do_send[fix_time]', true, false %><label class="inline">定时发送(分钟数请设置为5
|
83
|
+
<%= check_box_tag 'do_send[fix_time]', true, false %><label class="inline">定时发送(分钟数请设置为5分钟的整数倍)</label>
|
84
84
|
</div>
|
85
85
|
</div>
|
86
86
|
<div class="row">
|
87
87
|
<div class="columns small-offset-6 small-6">
|
88
88
|
<div class="row">
|
89
89
|
<div class="columns small-4">
|
90
|
-
<label class="inline"
|
90
|
+
<label class="inline">定时发送时间:</label>
|
91
91
|
</div>
|
92
92
|
<div class="columns small-4">
|
93
93
|
<%= date_field_tag 'send[fix_date]' %>
|
@@ -13,10 +13,10 @@
|
|
13
13
|
<td>
|
14
14
|
<%= rule.weixin_public_account_name %>
|
15
15
|
</td>
|
16
|
-
<td>
|
16
|
+
<td style="WORD-BREAK: break-all; WORD-WRAP: break-word">
|
17
17
|
<%= rule.key_word %>
|
18
18
|
</td>
|
19
|
-
<td>
|
19
|
+
<td style="WORD-BREAK: break-all; WORD-WRAP: break-word">
|
20
20
|
<%= rule.reply_message %>
|
21
21
|
</td>
|
22
22
|
<td>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<% @two_dimension_codes.each do |two_dimension_code|%>
|
2
2
|
<tr>
|
3
|
-
<td><img style="width:60px;height:60px;" src="https://mp.weixin.qq.com/cgi-bin/ showqrcode?ticket=<%= two_dimension_code.ticket %>"
|
3
|
+
<td><img style="width:60px;height:60px;" src="https://mp.weixin.qq.com/cgi-bin/ showqrcode?ticket=<%= two_dimension_code.ticket %>" ></td>
|
4
4
|
<td><%= two_dimension_code.action_info %></td>
|
5
5
|
<td><%= two_dimension_code.scene_str %></td>
|
6
6
|
<td>
|
@@ -34,7 +34,20 @@
|
|
34
34
|
<%= text_field_tag :province, params[:province] ,placeholder:"ALL" %>
|
35
35
|
</div>
|
36
36
|
|
37
|
-
|
37
|
+
</div>
|
38
|
+
<div class="row">
|
39
|
+
<div class="columns small-2 text-right">
|
40
|
+
<label class="inline">首次关注渠道</label>
|
41
|
+
</div>
|
42
|
+
<div class="columns small-2">
|
43
|
+
<%= text_field_tag :first_register_channel, params[:first_register_channel], placeholder: "ALL" %>
|
44
|
+
</div>
|
45
|
+
<div class="columns small-2 text-right">
|
46
|
+
<label class="inline">最后关注渠道</label>
|
47
|
+
</div>
|
48
|
+
<div class="columns small-2 end">
|
49
|
+
<%= text_field_tag :last_register_channel, params[:last_register_channel], placeholder: "ALL" %>
|
50
|
+
</div>
|
38
51
|
</div>
|
39
52
|
<div class="row">
|
40
53
|
<div class="columns small-2 text-right">
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateWeixinMediaNewsSentRecords < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :weixin_media_news_sent_records do |t|
|
4
|
+
t.integer :media_news_id
|
5
|
+
t.string :msg_id
|
6
|
+
t.integer :sent_count
|
7
|
+
t.integer :total_count
|
8
|
+
t.integer :filter_count
|
9
|
+
t.integer :error_count
|
10
|
+
t.string :status
|
11
|
+
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateWeixinCustomsServiceRecords < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
execute 'CREATE TABLE `weixin_customs_service_records` (
|
4
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
5
|
+
`openid` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
6
|
+
`opercode` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
7
|
+
`text` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
8
|
+
`time` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
9
|
+
`worker` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
10
|
+
`created_at` datetime DEFAULT NULL,
|
11
|
+
`updated_at` datetime DEFAULT NULL,
|
12
|
+
`weixin_public_account_id` int(11) DEFAULT NULL,
|
13
|
+
PRIMARY KEY (`id`)
|
14
|
+
) ENGINE=InnoDB AUTO_INCREMENT=88 DEFAULT CHARSET=utf8;'
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class CreateWeixinRedpackOrders < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :weixin_redpack_orders do |t|
|
4
|
+
t.integer :weixin_public_account_id
|
5
|
+
t.string :mch_billno
|
6
|
+
t.string :detail_id
|
7
|
+
t.string :send_type
|
8
|
+
t.string :hb_type
|
9
|
+
t.integer :total_num
|
10
|
+
t.integer :total_amount
|
11
|
+
t.string :reason
|
12
|
+
t.datetime :send_time
|
13
|
+
t.datetime :refund_time
|
14
|
+
t.integer :refund_amount
|
15
|
+
t.string :wishing
|
16
|
+
t.string :remark
|
17
|
+
t.string :act_name
|
18
|
+
t.timestamps
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateWeixinRedpacks < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :weixin_redpacks do |t|
|
4
|
+
t.integer :weixin_redpack_order_id
|
5
|
+
t.string :openid
|
6
|
+
t.integer :amount
|
7
|
+
t.datetime :rcv_time
|
8
|
+
t.string :status
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -84,15 +84,17 @@ module EricWeixin::MultCustomer
|
|
84
84
|
end
|
85
85
|
BusinessException.raise '公众账号未查询到' if pa.blank?
|
86
86
|
token = ::EricWeixin::AccessToken.get_valid_access_token_by_app_id app_id: options[:app_id]
|
87
|
-
|
88
|
-
|
87
|
+
t_options = {}
|
88
|
+
options[:data].each do |k,v|
|
89
|
+
t_options[k] = CGI::escape(v.gsub("\"","'"))
|
90
|
+
end
|
89
91
|
post_data = {
|
90
92
|
:touser => options[:openid],
|
91
93
|
:msgtype => options[:message_type],
|
92
|
-
options[:message_type] =>
|
94
|
+
options[:message_type] => t_options
|
93
95
|
}
|
94
96
|
url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=#{token}"
|
95
|
-
response = RestClient.post url, post_data.to_json
|
97
|
+
response = RestClient.post url, CGI::unescape(post_data.to_json)
|
96
98
|
response = JSON.parse response.body
|
97
99
|
::EricWeixin::MessageLog.transaction do
|
98
100
|
message = ::EricWeixin::MessageLog.where(message_id: options[:message_id]).first
|
@@ -23,9 +23,93 @@ module EricWeixin::Pay
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.generate_sign options, api_key
|
26
|
+
pp "**************** 签名参数 *********************"
|
27
|
+
pp options
|
28
|
+
pp "**************** api_key *********************"
|
29
|
+
pp api_key
|
26
30
|
query = options.sort.map do |k,v|
|
27
31
|
"#{k.to_s}=#{v.to_s}"
|
28
32
|
end.join('&')
|
29
33
|
Digest::MD5.hexdigest("#{query}&key=#{api_key}").upcase
|
30
34
|
end
|
35
|
+
|
36
|
+
# 参数
|
37
|
+
# wxappid
|
38
|
+
# re_openid
|
39
|
+
# total_amount
|
40
|
+
# wishing
|
41
|
+
# client_ip
|
42
|
+
# act_name
|
43
|
+
# remark
|
44
|
+
# mch_id
|
45
|
+
# send_name
|
46
|
+
# total_num
|
47
|
+
# mch_key
|
48
|
+
def self.sendredpack options
|
49
|
+
required_field = %i(wxappid re_openid total_amount wishing client_ip act_name remark mch_id send_name total_num mch_key)
|
50
|
+
required_field.each do |p|
|
51
|
+
BusinessException.raise "缺少参数:#{p.to_s},且值不可以为空白字符串。" if options[p.to_sym].blank?
|
52
|
+
end
|
53
|
+
|
54
|
+
options[:nonce_str] = SecureRandom.uuid.tr('-', '')
|
55
|
+
options[:mch_billno] = options[:mch_id] + Time.now.strftime("%Y%m%d") + Time.now.strftime("%H%M%S") + EricTools.generate_random_string(4,1).to_s
|
56
|
+
# 生成签名
|
57
|
+
api_key = options[:mch_key]
|
58
|
+
options.delete(:mch_key)
|
59
|
+
sign = generate_sign options, api_key
|
60
|
+
options[:sign] = sign
|
61
|
+
# 生成xml数据包
|
62
|
+
pay_load = "<xml>#{options.map { |k, v| "<#{k.to_s}>#{v.to_s}</#{k.to_s}>" }.join}</xml>"
|
63
|
+
require 'rest-client'
|
64
|
+
ca_path = Rails.root.join("ca/").to_s
|
65
|
+
Dir.mkdir ca_path unless Dir.exist? ca_path
|
66
|
+
BusinessException.raise '请下载证书' unless File.exist?(ca_path+"apiclient_cert.pem") && File.exist?(ca_path+"apiclient_key.pem")
|
67
|
+
response = RestClient::Request.execute(method: :post, url: 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack',
|
68
|
+
ssl_client_cert: OpenSSL::X509::Certificate.new(File.read(ca_path+"apiclient_cert.pem")),
|
69
|
+
ssl_client_key: OpenSSL::PKey::RSA.new(File.read(ca_path+"apiclient_key.pem"), "passphrase, if any"),
|
70
|
+
ssl_ciphers: 'AESGCM:!aNULL',
|
71
|
+
payload: pay_load)
|
72
|
+
|
73
|
+
# 分析请求结果
|
74
|
+
pp "********************** 发红包 请求结果 ******************************"
|
75
|
+
pp response.force_encoding("UTF-8")
|
76
|
+
result = Hash.from_xml(response.force_encoding("UTF-8"))
|
77
|
+
result['xml']
|
78
|
+
end
|
79
|
+
|
80
|
+
# mch_billno
|
81
|
+
# mch_id
|
82
|
+
# appid
|
83
|
+
# mch_key
|
84
|
+
def self.gethbinfo options
|
85
|
+
BusinessException.raise '请提供商户订单号。' if options[:mch_billno].blank?
|
86
|
+
BusinessException.raise '请提供商户号。' if options[:mch_id].blank?
|
87
|
+
BusinessException.raise '请提供公众账号ID。' if options[:appid].blank?
|
88
|
+
BusinessException.raise '请提供mch_key。' if options[:mch_key].blank?
|
89
|
+
options[:nonce_str] = SecureRandom.uuid.tr('-', '')
|
90
|
+
options[:bill_type] = 'MCHT'
|
91
|
+
|
92
|
+
api_key = options[:mch_key]
|
93
|
+
options.delete(:mch_key)
|
94
|
+
sign = generate_sign options, api_key
|
95
|
+
# sign = generate_sign options, options[:mch_key]
|
96
|
+
options[:sign] = sign
|
97
|
+
|
98
|
+
pay_load = "<xml>#{options.map { |k, v| "<#{k.to_s}>#{v.to_s}</#{k.to_s}>" }.join}</xml>"
|
99
|
+
require 'rest-client'
|
100
|
+
ca_path = Rails.root.join("ca/").to_s
|
101
|
+
Dir.mkdir ca_path unless Dir.exist? ca_path
|
102
|
+
BusinessException.raise '请下载证书' unless File.exist?(ca_path+"apiclient_cert.pem") && File.exist?(ca_path+"apiclient_key.pem")
|
103
|
+
response = RestClient::Request.execute(method: :post, url: 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo',
|
104
|
+
ssl_client_cert: OpenSSL::X509::Certificate.new(File.read(ca_path+"apiclient_cert.pem")),
|
105
|
+
ssl_client_key: OpenSSL::PKey::RSA.new(File.read(ca_path+"apiclient_key.pem"), "passphrase, if any"),
|
106
|
+
ssl_ciphers: 'AESGCM:!aNULL',
|
107
|
+
payload: pay_load)
|
108
|
+
# 分析查询红包结果
|
109
|
+
pp "********************** 红包查询 结果 ******************************"
|
110
|
+
pp response.force_encoding("UTF-8")
|
111
|
+
result = Hash.from_xml(response.force_encoding("UTF-8"))
|
112
|
+
result['xml']
|
113
|
+
end
|
114
|
+
|
31
115
|
end
|
data/lib/eric_weixin/version.rb
CHANGED
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eric_weixin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 刘晓琦
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 4.1.4
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 4.1.4
|
27
27
|
description: 快速开发微信公众账号
|
@@ -61,13 +61,17 @@ files:
|
|
61
61
|
- app/models/eric_weixin/article.rb
|
62
62
|
- app/models/eric_weixin/article_news.rb
|
63
63
|
- app/models/eric_weixin/customs_service_record.rb
|
64
|
+
- app/models/eric_weixin/jsapi_ticket.rb
|
64
65
|
- app/models/eric_weixin/media_article.rb
|
65
66
|
- app/models/eric_weixin/media_article_news.rb
|
66
67
|
- app/models/eric_weixin/media_news.rb
|
68
|
+
- app/models/eric_weixin/media_news_sent_record.rb
|
67
69
|
- app/models/eric_weixin/media_resource.rb
|
68
70
|
- app/models/eric_weixin/message_log.rb
|
69
71
|
- app/models/eric_weixin/news.rb
|
70
72
|
- app/models/eric_weixin/public_account.rb
|
73
|
+
- app/models/eric_weixin/redpack.rb
|
74
|
+
- app/models/eric_weixin/redpack_order.rb
|
71
75
|
- app/models/eric_weixin/reply_message_rule.rb
|
72
76
|
- app/models/eric_weixin/report/interface_data.rb
|
73
77
|
- app/models/eric_weixin/report/msg_data.rb
|
@@ -150,6 +154,13 @@ files:
|
|
150
154
|
- db/migrate/20150818095654_create_weixin_media_news.rb
|
151
155
|
- db/migrate/20150818100348_create_weixin_media_articles_news.rb
|
152
156
|
- db/migrate/20150904045253_add_host_name_to_public_account.rb
|
157
|
+
- db/migrate/20150906064203_add_error_count_to_weixin_media_news.rb
|
158
|
+
- db/migrate/20150906072855_create_weixin_media_news_sent_records.rb
|
159
|
+
- db/migrate/20150908023239_add_phone_to_weixin_users.rb
|
160
|
+
- db/migrate/20150910024059_create_weixin_customs_service_records.rb
|
161
|
+
- db/migrate/20150911023948_create_weixin_redpack_orders.rb
|
162
|
+
- db/migrate/20150911062057_create_weixin_redpacks.rb
|
163
|
+
- db/migrate/20150914061051_create_jsapi_tickets.rb
|
153
164
|
- lib/eric_weixin.rb
|
154
165
|
- lib/eric_weixin/engine.rb
|
155
166
|
- lib/eric_weixin/modules/analyze_data.rb
|