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