mixiアプリのユーザーIDプラットフォーム共通化の移行方法
mixiが海外のSNSとプラットフォーム共通化をするらしく、その関係で、今まで数字のIDだったのが、文字列のIDに切り替わります。その関係で、mixiアプリ提供者は今月中(2011年10月)に新方式に移行が必要です。
http://developer.mixi.co.jp/news/news_apps/009668.html
なんか、あまり手法とかブログで見かけなかったので、やり方とか書いておきます。手抜きしたい方の参考にどうぞ。
まず、変わるのは、ID だけで、API は変わりません。今まで、ID を文字列で管理していた人は、データベースの ID さえ、差し替えてしまえば対応完了です。数値でやっていた人は、文字列にプログラムを書き換える必要があります。
一連の話、テストアプリで一通り練習してから、本番アプリで行ってくださいね。
ステップ1
http://developer.mixi.co.jp/appli/com/change/setting/trans_id/ にあるように、ID変換API の申請をします。アプリが稼働中の状態でやってしまっても、通常は大丈夫です。
ステップ2
まず、旧ID の一覧が必要です。in.csv は(1列のCSV、つまりカンマなし)で旧IDをずらずらと並べた形式にしました。
in.csv の作り方は、アプリ次第ですが、僕の場合は、PostgreSQL でこんな感じでした。
COPY (SELECT mixi_id FROM account_mixi) TO '/tmp/in.csv' CSV;
ステップ3
次は、旧ID → 新ID の変換です。RESTful API を使うと、変換表が手に入ります。こんな感じの Java のアプリでやりました。http://code.google.com/p/opensocial-java-client/ が必要です。
java -classpath .;opensocial-1.0.jar;commons-codec-1.3.jar;json_simple-1.1.jar;oauth-20090825.jar MixiOldIdConverter in.csv out.csv failed.csv
で実行します。一度実行したら、out.csv や failed.csv に保管するので、2回目は差分だけ実行できます。1回目は、アプリが動いた状況で実行し、その後必要なら、数回、アプリが実行している状態で行い、最後にアプリを停止して変換すると、アプリの停止時間を小さく出来ます。
import org.opensocial.Client; import org.opensocial.Request; import org.opensocial.RequestException; import org.opensocial.Response; import org.opensocial.auth.OAuth2LeggedScheme; import org.opensocial.models.Model; import org.opensocial.services.PeopleService; import java.io.*; import java.util.Date; import java.util.HashSet; public class MixiOldIdConverter { // 本番 private static final String consumerKey = "fuga"; private static final String consumerSecret = "barbar"; // テスト // private static final String consumerKey = "fugaTest"; // private static final String consumerSecret = "barTest"; public static void main(String[] args) throws IOException { File inFile = new File(args[0]); File outFile = new File(args[1]); File failedFile = new File(args[2]); HashSet<String> converted = new HashSet<String>(); readOutFile(outFile, converted); readOutFile(failedFile, converted); BufferedReader reader = new BufferedReader(new FileReader(inFile)); PrintWriter writer = new PrintWriter(new FileWriter(outFile, true)); PrintWriter failedWriter = new PrintWriter(new FileWriter(failedFile, true)); int lineNo = 0; String line; while((line = reader.readLine()) != null) { if (line.length() == 0) continue; if (converted.contains(line)) continue; lineNo++; try { String platformUserId = convert(line); writer.println(line + "," + platformUserId); } catch (Exception e) { //e.printStackTrace(); // ここコメントアウトしてもあまり問題ない failedWriter.println(line); } if ((lineNo % 10) == 0) System.out.println(lineNo + " " + new Date()); } failedWriter.close(); writer.close(); reader.close(); } private static void readOutFile(File outFile, HashSet<String> converted) throws IOException { if (outFile.exists()) { BufferedReader reader = new BufferedReader(new FileReader(outFile)); String line; while((line = reader.readLine()) != null) { if (line.length() == 0) continue; converted.add(line.split(",")[0]); } reader.close(); } } public static String convert(String oldId) throws IOException, RequestException { OAuth2LeggedScheme authScheme = new OAuth2LeggedScheme(consumerKey, consumerSecret, oldId); Client client = new Client(new MixiProvider(), authScheme); Request viewer = PeopleService.getViewer(); viewer.addParameter("fields", "platformUserId"); Response response = client.send(viewer); Model person = response.getEntry(); return (String) person.getField("platformUserId"); } }
import org.opensocial.providers.Provider; public class MixiProvider extends Provider { public MixiProvider(){ super(); setName("mixi"); setVersion("0.8"); setSignBodyHash(false); setRestEndpoint("http://api.mixi-platform.com/os/0.8/"); } }
ステップ4
- Webアプリを停止する。
- データベースのバックアップをとる。
- in.csv の最終形を作る。
- 変換して、out.csv の最終形を作る。
- この後記載する SQL みたいな感じで、新 ID に置き換える。
- 念のため、別なファイル名で、再度、データベースのバックアップをとる。
- 「IDのプラットフォーム共通化対応完了」をクリック。これ以降、新 ID で mixi の方からは応答が来るようになります。
- Webアプリを再開する。
CREATE TABLE old_new_mixi_id_map ( old_mixi_id VARCHAR(255) PRIMARY KEY, new_mixi_id VARCHAR(255) NOT NULL ); COPY old_new_mixi_id_map FROM '/tmp/out.csv' CSV; UPDATE account_mixi SET mixi_id = (SELECT new_mixi_id FROM old_new_mixi_id_map WHERE old_new_mixi_id_map.old_mixi_id = account_mixi.mixi_id) WHERE mixi_id in (SELECT old_mixi_id FROM old_new_mixi_id_map);
場合によっては、他にも関連するテーブルの情報を削除する場合がアプリによってはあると思います。(僕の場合は、他に2カ所、データを削除しました)