2015年3月4日水曜日

ニフティクラウドmobile backendでPush通知できるRubyスクリプト

P.S 20150914
POST スクリプトも gist で公開しました
https://gist.github.com/kakakikikeke/ef34c3a0180961262607
同時に curl コマンドを出力できるようにしました

概要

ニフティクラウドmobile backendのプッシュ通知をコンパネからではなくRubyスクリプトからできるようにしてみました

環境

  • Mac OS 10.10.2
  • Ruby 2.2.0p0

スクリプト

  • post_push.rb
require 'rest_client'
require 'json'
require 'time'
require 'hmac'
require 'hmac-sha2'
require 'base64'
require 'openssl'

APPLICATION_KEY='Please input your apps application key'
CLIENT_KEY='Please input your apps client key'
ENDPOINT='mb.api.cloud.nifty.com'
VERSION='2013-09-01'
SIG_METHOD='HmacSHA256'
SIG_VERSION=2
PATH='/push'

def main
  post_push
end

def post_push
  timestamp = get_timestamp
  signature = create_signature(
    "POST",
    ENDPOINT,
    VERSION,
    PATH,
    CLIENT_KEY,
    "X-NCMB-Application-Key" => APPLICATION_KEY,
    "X-NCMB-Timestamp" => timestamp,
    "SignatureMethod" => SIG_METHOD,
    "SignatureVersion" => SIG_VERSION,
  );
  params = {
    'immediateDeliveryFlag' => true,
    'target' => [
      "ios"
    ],
    'message' => timestamp
  }
  response = RestClient.post( "https://#{ENDPOINT}/#{VERSION}#{PATH}",
    params.to_json,
    {
      :content_type => 'application/json',
      'X-NCMB-Application-Key' => APPLICATION_KEY,
      'X-NCMB-Timestamp' => timestamp,
      'X-NCMB-Signature' => signature
    })
  json = JSON.parse(response)
  puts json
end

def create_signature(method, endpoint, version, path, client_key, options = {})
  application_key = options["X-NCMB-Application-Key"]
  timestamp = options["X-NCMB-Timestamp"]
  canonical_querystring = options.sort.collect { |key, value| [key, value].join('=') }.join('&')
  string_to_sign = "#{method}\n#{endpoint}\n/#{version}#{path}\n#{canonical_querystring}"
  hmac = HMAC::SHA256.new(client_key)
  hmac.update(string_to_sign)
  signature = Base64.encode64(hmac.digest.to_s).chomp
  return signature
end

def get_timestamp
  return Time.now.utc.xmlschema.gsub("Z", ".456Z")
end

main
  • Gemfile
source "https://rubygems.org"

gem "rest-client", ">= 1.7.3"
gem "ruby-hmac", ">= 0.4.0"

実行方法

bundle install && bundle exec ruby post_push.rb

bundlerを使って実行していますがGemfileに書かれている必要なgemをインストールしてruby post_push.rbでもOKです

解説

必ずやらなければいけない設定はAPPLICATION_KEYCLIENT_KEYをコントロールパネルのアプリ設定から取得したキーに書き換えるくらいです
あとは必要に応じて実施すればOKです

プッシュのパラメータはparams変数で管理しています
即時配信でプッシュに送信されるメッセージは送信時のタイムスタンプが表示されます
対象はiOSだけなので必要であればandroid も配列に追加してください
その他のパラメータはここを参照してください
例えばsearchConditionを使って特定のデバイスにのみ送信したい場合はparams変数を以下のように変更します

params = {
  'immediateDeliveryFlag' => true,
  'searchCondition' => {
    'deviceToken' => 'hoge deviceToken'                                    
  },
  'target' => [
    "ios"
  ],
  'message' => timestamp
}

searchConditionパラメータはオブジェクト型なのでハッシュで設定しています
各パラメータに応じた適切な型を設定してあげないとうまくAPIをコールできないので注意してください

あとあくまでもこれが使えるのはプッシュ通知に必要な設定を実施しているのが前提です
プッシュ通知自体をまだ設定していないという場合は過去にやり方を紹介しているのでご覧ください

GET版も作ってみたのでよければ見てください

5 件のコメント:

  1. はじめまして。
    perlでNCMBにプッシュ通知をする方法を探してここにたどり着きました。

    かなり探したのですが、PerlとLWPモジュールでNCMBに接続する方法を解説しているところがなく、自分なりにコードも書いてみたのですが、httpsでの接続の段階でつまずいてる状況です。

    なんとかお教えいただけないでしょうか。
    サーバはさくらインターネットのライトプランを利用しています。

    返信削除
  2. usotch さん

    すいません、作ったことがないのでソースレベルのものはすぐに提供できないです、、、

    NCMB は普通の REST-API なので LWP でもいけると思います
    Signature を生成するロジックがちょっと大変かもしれませんが、Web で調べればいろいろ出てくると思います

    お約束はできませんが、もし作れたらコメントでお知らせします

    返信削除
  3. はい、よろしくお願いします。

    自分が書いたコードでpostしてみたところ、

    Can't connect to mb.ap.cloud.niftycom:443 nodename nor servname provided, or not known at /usr/local/perl/5.8/lib/perl5/site_perl/5.8/LWP/Protocol/http.pm line 51.

    というレスポンスで、httpsの接続ができていないようで、署名がうまくつくれているかどうかさえ判定できない腕前です。

    返信削除
  4. usotch さん

    かなり適当ですが、動作するレベルのものを作ってみました
    http://kakakikikeke.blogspot.jp/2016/04/perl-lwp-ncmb-push.html

    プッシュ通知を登録することができます

    返信削除
  5. 動きました!
    さくらインターネットにはCrypt::SSLeayとMozilla::CAは最初から入っていたので、特に何もせずに1発で。
    感動にちょっと震えてます。
    この1ヶ月、あれこれ悩んで軽く100回以上は自作コードを試したのですが、まったく歯が立たず、kakakikikekeさんのおかげでSSL周辺をどうすればいいのかがやっとうっすらと判ってきました。
    ありがとうございます。

    返信削除