TwitterOAuthで認証キャンセル時のエラー解決法

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 2,691

Yknd

score 22

前提・実現したいこと

TwitterApiを使ったphpでの簡易ツイッター投稿フォームを作成しています。
ユーザーに既定のツイートをしてもらうキャンペーンでの利用を想定しています。

サイト閲覧者が投稿ボタンを押す
→OAuthでアプリ認証
→閲覧者のアカウントから既定のメッセージをツイート

という流れになります。

実装に当たっては、TwitterOAuth(Abraham)というライブラリを使っています。
https://github.com/abraham/twitteroauth

投稿自体は問題なく行えるのですが、2点ほどエラーが発生しており困っています。。
今回TwitterApiの利用がはじめてで知見に乏しく、お力添え頂けないでしょうか?

以下に該当のソースファイルも記載しておりますので、
長文となりますが、改善点などコメント頂けますと幸いです。

実装環境

  • php5.4
  • OpenSSL support
  • TwitterOAuth ver.0.7.0

Twitterアプリケーション設定

  • Access: Read and Write
  • Callback URL: http://***.com/test/twitter/src/callback.php 
  • Callback URL Locked: No 

発生している問題・エラーメッセージ

1点目のエラーは以下の内容です。

投稿ボタンを押してOAuth認証ページ
(https://api.twitter.com/oauth/authorize?oauth_token=***)
にリダイレクトさせる時点で発生します。

Fatal error: Can't use function return value in write context in /home/sites/heteml/users/***/test/twitter/src/TwitterOAuth.php on line 366


上記のエラーは以下該当箇所のコード削除で消えましたが、
根本的な解決にはならないため、修正したいと考えています。

//↓TwitterOAuth.phpエラー該当箇所
/* Remove CACert file when in a PHAR file. */
if (!empty(\Phar::running(false))) {
  unset($options[CURLOPT_CAINFO]);
}


2点目のエラーは以下の内容です。

投稿ボタンを押してOAuth認証ページ
(https://api.twitter.com/oauth/authorize?oauth_token=***)
にリダイレクト後、「連携アプリを認証」ではなく「キャンセル」し、
「(アプリ名)に戻る」ボタンをクリックすると発生します。

Notice: Undefined index: oauth_verifier in /home/sites/heteml/users/***/test/twitter/src/callback.php on line 24

Fatal error: Uncaught exception 'Abraham\TwitterOAuth\TwitterOAuthException' with message 'Error processing your OAuth request: Invalid oauth_verifier parameter' in /home/sites/heteml/users/***/test/twitter/src/TwitterOAuth.php:138 Stack trace: #0
/home/sites/heteml/users/***/test/twitter/src/callback.php(24): Abraham\TwitterOAuth\TwitterOAuth->oauth('oauth/access_to...', Array) #1 {main} thrown in /home/sites/heteml/users/***/test/twitter/src/TwitterOAuth.php on line 138


こちらはエラー解消の目処が立っていません。

今回のプログラムのソースコード

※twitterディレクトリは、TwitterOAuthの「twitteroauth-master」からリネームしたものです。

post.php

投稿ボタンの設置ページ。redirect.phpに飛ばす。

<a href="twitter/src/redirect.php"><img src="img/tweet/post_btn.png" alt="投稿"></a>


twitter/src/redirect.php

Request Token、Request Secretを生成。Twitter認証ページのURLを作成し、リダイレクトする。

<?php
session_start();

require '../autoload.php';
require 'env.php';
use Abraham\TwitterOAuth\TwitterOAuth;

/* TwitterOAuthを生成 */
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);

/* Request Token、Request Secretを生成 */
$request_token = $connection->oauth('oauth/request_token', array('oauth_callback' => OAUTH_CALLBACK));

/* Request Token、Request Secretをsessionに保存 */
$_SESSION['oauth_token'] = $request_token['oauth_token'];
$_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret'];

/* Twitterと連携を行うURLを生成 */
$url = $connection->url('oauth/authorize', array('oauth_token' => $request_token['oauth_token']));

/* Twitterと連携を行うURLにリダイレクト */
header('Location: ' . $url);


twitter/src/callback.php

Twitter認証画面から戻って来た時にアクセスする。oauth_verifierからRequest Token、Request Secretの照合を行い、ユーザーの確認を行う。その後Access Token、Access Secretを生成。thanks.phpへリダイレクト。

<?php
session_start();

require '../autoload.php';
require 'env.php';
use Abraham\TwitterOAuth\TwitterOAuth;

/* Request Token、Request Secretをsessionから取得 */
$request_token = array();
$request_token['oauth_token'] = $_SESSION['oauth_token'];
$request_token['oauth_token_secret'] = $_SESSION['oauth_token_secret'];

/* Request Tokenが間違っている場合はclearsessions.phpへリダイレクト */
if (isset($_REQUEST['oauth_token']) && $request_token['oauth_token'] !== $_REQUEST['oauth_token']) {
    // 中断する。何かが違っている。
    $_SESSION['oauth_status'] = 'oldtoken';
    header('Location: ./clearsessions.php');
}

/* TwitterOAuthを生成 */
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $request_token['oauth_token'], $request_token['oauth_token_secret']);

/* Access Token、Access Secretを生成 */
$access_token = $connection->oauth("oauth/access_token", array("oauth_verifier" => $_REQUEST['oauth_verifier']));

/* Access Token、Access Secretをsessionに保存 */
$_SESSION['access_token'] = $access_token;

/* 以降ではRequest Token、Request Secretは使用しないのでsessionから削除 */
unset($_SESSION['oauth_token']);
unset($_SESSION['oauth_token_secret']);

/* thanks.phpへリダイレクト */
header('Location: ../../thanks.php');


thanks.php

Twitter認証が完了した後にstatuses/updateでツイート投稿する。連携の前にアクセスされた場合はclearsessions.phpへリダイレクト。

<?php
session_start();

require 'twitter/autoload.php';
require 'twitter/src/env.php';
use Abraham\TwitterOAuth\TwitterOAuth;

/* Access Token、Access Secretがsessionにない場合はclearsessions,phpへリダイレクト */
if (empty($_SESSION['access_token']) || empty($_SESSION['access_token']['oauth_token']) || empty($_SESSION['access_token']['oauth_token_secret'])) {
    header('Location: ./twitter/src/clearsessions.php');
}

/* Access Token、Access Secretを取得 */
$access_token = $_SESSION['access_token'];

/* TwitterOAuthを生成(パラメータによって使用できる関数を制御) */
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $access_token['oauth_token'], $access_token['oauth_token_secret']);

/* 認証済みアカウントから投稿 */
$status = $connection->post('statuses/update', ['status' => '投稿内容 投稿日: ' . date( 'Y/m/d H:i' ) . ' http://*****.com/test/']);
?>

///
///
<p>投稿が完了しました。ご応募ありがとうございます。</p>


twitter/src/clearsessions.php

セッションをクリアする処理。ログアウトや、エラーの時に使用。その後post.phpへリダイレクトする。

<?php

/* sessionsをクリア */
session_start();
session_destroy();

/* post.phpへリダイレクト */
header('Location: ../../post.php');


twitter/src/env.php

Consumer KeyとConsumer Secret、Twitter公式サイトからのリダイレクト先であるcallback.phpのURLを定義。

<?php

define('CONSUMER_KEY', '---');
define('CONSUMER_SECRET', '---');
define('OAUTH_CALLBACK', 'http://*****.com/test/twitter/src/callback.php');

補足

同一ユーザーによる再投稿も想定していますが、
TwitterApiの仕様で同一ユーザーからの同一文言のツイートができないため、
statusにタイムスタンプを入れて対応しています。

少し不格好なツイートになるため他の回避策があればいいのですが・・

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

+1

自己解決しましたので、後学のために修正点を記載します。

1点目のエラー
PHPバージョンに起因したエラーでした。
現行のTwitterOAuthのgitソースはPHP5.5以上を想定しているため、
0.7.0→0.6.0にバージョンダウンすることで解決しました。

2点目のエラー
こちらは自作のcallback.phpのバグでした。

if (isset($_REQUEST['oauth_token']) && $request_token['oauth_token'] !== $_REQUEST['oauth_token']) {
↓
if (!isset($_REQUEST['oauth_token']) || (isset($_REQUEST['oauth_token']) && $request_token['oauth_token'] !== $_REQUEST['oauth_token'])) {


リクエストトークンが取得できていなくても中断されず、
TwitterOAuthを生成してしまっていました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる