読者です 読者をやめる 読者になる 読者になる

PenguinがWorkWorkする blog

ネット上で気になることや、android等について書くブログ

Twitterのoauth認証 - request-token の取得 (QT)

Twitterのrequest_tokenがもらえないことに、三日間ずっと頭を悩ましてました。

書くのはめんどくさいので、QTにライブラリがあるかなと探して見た・・・、

が、ない・・・!

不幸だ・・・。


だがしかし!!!

なんとか書けてtokenをもらい一安心。
お陰でC++自体何書いていいかわからない状態から、普通に書けるようになりました・・・。
やったね!タエちゃん!!

まだゴールであるツイートまでたどり着いてないですけどね・・・。

ハマった点をいくつか書いておきます。

■QDateTime::currentMSecsSinceEpoch()の値がsecではない!
 currentMSecsSinceEpoch()は見ての通り1/msで出てくるので1/sで出しました。
 
関数の名前にミリって書いてあるのに気付かなかった・・・!
『あたしって、ほんとバカ・・・』

■signatureの生成
多分、初心者だったらみんな多く悩ましてたであろうsignatureの生成。
参考URL先に詳しいことは書いている。

例えば、Request Token は

"GET" で
"http://twitter.com/oauth/request_token" に
"oauth_consumer_key=CONSUMER_KEY&oauth_nonce=NONCE&oauth_signature_method=HMAC-SHA1&oauth_timestamp=TIME&oauth_version=1.0" を投げるので
こんな感じになります。

GET&http%3A%2F%2Ftwitter.com%2Foauth%2Frequest_token&oauth_consumer_key%3DCONSUMER_KEY%26oauth_nonce%3DNONCE%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3DTIME%26oauth_version%3D1.0
投げるパラメタの文字列と URL は、ちゃんとエスケープしてあげてくださいねw

暗号化する前にURLエンコードするのですが、
GETとURLとパラメータを全てURLエンコードしてしまい、一纏めのクエリ形式になっておかしな事になってました。


✕{GET&URL&パラメータ} ⇒ URLエンコード
◯[GET} & {URL ⇒ URLエンコード} & {パラメータ ⇒ URLエンコード}


GETは英字だけなのでエンコードしなくていいですが、URLとパラメータは分けてURLエンコードしましょう。

HMAC-SHA1で暗号化してBase64に変換してURLエンコードすれば、signatureの完成です。

QT限定ですが、クエリはQList\ > hoge を用意して、
QUrlQuery::setQueryItemsでまるごと渡せるみたいです。

最初はiteratorを使ってグルグル回して取り出していたけど、必要ないみたい。


ということで、今日は寝ますzzz

参考URL
Twitter API を OAuth で認証するスクリプトを 0 から書いてみた - trial and error


【request_token取得】

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    manager = new QNetworkAccessManager();
    tedTweet = this->ui->tedTweet;
    connect(ui->btnexit, SIGNAL(clicked()),this,SLOT(on_btnexit_clicked()));
    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(oauth_Reply(QNetworkReply*)));

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_btnTweet_clicked()
{
    QString consumer_key = "Consumer_keyをセット";
    QString consumer_secret = "Consumer_secretをセット";
    QString oauth_nonce = QString::number(qrand());
    QString oauth_signature_method = "HMAC-SHA1";
    QString oauth_timestamp = QString::number(QDateTime::currentMSecsSinceEpoch()/1000);

    QString oauth_vertion = "1.0";

    QString access_token = "";
    QString secret_token = "";

    QString Tweet = this->ui->tedTweet->toPlainText();

    QString const request_token_url = "https://api.twitter.com/oauth/request_token";
    QString const authorize_url     = "https://api.twitter.com/oauth/authorize";
    QString const access_token_url  = "https://api.twitter.com/oauth/access_token";


    QList<QPair<QString, QString> > Params;
    Params.append(qMakePair(QString("oauth_consumer_key"), consumer_key));
    Params.append(qMakePair(QString("oauth_nonce"), oauth_nonce));
    Params.append(qMakePair(QString("oauth_signature_method"), oauth_signature_method));
    Params.append(qMakePair(QString("oauth_timestamp"), oauth_timestamp));
    Params.append(qMakePair(QString("oauth_vertion"), oauth_vertion));

    QString key = consumer_secret +
            "&";

    QUrlQuery RequestQuery;
    RequestQuery.setQueryItems(Params);
    QString signature =  "GET&" +
            request_token_url.toUtf8().toPercentEncoding() +
            "&" +
            RequestQuery.toString().toUtf8().toPercentEncoding();

    // Signature作成

    QString oauth_signature = QMessageAuthenticationCode::hash (
                signature.toUtf8(),
                key.toUtf8(),
                QCryptographicHash::Sha1).toBase64().toPercentEncoding();

    Params.append(qMakePair(QString("oauth_signature"), oauth_signature));

    //URLとSignatureを追加したパラメータを再セット
    QUrl message(request_token_url);
    RequestQuery.setQueryItems(Params);
    message.setQuery(RequestQuery);
    QUrl url(message);
    QNetworkRequest request(url);
    manager->get(request);
}

void MainWindow::on_btnexit_clicked()
{
    QWidget::close();
}

void MainWindow::oauth_Reply(QNetworkReply* reply)
{
    QByteArray result = reply->readAll();
    tedTweet->setText(QString::fromUtf8(result));
}