2011年11月6日日曜日

Google Cloud SQL

Google Cloud SQLとは?

Google Cloud SQLとは、GoogleAppEngineのアプリケーションから利用できる、リレーショナルデータベースサービスです。
それは、データベースの保守管理や運用について、(Google側で)完全に管理されたサービスであり、
利用者は、煩わしいデータベースの保守管理は不要で、自身のアプリケーションにのみ注力することができます。

データベースの仕様はMySQLに準拠しています。
これにより、データ、アプリケーション、サービスを、簡単にクラウドに載せることが可能になります。
つまり、既存のデータベースをすばやくAppEngineから利用できるようになりますので、
データの可搬性やサービスのマーケットへの投入速度を高めることができます。


アプリケーションやサービスを常に動作させるために、
GoogleCloudSQLはデータを地理的に異なる複数の場所に保存し、信頼性を高めています。

このサービスは現在プレビュー版です。
まもなく、価格についての発表があるでしょう。

機能のハイライト:

・簡単に使えます
データベースの生成、管理、監視のためのリッチなGUIがあります。

・完全に管理されています
データベースは完全に管理されており、データベースのレプリケーションや、パッチの管理など、データベースの管理運用に関わる作業は不要です。

・高い信頼性
今日のサービスやアプリケーションが必要とする信頼性を実現するため、
複数のデータセンターにまたがるデータのレプリケーション機能が組み込まれており、
ひとつのデータセンターがダウンしたとしてもサービスは使い続けることができます。

・GoogleAppEngineやその他Googleサービスとの統合
GoogleAppEngineやその他Googleサービスとの統合により、
複数の製品を簡単に連携させられるようになります。
データをクラウドに配置すれば、より高いパフォーマンスを得られるでしょう。

2011年8月13日土曜日

Google Prediction API --Hello Prediction!--

元ネタ:http://code.google.com/apis/predict/docs/hello_world.html

このページは、PredictionAPIを15分程度で、とりあえず使ってみるサンプルを紹介します。
とりあえずこのサンプルを試したあとに、他のドキュメントを読むとよいでしょう。

Prerequisites 前提条件






The Problem 解決課題


あなたの会社では、電子メールで複数の言語での問い合わせを受け付けていると考えてください。
そしてあなたは、該当する言語の担当者に、電子メールを振り分けなければなりません。
つまりここでの問題は、与えられたテキストが英語なのかスペイン語なのかフランス語なのか判別する、ということになります。

これをするためにあなたは、予測エンジンに学習させるための学習データを作成する必要があります。
一つの学習データは、いくつかのテキストで構成されており、そのテキストの言語を表す、「英語」「スペイン語」「フランス語」のいずれかのラベルが振られているものとします。

学習の後に、任意の言葉や文章を与えると、予測エンジンはそれを上記の言語のうち一番近いものに分類します。


The Solution 解法

Hello Predictionを行う処理の流れは以下のようになります。

1.認証トークンの取得
    PredictionAPIへのリクエストは、すべて認証されている必要があります。 APIはOAuth認証をサポートします。このサンプルでは、OAuthに対応したoacurlコマンドラインツールを使います。最初にトークンをリクエストし、その後のリクエストには、すべてトークンを含める必要があります。

2.学習データのアップロード
    Google Storageに、英語、スペイン語、フランス語を含んだ学習データをアップロードします。 Google Storageにアップロードしたデータのbucket名やオブジェクト名は、学習モデルの一意識別子として使われます。 Prediction APIのリクエストは、この一意識別子により、学習モデルを指定する必要があります。

3.学習
    Prediction APIに、学習データを読み込んで学習するように指示します。 この処理は非同期に行われるため、定期的にサーバーに問い合わせを行って、学習の状態を調べる必要があります。 学習に基づく予測問い合わせを行う前に、学習は完了していなければなりません。

4.問い合わせの実行
    学習の完了後、単語や文章を含んだクエリをサーバーに送信し、サーバーから、そのテキストに対応した言語を受け取ります。 このステップは何回でも実行できます。

このサンプルでは、oacurlコマンドラインツールと、リクエスト送信用のヘルパースクリプトを使用します。
oacurlのヘルパースクリプトは、ライブラリのページにあります。(スクリプトの使い方や、注意点を解説しています。)

oacurlはここからダウンロード

1.認証トークンの取得
oacurlを使用した認証を行う際、インターネットにアクセスでき、ブラウザが使用可能である必要があります。
ダウンロードしたoacurlのjarファイルを置いたディレクトリに移動し、以下のコマンドを実行してください。
このコマンドはブラウザを立ち上げ、Googleアカウントのログインページを表示します。
ログインの後、oacurlがあなたのGoogleアカウントでPrediction APIにアクセスすることを許可するかどうかを聞いてきます。
Prediction APIをアクティブにしたGoogleアカウントでログインすることを忘れないでください。
$ java -cp oacurl-1.2.0.jar com.google.oacurl.Login --scope https://www.googleapis.com/auth/prediction

※このコマンドにより取得したトークンには長めのライフタイムがあり、セッションの最初に一度実行すればOKです。
もし、セッションの途中で認証エラーが発生した場合は、もう一度このコマンドを実行し、再度トークンを取得してください。

2.学習データのアップロード

この学習ファイルをダウンロードしてください。
これは、英語とスペイン語とフランス語の学習データを含んでいます。
学習ファイルのフォーマットは、カンマ区切りのテキストファイルで、2つのカラムと、多数のレコードからなります。
2つ目のカラムは、一つの言語に対するサンプルテキストです。
1つ目のカラムは、サンプルテキストの言語を表すラベル名です。
学習ファイルを開いて、中身を見てみてください。

学習ファイルをGoogle Storage Bucketにコピーしてください。
このサンプルでは、「examplebucket」というbucketを使っていますが、あなた自身のbucketに読み替えてください。
(bucket名は他ユーザーとの間でもユニークでなければならない。)
オブジェクト名については、好きな名前にすることができます。オリジナルの学習ファイルと同じにする必要はありません。

$ gsutil cp ./language_id.txt gs://examplebucket/prediction_models/languages
$ gsutil ls gs://examplebucket
gs://examplebucket/prediction_models/languages

3.学習
次のステップはシステムに学習させることです。
そのためには、先ほどアップロードした学習ファイルのbucket/objectを指定したPOSTリクエストをサーバーに送信します。
リクエストの送信後、学習が完了するまでポーリングします。

このサンプルでは、oauth-train.shと、oauth-check-training.shという、ヘルパースクリプトを使います。
これらのスクリプトファイルをローカルにコピーして、以下のように実行してください。

この学習は、1分以内に終了するはずです。もしそれ以上かかるようなら、障害が発生している可能性が高いです。
学習データをGoogle Storageにアップロードしたか、また、スクリプト実行の際にGoogle Storageのbucket/objectを正しく指定したかを確認してください。
なお、スクリプトを実行する際、gs:// は不要です。

$ ./oauth-train.sh examplebucket/prediction_models/languages
{
 "kind": "prediction#training",
 "id": "examplebucket/prediction_models/languages",
 "selfLink": "https://www.googleapis.com/prediction/v1.2/training/examplebucket/prediction_models/languages"
}

$ ./oauth-check-training.sh examplebucket/prediction_models/languages
{
 "kind": "prediction#training",
 "id": "examplebucket/prediction_models/languages",
 "selfLink": "https://www.googleapis.com/prediction/v1.2/training/examplebucket/prediction_models/languages",
 "modelInfo": {
  "modelType": "classification",
  "classificationAccuracy": 0.95
 },
 "trainingStatus": "DONE"
}

4.問い合わせの実行
学習が完了すれば、サーバーに問い合わせを送信し、予測させることができるようになります。
oauth-predict.shスクリプトファイルをダウンロードし、以下のコマンドを実行して、"muy bueno"が、フランス語、スペイン語、英語のうち、どれに一番近いと判断されるか試してください。

$ ./oauth-predict.sh examplebucket/prediction_models/languages "\"muy bueno\""
{
 "kind": "prediction#output",
 "id": "examplebucket/prediction_models/languages",
 "selfLink": "https://www.googleapis.com/prediction/v1.2/training/examplebucket/prediction_models/languages/predict",
 "outputLabel": "Spanish",
 "outputMulti": [
  {
   "label": "French",
   "score": 0.334130
  },
  {
   "label": "Spanish",
   "score": 0.418339
  },
  {
   "label": "English",
   "score": 0.247531
  }
 ]
}
スコアが最大のものが、一番近いと判断されたもので、それは"outputLabel"で示されているスペイン語となります。

2011年8月12日金曜日

Google Prediction API --Getting Started--

元ネタ:http://code.google.com/apis/predict/docs/getting-started.html

このページでは、Google Prediction API について、それが何なのか、どのように使うのか、さらに詳しいドキュメントのありかについて説明します。


Introduction 導入

このドキュメントは、わずか数分でAPIを試せる、Hello World アプリケーションを含んでいます。
また、APIを使用した、完全なwebサイトの例も2件示します。
1つはスパム検出を行うwebサイトであり、もう1つは、ユーザーの動画の閲覧履歴に基づいて、お勧め動画を提案するwebサイトです。


What Can the Prediction API Do? Prediction APIでなにができるの?

Prediction APIは、パターンマッチングと、機械学習の機能を実現します。
与えられた学習データのセットから、以下のような機能を実現するアプリケーションを作ることができます。

  • ユーザーの過去の閲覧履歴から、そのユーザーの嗜好に合った動画や製品を予測します。
  • メールを、スパムかどうか判断します。
  • 製品レビューが、マイナス評価であるか、プラス評価であるかを分析します。
  • ユーザーの今までの製品の利用履歴から、特定の日にどのぐらいの時間製品を利用するかを予測します。


Prerequisites 必要なもの






Questions, Feedback, and Notifications 質問、フィードバック、通知


Prediction API コミュニティに参加する方法は以下の通りです。




Recommended Reading Order ドキュメントはこの順に読むとよいです

  1. Hello World アプリケーションで、APIを試してください
  2. デベロッパガイドや、リファレンスを読んで、APIの使い方を学んでください。
  3. 料金と利用規約のページで、無料でできることと、料金を確認してください。
  4. 現実世界におけるソリューションの一通りのコーディング例として、example アプリケーションを見てください。
  5. APIを様々な言語から使用するための、helper ライブラリをみてください。


2011年8月8日月曜日

Google Prediction API --Libraries and Sample Code--

元ネタ:http://code.google.com/apis/predict/docs/libraries.html#oacurltraining

このページでは、いくつかの言語からPrediction APIを使うためのヘルパーライブラリを紹介します。
また、よくあるシナリオでAPIを使用するアプリケーションのサンプルを提示します。


Generic Google API Client Libraries



ここでは、Google Prediction APIにアクセスするための一般的なREST形式のAPIを紹介します。
以下の表で、1列目に現在の開発段階を示しています。アルファ版のものもあることに注意してください。
各言語のサンプルも提示していますが、中にはまだサンプルがないものもあります。
必要に応じて他の言語のサンプルを参考にしてください。

Client libraryPublic repositoryAll client library samples
Google APIs Client Library for .NET (alpha)google-api-dotnet-client/.NET samples
Google API Libraries for Google Web Toolkit (alpha)gwt-google-apis/GWT samples
Google APIs Client Library for Java (beta)google-api-java-client/Java samples
Google APIs Client Library for PHP (alpha)google-api-php-client/PHP samples
Google APIs Client Library for Python (beta)google-api-python-client/Python samples
Google APIs Client Library for Ruby (alpha)google-api-ruby-client/Ruby samples



Specialized Google Prediction API Client Libraries


ここでは、Google Prediction API用に作られたAPIについて紹介します。

LanguageLibrary NameLink to the Repository
.NET.NET Prediction API libraryhttp://gpapi.codeplex.com/
BASH scriptoacurlSee the scripts below
JavaPrediction API Java libraryhttp://code.google.com/p/google-api-java-client/wiki/APILibraries#Prediction_API
JavaScript (Experimental)Google Prediction API Javascript LibraryLibrary source is available at https://ajax.googleapis.com/ajax/libs/googleapis/prediction-0.0.1/prediction.js. See information below.
PHPPHP Prediction API libraryhttp://code.google.com/p/predictionapiphpwrapper/source/browse/trunk/GooglePredictionWrapper.php
RGoogle Prediction Client Library for Rhttp://code.google.com/p/google-prediction-api-r-client/
RubyOpen-source Prediction API clienthttp://code.google.com/p/ruby-google-prediction-api/
RubyRubyForge Prediction API clienthttp://rubyforge.org/projects/google-predict/



JavaScript Library (Experimental) --省略--





BASH Using oacurl



注意:oacurlは、現在、OAuth1.0のみサポートしています。

oacurlは、OAuth認証に対応したHTTPリクエストをサポートする、オープンソースのコマンドラインツールです。

製品として販売するようなコードでoacurlを使用することは勧められませんが、
テストやデバックを手っ取り早く実行するときは便利です。

このセクションでは、Predicton APIのREST呼び出しにoacurlを使用したスクリプトを紹介します。

ここから最新バージョンのoacurlを入手してください。

認証トークンの取得
Prediction APIの最初のステップは、OAuth認証トークンの取得です。
以下のスクリプトは認証トークンを要求するリクエストを生成します。
このスクリプトはブラウザを立ち上げ、Googleの認証ページを開きます。
ブラウザに表示されたページで、GoogleアカウントのIDとパスワードを入力します。
するとブラウザは、oacurlにあなたのPrediction APIアカウントにアクセスするための認証トークンを返します。
oacurlがあなたのIDとパスワードを見たり受け取ったりすることはありません。

上記の認証プロセスを実行する際に、oacurlにブラウザを起動させるかそれとも自分でブラウザを立ち上げるか選択することができます。
もし自分で立ち上げることを選んだ場合、Googleアカウントのログインページを開くためのURLを受け取ります。
自分で立ち上げる場合は、 --nobrowser フラグをつけてコマンドを実行してください。

以下のコマンドは、oacurlを使ってOAuth認証を行うコマンドです。
oacurlのJARファイルは、ダウンロードしたローカルファイルを指すように変更してください。
$ java -cp oacurl-1.2.0.jar com.google.oacurl.Login --scope https://www.googleapis.com/auth/prediction
認証トークンの有効期限は長いので、認証は一度行えばOKです。
認証後は、oacurlはトークンを見つけると自動的にそれをリクエストに含めますので、
認証について特に気にする必要はありません。


学習
oauth-train.sh
#!/bin/bash
# Train a prediction model.
# Usage: oauth-train.sh MODEL_NAME

ID=$1
KEY=`cat googlekey`

post_data="{\"id\":\"$ID\"}"

# Train the model.
java -cp ./oacurl-1.2.0.jar com.google.oacurl.Fetch -X POST \
-t JSON \
"https://www.googleapis.com/prediction/v1.3/training?key=$KEY" <<< $post_data
echo
このスクリプトは、Google Storageにアップロードした学習データを使っての学習を行います。

注意:このスクリプトを実行する際には、Google Storageのアクセスキーを"googlekey"という名前のファイルに保存して、スクリプトからアクセス可能な場所に置いておく必要があります。 「アクセスキー」は、Google APIs Consoleから取得できます。
このスクリプトは、以下のように使用します。
$ oauth-train.sh mybucket/myobject


学習状態の取得
oauth-check-training.sh
#!/bin/bash
# Check training status of a prediction model.
# Usage: oauth-training.sh MODEL_NAME

DATA=$1
KEY=`cat googlekey`

# Encode the model name.
MODEL=`echo $DATA | perl -pe 's:/:%2F:g'`

# Check training status.
java -cp ./oacurl-1.2.0.jar com.google.oacurl.Fetch -X GET \
  "https://www.googleapis.com/prediction/v1.3/training/$MODEL?key=$KEY"
echo

このスクリプトは、モデルの学習状態をチェックします。
このスクリプトも、Google Storageのアクセスキーを"googlekey"という名前のファイルに保存して、アクセス可能な場所に置いておく必要があります。

問い合わせの実行
oauth-predict.sh
#!/bin/bash

# Run a prediction against a model.
# Usage: oauth-predict.sh MODEL_NAME DATA

DATA=$1
INPUT="$2"
KEY=`cat googlekey`
MODEL=`echo $DATA | perl -pe 's:/:%2F:g'`
data="{\"input\" : { \"csvInstance\" : [ $INPUT ]}}"

java -cp ./oacurl-1.2.0.jar com.google.oacurl.Fetch -X POST \
-t JSON \
"https://www.googleapis.com/prediction/v1.3/training/$MODEL/predict?key=$KEY" <<< $data
echo
このスクリプトは判断のリクエストを送信します。 このスクリプトは、複数のテキストや数値の列を処理します。 このスクリプトも、Google Storageのアクセスキーを"googlekey"という名前のファイルに保存して、アクセス可能な場所に置いておく必要があります。
$ oauth-predict.sh mybucket/myobject "col1, col2 ..."
データリストは、全体をダブルクォーテーション(")で囲む必要があります。 そして、カラムごとにカンマで区切ります。 カラムが文字列データの場合、さらにシングルクォーテンション(')で囲む必要があります。 カラムが数値データの場合は、クォーテーションは不要です。 以下にいくつか例を示します。
oauth-predict.sh example/bucket "'some string data', 'singleval', 123 "
oauth-predict.sh example/bucket "1234, 'Man\'s best friend' "
oauth-predict.sh example/bucket "1234, 3345" # Numerical data does not need additional quotes.




2011年7月31日日曜日

AppEngineアプリで2-Legged-Oauthを使ってAppsのドメイン管理者かどうかをチェックする

shin1ogawaさんからご指摘頂いた方法です。
すげえ簡単じゃん・・AuthSubとかアホすぎる・・
この投稿は、AppEngineアプリでAuthSubを使ってAppsのドメイン管理者かどうかをチェックする の続きです。

まず、マーケットプレースに登録するアプリの、Application Manifestで、
Provisioning APIを使うよ、って宣言しときます。
<?xml version="1.0" encoding="UTF-8" ?>
<ApplicationManifest xmlns="http://schemas.google.com/ApplicationManifest/2009">
  <Name>Hello World</Name>
  <Description>Demonstrates a simple Google Apps Marketplace application</Description>

  <!-- Administrators and users will be sent to this URL for application support -->
  <Support>
    <Link rel="support" href="https://***.appspot.com/" />
  </Support>

  <!-- Show this link in Google's universal navigation for all users -->
  <Extension id="navLink" type="link">
    <Name>Hello World</Name>
    <Url>https://***.appspot.com?from=google&amp;domain=${DOMAIN_NAME}</Url>
    <Scope ref="ProvisioningAPI"/>
  </Extension>

  <!-- Declare our OpenID realm so our app is white listed -->
  <Extension id="realm" type="openIdRealm">
    <Url>https://***.appspot.com</Url>
  </Extension>
  <!-- Need access to the Provisioning API -->
  <Scope id="ProvisioningAPI">
    <Url> https://apps-apis.google.com/a/feeds/user/#readonly</Url>
    <Reason>This app grants some control to domain admin.</Reason>
  </Scope>
</ApplicationManifest>

上の様にScopeを定義しておくと、「Add it Now」でのインストール時に、こんな感じで聞いてきます。












「データアクセスを許可する」をクリックすることで、Provisioning APIの使用が可能になります。
なお、この許可は、ドメイン管理画面から後で取り消すこともできますし、
ここでキャンセルしたとしても、ドメイン管理画面から後で許可することもできます。

んで、アプリの方はこんな感じ。一部抜粋です。

from gdata.apps.service import AppsService 

CONSUMER_KEY = "..."
CONSUMER_SECRET = "..."
SIG_METHOD = gdata.auth.OAuthSignatureMethod.HMAC_SHA1

class MainHandler(webapp.RequestHandler):
  def get(self):
    template_values = {}
    user = users.get_current_user()
    if user and check_email(user):
        srv = AppsService(domain=urlparse(user.federated_identity()).hostname , source="Hello World")
        srv.SetOAuthInputParameters(SIG_METHOD, CONSUMER_KEY, consumer_secret=CONSUMER_SECRET,
                                   two_legged_oauth=True, requestor_id=user.email())
        srv.ssl = True
        gdata.alt.appengine.run_on_appengine(srv)
        user_name = user.email().split('@', 1)[0]
        user_entry = srv.RetrieveUser(user_name)
        if user_entry.login.admin == "true":
            self.response.out.write("%s is admin." % user_name)
        else:
            self.response.out.write("%s is not admin." % user_name)
    else:
        greeting = 'You need to log in!'
        template_values['greeting'] = greeting
        path = os.path.join(os.path.dirname(__file__), 'templates/index.html')
        self.response.out.write(template.render(path, template_values))
CONSUMER_KEY とCONSUMER_SECRETは、マーケットプレースの「My Vendor Profile」を開いて、
リスティングの「View OAuth Consumer Key 」で見ることができます。

ホント、shin1ogawaさんに感謝です!ありがとうございます!

2011年7月25日月曜日

MarketplaceでのGoogleへの支払いについて

元ネタ:Payment Policy

・登録料

マーケット出品者のアプリをマーケットプレースに掲載するための料金。100US$。
Googleに対し、1回だけ支払う。(ベンダーごとに1回?アプリごとに1回?不明)

・インストール時の料金

「Add it Now」を使用して、ユーザーがアプリをインストールした際に発生する料金のうち、
20%をGoogleに支払う。

・その他

マーケット出品者が、顧客に請求する料金のうち、以下のものは、Googleへの支払いの対象となる。
  1. Google Appsにインストールされるアプリに料金が発生した場合(例えば、インストール時は無料で、無料試用期間の終了後に料金が発生するようなアプリの料金を指します。)
  2. 定期的に発生する基本使用料
  3. 従量課金される料金(例えば、データ量に応じてとか、使用時間に応じて、とか)
  4. 製品エディションのアップグレード時に発生する料金。例えば
スタンダード版をプレミアム版にアップグレードする場合の料金
ユーザー数(ライセンス数)の追加により発生する料金
ストレージ容量の追加などのアップグレード

また、マーケット出品者が、顧客に請求する料金のうち、以下のものは、Googleへの支払いの対象とならない。

  1. 既存の顧客の既存の支払い
  2. 広告料
  3. 導入費用、コンサル費用、サポート費用などのサービス料
  4. Ecommerceによる、商品販売の料金(チケットや、サービスの予約、書籍、食品などの販売)
  5. もはやGoogle Appsユーザーではなくなった顧客からの支払い
  6. 税金
  7. 支払い免除期間に獲得した顧客からの支払い(例えば、以下に示す、『Revenue sharing exemption period』

・無料で使えるものは?

Googleの無料API、ガジェット、OpenIDサービスなどは、無料で使えます。
また、「Add it Now」フィーチャーを使わない、インストールできないアプリをリストすることができます。

ただし、「Add it Now」フィーチャーを使用してインストールするアプリのみが、
Googleユニバーサルナビゲーションリンク、Appsコントロールパネル、または
その他Googleがインストールアプリのロードマップに載せている機能にアクセスすることができます。

・質問があったら?

もし、あなたのアプリの課金方法が、上記の例に当てはまらないのであれば、
あなたのアプリと課金方法の詳細を「solutions-marketplace-feedback@google.com」にメールしてください。
課金対象となるか否かをこちらで判断してお返事します。
もし、こちらの判断に同意いただけない場合は、アプリをインストールできない状態のままにしておくか、リストから削除してください。

・インストール可能なアプリの販売について

Google Appsマーケットプレースを通じて、インストール可能なアプリを販売する場合は、Googleへの支払いが必要です。
Googleへの支払いはGoogle Checkoutによって行われます。
すべての販売、アップグレード、その他関連する契約は、GoogleCheckoutを通さなければなりません。
それらの請求をシステムに統合する詳細な方法については、後で説明します。(どこ?)

・Google Apps マーケットプレースでの支払いについて
支払い免除期間(Revenue sharing exemption period)


Google Apps マーケットプレースは、現在のところ、請求機能をサポートしていません。
そのため、2010年3月9日以降、【あなたの所在地でのマーケットプレースBilling APIのリリース3ヶ月後】までの間、Googleへの支払いを免除します。
なお、この免除は予告無しに取り消される可能性があります。
また、Checkout APIの使用に関して、「開発者の所在地がどこであるか」は、Googleが決定します。

Googleは、開発者に向けて、APIとテスト環境を早いうちにリリースするつもりです。
開発規約に規定されているように、開発者の所在地でのBilling APIのリリース後3ヶ月以内に、開発者は、BillingAPIをアプリに統合しなければなりません。
Googleは、Google Apps Developer Blogや、emailを通じて、APIがリリースされ、支払い免除期間が終了したことを通知します。
Googleは、2010年の第4四半期にBilling APIをリリースする予定です。(まだ?今日は2011/07/26)

支払い免除期間中に獲得した顧客については、支払い免除期間の終了後も支払いをする必要はありません。
より詳しい情報は、Payment Policy FAQを見てください。

・Google AppsマーケットプレースBillingの統合について(?)

Google Checkoutに基づくGoogle Appsマーケットプレース支払いサービスは、マーケットプレースのベンダーへの支払いも扱います。
開発者は、アプリのマーケットプレースへのリスティングの過程で、アプリの値段や更新料を決定できるようになります。

・Checkout API --まもなく公開--

APIのドキュメントは、code.google.comでまもなく公開されます。

AppEngineアプリでAuthSubを使ってAppsのドメイン管理者かどうかをチェックする

AppsアカウントとOpenIDによる認証を行い、マーケットプレイスに載せるAppEngineのアプリで、あるAppsアカウントがドメイン管理者であるか否かを知りたい、という要件が出てきました。

そのようなAPIを探したのですが、どうもないようです。
(もしご存知の方はご一報を!)

そこで、ドメイン管理者にのみ利用可能なApps APIである、Reporting APIを使用することとしました。
つまり、Reporting APIを実行してみて、結果が無事返ってくればドメイン管理者、
認証エラーが返ってきたらドメイン管理者ではない、と判断します。

しかし、Reporting APIを呼び出す際には、ユーザー名とパスワードが必要です。
もちろんアプリ側でユーザー名とパスワードを入力してもらう画面を作ればいいのですが、
そのユーザー名とパスワードはGoogleアカウントのものであり、自分のアプリに入力させたくありません。
(利用者からすればフィッシングにも見えてしまう)
せっかく認証にOpenIDを使ったのですから、ユーザー名とパスワードは自分のアプリに入力させたくないのです。

そこで、AuthSubという、Google側で認証を行い、認証が通れば、トークン(セッションIDのようなもの)をこちらに返してくれるサービスがありますので、それを使うことにしました。

ちなみに、ソースコードは、マーケットプレースのOpenID利用のサンプルソースコードを元にしています。

基本的な方法は、ここの方法と同じです。
Google App Engine 上で認証が必要な Google Data Feeds を取得する方法

import os, re
from datetime import datetime
from datetime import timedelta
from urlparse import urlparse
import gdata.auth
from gdata import service
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp import util
import logging
import gdata.apps.reporting
import gdata.alt.appengine

def check_email(user):
  """Performs basic validation of the supplied email address as outlined
  in http://code.google.com/googleapps/marketplace/best_practices.html
  """
  domain = urlparse(user.federated_identity()).hostname
  m = re.search('.*@' + domain, user.email())
  if m:
    return True
  else:
    return False

class MainHandler(webapp.RequestHandler):
  def get(self):
    #まず最初にここが呼ばれます。
    #ログインを確認した後、AuthSubの認証をするためのリンクをユーザーに返します。
    #(ユーザーにクリックしてもらう)
    #ユーザーがクリックすると、Googleが、認証を許可するかどうかのページを表示します。
    #ユーザーが認証を許可すると、gdata.auth.GenerateAuthSubUrlのnextに指定したurlに返ってきます。
    #その際、認証トークンを、getパラメータに含めてくれます。
    template_values = {}
    user = users.get_current_user()
    if user and check_email(user):
      next = 'https://***.appspot.com/check_domain_admin'
      #scopeは、許可対象のAPIを指定します。これはReporting APIです。
      scope = ('https://www.google.com'
                    '/hosted/services/v1.0/reports/ReportingData')
      secure = 0
      session = 0 #1回限りのアクセスの場合は0(=False)。1(=True)にした場合は、トークンをセッションIDにアップグレードできます。
      auth_url = gdata.auth.GenerateAuthSubUrl(next, scope, secure=secure, session=session)
      self.response.out.write("""<html><body>
        <a href="%s">Request token for the Google Documents Scope</a>
        </body></html>""" % auth_url)     
    else:
        greeting = 'You need to log in!'
        template_values['greeting'] = greeting
        path = os.path.join(os.path.dirname(__file__), 'templates/index.html')
        self.response.out.write(template.render(path, template_values))

class CheckDomainAdmin(webapp.RequestHandler):
    def get(self):
        #認証を許可すると、ここが呼ばれます。(GenerateAuthSubUrlのnext)
        user = users.get_current_user()
        if user and check_email(user):
            self.response.out.write(user.email())
        else:
            logging.info("user NOT exist")
        #トークンを取得します。これが欲しかったんです。
        token = self.request.get("token")
        #GDataServiceの、run_on_appengineを実行する必要があります。
        #これは、「GAEのurlfetchを使え」という指示だそうです。
        srv = service.GDataService()
        gdata.alt.appengine.run_on_appengine(srv)
        #Reporting APIのpython-clientライブラリのReportRequestクラスを使います。
        req = gdata.apps.reporting.ReportRequest()
        req.token = token
        req.domain = urlparse(user.federated_identity()).hostname
        prev_day = datetime.now() - timedelta(days=1) #当日だと、まだレポートがないよ、って怒られる場合があるので一日前
        req.date = prev_day.strftime('%Y-%m-%d')
        req.report_name = "summary" #なんでもいいのですが、summaryで

        #Query url
        query = service.Query()
        query.feed = ('https://www.google.com'
                    '/hosted/services/v1.0/reports/ReportingData')
        try:
            #converterは、デフォルトのGDataEntryFromStringがエラーになります。
            feed = srv.Post(req.ToXml(), query.ToUri() ,converter=str) 
            self.response.out.write(feed) #これは別にいらないです。確認してるだけ
            #Exceptionが発生しなければDomain Adminと判断します。
        except gdata.service.RequestError,e:
            #Domain Adminでは無い場合、RequestErrorが発生します。
            #このとき、POSTの戻り値は、<hs:reason>AuthenticationFailure(1006)</hs:reason>を含んでいます。
            logging.info(e)

class OpenIDHandler(webapp.RequestHandler):
    def get(self):
      """Begins the OpenID flow and begins Google Apps discovery for the supplied domain."""
      self.redirect(users.create_login_url(dest_url='http://***.appspot.com/',
                                           _auth_domain=None,
                                           federated_identity=self.request.get('domain')))

def main():
  application = webapp.WSGIApplication([('/', MainHandler),
                                        ('/check_domain_admin', CheckDomainAdmin),
                                        ('/_ah/login_required', OpenIDHandler)],
                                       debug=True)
  util.run_wsgi_app(application)

if __name__ == '__main__':
  main()
当然ですが、「http://***.appspot.com」は自分のアプリに合わせてくださいね
Reporting APIのpython クライアントライブラリは、↓ここにあります。
google-apps-reporting-api-client

ソースコードではgdata.apps.reportingとしてインポートしているやつです。
最初はこのライブラリのReportRunnerクラスを使おうと思ったのですが、上手くいきませんでした。
ReportRunner.GetReportDataを実行すると、400 BadRequestが返ってきます。run_on_appengineが関係してる?
上記のソースコードでは、ReportRequestクラスを使ってるだけです。

2011年7月24日日曜日

アプリケーションのリスティング

元ネタ:Writing your First Marketplace App using Python


英語のドキュメントでは、アプリケーションのマーケットプレイスへの登録を「Listing」と表現しているため、「リスティング」と書くことにします。

リスティングするリストには、「プライベートリスト」というものがあり、
これは開発とテストのために利用することができます。

マーケットプレイスのページを開いて、まずは「Become a Vendor」にてベンダーとして登録する。
これは、どんなGoogleアカウントでも可能です。
(Gmailアカウントでも、Appsアカウントでも)

でも、一人でたくさんGoogleアカウントを持っているからと言って、
アカウント間で、アプリケーションリストを共有することはできません。

ベンダー登録の後、リスティングを行うわけですが、
この際、 "My product may be directly installed into Google Apps domains"をチェックします。
アプリケーションのカテゴリと同様、これは、後で変更することができません。
また、現在のところ、リストから削除することもできません。

元ネタページのmanifest.xml をコピーして、「ApplicationManifest」欄に貼り付け、
「https://my-app.appspot.com」を、自分のアプリに合わせて変更します。
「ListingManifest」は、テストなのでとりあえず空欄でいいです。

「Save and Preview」ボタンを押せばリスティングは完了です!




※リスティング後、「Please review (and test) your listing.」と表示されます。
これがプライベートリストの状態で、他の人からは見えないが、テストできる状態、
ということになります。

テスト完了後、「I am ready! Submit this listing for approval」をクリックすることで、
グーグルの承認プロセスに回され、承認後にアプリケーションリストに出現することになります。
初回リスティング時に、100$がグーグルから請求されます、と書いてあります。
ということは、2回目以降は請求されないのでしょうか・・ベンダーあたり1回だけ?なのかな?