Using Xinge Notification Push Services In Rails

为了配合移动 APP 产品方面的设计,先考虑在 APP 功能上,增加消息推送的功能。
能够做到即时消息的提醒,提升用户的活跃度和使用 APP 的粘性。
本篇介绍一下,在 Rails 后端项目中,如何对接信鸽的推送服务。

1. 信鸽介绍

信鸽(XG Push)是一款专业的免费移动 App 推送平台,支持百亿级的通知/消息推送,秒级触达移动用户,现已全面支持 Android 和 iOS 两大主流平台。
信鸽推送平台是腾讯旗下的一个产品,相信在并发,可靠性和稳定性方面,经得住考验。

2. 注册信鸽账号,制作证书

使用 QQ 号可以直接登录信鸽管理平台,相当于注册。登录后,可以创建应用,选择 iOS 还是 Android 平台。
目前,我们只做 iOS 平台,信鸽区分开发环境和测试环境,因此,需要创建两个应用。
应用创建完成之后,将开发相关同事的 QQ 号,添加进应用的管理员,这样其他人登录信鸽后,可以直接查看到应用了。
为了实现消息的推送,需要 iOS 开发者,制作证书,并上传至信鸽平台, 交由信鸽托管,以此来对接苹果的消息中心。
证书制作,请参考:iOS 证书设置指南

3. 下载,编译 SDK

iOS 证书上传,并验证通过后,可以下载信鸽 iOS 客户端 SDK
参考 iOS SDK 指南 ,编译 SDK 以嵌入应用。注册设备信息后,将设备的 Device Token,添加到信鸽里的测试设备 Token。

4. 配置 Access ID, Secret Key

以上准备工作完成之后,将信鸽内创建的应用配置信息:Access ID 和 Secret Key,放入 Rails 的配置项内。

  development:
    xinge_host: openapi.xg.qq.com
    xinge_api_url: http://openapi.xg.qq.com
    xinge_access_id: access_id
    xinge_secret_key: secret_key


  production:
    xinge_host: openapi.xg.qq.com
    xinge_api_url: http://openapi.xg.qq.com
    xinge_access_id: access_id
    xinge_secret_key: secret_key

5. 对接信鸽接口,给设备 Push 消息通知

下面列举几段代码,给单个设备 Push 消息通知。

Xinge 模块的 Base 基类,实现了对接信鸽接口的:配置和具体 API 的功能。

module Xinge
  class Base

    class << self

      # push 消息(包括通知和透传消息)给单个设备
      def push_single_device(device_token, message, params = {})
        params.merge!({
          device_token: device_token,
          message: message,
          message_type: 1
          })
        send_request('push', 'single_device', params)
      end

      protected

      def send_request(type, method, params = {})
        request_path = get_request_url(type, method)
        params.merge!({access_id: Settings.xinge_access_id, timestamp: Time.now.to_i})

        # sort params and calculate sign
        params_string = params.sort.map{ |h| h.join('=') }.join
        sign_str = "POST#{Settings.xinge_host}#{request_path}#{params_string}#{Settings.xinge_secret_key}"
        sign = Digest::MD5.hexdigest(sign_str)
        params.merge!({ sign: sign })

        begin
          request_url = "#{Settings.xinge_api_url}#{request_path}"
          reuqest_header = {'Content-Type' => 'application/x-www-form-urlencoded'}
          response = RestClient.post(request_url, params, reuqest_header)
          if response.present?
            result = JSON.parse(response)
            if result
              [result["ret_code"], result["err_msg"]]
            end
          end
        rescue => e
          puts e.response
          return false
        end
      end

      def get_request_url(type, method)
        "/v2/#{type}/#{method}"
      end

    end

  end
end

Xinge 模块的 Ios 类,信鸽针对 iOS 设备的消息推送,接口上有部分特殊要求。如:消息结构体较 Android 复杂,需要指明是开发还是生产环境,消息的内容字节数限制等。

module Xinge
  class Ios < Base

    class << self

      def push_to_single_device(device_token, title, content)
        push_single_device(device_token, build_simple_message(title, content),
          environment_param)
      end

      protected

      def environment_param
        env_val = Rails.env.production? ? 1 : 2
        { environment: env_val }
      end

      def build_simple_message(title, content)
        {
          aps: {
            alert: {
              title: title,
              body: content
            },
            sound: 'default',
            badge: 5
          }
        }.to_json
      end

    end

  end
end

Xinge 模块的 Notification 类,实现的时,对接 APP 内部的具体业务。如:准备发送用户评论的消息内容等。

module Xinge
  class Notification

    class << self

      def reply_push(reply_id)
        reply = Reply.where(id: reply_id).first
        if reply.present?
          content = "#{reply.to_user.name}: 对您发表了新的评论,快去看看吧~"
          do_push(reply.to_user_id, content)
        end
      end

      def do_push(user_id, content)
        title = "APP名称"
        device = UserDevice.notification_device(user_id)
        if device.present?
          if device.is_ios?
            Xinge::Ios.push_to_single_device(device.device_token, title, content)
          else
            Xinge::Android.push_to_single_device(device.device_token, title, content)
          end
        end
      end

    end

  end
end

参考链接
国内一位 Ruby 朋友写的库,值得参考:A Ruby portal for Tencent Xinge
本人写的一个 Grape Demo 项目,提交了对接信鸽的逻辑:xinge ios,android notification push logic

2015-05-06

rocket-wing