7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ライブラリを使わずにTwitter APIでダイレクトメッセージを送信する [PHP]

Last updated at Posted at 2019-06-25

TwitterのAPIを利用して、任意のユーザーへダイレクトメッセージを送信するPHPのコードです。ライブラリは使わずに直接実装するケースを想定しています。

#前提条件
・送信元のアカウントでAPIを利用出来る。(Twitter Developersに登録済み)
・送信相手のユーザーIDが判明している。
送信相手がこちら(送信元)のアカウントをフォローしている。

#処理の流れ

  1. 署名キーを作る
  2. HTTPヘッダ用のパラメータを作る
  3. パラメータ(2.)をソートする
  4. 署名キー(1.)とパラメータ(3.)から署名を作る
  5. パラメータ(3.)に署名(4.)を追加する
  6. パラメータ(3.)からHTTPヘッダ用の配列を作る
  7. POSTデータ用の配列を作る
  8. cURLでエンドポイントにデータを投げる
  9. エンドポイントの応答を受け取る

##接続先(エンドポイント)
https://api.twitter.com/1.1/direct_messages/events/new.json

##処理に必要な値
Twitter Developersで下記の値を予め取得しておく必要があります。

$api_key = 'APIキー';
$api_secret = 'APIシークレット';
$access_token = 'アクセストークン';
$access_token_secret = 'アクセストークンシークレット';

#1. 署名キーを作る
APIシークレットとアクセストークンシークレットを用いて署名キーを作成します。

$signature_key = rawurlencode( $api_secret )."&".rawurlencode( $access_token_secret );

#2. HTTPヘッダ用のパラメータを作る
エンドポイントへ渡すための認証データを連想配列で作成します。

$paramData = array(
  "oauth_token" => rawurlencode( $access_token ),
  "oauth_consumer_key" => rawurlencode( $api_key ),
  "oauth_signature_method" => rawurlencode( "HMAC-SHA1" ),
  "oauth_timestamp" => time(),
  "oauth_nonce" => microtime(),
  "oauth_version" => rawurlencode( "1.0" )
);

#3. パラメータをソートする
ksortで連想配列をソートします。これを忘れると認証エラーが起き得ます。

ksort( $paramData );

#4. 署名キーとパラメータから署名を作る
1で作成した署名キーと、2で作成したパラメータの配列を利用して、署名を作ります。

$sig_param = rawurlencode('POST')."&".
  rawurlencode('https://api.twitter.com/1.1/direct_messages/events/new.json')."&".
  rawurlencode( http_build_query( $paramData , "", "&" ) );

$signature = hash_hmac( "sha1", $sig_param, $signature_key, TRUE );
$signature = base64_encode( $signature );

#5. パラメータに署名を追加する
連想配列に署名を追加します。

$paramData['oauth_signature'] = $signature;

#6. パラメータからHTTPヘッダ用の配列を作る
cURLで使うための配列を新たに作成しておきます。

$httpHeader = array(
  'Authorization: OAuth '.http_build_query( $paramData, "", "," ),
  'content-type: application/json'
);

#7. POSTデータ用の配列を作る
cURLで送信するボディにあたるデータを作成します。これは後にjsonエンコードします。
ここで送信先のユーザーIDと、送信したいメッセージもセットします。

$postData = array(
  "event" => array(
    "type" => "message_create",
    "message_create" => array(
      "target" => array(
        "recipient_id" => '送信先のユーザID'  //送信先ID
      ),
      "message_data" => array(
        "text" => '送信メッセージ'  //送信したいメッセージ
      )
    )
  )
);

Eventオブジェクトの中に入れ子で情報を詰め込んでいます。
上記のサンプルコードは必須項目のみを記述していますが、message_dataオブジェクト(メッセージが入っているところ)にはオプションも追記可能です。

詳しくはTwitter公式のAPIリファレンスを確認してください。1

#8. cURLでエンドポイントにデータを投げる
これまでに作成した各種配列をセットして、cURLでエンドポイントへデータを渡します。

$ch = curl_init();

curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeader);
curl_setopt($ch, CURLOPT_URL, 'https://api.twitter.com/1.1/direct_messages/events/new.json');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, rawurlencode('POST'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode( $postData ));

$json = curl_exec($ch);

curl_close($ch);

#9. エンドポイントの応答を受け取る
ダイレクトメッセージの送信に成功すると、message_createイベントのIDやタイムスタンプを含んだjsonデータが返されます。ここでjsonデータを連想配列へ変換しておきます。

$response = json_decode( $json, true );

echo var_dump( $response );

var_dumpした結果が下記です。

array(1) {
  ["event"]=> array(4) {
    ["type"]=> string(14) "message_create"
    ["id"]=> string(19) "イベントID"
    ["created_timestamp"]=> string(13) "1561275503817"  //ミリ秒
    ["message_create"]=> array(3) {
      ["target"]=> array(1) {
        ["recipient_id"]=> string(10) "送信先のID"
      }
      ["sender_id"]=> string(19) "送信元のID"
      ["message_data"]=> array(2) {
        ["text"]=> string(24) "送信メッセージ"
        ["entities"]=> array(4) {
          ["hashtags"]=> array(0) { }
          ["symbols"]=> array(0) { }
          ["user_mentions"]=> array(0) { }
          ["urls"]=> array(0) { }
        }
      }
    }
  }
}

これ以降の処理は、idが含まれているか、などの条件で処理判定すればよいかと思います。

if( empty( $response['event']['id'] ) ){
  //失敗時の処理
} else {
  //成功時の処理
}

尚、レスポンスデータに含まれるタイムスタンプはミリ秒で返ってきます。2
そのままでは日付表示が出来ないので、秒に変換する必要があります。

$timestamp = $response['event']['created_timestamp'];
echo date('Y-m-d H:i:s', ( $timestamp / 1000 )); //1000で割って秒にする

結果
2019-06-24 06:42:31

#最後に
Qiitaに登録して初めて書く記事となります。コードや文章に稚拙な部分があるかもしれませんが、ご容赦ください。可読性を優先してわざと定数化していない箇所はあります。

誤りのご指摘やご意見などがありましたら、是非お願いいたします。

####注釈(参考サイト)

  1. Twitter API Reference [direct_messages/events/new]

  2. LINEのMessaging APIで送られてくるタイムスタンプの変換にはまった

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?