module BlsmMpWx

Constants

ERROR_CODES
VERSION

Attributes

APP_ID[RW]
APP_ID_2[RW]

Public Class Methods

access_token(app_id=nil) click to toggle source

根据app_id获取access_token 系统会根据当前的access_token即过期时间,自动更新并返回 开发者无需关心这里的access_token怎么更新

Parameters

* +app_id+ -公众号的appid
# File lib/blsm-mp-wx.rb, line 34
def access_token(app_id=nil)
  app_id ||= self.APP_ID
  app = VdMpWx.where(app_id: app_id).first
  return nil unless app
  return app.access_token unless app.access_token_expired? #没有过期,直接返回

  response = Faraday.new(:url => 'https://api.weixin.qq.com').get do |req|
    req.url '/cgi-bin/token'
    req.params[:appid] = app.app_id
    req.params[:secret] = app.app_secret
    req.params[:grant_type] = 'client_credential'
  end

  json_obj = parse_json(response.body)
  return nil unless json_obj
  return nil unless json_obj.has_key?('access_token')

  access_token = json_obj['access_token']
  app.save_access_token(access_token, json_obj['expires_in'])

  access_token
end
all_openid(app_id=nil, next_openid='', returned_openids = []) click to toggle source
# File lib/blsm-mp-wx.rb, line 318
def all_openid(app_id=nil, next_openid='', returned_openids = [])
  app_id ||= self.APP_ID
  p "getting openid... next_openid:#{next_openid}"

  begin
    conn = Faraday.new(:url => 'https://api.weixin.qq.com')
    response = conn.get do |req|
      req.url '/cgi-bin/user/get'
      req.headers['Content-Type'] = 'application/json'
      req.params[:access_token] = access_token(app_id)
      req.params[:next_openid] = next_openid
    end
    response_body = response.body
    p response_body
    jobject = JSON.parse(response_body)

    if jobject
      if jobject['data'] && jobject['data']['openid']
        p "total:#{jobject['total']},count:#{jobject['count']}"
        returned_openids += jobject['data']['openid']
      end

      if jobject['next_openid'].to_s != ''
        return all_openid(jobject['next_openid'], returned_openids)
      end
    end

    if !jobject || jobject['next_openid'].to_s ==''
      return returned_openids
    end
  rescue Exception => e
    puts e
  end
  returned_openids
end
batchget_material(app_id, type, offset, count=20) click to toggle source

批量获取公众号的素材列表

Parameters
* +app_id+
* +type+ 素材类型:voice、video、image、news
* +offset+
* +count+
# File lib/blsm-mp-wx.rb, line 295
def batchget_material(app_id, type, offset, count=20)
  app_id ||= self.APP_ID
  access_token = access_token(app_id)
  return nil unless access_token
  response = Faraday.new(:url => 'https://api.weixin.qq.com').post do |req|
    req.url '/cgi-bin/material/batchget_material'
    req.headers['Content-Type'] = 'application/json'
    data = {
        type: type,
        offset: offset,
        count: count
    }
    req.params[:access_token] = access_token
    req.body = data.to_json
  end

  json_obj = parse_json(response.body)
  return nil unless json_obj
  return nil unless json_obj.has_key?('total_count')
  json_obj.inject({}) { |memo, (key, v)| memo[key.to_s.to_sym]=v; memo }
end
create_msg(app_id, openid, content, msg_name, template_msg=true) click to toggle source

创建消息,存储到消息队列中

Parameters

* +app_id+ - 公众号的唯一标识
* +openid+ - 发送给用户的openid
* +content+ - 消息内容
* +msg_name+ - 消息种类:new_order(新订单通知)、balance(结算通知)、score_change(积分变动通知)、order(订单通知)、todo(待处理)、split_order(分单)、custom(普通消息)
 new_order => content: {touser:'openid',order_id:''} 系统自动优先使用模板消息发送通知
 balance   => content: {touser:'openid',clearing_id} 系统自动优先使用模板消息发送通知
 score_change => content: {touser:'',change:5,total:25,content:'邀请他人。。。。'}
# File lib/blsm-mp-wx.rb, line 221
def create_msg(app_id, openid, content, msg_name, template_msg=true)
  app_id ||= self.APP_ID
  return nil unless openid
  return nil unless content[:touser]==openid
  # return nil unless MP_MSG_TYPES.include?(msg_name)
  VdMpMsg.create({
                     app_id: app_id,
                     openid: openid,
                     content: content.to_json,
                     msg_name: msg_name,
                     template_msg: template_msg,
                     status: 'none'
                 })
end
create_msg!(app_id, openid, content, msg_name, template_msg=true) click to toggle source
# File lib/blsm-mp-wx.rb, line 237
def create_msg!(app_id, openid, content, msg_name, template_msg=true)
  app_id ||= self.APP_ID
  VdMpMsg.create!({
                      app_id: app_id,
                      openid: openid,
                      content: content.to_json,
                      msg_name: msg_name,
                      template_msg: template_msg,
                      status: 'none'
                  })
end
gen_forever_qr_ticket(app_id=nil, scene_id) click to toggle source

生成永久二维码ticket

# File lib/blsm-mp-wx.rb, line 174
def gen_forever_qr_ticket(app_id=nil, scene_id)
  app_id ||= self.APP_ID
  access_token = access_token(app_id)
  return nil unless access_token

  response = Faraday.new(:url => 'https://api.weixin.qq.com').post do |req|
    req.url '/cgi-bin/qrcode/create'
    req.params[:access_token] = access_token
    req.body="{\"action_name\": \"QR_LIMIT_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": #{scene_id}}}}"
  end

  json_obj = parse_json(response.body)
  return nil unless json_obj
  return nil unless json_obj.has_key?('ticket')

  json_obj['ticket']
end
gen_short_url(app_id=nil, long_url) click to toggle source

长链接转短连接

# File lib/blsm-mp-wx.rb, line 193
def gen_short_url(app_id=nil, long_url)
  app_id ||= self.APP_ID
  access_token = access_token(app_id)
  return nil unless access_token

  response = Faraday.new(:url => 'https://api.weixin.qq.com').post do |req|
    req.url '/cgi-bin/shorturl'
    req.headers['Content-Type'] = 'application/json'
    req.params[:long_url] = long_url
    req.params[:access_token] = access_token
    req.body = "{\"action\":\"long2short\",\"long_url\":\"#{long_url}\"}"
  end

  json_obj = parse_json(response.body)
  return nil unless json_obj
  return nil unless json_obj.has_key?('short_url')
  json_obj['short_url']
end
gen_wx_user_info(app_id=nil, openid) click to toggle source

获取用户的基本信息(包括UnionID机制)

# File lib/blsm-mp-wx.rb, line 154
def gen_wx_user_info(app_id=nil, openid)
  app_id ||= self.APP_ID
  access_token = access_token(app_id)
  return nil unless access_token

  response = Faraday.new(:url => 'https://api.weixin.qq.com').get do |req|
    req.url '/cgi-bin/user/info'
    req.params[:openid] = openid
    req.params[:access_token] = access_token
  end

  json_obj = parse_json(response.body)
  puts "#{json_obj}"
  return nil unless json_obj
  return json_obj.inject({}) { |memo, (key, v)| memo[key.to_s.to_sym]=v; memo } if json_obj.has_key?('openid')

  nil
end
get_material(app_id, media_id) click to toggle source

根据media_id来获取永久素材

Parameters
* +app_id+
* +media_id+ 要获取的素材的media_id
# File lib/blsm-mp-wx.rb, line 273
def get_material(app_id, media_id)
  app_id ||= self.APP_ID
  access_token = access_token(app_id)
  return nil unless access_token
  response = Faraday.new(:url => 'https://api.weixin.qq.com').post do |req|
    req.url '/cgi-bin/material/get_material'
    req.headers['Content-Type'] = 'application/json'
    req.params[:access_token] = access_token
    req.body= {media_id: media_id}.to_json
  end
  body = response.body
  json_obj = parse_json(body)
  return body unless json_obj
  json_obj.inject({}) { |memo, (key, v)| memo[key.to_s.to_sym]=v; memo }
end
get_material_count(app_id, type) click to toggle source

批量获取公众号的素材列表

Parameters
* +app_id+
* +type+ 素材类型:voice、video、image、news
# File lib/blsm-mp-wx.rb, line 253
def get_material_count(app_id, type)
  app_id ||= self.APP_ID
  access_token = access_token(app_id)
  return nil unless access_token
  response = Faraday.new(:url => 'https://api.weixin.qq.com').post do |req|
    req.url '/cgi-bin/material/get_materialcount'
    req.headers['Content-Type'] = 'application/json'
    req.params[:access_token] = access_token
  end

  json_obj = parse_json(response.body)
  return nil unless json_obj
  return nil unless json_obj.has_key?("#{type}_count")
  json_obj["#{type}_count"].to_i
end
js_api_sign_package(app_id=nil, url) click to toggle source

JSAPI签名package

# File lib/blsm-mp-wx.rb, line 135
def js_api_sign_package(app_id=nil, url)
  app_id ||= self.APP_ID
  ticket = js_api_ticket(app_id)
  timestamp = Time.new.to_i
  nonce_str = Digest::MD5.hexdigest(Time.new.to_i.to_s + Random.rand(99999).to_s)
  string = "jsapi_ticket=#{ticket}&noncestr=#{nonce_str}&timestamp=#{timestamp}&url=#{url}"
  signature = Digest::SHA1.hexdigest(string)
  {
      appId: app_id,
      nonceStr: nonce_str,
      timestamp: timestamp,
      url: url,
      signature: signature,
      rawString: string
  }
end
js_api_ticket(app_id=nil) click to toggle source

获取jsapi全局唯一票据

# File lib/blsm-mp-wx.rb, line 58
def js_api_ticket(app_id=nil)
  app_id ||= self.APP_ID
  access_token = access_token(app_id)
  app = VdMpWx.where(app_id: app_id).first

  return nil unless access_token
  return nil unless app
  return app.js_api_ticket unless app.js_api_ticket_expired? #没有过期,直接返回

  response = Faraday.new(:url => 'https://api.weixin.qq.com').get do |req|
    req.url '/cgi-bin/ticket/getticket'
    req.params[:access_token] = access_token
    req.params[:type] = 'jsapi'
  end

  json_obj = parse_json(response.body)
  return nil unless json_obj
  return nil unless json_obj.has_key?('ticket')

  ticket = json_obj['ticket']
  app.save_js_api_ticket(ticket, json_obj['expires_in'])

  ticket
end
send_msg(app_id=nil, openid, msg) click to toggle source

发送普通消息 文本消息:

{
  "touser":"OPENID",
  "msgtype":"text",
  "text":
  {
        "content":"Hello World"
  }
}

图文消息:

{
"touser":"OPENID",
    "msgtype":"news",
    "news":
  {
    "articles": [
        {
            "title":"Happy Day",
        "description":"Is Really A Happy Day",
        "url":"URL",
        "picurl":"PIC_URL"
        },
        {
         "title":"Happy Day",
        "description":"Is Really A Happy Day",
        "url":"URL",
        "picurl":"PIC_URL"
        }
    ]
  }
}
# File lib/blsm-mp-wx.rb, line 115
def send_msg(app_id=nil, openid, msg)
  app_id ||= self.APP_ID
  access_token = access_token(app_id)
  return nil unless access_token
  return nil unless openid
  return nil unless msg[:touser]==openid

  response = Faraday.new(:url => 'https://api.weixin.qq.com').post do |req|
    req.url '/cgi-bin/message/custom/send'
    req.params[:access_token] = access_token
    req.headers['Content-Type'] = 'application/json'
    req.body = msg.to_json
  end

  json_obj = parse_json(response.body)
  return nil unless json_obj
  json_obj['errcode']==0
end
sns_login_userinfo(code,app_id=nil) click to toggle source

sns登录获取用户信息

# File lib/blsm-mp-wx.rb, line 355
def sns_login_userinfo(code,app_id=nil)
  app_id = app_id || 'wx143306afc47c63a6'
  app = VdMpWx.where(app_id: app_id).first

  conn = Faraday.new(:url => 'https://api.weixin.qq.com')
  response = conn.post do |req|
    req.url '/sns/oauth2/access_token'
    req.headers['Content-Type'] = 'application/xml'
    req.params[:appid] = app_id
    req.params[:secret] =app.app_secret
    req.params[:code] = code
    req.params[:grant_type] = 'authorization_code'
  end

  if response.body.encoding != 'UTF-8'
    response_body = response.body.force_encoding('UTF-8')
  else
    response_body = response.body
  end

  res = parse_json(response_body)
  return res unless res['access_token']


  conn = Faraday.new(:url => 'https://api.weixin.qq.com')
  response = conn.post do |req|
    req.url '/sns/userinfo'
    req.headers['Content-Type'] = 'application/xml'
    req.params[:access_token] = res['access_token']
    req.params[:openid] = res['openid']
  end
  if response.body.encoding != 'UTF-8'
    response_body = response.body.force_encoding('UTF-8')
  else
    response_body = response.body
  end

  res = parse_json(response_body)
  return res unless res['nickname']

  VdWxUser.find_or_create_by({app_id: app_id, openid: res['openid']}) do |u|
    u.update_attributes({nickname: res['nickname'],
                         sex: res['sex'],
                         unionid: res['unionid'],
                         language: res['language'],
                         city: res['city'],
                         province: res['province'],
                         country: res['country'],
                         headimgurl: res['headimgurl'],
                        })
  end
end

Private Class Methods

parse_json(json_data_str) click to toggle source

解析json类型的数据,并将最后的数据转为hash或array

+json_data_str+ 要转换的json数据
# File lib/blsm-mp-wx.rb, line 411
def parse_json(json_data_str)
  begin
    return JSON.parse(json_data_str)
  rescue
  end
  nil
end