Twitter APIへcURLを使ってPHPで利用する方法〜update編〜

2019年12月5日システムAPI,PHP,php-fpm,Twitter

どうも、UT(@ut_1029)です。Webサービスを運営するとTwitterなどのSNS連携することってよくありますよね?今回はPHPcURLを使ってTwitter APIを利用した時のプログラムを紹介します。

Twitter APIへcURLを使ってPHPで利用する方法〜update編〜
Twitter APIへcURLを使ってPHPで利用する方法〜update編〜

Twitter APIについて

Webサイトやアプリから、Twitterの情報にアクセスして取得したり、Twitterへツイートを行ったりすることができるTwitterが提供してくれているシステムです。よくある例としては、Instagramに画像を投稿するとTwitterに自動でツイートする機能が、このTwitter APIを利用しているシステムになります。

TwitterのAPIについて

ウェブやモバイル端末からTwitterにアクセスできます。Twitterにある情報をできるだけ広く共有するために、API (アプリケーション・プログラミング・インタフェイス)を通してTwitterデータにプログラムレベルでアクセスし、企業、開発者、利用者に提供します。

Twitter APIのupdateを要求するサンプルコード

今回紹介するTwitter APIupdateを行う前段にrequest_tokenを行い、access_tokenを行う必要があります。Twitter APIrequest_tokenを利用するサンプルコードは、前回に紹介したので、そちらをご覧ください。
Twitter APIへcURLを使ってPHPで利用する方法〜request_token編〜
Twitter APIへcURLを使ってPHPで利用する方法〜access_token編〜

<?php
	/**
	 * update
	 */
	// Twitter Developer登録でアプリ登録した時の値
	$consumer_key     = '';
	$consumer_secret  = '';
	$token            = '';
	$secret           = '';

	$request_method = 'POST';
	$request_url    = 'https://api.twitter.com/1.1/statuses/update.json';
	$boundary       = 's-a-m-p-l-e-------------' . md5(uniqid(rand(), true));

	// Twitter APIのaccess_tokenのレスポンス値
	$oauth_access_secret = '';

	// リクエストパラメータ配列
	$request_params = [
		'status'    => 'ハロー', // 内容
// 画像付き投稿する場合
//		'media_ids' => '', // メディアID(複数の場合はカンマ(,)区切りで指定)
	];

	$authorizations = [
		'oauth_nonce'            => md5(uniqid(rand(), true)),
		'oauth_signature_method' => 'HMAC-SHA1',
		'oauth_timestamp'        => time(),
		'oauth_consumer_key'     => $consumer_key,
		'oauth_version'          => '1.0',
//		'oauth_callback'         => '',
		'oauth_callback'         => 'oob',
		// Twitter APIのaccess_tokenのレスポンス値
		'oauth_token'            => '',
		'status'                 => $request_params['status'],
// 画像付き投稿する場合
//		'media_ids'              => $request_params['media_ids'],
	];

	// 署名(signature)作成では、アルファベット順にソートする決まり
	ksort($authorizations);

	/*
	 * Signature_base_stringを作成
	 * ・oauth_signatureを作る時のメッセージ部分
	 */
	$signature_base_string = http_build_query($authorizations, '', '&');
	// HTTPメソッドとリクエストトークンURLをURLエンコードして&で繋ぐ
	$signature_base_string = _rawurlencode($request_method)
								. '&'
								. _rawurlencode($request_url)
								. '&'
								. _rawurlencode($signature_base_string);

	/*
	 * Signature_keyの作成
	 * oauth_signatureを作る時のキー部分
	 * oauth_access_secretがあれば"&"の後ろにつける
	 */
	$signing_key = _rawurlencode($consumer_secret) . '&';
	if (isset($oauth_access_secret) && $oauth_access_secret) {
		$signing_key .= _rawurlencode($oauth_access_secret);
	}

	/*
	 * oauth_signatureの作成
	 */
	$oauth_signature = base64_encode(
		hash_hmac('sha1', $signature_base_string, $signing_key, true)
	);
	$authorizations['oauth_signature'] = $oauth_signature;

	/*
	 * リクエスト準備
	 */
	// リクエスト用コンテキスト作成
	$request_context = [
		'http' => [
			'method' => $request_method,
			'header' => [
				'Authorization: OAuth ' . http_build_query($authorizations, '', ',')
			]
		]
	];

	// リクエストクエリー
	if (isset($request_params) && $request_params && count($request_params) > 0) {
		$request_params = http_build_query($request_params, '', '&');
		if ($request_method == 'GET') {
			$request_url .= '?' . $request_params;
		}
		else {
			$request_context['http']['content'] = $request_params;
		}
	}
	elseif (isset($request_body) && $request_body) {
		// 画像リクエストの時
		$request_context['http']['header'][] = 'Content-Type: multipart/form-data; boundary= ' . $boundary;
		$request_context['http']['content'] = $request_body;
	}

	/*
	 * cURL設定
	 */
	$curl = curl_init();
	curl_setopt($curl, CURLOPT_URL, $request_url);
	curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $request_context['http']['method']);
	curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
	curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
	curl_setopt($curl, CURLOPT_TIMEOUT, 30);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
	// SSL
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
	// レスポンスヘッダの出力
	curl_setopt($curl, CURLOPT_HEADER, false);
	curl_setopt($curl, CURLINFO_HEADER_OUT, true);
	// Locationヘッダを追跡
	curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
	// HTTPヘッダ
	curl_setopt($curl, CURLOPT_HTTPHEADER , $request_context['http']['header']);
	if (isset($request_context['http']['content']) && $request_context['http']['content']) {
		curl_setopt($curl, CURLOPT_POSTFIELDS , $request_context['http']['content']);
	}

	// 結果達
	$response = curl_exec($curl);
	$code     = curl_getinfo($curl, CURLINFO_HTTP_CODE);
	$info     = curl_getinfo($curl);
	$error    = curl_error($curl);
	$errno    = curl_errno($curl);

	// 終了
	curl_close($curl);

	/*
	 * cURLの結果
	 */
	$result = [
		'response' => $response,
		// cURLでリクエストした結果達
		'code'     => $code,
		'info'     => $info,
		'error'    => $error,
		'errno'    => $errno,
	];

	echo "<pre>";
	print_r($result['response']);
// cURLリクエストで失敗した時とかは、$resultをprint_rすると原因が分かるかも....
//	print_r($result);
	echo "</pre>";

	if (!$response || $error || $errno || $code != 200) {
		echo "<span>";
		echo 'Twitter APIのリクエストに失敗';
		echo "</span>";
	}

	exit;

	/**
	 * URLエンコード RFC2986版
	 */
	function _rawurlencode($str='') {
		if (!$str) {
			return $str;
		}
		$result = str_replace(['+', '%7E'], ['%20', '"'], $str);
		$result = rawurlencode($result);
		return $result;
	}

サンプルコードの解説

	// Twitter Developer登録でアプリ登録した時の値
	$consumer_key     = '';
	$consumer_secret  = '';
	$token            = '';
	$secret           = '';

この部分ですが、前回の記事Twitter APIを利用する方法〜Developer登録〜でやったTwitterDeveloper登録を行い、アプリ登録を行った時に発行される情報であるアプリの情報をセットします。

boundary

	$request_method = 'POST';
	$request_url    = 'https://api.twitter.com/1.1/statuses/update.json';
	$boundary       = 's-a-m-p-l-e-------------' . md5(uniqid(rand(), true));

boundaryは、

oauth_access_secret

	// Twitter APIのaccess_tokenのレスポンス値
	$oauth_access_secret = '';

oauth_access_secretは、

statusとmedia_ids

	// リクエストパラメータ配列
	$request_params = [
		'status'    => 'ハロー', // 内容
// 画像付き投稿する場合
//		'media_ids' => '', // メディアID(複数の場合はカンマ(,)区切りで指定)
	];

statusは、

media_idsは、

	$authorizations = [
		'oauth_nonce'            => md5(uniqid(rand(), true)),
		'oauth_signature_method' => 'HMAC-SHA1',
		'oauth_timestamp'        => time(),
		'oauth_consumer_key'     => $consumer_key,
		'oauth_version'          => '1.0',
//		'oauth_callback'         => '',
		'oauth_callback'         => 'oob',
		// Twitter APIのaccess_tokenのレスポンス値
		'oauth_token'            => '',
		'status'                 => $request_params['status'],
// 画像付き投稿する場合
//		'media_ids'              => $request_params['media_ids'],
	];

oauth_token

oauth_tokenは、前回の記事Twitter APIへcURLを使ってPHPで利用する方法〜access_token編〜で行ったTwitter APIrequest_tokenで取得した以下のようなレスポンス値(oauth_token=****)をセットします。

署名を作成

	// 署名(signature)作成では、アルファベット順にソートする決まり
	ksort($authorizations);

	/*
	 * Signature_base_stringを作成
	 * ・oauth_signatureを作る時のメッセージ部分
	 */
	$signature_base_string = http_build_query($authorizations, '', '&');
	// HTTPメソッドとリクエストトークンURLをURLエンコードして&で繋ぐ
	$signature_base_string = _rawurlencode($request_method)
								. '&'
								. _rawurlencode($request_url)
								. '&'
								. _rawurlencode($signature_base_string);

	/*
	 * Signature_keyの作成
	 * oauth_signatureを作る時のキー部分
	 * oauth_access_secretがあれば"&"の後ろにつける
	 */
	$signing_key = _rawurlencode($consumer_secret) . '&';
	if (isset($oauth_access_secret) && $oauth_access_secret) {
		$signing_key .= _rawurlencode($oauth_access_secret);
	}

この配列情報は、署名を作成するための情報になります。

	$oauth_signature = base64_encode(
		hash_hmac('sha1', $signature_base_string, $signing_key, true)
	);
	$authorizations['oauth_signature'] = $oauth_signature;

そして上記のように署名を作成します。

	// リクエスト用コンテキスト作成
	$request_context = [
		'http' => [
			'method' => $request_method,
			'header' => [
				'Authorization: OAuth ' . http_build_query($authorizations, '', ',')
			]
		]
	];

署名が作成できたので、次にTwitter APIcURLでリクエストする準備を行います。HTTPリクエストのヘッダをカスタマイズします。
「Authorization: OAuth パラメータ名=値,パラメータ名=値,パラメータ名=値,…」

	// リクエストクエリー
	if (isset($request_params) && $request_params && count($request_params) > 0) {
		$request_params = http_build_query($request_params, '', '&');
		if ($request_method == 'GET') {
			$request_url .= '?' . $request_params;
		}
		else {
			$request_context['http']['content'] = $request_params;
		}
	}
	elseif (isset($request_body) && $request_body) {
		// 画像リクエストの時
		$request_context['http']['header'][] = 'Content-Type: multipart/form-data; boundary= ' . $boundary;
		$request_context['http']['content'] = $request_body;
	}

リクエストクエリを作成します。

	$curl = curl_init();
	curl_setopt($curl, CURLOPT_URL, $request_url);
	curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $request_context['http']['method']);
	curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
	curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
	curl_setopt($curl, CURLOPT_TIMEOUT, 30);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
	// SSL
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
	// レスポンスヘッダの出力
	curl_setopt($curl, CURLOPT_HEADER, false);
	curl_setopt($curl, CURLINFO_HEADER_OUT, true);
	// Locationヘッダを追跡
	curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
	// HTTPヘッダ
	curl_setopt($curl, CURLOPT_HTTPHEADER , $request_context['http']['header']);
	if (isset($request_context['http']['content']) && $request_context['http']['content']) {
		curl_setopt($curl, CURLOPT_POSTFIELDS , $request_context['http']['content']);
	}

	// 結果達
	$response = curl_exec($curl);
	$code     = curl_getinfo($curl, CURLINFO_HTTP_CODE);
	$info     = curl_getinfo($curl);
	$error    = curl_error($curl);
	$errno    = curl_errno($curl);

	// 終了
	curl_close($curl);

そしてcURLで実行を行います。

UT
UTの日常

当ブログ(UTの日常)を運営しているUTは「プログラミング関係の仕事をしている30代1児の父親」です。詳しくは「UTのプロフィール」をご覧ください。

UTの日常では、システム開発における LinuxPHPJavaScriptJQueryMySQLなどの知識やプログラミング技術、サーバ構築や運用などAWSをメインに知識を紹介しています。

内容としては、Webシステムの開発中や運用中に発生したトラブルやエラーの対応や解決方法をまとめた備忘録やWebシステム開発の方法を未経験者の人を対象に説明したプログラム教科書を記事にしています。
Webシステム開発の知識やプログラム技術の備忘録

2019年12月5日システムAPI,PHP,php-fpm,Twitter

Posted by UT