mixiアプリ » mixiアプリ for PC » mixiアプリを作ってみよう » ライフサイクルイベントについて
ライフサイクルイベントについて
ライフサイクルイベントは、OpenSocial 0.8.1 にて規定されている「コンテナ上で起こったアプリケーションに関する事象を、アプリケーションプロバイダに送信するための仕様」です。mixi ではライフサイクルイベントのうち、現在
- event.addapp
- event.removeapp
の2つをご提供しています。アプリケーションプロバイダはGadget XML内にライフサイクルイベントを受け取るための記述を行うことで、そのmixiアプリに関して、
- どのユーザが使用を開始したのか
- どのユーザが使用を終了したのか
といった情報を外部サーバにて受けとることが可能になります。開発、公開したmixiアプリの利用状況の把握や、使用を終了したユーザに関する情報の削除処理などを行うためのきっかけとして、ライフサイクルイベントを利用すると良いでしょう。
ライフサイクルイベントの使用宣言
開発したmixiアプリに関するライフサイクルイベントを利用するためには、Gadget XMLファイルに以下のように記述を行います。
<Module>
<ModulePrefs ...>
<Link rel="event.addapp" href="http://example.com/add" method="GET" />
<Link rel="event.removeapp" href="http://example.com/remove" method="POST" />
</ModulePrefs>
</Module>
以下の属性を持つLink要素をModulePrefsの子要素として記述します。
| 属性名 | 説明 |
|---|---|
| rel | 受け取るイベントの種類 (event.addappもしくはevent.removeapp) |
| href | 通知を受け取るエンドポイントのURL |
| method | HTTPリクエストの種類 (GETまたはPOST) |
上記のコード例では、以下のような定義となります。
- ユーザがこのmixiアプリの使用を開始したことを、http://example.com/add にGETでリクエストを送信する
- ユーザがこのmixiアプリの使用を終了したことを、http://example.com/remove にPOSTでリクエストを送信する
Gadget XMLファイルにLink要素を追加・修正あるいは削除した後、対象のmixiアプリのedit_appli.plにて「設定を変更する」ボタンを押下します。これによりGadget XMLの読み込みが行われ、Link要素の解釈とライフサイクルイベントの登録・解除が行われます。
※ rel属性値として”event”のみの記述はサポート外となります。
送信されるパラメータ
実際にライフサイクルイベントに関する通知が行われる際には、関係する情報がパラメータ値として同時に送信されます。以下に送信されるパラメータをイベントごとに示します。
event.addapp
rel属性にevent.addappを指定した場合、以下のパラメータが渡されます。
- eventtype – “event.addapp”
- opensocial_app_id – mixiアプリのID
- id – mixiアプリの使用を開始したユーザのID
- mixi_invite_from – 招待を受けてmixiアプリの使用を開始した場合の、招待したユーザのID
※ 開発中アプリの場合、mixi_invite_fromパラメータは送信されません。
event.removeapp
rel属性にevent.removeappを指定した場合、以下のパラメータが渡されます。
- eventtype – “event.removeapp”
- opensocial_app_id – mixiアプリのID
- id – mixiアプリの使用を終了したユーザのID
ライフサイクルイベントの通知頻度
エンドポイントへのライフサイクルイベントの通知は、これにかかる負荷などのコストを考慮し、ユーザのアクションに対してリアルタイムに行われるのではなく、定期的に通知が行われます。そのため、ユーザのアクションと実際の通知に関して、遅延が発生いたしますので、それを前提とした設計を行ってください。
また、エンドポイントへの各通知に関して、エンドポイントから結果としてHTTPステータスコード200以外の値が返却された場合は、次の通知タイミングにて再送されます。準備するエンドポイントに関しては、必ずリクエストの受信成功とステータスコードとして200を返却するようにしてください。
各イベントのマージ
ライフサイクルイベントの通知は定期的に行われます。その際に、一定期間内で発生した各イベントごとにリクエストが行われるのではなく、同一イベントであれば一つのリクエストにまとめられます。具体的には、同じイベント種別であり、ユーザのIDのみが異なる複数のイベントについて、リクエストがマージされます。
例えば、mixiアプリXについて、ユーザID=A,B,Cそれぞれのユーザーがそのアプリの使用を開始したことを”http://example.com/add”にGETで送信する場合、
- GET /add?opensocial_app_id=X&id=A
- GET /add?opensocial_app_id=X&id=B
- GET /add?opensocial_app_id=X&id=C
というリクエストが個別に送信されるのではなく、
- GET /add?opensocial_app_id=X&id=A&id=B&id=C
といったようにリクエストが一つにまとめられます。エンドポイント側で、複数のidパラメータが指定されている場合についても、正しく受け取れるように処理を行うようにしてください。
また、あるユーザに招待されたことを受けてアプリの利用を開始したユーザに関するリクエストの場合、mixi_invite_fromパラメータは各リクエストで0個もしくは1個となります。例えば、
- ユーザAの招待を受けて、ユーザBとユーザCが利用開始した。
- ユーザBの招待を受けて、ユーザDが利用開始した。
- 招待に関係なく、ユーザAが利用開始した。
という場合は、
- id=B&id=C&mixi_invite_from=A
- id=D&mixi_invite_from=B
- id=A
という3つのリクエストが送信されます。
署名の検証
ライフサイクルイベントによって送信されるリクエストには、Authorizationリクエストヘッダに署名が付与されています。これを検証することによって、妥当なリクエストかどうかをエンドポイント側で判断することが可能です。
署名の方式は、gadgets.io.makeRequest()関数での署名付きリクエストと同じとなります。具体的な検証方法は、以下のドキュメントをご参照ください。
[署名付きリクエストの検証]
http://developer.mixi.co.jp/appli/pc/lets_enjoy_making_mixiapp/require_servers#toc-4
ライフサイクルイベントでのリクエストでは、opensocial_owner_idパラメータおよびopensocial_viewer_idパラメータが送信されることはありません。上記の署名検証に加えて、これらのパラメータがリクエストに含まれないことも同時に確認を行うようにしてください。
公開鍵
-----BEGIN CERTIFICATE----- MIICdzCCAeCgAwIBAgIJAKGOeYQLKTWjMA0GCSqGSIb3DQEBBQUAMDIxCzAJBgNV BAYTAkpQMREwDwYDVQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcDAeFw0x MDAzMjMwODUyMTBaFw0xMjAzMjIwODUyMTBaMDIxCzAJBgNVBAYTAkpQMREwDwYD VQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcDCBnzANBgkqhkiG9w0BAQEF AAOBjQAwgYkCgYEAuJFpLk23q/cXdCFpPxRxqrOmwGfd4HSsj1J5QlO3fG7v+a8b c/6Xl+/moDg0IxC0pzRJRrlgOM//832lMS0NvR/jnD8BGpL7YZ7m2DBZC+UY+G/5 Qyi6FU3nalX3zLFQMh2loI5ZrjwFLTtQMZ0H2VjurRMrRH7Cxhdz60ZVUysCAwEA AaOBlDCBkTAdBgNVHQ4EFgQUgNw38uBob76/jfcczwpc04wYWEowYgYDVR0jBFsw WYAUgNw38uBob76/jfcczwpc04wYWEqhNqQ0MDIxCzAJBgNVBAYTAkpQMREwDwYD VQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcIIJAKGOeYQLKTWjMAwGA1Ud EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAGI/mGjoefXBZtyoNc4cS781Nbk04 VAdricgfJzbgl8fO6ArF7XHLjeU5gAEp0OVstRSS6eE5ZPssBKNtZHiWV1+nAmTl gSL+ifnq12AVVldlRfANo2sR12fMapoiKelnLSE3YJ0QHGXWlE8luEUHQ2LrhpXs y1qxpzbKX056zco= -----END CERTIFICATE-----
サンプルコード
ライフサイクルイベントに付加されている署名を検証するためのサンプルコード(PHP)を以下に掲載します。
<?php
require_once("OAuth.php");
class MixiSignatureMethod extends OAuthSignatureMethod_RSA_SHA1 {
protected function fetch_public_cert(&$request) {
return <<< EOD
-----BEGIN CERTIFICATE-----
MIICdzCCAeCgAwIBAgIJAKGOeYQLKTWjMA0GCSqGSIb3DQEBBQUAMDIxCzAJBgNV
BAYTAkpQMREwDwYDVQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcDAeFw0x
MDAzMjMwODUyMTBaFw0xMjAzMjIwODUyMTBaMDIxCzAJBgNVBAYTAkpQMREwDwYD
VQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcDCBnzANBgkqhkiG9w0BAQEF
AAOBjQAwgYkCgYEAuJFpLk23q/cXdCFpPxRxqrOmwGfd4HSsj1J5QlO3fG7v+a8b
c/6Xl+/moDg0IxC0pzRJRrlgOM//832lMS0NvR/jnD8BGpL7YZ7m2DBZC+UY+G/5
Qyi6FU3nalX3zLFQMh2loI5ZrjwFLTtQMZ0H2VjurRMrRH7Cxhdz60ZVUysCAwEA
AaOBlDCBkTAdBgNVHQ4EFgQUgNw38uBob76/jfcczwpc04wYWEowYgYDVR0jBFsw
WYAUgNw38uBob76/jfcczwpc04wYWEqhNqQ0MDIxCzAJBgNVBAYTAkpQMREwDwYD
VQQKEwhtaXhpIEluYzEQMA4GA1UEAxMHbWl4aS5qcIIJAKGOeYQLKTWjMAwGA1Ud
EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAGI/mGjoefXBZtyoNc4cS781Nbk04
VAdricgfJzbgl8fO6ArF7XHLjeU5gAEp0OVstRSS6eE5ZPssBKNtZHiWV1+nAmTl
gSL+ifnq12AVVldlRfANo2sR12fMapoiKelnLSE3YJ0QHGXWlE8luEUHQ2LrhpXs
y1qxpzbKX056zco=
-----END CERTIFICATE-----
EOD;
}
protected function fetch_private_cert(&$request) {
return;
}
}
//Build a request object from the current request
$request = OAuthRequest::from_request();
$signature = $request->get_parameter('oauth_signature');
//Initialize the new signature method
$signature_method = new MixiSignatureMethod();
//Check the request signature
@$signature_valid = $signature_method->check_signature($request, null, null, $signature);
if (!$signature_valid) {
header('HTTP/1.0 400 Bad Request');
echo "This request was spoofed";
} else {
echo "Success! The data was validated";
}
上記プログラムの動作には、OAuth.php が必要です。
2010年5月18日時点の最新バージョンである r1171 では署名の生成方法に問題がありますので、以下のように修正してご利用ください。
--- OAuth.php.org 2010-05-17 17:25:38.000000000 +0900
+++ OAuth.php 2010-05-17 17:29:12.000000000 +0900
@@ -276,7 +276,7 @@
// and add those overriding any duplicates from GET or POST
if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") {
$header_parameters = OAuthUtil::split_header(
- $request_headers['Authorization']
+ $request_headers['Authorization'], false
);
$parameters = array_merge($parameters, $header_parameters);
}
@@ -857,7 +857,7 @@
if (is_array($value)) {
// If two or more parameters share the same name, they are sorted by their value
// Ref: Spec: 9.1.1 (1)
- natsort($value);
+ sort($value, SORT_STRING);
foreach ($value as $duplicate_value) {
$pairs[] = $parameter . '=' . $duplicate_value;
}