Class: Utils::Weixin

Inherits:
Object
  • Object
show all
Defined in:
lib/utils/weixin.rb

Constant Summary collapse

@@ticket_list =
{}
@@access_token_list =
{}
@@oauth2_access_token_list =
{}

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.app_idObject

Returns the value of attribute app_id.



8
9
10
# File 'lib/utils/weixin.rb', line 8

def app_id
  @app_id
end

.app_secretObject

Returns the value of attribute app_secret.



8
9
10
# File 'lib/utils/weixin.rb', line 8

def app_secret
  @app_secret
end

.mch_idObject

Returns the value of attribute mch_id.



8
9
10
# File 'lib/utils/weixin.rb', line 8

def mch_id
  @mch_id
end

.oauth2_stateObject

Returns the value of attribute oauth2_state.



8
9
10
# File 'lib/utils/weixin.rb', line 8

def oauth2_state
  @oauth2_state
end

.pay_sign_keyObject

Returns the value of attribute pay_sign_key.



8
9
10
# File 'lib/utils/weixin.rb', line 8

def pay_sign_key
  @pay_sign_key
end

Class Method Details

.api_sign(sign_params = {}, sign_type = 'SHA1') ⇒ Object

sign_string :appid, :appkey, :noncestr, :package, :timestamp



241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/utils/weixin.rb', line 241

def self.api_sign(sign_params = {},sign_type = 'SHA1')
  #logger.debug(sign_params)
  result_string = ''
  sign_params = sign_params.sort
  sign_params.each{|key,value|
    result_string += (key.to_s + '=' + value.to_s + '&')
  }
  result_string = result_string[0, result_string.length - 1]#去掉多余的&号
  logger.debug(result_string)    
  sign = Digest::MD5.hexdigest(result_string).upcase if sign_type == 'MD5'
  sign = Digest::SHA1.hexdigest(result_string) if sign_type == 'SHA1'
  sign
end

.get_access_token(app_id = nil, app_secret = nil) ⇒ Object

获取基础access_token



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/utils/weixin.rb', line 143

def self.get_access_token(app_id=nil,app_secret=nil)
   app_id = Utils::Weixin.app_id if app_id.nil?
   app_secret = Utils::Weixin.app_secret if app_secret.nil?
   cache = @@access_token_list[app_id]

   token = nil
   logger.debug("Utils::Weixin.get_access_token,cache access_token:"+cache.to_s)      
   if cache.nil? || cache[:expire_time].nil? || 
                    cache[:expire_time] - 600 < Time.now.to_i
      #提前十分钟过期,避免时间不同步导致时间差异

     url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+
           app_id.to_s + "&secret=" + app_secret.to_s 
     result =JSON.parse(Net::HTTP.get(URI.parse(url)))
     logger.debug("get access_token result :"+result.to_s)
     if result['access_token']
       cache = {} if cache.nil?
       cache[:access_token] = result['access_token']
       cache[:expire_time] = Time.now.to_i + result['expires_in'].to_i
       token =  cache[:access_token]
       @@access_token_list[app_id] = cache # 更新缓存
       logger.debug("Utils::Weixin.get_access_token,access_token is update:"+cache[:access_token])
     else
       logger.error('Utils::Weixin.get_access_token,获取access_token出错:' + result['errmsg'].to_s)
     end
  else
     token =  cache[:access_token]
  end
  return token
end

.get_oauth2_access_token(code, app_id = nil, app_secret = nil) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/utils/weixin.rb', line 46

def self.get_oauth2_access_token(code,app_id=nil,app_secret=nil)
   app_id = Utils::Weixin.app_id if app_id.nil?
   app_secret = Utils::Weixin.app_secret if app_secret.nil?
   cache = @@oauth2_access_token_list[app_id]

   token = nil
   logger.debug("Utils::Weixin.get_access_token,cache access_token:"+cache.to_s)      
   if cache.nil? || cache[:expire_time].nil? || 
                    cache[:expire_time] - 600 < Time.now.to_i
      #提前十分钟过期,避免时间不同步导致时间差异

     return if code.blank? # 首次调用code为空时直接返回
 
     url = "https://api.weixin.qq.com/sns/oauth2/access_token"
     url += "?appid=" + app_id
     url += "&secret=" + app_secret
     url += "&code=" + code
     url += "&grant_type=authorization_code"

     conn = Faraday.new(:url => url,headers: { accept_encoding: 'none' })
     result = JSON.parse conn.get.body
     logger.debug("get oauth2_access_token result :"+result.to_s)
     if result['access_token']
       cache = {} if cache.nil?
       cache[:access_token] = result['access_token']
       cache[:expire_time] = Time.now.to_i + result['expires_in'].to_i
       token =  cache[:access_token]
       @@oauth2_access_token_list[app_id] = cache # 更新缓存
       logger.debug("Utils::Weixin.get_oauth2_access_token,access_token is update:"+cache[:access_token])
     else
       logger.error('Utils::Weixin.get_oauth2_access_token,获取access_token出错:' + result['errmsg'].to_s)
     end
  else
     token =  cache[:access_token]
  end
  return token       
end

.get_oauth2_url(redirect_uri, auth_type = "snsapi_userinfo", app_id = nil) ⇒ Object

获取oauth2 url



34
35
36
37
38
39
40
41
42
43
44
# File 'lib/utils/weixin.rb', line 34

def self.get_oauth2_url(redirect_uri,auth_type="snsapi_userinfo",app_id=nil)
   app_id = Utils::Weixin.app_id if app_id.nil?
   redirect_uri = CGI::escape(redirect_uri)
   
   state = 'oauth2'
   state = Utils::Weixin.oauth2_state if Utils::Weixin.respond_to?('oauth2_state')  
   url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + 
         "appid=" + app_id + "&redirect_uri=" + redirect_uri + "&response_type=code" + 
         "&scope=" + auth_type + "&state=" + state + "#wechat_redirect"
   return url     
end

.get_openid(code, app_id = nil, app_secret = nil) ⇒ Object

获取opendid,用于snsapi_base授权



85
86
87
88
# File 'lib/utils/weixin.rb', line 85

def self.get_openid(code,app_id=nil,app_secret=nil)
   openid,access_token = Utils::Weixin.get_openid_and_access_token(code,app_id,app_secret)
   return openid      
end

.get_openid_and_access_token(code, app_id = nil, app_secret = nil) ⇒ Object

同时获取openid和access_token,用于snsapi_userinfo授权



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/utils/weixin.rb', line 90

def self.get_openid_and_access_token(code,app_id=nil,app_secret=nil)
   app_id = Utils::Weixin.app_id if app_id.nil?
   app_secret = Utils::Weixin.app_secret if app_secret.nil?
   path = "/sns/oauth2/access_token?appid=" + app_id + "&secret=" + app_secret + 
           "&code=" + code + "&grant_type=authorization_code"
   uri = URI.parse("https://api.weixin.qq.com/")
   http = Net::HTTP.new(uri.host, uri.port)
   http.use_ssl = true
   http.verify_mode = OpenSSL::SSL::VERIFY_NONE
   request = Net::HTTP::Get.new(path)
   request.add_field('Content-Type', 'application/json')
   response = http.request(request)        
   result = JSON.parse(response.body)
   logger.error("Utils::Weixin.get_openid fail,result:"+result.to_s) if result["openid"].blank?
   openid = access_token = nil
   openid = result["openid"] if result["openid"]
   access_token = result["access_token"] if result["access_token"]
   return openid,access_token      
end

.get_ticket(type = "jsapi", access_token = "", app_id = nil, app_secret = nil) ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/utils/weixin.rb', line 174

def self.get_ticket(type="jsapi",access_token="",app_id=nil,app_secret=nil)
    access_token = get_access_token(app_id,app_secret) if access_token.blank?
    key = access_token.to_s + "_" + type
    cache = @@ticket_list[key]
    ticket = nil
    logger.debug("Utils::Weixin.get_ticket,cache ticket:"+cache.to_s)      
    if cache.nil? || cache[:expire_time].nil? || 
                     cache[:expire_time] - 600 < Time.now.to_i
       #提前十分钟过期,避免时间不同步导致时间差异
      url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token.to_s +
            "&type=" + type.to_s
      result =JSON.parse(Net::HTTP.get(URI.parse(url)))
      logger.debug("get get_ticket result :"+result.to_s)
      if result['ticket']
        cache = {} if cache.nil?
        cache[:ticket] = result['ticket']
        cache[:expire_time] = Time.now.to_i + result['expires_in'].to_i
        ticket =  cache[:ticket]
        @@ticket_list[key] = cache # 更新缓存
        logger.debug("Utils::Weixin.get_ticket,ticket is update:" + cache[:ticket].to_s)
      else
        logger.error('Utils::Weixin.get_ticket,获取ticket出错:' + result['errmsg'].to_s)
      end
   else
      ticket =  cache[:ticket]
   end
   return ticket
end

.get_userinfo(openid, app_id = nil, app_secret = nil) ⇒ Object

获取用户信息(仅对关注者有效)



128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/utils/weixin.rb', line 128

def self.get_userinfo(openid,app_id=nil,app_secret=nil)
  app_id = Utils::Weixin.app_id if app_id.nil?
  app_secret = Utils::Weixin.app_secret if app_secret.nil?
  access_token = get_access_token(app_id,app_secret)
  url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + access_token + 
        "&openid=" + openid + "&lang=zh_CN"
  conn = Faraday.new(:url => url)
  result = JSON.parse conn.get.body 
  if result["errmsg"]
     logger.error("Utils::Weixin.get_userinfo of "+ openid.to_s + " error:" + result["errmsg"]) 
  end
  result
end

.get_userinfo_by_auth(access_token, openid) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/utils/weixin.rb', line 115

def self.get_userinfo_by_auth(access_token,openid)
  url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token.to_s + 
        "&openid=" + openid.to_s + "&lang=zh_CN"
  conn = Faraday.new(:url => url)
  result = JSON.parse conn.get.body 
  if result["errmsg"]
     logger.error("Utils::Weixin.get_userinfo_by_auth of openid: "+ openid.to_s + 
                  ",access_token:" + access_token.to_s + ", error:" + result["errmsg"]) 
  end
  result
end

.get_userinfo_by_authcode(code, app_id = nil, app_secret = nil) ⇒ Object

通过网页授权获取用户信息(无须关注公众号)



111
112
113
114
# File 'lib/utils/weixin.rb', line 111

def self.get_userinfo_by_authcode(code,app_id=nil,app_secret=nil)  
   openid,access_token = get_openid_and_access_token(code,app_id,app_secret)
  return get_userinfo_by_auth(access_token,openid)
end

.loggerObject

定义logger



12
13
14
# File 'lib/utils/weixin.rb', line 12

def self.logger
  Rails.logger
end

.pay_sign(sign_params = {}, sign_type = 'SHA1') ⇒ Object

兼容老接口



255
256
257
# File 'lib/utils/weixin.rb', line 255

def self.pay_sign(sign_params = {},sign_type = 'SHA1')      
    api_sign(sign_params,sign_type)
end

.post_data(data, path) ⇒ Object

提交数据



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/utils/weixin.rb', line 17

def self.post_data(data,path)
   logger.debug("data:"+ JSON.parse(data).to_s) 
   uri = URI.parse("https://api.weixin.qq.com/")
   http = Net::HTTP.new(uri.host, uri.port)
   http.use_ssl = true
   http.verify_mode = OpenSSL::SSL::VERIFY_NONE
   request = Net::HTTP::Post.new(path)
   request.add_field('Content-Type', 'application/json')
   request.body = data
   response = http.request(request)
   
   result = JSON.parse(response.body)
   logger.debug("result:"+result.to_s) 
   return result
end

.send_customer_message(to_openid, message, app_id = nil, app_secret = nil) ⇒ Object

发送客服消息



204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/utils/weixin.rb', line 204

def self.send_customer_message(to_openid,message,app_id=nil,app_secret=nil)
  app_id = Utils::Weixin.app_id if app_id.nil?
  app_secret = Utils::Weixin.app_secret if app_secret.nil?
  access_token = get_access_token(app_id,app_secret)
  data = '{"touser":"'+ to_openid +'" , "msgtype": "text", "text": {"content": "' + 
           message + '"}}'                              
  path = '/cgi-bin/message/custom/send?access_token=' + access_token
  result = post_data(data,path)
  if result["errcode"] != 0
     logger.error("Utils::Weixin.send_customer_message to :"+to_openid + " result:" + result["errmsg"]) 
  end
end

.send_template_message(to_openid, template_id, message, url = '', top_color = '#FF0000', value_color = '#173177', app_id = nil, app_secret = nil) ⇒ Object

发送模板消息



218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/utils/weixin.rb', line 218

def self.send_template_message(to_openid,template_id,message,url='',top_color='#FF0000',value_color='#173177',
                               app_id=nil,app_secret=nil)
  app_id = Utils::Weixin.app_id if app_id.nil?
  app_secret = Utils::Weixin.app_secret if app_secret.nil?
  access_token = get_access_token(app_id,app_secret)

  data = '{"touser":"'+ to_openid +'","template_id":"' + template_id +'","url":"' + url  + '",' +
          '"topcolor":"' + top_color + '","data":{'
  message.each do |m_k,m_v|
     data += '"' + m_k + '":{"value":"' + m_v + '","color":"' + value_color + '"},'         
  end
  data.chop! if data.end_with?(',')
  data += '}}'                 
  logger.debug("send_template_message data:" + data)         
  path = '/cgi-bin/message/template/send?access_token=' + access_token
  result = post_data(data,path)
  if result["errcode"] != 0
     logger.error("Utils::Weixin.send_template_message to :"+to_openid + " result:" + result["errmsg"]) 
  end
end