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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/eric_weixin/cms/weixin/customs_service_records_controller.rb +1 -1
  3. data/app/controllers/eric_weixin/cms/weixin/weixin_users_controller.rb +3 -1
  4. data/app/controllers/eric_weixin/wz/pays_controller.rb +24 -0
  5. data/app/models/eric_weixin/access_token.rb +1 -1
  6. data/app/models/eric_weixin/customs_service_record.rb +4 -0
  7. data/app/models/eric_weixin/jsapi_ticket.rb +67 -0
  8. data/app/models/eric_weixin/media_news.rb +26 -1
  9. data/app/models/eric_weixin/media_news_sent_record.rb +6 -0
  10. data/app/models/eric_weixin/public_account.rb +28 -0
  11. data/app/models/eric_weixin/redpack.rb +30 -0
  12. data/app/models/eric_weixin/redpack_order.rb +92 -0
  13. data/app/models/eric_weixin/reply_message_rule.rb +136 -34
  14. data/app/models/eric_weixin/weixin_user.rb +9 -3
  15. data/app/views/eric_weixin/cms/weixin/customs_service_records/index.html.erb +2 -1
  16. data/app/views/eric_weixin/cms/weixin/media_news/_select_article.html.erb +1 -1
  17. data/app/views/eric_weixin/cms/weixin/media_news/new.html.erb +2 -2
  18. data/app/views/eric_weixin/cms/weixin/reply_message_rules/index.html.erb +2 -2
  19. data/app/views/eric_weixin/cms/weixin/two_dimension_codes/_two_dimension_code_form.html.erb +1 -1
  20. data/app/views/eric_weixin/cms/weixin/weixin_users/index.html.erb +14 -1
  21. data/db/migrate/20150906064203_add_error_count_to_weixin_media_news.rb +5 -0
  22. data/db/migrate/20150906072855_create_weixin_media_news_sent_records.rb +15 -0
  23. data/db/migrate/20150908023239_add_phone_to_weixin_users.rb +5 -0
  24. data/db/migrate/20150910024059_create_weixin_customs_service_records.rb +16 -0
  25. data/db/migrate/20150911023948_create_weixin_redpack_orders.rb +21 -0
  26. data/db/migrate/20150911062057_create_weixin_redpacks.rb +13 -0
  27. data/db/migrate/20150914061051_create_jsapi_tickets.rb +10 -0
  28. data/lib/eric_weixin/modules/mult_customer.rb +6 -4
  29. data/lib/eric_weixin/modules/pay.rb +84 -0
  30. data/lib/eric_weixin/version.rb +1 -1
  31. metadata +15 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2f6d9f69457b61be06879a23c862aaf030b12f8d
4
- data.tar.gz: cbe07f22927fce38bc6d5fef9e9bf0202206d928
3
+ metadata.gz: f051bb6d4db95b0b0dc05755a37b0cb58cac07ec
4
+ data.tar.gz: e7d315eb8728a9e5b76dffa7f1b88e381f0ddf80
5
5
  SHA512:
6
- metadata.gz: 91c9d6965d3414cb46467164e89bde9affc068c75d2cc4597e3b152e551e98b6897076ec2d34ec88efa80d3303be4f78194bfb673ccb9b46b3082078e149049f
7
- data.tar.gz: bbfb01d2e6cced5b28168e27ada9ee03439ced65463bfcfba86ccf774df888c08167bc515fc4e374560ffa69b67c992e96d87b314fbd534bf47b0006f58b1487
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: :experience_center_id
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
@@ -0,0 +1,6 @@
1
+ class EricWeixin::MediaNewsSentRecord < ActiveRecord::Base
2
+ self.table_name = 'weixin_media_news_sent_records'
3
+ belongs_to :media_news, foreign_key: 'media_news_id'
4
+
5
+
6
+ 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
- #todo xiameng 注释 勾子使用方法
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: receive_message.to_json,
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
- if need_to_mult_service
196
- return ::EricWeixin::ReplyMessage::transfer_mult_customer_service ToUserName: receive_message[:FromUserName],
197
- FromUserName: receive_message[:ToUserName]
198
- else
199
- return '' #当匹配不上,也不需要去多客服的时候,就直接返回。
200
- end
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
- reply_msg = case matched_rule.reply_type
204
- when "text"
205
- ::EricWeixin::ReplyMessage.get_reply_user_message_text ToUserName: receive_message[:FromUserName],
206
- FromUserName: receive_message[:ToUserName],
207
- Content: matched_rule.reply_message
208
- when "news"
209
- weixin_news = ::EricWeixin::News.find_by_match_key matched_rule.reply_message
210
- ::EricWeixin::ReplyMessage::get_reply_user_message_image_text ToUserName: receive_message[:FromUserName],
211
- FromUserName: receive_message[:ToUserName],
212
- news: weixin_news.weixin_articles
213
- when "wx_function"
214
- ::Weixin::WeixinAutoReplyFunctions.send(matched_rule.reply_message, ({:key_word => wx_key_word, :receive_message => receive_message}))
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
- response = ::EricWeixin::WeixinUser.create_weixin_user self.weixin_public_account_id, self.openid
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 '选中️', "javascript:select_this_to_target_news(#{media_article.id})" %></td>
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分钟的整数倍:如10点05分,10点10分)</label>
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">定时发送时间:()</label>
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 %>" %></td>
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,5 @@
1
+ class AddErrorCountToWeixinMediaNews < ActiveRecord::Migration
2
+ def change
3
+ add_column :weixin_media_news, :error_count, :integer
4
+ end
5
+ end
@@ -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,5 @@
1
+ class AddPhoneToWeixinUsers < ActiveRecord::Migration
2
+ def change
3
+ add_column :weixin_users, :phone, :string
4
+ end
5
+ 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
@@ -0,0 +1,10 @@
1
+ class CreateJsapiTickets < ActiveRecord::Migration
2
+ def change
3
+ create_table :weixin_jsapi_tickets do |t|
4
+ t.string :jsapi_ticket
5
+ t.string :expired_at
6
+ t.integer :public_account_id
7
+ t.timestamps
8
+ end
9
+ end
10
+ 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] => options[:data]
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
@@ -1,3 +1,3 @@
1
1
  module EricWeixin
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
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.0
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-09-05 00:00:00.000000000 Z
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