前回はAWSコンソールからPush Notificationしましたが、API経由じゃないと何の旨味もないので、Apexを使ってPush Notificationしてみます。
SNS REST API リファレンス→http://docs.aws.amazon.com/sns/latest/api/Welcome.html
以下サンプル
public with sharing class SNSCommon {
/**
* AccessKey
*/
public String AWSAccessKeyId = 'Input Your Access Key Id';
/**
* SecretKey
*/
public String AWSSecretKeyId = 'Input Your Access Key Secret';
//Publishする(us-east region)
public String publish(String message) {
Map<String, String> params = new Map<String, String>{
'Action' => 'Publish',
'AWSAccessKeyId' => this.AWSAccessKeyId,
'SignatureMethod' => 'HmacSHA256',
'SignatureVersion' => '2',
'Message' => message,
// 'TargetArn' => 'Input Your Target Arn',
'TopicArn' => 'Input Your Topic Arn',
'Timestamp' => DateTime.now().format('YYYY-MM-dd') + 'T' +
DateTime.now().format('HH:mm:ssZ')
};
params.put('Signature', this.createSignature('POST', 'sns.us-east-1.amazonaws.com', '/', params));
HttpRequest req = new HttpRequest();
req.setEndpoint('https://sns.us-east-1.amazonaws.com');
req.setMethod('POST');
req.setBody(Utility.getSortedParam(params));
Http http = new Http();
HTTPResponse res = http.send(req);
return res.getBody();
}
//signature生成
private String createSignature(
String method,
String hostname,
String resource,
Map<String, String> params
) {
String signature =
method + Constants.LF +
hostname + Constants.LF +
resource + Constants.LF +
Utility.getSortedParam(params);
System.debug(signature);
return String.valueOf(EncodingUtil.base64Encode(
Crypto.generateMac(
'hmacSHA256',
Blob.valueOf(signature),
Blob.valueOf(this.AWSSecretKeyId)
)
));
}
}
public without sharing class Utility {
//セットをソートしてリストにする
public static List<String> getSortedList(Set<String> keys) {
List<String> sortedList = new List<String>();
sortedList.addAll(keys);
sortedList.sort();
return sortedList;
}
/**
* key=value&...でつないだ文字列を返却
* @param mapParam 対象文字列=>文字列マップ
* @return key=value&...でつないだ文字列
*/
public static String getSortedParam(Map<String,String> mapParam){
if (mapParam == null || mapParam.keySet().isEmpty()) {
return '';
}
String param = '';
List<String> sortedKey = getSortedList(mapParam.keySet());
for(String key: sortedKey){
param += percentEncodeRfc3986(key) + '=' + percentEncodeRfc3986(mapParam.get(key)) + '&';
}
return param.substring(0,param.length() - 1);
}
//Rfc3986に則ったURLエンコード
public static String percentEncodeRfc3986(String s) {
return EncodingUtil.urlEncode(s, 'UTF-8')
.replace('+', '%20')
.replace('*', '%2A')
.replace('%7E', '~');
}
}
signature versionは2を使ってます。
http://docs.aws.amazon.com/general/latest/gr/signature-version-2.html
実装方法はサンプル通りで
[URL Method] + \n
[Http Header Host Name] + \n
[Resource] + \n
[キー値でソートしたURLパラメータ]
の文字列をhamc-sha1かhmac-sha256でAWS Secret Key使ってハッシュ化してbase64エンコードするだけ。
[キー値でソートしたURLパラメータ]の部分は普通のURLエンコードではなくて、RFC 3986 という規格に則ってエンコードする必要があります。
参考URL:http://docs.aws.amazon.com/AWSECommerceService/latest/DG/AuthJavaSampleSig2.html