この記事は、 Salesforce の Apex から Twitter Developer Platform 上に作成した Twitter Developer App を介して自身の Twitter アカウントにツイートを投稿する方法を紹介します。
Twitter Developer Platform とは
Twitter Developer Platform に登録(審査あり)すると、自身の Twitter アカウントに紐づく Twitter Developer App を作成できるようになります。App を作成すると様々な API にアクセスできるので、BOT を作成したり、マーケティングツールなどと連携しツイートやエンゲージメントの分析、投稿やキュレーションが可能になります。
Twitter Developer API のプラン
Twitter Developer の API には、Standard/Premium/Enterprise などの API が存在し、それぞれ目的やできる事、
お値段が異なります。今回は、ツイートを投稿したいだけなので無料の Standard APIs を使わせて頂きます。
認証
Standard APIs を利用するには、 HTTP リクエストの Authorization ヘッダーに OAuth 1.0a HMAC-SHA1 signature を作成し設定してあげる必要があります。そのため、 Twitter Developer Platform で App を作成した際に UI 上から以下の情報を発行しておきます。
- OAuth Consumer Key
- OAuth Consumer Secret
- OAuth Token
- OAuth Token Secret
Apex での OAuth1.0a 認証
通常、Salesforce から Apex で外部サービスの API をコールする際には、指定ログイン情報による認証を行います。
しかし、現在の指定ログイン情報は OAuth1.0a での認証方式をサポートしていません。
そのため、今回は Twitter の公式ドキュメントに従って Apex で記述する事にしました。
public class TwitterUtil {
static final String ENCODING_SCHEME = 'UTF-8';
public static HttpRequest signRequest(HttpRequest req, String consumerKey, String consumerSecret, String oauthToken, String oauthTokenSecret) {
Boolean isMultipartPost = req.getMethod().toUpperCase() == 'POST' && req.getHeader('Content-Type').startsWith('multipart/form-data;');
// Collecting parameters
String nonce = String.valueOf(Crypto.getRandomLong());
String timestamp = String.valueOf(DateTime.now().getTime() / 1000);
Map<String,String> parameters = new Map<String,String>();
parameters.put('oauth_signature_method','HMAC-SHA1');
parameters.put('oauth_version','1.0');
parameters.put('oauth_consumer_key', consumerKey);
parameters.put('oauth_timestamp', timestamp);
parameters.put('oauth_nonce', nonce);
parameters.put('oauth_token', oauthToken);
if (!isMultipartPost) {
parameters.putAll(getParameterMap(req.getBody()));
parameters.putAll(getParameterMap(req.getEndpoint().substringAfter('?')));
}
// Creating the parameter string
List<String> keyValues = new List<String>();
for (String key : parameters.keySet()) {
keyValues.add(percentEncode(key) + '=' + percentEncode(parameters.get(key)));
}
keyValues.sort();
String parameterString = String.join(keyValues, '&');
// Creating the signature base string
String endpoint = req.getEndpoint();
String baseURL = endpoint.contains('?') ? endpoint.substringBefore('?') : endpoint;
String signatureBaseString = req.getMethod().toUpperCase()
+ '&' + percentEncode(baseURL)
+ '&' + percentEncode(parameterString);
// Getting a signing key
String signingKey = percentEncode(consumerSecret) + '&' + percentEncode(oauthTokenSecret);
// Calculating the OAuth signature
Blob sig = Crypto.generateMac('HmacSHA1', Blob.valueOf(signatureBaseString), Blob.valueOf(signingKey));
String oauthSignature = percentEncode(EncodingUtil.base64encode(sig));
// Building the header string
String header = 'OAuth' +
+ ' oauth_consumer_key="' + consumerKey + '"'
+ ', oauth_nonce="' + nonce + '"'
+ ', oauth_signature="' + oauthSignature + '"'
+ ', oauth_signature_method="HMAC-SHA1"'
+ ', oauth_timestamp="' + timestamp + '"'
+ ', oauth_token="' + oauthToken + '"'
+ ', oauth_version="1.0"';
req.setHeader('Authorization', header);
return req;
}
private static Map<String,String> getParameterMap(String parameterString) {
Map<String,String> parameters = new Map<String,String>();
if (String.isNotBlank(parameterString)) {
for (String pair : parameterString.split('&')) {
List<String> kv = pair.split('=');
if (kv.size() == 2) parameters.put(kv[0], EncodingUtil.urlDecode(kv[1], ENCODING_SCHEME));
}
}
return parameters;
}
private static String percentEncode(String s) {
return EncodingUtil.urlEncode(s, ENCODING_SCHEME)
.replace('+', '%20')
.replace('*', '%2A')
.replace('%7E', '~');
}
}
※ % エンコードは手抜きです。だれか正しく実装する方法を教えて下さい。
ツイートする
ツイートを投稿するには、 POST statuses/update の API を利用します。
一般に「ツイート」と呼ばれるものは、API 上では「status」と呼ばれるので注意が必要ですね。
リクエストが成功すると、自身の Twitter タイムラインにツイート本文が表示されます。
// ツイート本文
String tweetText = 'Hello Twitter!';
// Twitter Developer App で発行した情報
String clientKey = 'XXXXXXXX';
String clientSecret = 'XXXXXXXX';
String oauthToken = 'XXXXXXXX';
String oauthTokenSecret = 'XXXXXXXX';
// HTTP リクエストを作成
HttpRequest req = new HttpRequest();
req.setMethod('POST');
req.setEndpoint('https://api.twitter.com/1.1/statuses/update.json');
req.setHeader('Content-Type','application/x-www-form-urlencoded');
req.setBody('status='+ EncodingUtil.urlEncode(tweetText, 'UTF-8'));
// HTTP リクエストから Authorization ヘッダーを作成し設定する
req = TwitterUtil.signRequest(req, clientKey, clientSecret, oauthToken, oauthTokenSecret);
// リクエストを送信
Http http = new Http();
HttpResponse res = http.send(req);
// リクエストが成功したら結果をログに出力
if (res.getStatusCode() == 200) {
System.debug(res.getBody())
}