# README 这个项目集成了一系列的推送服务。个推,小米,华为。 ### 使用准备 * 向项目负责人申请app_name,app_id,app_secret ### 关键api * /api/v1/token * 请求参数 |参数名称|类型|是否必填|说明| |-----|-----|------|----| |app_name|String|是|应用名称| |app_id|String| 是| 应用app_id| |app_secret|String |是|应用app_secret| 这些配置都有在app.yml 文件中配置 * 返回结果 |code|message|token|ttl| |----|----|---|---| |0|success|token值|token 过期时间| |-1|应用不存在或者app_id/app_secret不匹配||| * /api/v1/push * 请求参数 |参数名称|类型|是否必填|说明| |-----|-----|------|----| |app_name|String|是|应用名称| |user_device_ids|Array/String| 是| 设备id| |message|String|是|需要返送的信息的json字符串| |igetui_opts|String|是|个推的一些额外参数| * 返回结果 |code|message|说明| |----|----|---| |0|success|异步任务正在处理| |-1|token 错误/过期| ### 使用案例 * 配置文件 ``` app_push: host: 'http://localhost:3001' app_name: 'crm' app_id: '****' app_secret: '****' ``` AppSettings(可以使用gem settingslogic)读取配置文件信息 * 关键代码 ``` module PushService module Push TOKEN_URL = '/api/v1/token'.freeze PUSH_URL = '/api/v1/push'.freeze TOKEN_KEY = 'push_service:push:token'.freeze EXPIRE_TIME = 3500 class << self # 调用推送服务,推送信息 # user_device_ids, 用户设备信息,可以是字符串数组,也可以是字符串。 # message 要推送的具体信息 # igetui_opts 是hash类型,主要是一些其他的信息。 # 由于历史遗留问题,封装的不够好,这里主要用来处理个推的一些参数。 # 目前华为推送,小米推送不需要到这个。 def push(user_device_ids, message, igetui_opts = {}) url = AppSettings.app_push['host'] + PUSH_URL headers = { 'Accept' => 'application/json;', 'Authorization' => "Token token=#{token}" } body = { app_name: AppSettings.app_push['app_name'], user_device_ids: user_device_ids, message: message.to_json, igetui_opts: igetui_opts.to_json } response = HTTParty.post(url, body: body, headers: headers, timeout: 5) PushService::Log.info("url: #{url} headers: #{headers} body: #{body} response: #{response}") end # 获取token def token return $redis.get(TOKEN_KEY) if $redis.get(TOKEN_KEY).present? res = req_token store_token(res) end def token_ttl $redis.ttl(TOKEN_KEY) end def req_token body = { app_name: AppSettings.app_push['app_name'], app_id: AppSettings.app_push['app_id'], app_secret: AppSettings.app_push['app_secret'] } url = AppSettings.app_push['host'] + TOKEN_URL response = HTTParty.post(url, body: body, headers: { Accept: 'application/json' }, timeout: 5) PushService::Log.info("url: #{url} body: #{body} response: #{response}") response end def store_token(response) if response['code'].zero? token = response['token'] $redis.set(TOKEN_KEY, token, ex: EXPIRE_TIME) token else '' end end end end end ``` * 异步执行代码 ``` class VariousPushWorker include Sidekiq::Worker sidekiq_options queue: :low, retry: true, backtrace: true def perform(client_ids, message, opts) PushService::Push.push(client_ids, message, opts) rescue StandError => e logger.error "exec_sync exception: #{e.message}:#{e.backtrace}" end private def logger @logger ||= ActiveSupport::Logger.new("#{Rails.root}/log/various_push_sidekiq.log", 'weekly') end end ``` * 参数例子 ``` user_device_ids = ["f30b426be09f5111fde8e717919c35d9"] message = {"category"=>0, "push_type"=>2, "extras"=>{"due_at"=>"2019-05-22", "title"=>"工作报告通知", "text"=>"温馨提示,现在还没有人提交工作报告,第一个会不会是你呢?去写日报。"}, "id"=>1261514, "title"=>"工作报告通知", "text"=>"温馨提示,现在还没有人提交工作报告,第一个会不会是你呢?去写日报。", "notifiable_id"=>5501712, "notifiable_type"=>"User", "subject_id"=>nil, "subject_type"=>"ScheduleReport::Daily", "notify_type"=>"notify_should_create", "created_at"=>1558518806, "user_id"=>5501712, "is_ring"=>true, "is_vibrate"=>true} igetui_opts = {"transmission_type"=>0} VariousPushWorker.perform_async(user_device_ids, message,igetui_opts ) ```