2013年12月6日金曜日

テーブルの正規化のメモ

この記事が第5正規形まで簡単にまとまっていてわかりやすかった。
素早く正規形を見抜く実践テクニック

下記メモ。ビジネスロジックを入れなければ第3正規形までで正規化は完了するらしい。


正規化
・1事実1箇所のポリシー
非正規形(※正規形ではないが、第1正規化の対象を非正規形という)
第1正規形(1NF)
第2正規形(2NF):部分関数従属性の排除
第3正規形(3NF)
ボイスコッド正規形(BCNF)
第4正規形(4NF)
第5正規形(5NF/PJNF)

重複更新(特定テーブルのデータ更新時に複数箇所を更新する必要が生じる)

関数従属性:商品IDが決まれば商品名は一意に決まる
注文明細テーブルが下記の形式だと商品名が変わったら同じ商品IDのデータをすべて更新しなければならなくなる
注文番号、商品ID、商品名、フォーマット、単価、数量

部分関数従属性:複合キーのいずれかに対する関数従属性がある
注文番号、商品IDの複合キーになっているが、商品名とか商品IDに紐付いているよね
注文番号、商品ID、商品名、フォーマット、単価、数量

推移関数従属性:主キー以外のフィールドに関数従属性がある
名前、住所、電話番号って顧客IDに紐付いているよね
注文番号、注文年月日、顧客ID、名前、住所、電話番号、支払い方法

ボイスコッド正規形:非キーからキーへの関数従属性を取り除く
学生、科目が主キーのテーブル。だが講師が決まれば科目も決まるという非キーからキーへの関数従属性がある
学生、科目、講師

講師、科目
学生、講師

ただし、この分解をすると一人の学生が一つの科目を複数の講師から履修できないという制約が失われてしまう。つまり後者のテーブル構造にはそういった登録が可能になってしまう。

ちなみに実際使うとなると上記の分け方は気持ち悪いから、授業フィールドを作ってこうするだろうなとは思う。
学生、科目、講師

学生、授業
授業、科目、講師


第4正規形、第5正規形はキーだけで構成される対照表が対象
多値従属性:チームが決まればメンバーが決まる
チーム名、メンバー名

チーム名、メンバー名、道具名

チーム名、メンバー名
チーム名、道具名
この正規化をしないとチームにまつわる道具が変わったらテーブルの全ての値を更新するハメになる

下記だとチーム名、会場、ダンスの全てが揃わないとデータ登録ができない
チーム名、会場、ダンス

チーム名、会場
チーム名、ダンス
会場、ダンス

テーブル構造からビジネス構造を排除すると第3正規化までで正規化が完了する

専門の人が書いたスライドもあるけど、ちょっと用語がわかりにくい。
http://www.slideshare.net/nippondanji/db-engineerstudyanim?ref=http://nippondanji.blogspot.jp/2013/11/db.html

2013年11月6日水曜日

httpd.confの設定に関して

この記事がわかりやすいのでメモ。
httpd.confについて調べたのでまとめたよ

個人的に必要な部分をメモ。
httpd.confはCentOS系だと/etc/httpd/conf/httpd.confにある
ServerRoot:Apacheがあるパス





2013年10月14日月曜日

Github と Pull Request とコードレビューって当たり前じゃなかったのか...

メモ。
Webサービス開発現場から / 近頃の開発のやり方 ・・・ Github と Pull Request とコードレビュー

てっきり当たり前の開発手法だと思ってた。
この手法を導入するためにやることは2つ。リポジトリ管理をGithubにすることと
Jenkinsを導入し、テスト用サーバーを用意してテストを回し続けるようにすることだけだ。

開発者としてやることは
・開発をする
・テストを書く
・Pull Requestを飛ばして誰かにマージしてもらう
の3つだ。

Jenkins導入とテストを書くことのメリットだが、これをやることで糞コードが減る。
Jenkinsは特定ブランチにコードがコミットされるたびにテストが実行されるので、
テストが通らないおかしなコードがコミットされるとエラーを吐いて知らせてくれる役割をする。
テストを書くことでなぜ糞コードが減るかというと、テストが書きやすいようにコードを
分割するようになるので、メイン関数にすべてのコードをベタ書きするような、
あの誰も触れないコードを書くような事象を構造的に減らせるというわけだ。

重要なのはそこなので、カバレッジは別に100%じゃなくても構わないと思う。
最悪分岐の多い関数だけ書いておいてもいいわけだし。
バッチとかはメインロジックはそこに書かずにそこで呼び出すモジュールの方に
書いておけばテストもしやすい。

Pull Requestを飛ばしてだれかにマージしてもらうのは、コードレビューを構造的に
組み込むという意味で優れていると思う。これは本番用のブランチにマージする際に
自分でマージするのではなく、他の人にマージしてもらうということだ。
ここでレビューが入ることで、明らかにおかしなコードは入りにくくなるわけだ。

ちなみに設計などはwikiにドキュメントを残して開発チームでレビューを行う仕組み。
ここも属人化を避けるために複数人でミーティングを行っている。



2013年8月30日金曜日

git cloneしようとしたらBad owner or permissions on /home/ユーザー名/.ssh/configと出た

この手順に従ってやったら問題が解決した。
http://futuremix.org/2005/10/openssh-config-permission

どうも本人以外が~/.ssh/configを編集できるのがまずいということらしい。なので、
chmod 600 ~/.ssh/config
にして、本人以外は書き込み(w)ができない状態にしたら、表題の、
Bad owner or permissions on /home/ユーザー名/.ssh/config
はなくなりうまくいった。

ssh-addしようとしたらCould not open a connection to your authentication agentと出てきて困った

このサイトに書いてある通りにやったらとりあえずできるようになった。
http://www.geocities.jp/sugachan1973/doc/funto39.html

とりあえず
eval `ssh-agent`
と打った後に
ssh-add id_rsaファイルのフルパス
と打ったら
Could not open a connection to your authentication agent
は出なくなり、パスフレーズの要求がされ、うまくいった。
うまく行けば
ssh-add -l
と打ったときに
2048 2e:c0・・・
みたいな感じで鍵の内容が表示されるようだ。


どうもこの作業、手順に記載されているとおりおまじないとしてやっていたのだが、
ssh-addってのは認証エージェントにパスフレーズを登録する作業らしい。
gitでリモートサーバーとのやり取りをするとき、いちいち作業ごとにパスフレーズを打つのは
だるいので、認証エージェントという、認証作業を勝手にやってくれるプログラムに
パスフレーズを登録しているということかと。


2013年8月29日木曜日

Perlのテスト系モジュールまとめ

Test::***系の便利なモジュールをまとめて端的に説明しているサイトがあったのでメモ。
PerlでTDD(テスト駆動開発)するなら覚えておきたいCPANモジュール群

あー、なるほど。Test::Mock::Guardってのが何やっているのかよくわからなかったが、
Test::MockObjectみたいなモック化モジュールなのね。そっちに関してはこの説明がわかりやすい。
Test::Mock::Guard Released

あと
Test::MockTimeは便利。time()を固定できる。
Test::MockTime::set_fixed_time(1373954400);
のようにして使う。上記例だと2013-07-16 15:00に固定。




VMwareでLinux(CentOS)のキーボードを日本語キーボードにする

VMWareでLinux(CentOS)をインストールしたらキーボードが英語キーボードで困った。
「:」が該当場所にないのでvimで編集した結果を保存できなくて何が起きているのかわからず
かなりはまったし。

とりあえず暫定で必要そうな文字の出し方を下記に記載しておく。
む+shift:|
れ+shift::
6+shift:^
2+shift:@
この辺打てないとなんもできないだろうから・・。

あとは
ls /lib/kbd/keymaps/i386/qwerty/jp106.map.gz
で日本語キーボードの対応キーマップファイルがあるかどうかを確認し、
su
でrootになったら、
vim /etc/sysconfig/keyboard
で設定ファイルを開いて
KEYTABLE="us"
KEYTABLE="jp106"
に直して
reboot
で再起動したら直っているはず。


2013年8月19日月曜日

puttyからpoderosaへの移行時のエージェントフォワーディング設定

設定系、意味がよくわかっていないのでいつも苦戦する。結果的にこれがわかりやすかった。
http://d.hatena.ne.jp/MOZZ/20070208

2013年8月1日木曜日

金融系SIerの仕事の現状に関するメモとWeb系の現状について少し

興味深い記事があったのでメモとWeb系の現状を少し書こうかと。

人月計算とExcelとスーツの世界より
・資格取得で学んだスタックや木など、勉強していて楽しかったが業務で使うことはなかった
・多くの人が入れ替わり立ち代りメンテしたレガシーコードの存在
・方眼紙状のエクセルテンプレにコピペしまくる設計書作成作業
・ExcelVBAを使って業務の自動化を試み、生産性を向上させるも、周りから業務とはみなされない
・大事なのは技術関連の知識ではなく、顧客の業務フローに関する知識

SIerを退職し、Web系に転職しました
・顧客のためにエクセル方眼紙にわかりやすい日本語で仕様書を書くのが主な仕事
・大事なのは技術ではなく業務知識
・顧客の業務フローを理解している人が優秀なエンジニア。フローを作ったらあとは外注すればよい
・このままだとエクセル方眼紙のメンテが仕事のプロジェクトマネージャーになってしまう

2つの別の人が書いた記事だがこれはひどいな。でもこの人達にどこまでウェブ系が綺麗に
見えているのだろうというのも気になったので、ちょっとだけウェブ系の現状に関して書いておくと、


・Web系開発でもスタックも再帰もメモリ管理も、基本的には使わない
だってスクリプト言語だし、再帰とかスタックとかそんな凝ったロジックは基本的に使わない

・レガシーコードはどの会社にも存在する。例え最初に凄腕エンジニアが作ったシステムであっても
多くの人が使うようなサービスになれば、機能拡張が当然行われ、メンテナンスをする人が
増えるのでやっぱりレガシーなコードになりがちになる。ただ、もちろん、そうしたコードに危機感を
持っている人も多数いて、テストコードを書いて、テスタブルなコードにリファクタリングをし、
Jenkinsなど自動テストを回す仕組みを導入したりというところに工数を割く動きもある。

・自社サービスならエクセル方眼紙に書かれた設計書はないことも
ただしこれは良し悪し。ドキュメントを作る文化がないと、コード読んで理解しろという流れに
なり、仕様把握に時間がかかることもよくある話。もっとドキュメント作れと思ったりもする。


まぁでもコード書きたい人にはWeb系の方がよいのかなと上記の金融SIerのエントリー
見てて思った。


2013年7月24日水曜日

Ruby on Railsが人気な理由がわかった

今すぐ辞めて欲しい、「Ruby on Rails勉強してます」「CakePHP勉強してます」
この記事読んでわかった。なるほど、Rubyだとコードの量が劇的に少なくなるのね。
具体例を見てわかった。前にPerlとPythonとRubyを同時に学習してRubyがベストだと
結論づけている人がいたけどそういうことだったのか。

2013年7月23日火曜日

エンドポイントとエントリーポイントの違い

おんなじような言葉が2つあってわかりにくかったのだが、これ読んで分かった。
http://okwave.jp/qa/q8061906.html
自分の作ったシステムからgoogleのAPIを使うとしたら、
GoogleのAPIのURLはエンドポイント、Googleから見たそのURLは処理が始まるポイント
だからエントリーポイントになるとのこと。指している部分は同じなのだが、プログラムが
始まる側から見るか終わる側から見るかの違いということ。

2013年7月17日水曜日

git checkoutできないときは-fオプションを付ける

http://ja.nishimotz.com/git_checkout
によると-f は「ローカルに行われている変更を捨ててチェックアウトする」ためのオプション。
ローカルの変更を捨てて別ブランチに切り替えたいときは
git checkout -f ブランチ名
をすればよい。

2013年6月6日木曜日

Google Play In-app Billingを訳してみる「In-app Billing Version 2」

In-app Billingバージョン2

In-app Billingバージョン2は取って代わられている。都合がつく限り早く、バージョン3に移行してください。

In-app Billingバージョン2はGoogle Play In-app Billingの旧バージョンである。バージョン3のようにこのバージョンはあなたにGoogle Play決済フローと相互作用をさせ、決済システムを非直接的に行い、IPCを使うことでデバイスがインストールされたPlay Storeアプリと相互作用をするようになっている。

バージョン3と違うのは、バージョン2のAPIは非同期で、送信目的として送られたサービスメッセージを使用している点である。だからバージョン3よりも込み入っている。

バージョン2は非マネージドもマネージド商品もサポートしている。これは定期購入のサポートも同様である。この点に関して、バージョン3はまだ定期購入に対してサポートを提供していない。もしあなたがアプリ内で定期購入を売りたい場合、あなたはバージョン3よりもむしろIn-app Billingバージョン2を実装するべきである。

もしあなたが定期購入を売る必要がない場合は、あなたはIn-app Billingバージョン3を代わりに実装するべきである。

商品タイプ

In-app Billing バージョンは3つの異なる商品タイプをサポートしている。これはあなたにアプリを監視する方法に関して柔軟性を与えるためである。すべてのケースにおいて、あなたはGoogle Playデベロッパーコンソールを使って商品を定義する。定義には商品タイプ、SKU、価格、詳細説明などが含まれている。より詳細を知りたい人はAdministering in-app Billingを参照。

・ユーザーアカウントごとのマネージ-アイテムはGoogle Play上のユーザーアカウントごとに一度のみ決済される。"managed per user account"商品タイプを使用しているアイテムをユーザーが決済する際、Google Playはユーザーごとの各々のアイテムのトランザクション情報を永久的に保存する。これはあなたがあとでGoogle Playに対して特定のユーザーが決済したアイテムの情報を回復するための問い合わせを行うことを可能にする。もしユーザーが既に決済したマネージドアイテムを決済しようとした場合、Google Playはそのユーザーが再びアイテムを購入することを防ぐことができ、"Item already puchased"エラーを表示する。

あなたがゲームレベルやアプリ機能などのアイテムを売る際に、"managed"商品タイプは便利である。これらのアイテムは一時的なものではなく、通常アプリを再インストールする際、デバイスからデータを消去する際、そして新たなデバイスにあなたのアプリをインストールする際には保存しておく必要があるからである。

・非マネージド-Google Play上でトランザクション情報を保存していないアイテムのことである。この意味は、これらのアイテムに対するトランザクション情報を取り出すためにGoogle Playに問い合わせをあとで行うことができないということである。"unmanaged"決済に対しては、あなたはトランザクション情報を管理する責任がある。その上、もし"unmanaged"商品タイプを使った場合、Google Playはユーザーが複数回商品の購入をすることを防ごうとはしない。非マネージドアイテムが何回決済されたかを管理するのはあなた次第である。

あなたが燃料や魔法の呪文などのような消費アイテムを売りたい場合、"unmanaged"商品タイプは便利である。これらのアイテムはあなたのアプリ内で消費され、通常何度も購入する。

・定期購入-デベロッパーが定義した決済間隔ごとに販売をするアイテムである。ユーザーが定期購入決済を行った場合、Google Playとその決済処理は特定の間隔と金額でユーザーアカウントに対して請求がされる。元となる決済メソッドに対し金額を請求しながらそれは行われる。一度ユーザーが定期購入の決済を行うと、Google Playはアカウントに対し無期限に請求をし続ける。ユーザーからの承認やアクションを要求することなしに。ユーザーは定期購入をいつでも取りやめることができる。

定期購入は"managed per user account"決済タイプを使用することによってのみ販売することができる。in-app商品と同様、一度ユーザーがin-app商品を購入すると払い戻しウィンドウは表示されない。払い戻しを希望するユーザーはデベロッパーと直接連絡をしなければならない。定期購入やあなたのアプリでこの商品をどうやって売ればよいかに関する詳細を知りたい方はSubscriptionsドキュメントを参照。


サービス設計

あなたのアプリはAPIを用いることでIn-app Billingサービスにアクセスする。そのAPIはデバイス上でインストールされたGoogle Playアプリによって露出しているものである。Google PlayアプリはあなたのアプリとGoogle Playサーバー間の決済リクエストとレスポンスを通信するために非同期のメッセージループを用いる。実際にはあなたのアプリはGoogle Playサーバーと直にやり取りは決して行わない(図1参照)。その代わり、あなたのアプリは精算リクエストをプロセス間通信(IPC)を通じてGoogle Playアプリに対して送り、Google Playアプリから非同期ブロードキャスト目的の形で決済レスポンスを受け取る。あなたのアプリはアプリ自身とGoogle Playサーバー間のネットワーク接続を管理しないせず、アンドロイドプラットフォームからの特別なAPI群を使用する。

いくつかのin-app精算実装はコンテントを届けたり、トランザクションをバリデートするためにプライベートリモートサーバーを使用するかもしれない。しかし、リモートサーバーはin-appの実装の際に必要ではない。もしあなたがメディアファイルや画像のようなユーザーデバイスに届ける必要があるデジタルコンテンツを得る場合にはリモートサーバーは有用である。署名のバリデーションのような様々なin-app精算のセキュリティタスクに対して何か実施をしたり、ユーザーのトランザクション履歴を保存するためにもリモートサーバーを使うかもしれない。あなたがアプリ内ですべてのセキュリティ関連のタスクをコントロールしたとしても、これらのタスクをリモートサーバー上で行うことが推奨される。なぜならリモートサーバー上でセキュリティタスクを行うことで、あなたのアプリに対するセキュリティ攻撃に対する脆弱性を弱めることができるからである。

基本的なin-app精算実装は3つのコンポーネントに頼っている。

Service(サンプルアプリでBillingServiceと名付けられている)、これはアプリからの決済メッセージを処理し、Google Play in-app精算サービスに精算リクエストを送る

BroadcastReceiver(サンプルアプリでBillingReceiverと名付けられている)、これはGoogle Playアプリケーションからのすべての非同期精算レスポンスを受け取る

・セキュリティコンポーネント(サンプルアプリでSecurityと名付けられている)、これは署名照合やnonce生成などのセキュリティ関連タスクを実行する

あなたはin-app精算をサポートする2つの他のコンポーネントも組み込みたいかも知れない

・レスポンスHandler(サンプルアプリでResponseHandlerと名付けられている)、これは決済の通知、エラー、その他のステータスメッセージのアプリ固有の処理を提供する

これらのコンポーネントに加え、あなたのアプリケーションはユーザーの決済情報を保存する方法と、決済アイテムをユーザーに選択させるためのある種のユーザーインターフェースを提供しなければならない。あなたは精算インターフェースを提供する必要はない。ユーザーがin-app決済を初期化させたとき、Google Playアプリケーションがユーザーに精算インターフェースを提供するからである。ユーザーが精算プロセスを完了した際には、あなたのアプリが再開される。


In-app精算メッセージ

ユーザーが決済を初期化した際に、あなたのアプリはGoogle Playのin-app精算サービス(MarketBillingServiceと名付けられている)に対してシンプルなIPCメソッドコールを利用した精算メッセージを送る。Google Playアプリケーションはすべての精算リクエストを同期的にステータス通知やその他の情報をアプリに提供しながら反応をする。Google Playアプリケーションはいくつかの精算リクエストに関しては非同期的に反応をしている。あなたのアプリに対してエラーメッセージや詳細トランザクション情報を提供しながら。後続のセクションは基本的なレスポンスメッセージについて記載をしている。そのメッセージはあなたのアプリとGoogle Playアプリ間で起きるものである。


In-app 精算リクエスト

あなたのアプリはシングルIPCメソッド(sendBillingRequest())を呼び出すことでin-app精算リクエストを送っている。このメソッドはMarketBillingServiceインターフェースによって露出されている。このインターフェースはアンドロイドインターフェース定義言語ファイル(IMarketBillingService.aidl)内で定義されている。あなたはこのAIDLファイルをin-app精算サンプルアプリとともにダウンロードできる。

sendBillingRequestメソッドは単体バンドルパラメーターを持っている。あなたが送るバンドルはいくつかのkey-valueペアを含まなければならない。このペアはリクエストの様々なパラメーターで規定される。例えばあなたが生成した精算リクエストタイプ、決済したアイテムやそのタイプ、リクエストを作成したアプリケーションなどである。リクエストとともに送られるバンドルキーに関するさらなる情報を知りたい場合は、in-app Billing Service Interfaceを参照。

すべてのリクエストバンドルが持たなければならない最も重要なキーの一つはBILLING_REQUESTキーである。このキーはあなたに自分の作った精算リクエストタイプを規定させている。Google Playのin-app精算サービスは次の5つの生産リクエストタイプをサポートしている。

・CHECK_BILLING_SUPPORTED
このリクエストはGoogle Playアプリケーションがin-app精算をサポートしているかどうかを照合する。あなたのアプリがはじめて立ち上がった際に通常このリクエストは送られる。このリクエストはin-app精算にのみ関連するあるUI機能を有効にしたり、無効にしたりしたいときに有用である。

・REQUEST_PURCHASE
このリクエストはGoogle Playアプリに決済メッセージを送り、in-app精算の土台となっているものである。ユーザーがあなたのアプリ内でアイテムの決済をしたい事を示したいときにあなたはこのリクエストを送る。Google Playは精算インターフェースを表示することによって金銭トランザクションを管理する。

・GET_PURCHASE_INFOMATION
このリクエストは決済状態の変化の詳細を取り出す。リクエストされた決済が精算に成功したり、ユーザーが清算中にトランザクションをキャンセルした時に決済は状態を変える。これは前の決済が返金された時にも起きる。Google Playは決済が状態を変えたとき、あなたのアプリに通知を送る。だからあなたはトランザクション情報が取り出された時にこのリクエストを送ること飲みが必要とされている。

・CONFIRM_NOTIFICATIONS
このリクエストはあなたのアプリが決済状態の変化の詳細を受け取ったことを応答するものである。Google Playは決済状態の変化通知をあなたのアプリに送る。あなたがそれら通知を受け取ったことを確認するまで。

・RESTORE_TRANSACTION
このリクエストはマネージド決済定期購入に対するユーザーのトランザクション状態を取り出すものである。あなたはユーザーのトランザクション状態を取り出す必要があるときのみこのリクエストを送るべきである。トランザクション状態は通常、あなたのアプリが再インストールされたとき、もしくはデバイスからはじめてインストールされたときのものである。


In-app精算レスポンス

Google Playアプリケーションはin-app精算リクエストに対して、同期的、非同期的両方のレスポンスを返す。同期的レスポンスは次の3つのキーのバンドルである。

・RESPONSE_CODE
このキーはリクエストに対するステータス情報とエラー情報を与える

・PURCHASE_INTENT
このキーはPendingIntentを与える。PendingIntentはあなたが精算処理を始める際に使う。

・REQUEST_ID
このキーはあなたにリクエスト識別子を与える。リクエスト識別子はあなたがリクエストに対する非同期レスポンスと一致しているか確かめるのに使うことができる。

これらのキーのいくつかはすべてのリクエストに関連しているわけではない。さらなる情報を得たい方はこのドキュメントで後述するMessaging sequenceを参照。

非同期レスポンスメッセージは個別のブロードキャスト目的の形で送られ、下記を含んでいる。

・com.android.vending.billing.RESPONSE_CODE
このレスポンスはGoogle Playサーバーレスポンスコードを含んでおり、また、あなたがin-app精算リクエストを作った後に送られる。サーバーレスポンスコードは精算リクエストがGoogle Playに届くのに成功したこと、もしくは、精算リクエストを送る途中で何かエラーが生じたことを示している。このレスポンスは(返金や決済情報などの)なんらかの決済状態の変化をレポートするのには使われない。レスポンスと共に送られるレスポンスコードに関するさらなる情報を知りたい方は、Server Response Codes for In-app Billingを参照。

・com.android.vending.billing.IN_APP_NOTIFY
このレスポンスは決済が状態変化をしたことを示している。決済の状態変化とは、決済が成功した、キャンセルになった、返金になったということを意味している。このレスポンスはひとつ、またあhそれ以上の通知IDを含んでいる。各々の通知IDは特定のサーバーサイドメッセージと一致しており、各々のメッセージはひとつ、もしくはそれ以上のトランザクションに関する情報を含んでいる。あなたのアプリがIn_APP_NOTIFYブロードキャスト目的を受け取った後、あなたはメッセージ詳細を取り出すための通知IDとともにGET_PURCHASE_INFORMATIONリクエストを送る。

・com.android.vending.billing.PURCHASE_STATE_CHANGED
このレスポンスはひとつ、またはそれ以上のトランザクションに間s塗る詳細情報を含んでいる。トランザクション情報はJSON文字列を含んでいる。JSON文字列は署名されており、署名は(暗号化されていない)JSON文字列とともにあなたのアプリに送られる。あなたのin-app精算メッセージのセキュリティを確かなものにするために、あなたのアプリはJSON文字列の署名をチェックすることができる。

PURCHASE_STATE_CHANGED目的とともに返されるJSON文字列はあなたのアプリに対して、一つ、もしくはそれ以上の精算トランザクションの詳細を与える。定期購入アイテムに対するJSON文字列の一例は下記に示している。

JSON文字列のフィールドに関するより多くの情報を知りたい方は、In-app Billing Broadcast intentsを参照。


メッセージシーケンス

基本的な決済リクエストに対するメッセージシーケンスは図2で示されている。各々のsendBillingRequest()メソッドに対するリクエストタイプは太字で示されており、ブロードキャスト目的はイタリックで示されている。明確にするために、図2はリクエスト毎に送られるRESPONSE_CODEブロードキャスト目的は示さない。

in-app決済リクエストに対する基本的なメッセージシーケンスは以下のとおり。

1.あなたのアプリケーションは決済リクエスト(REQUEST_PURCHASEタイプ)を送り、プロダクトIDやその他のパラメーターを規定する
2.Google Playアプリケーションはあなたのアプリに次のキーと共にバンドルを送る:RESPONSE_CODE,PURCHASE_INTENT,REQUEST_ID。PURCHASE_INTENTキーはPendingIntentを提供する。PendingIntentはあなたのアプリが与えられたプロダクトIDに対して精算UIを始めるために使うものである。
3.あなたのアプリは未決済の目的を始める。未決済の目的(pending intent)とは精算UIを始めるものである。
ノート:あなたは未決済の目的をアプリケーション文脈からではなく、アクティビティ文脈からはじめなければならない
4.精算フローが完了したとき(これはユーザーがアイテムの決済を完了するか、またはキャンセルしたことを意味する)、Google Playはあなたのアプリに通知メッセージ(IN_APP_NOTIFYブロードキャスト目的)を送る。通知メッセージは通知IDを含んでいる。この通知IDはトランザクションを言及している。
5.あなたのアプリはGET_PURCHASE_STATE_CHANGEDリクエストを送ることによってトランザクション情報のリクエストを送り、トランザクションに対する通知IDを規定する。
6.Google PlayアプリケーションはRESPONSE_CODEキーとREQUEST_IDキーをバンドルとともに送信する。
7.Google PlayはPURCHASE_STATE_CHANGEDブロードキャスト目的内であなたのアプリにトランザクション情報を送る
8.与えられた通知IDに対し、確認メッセージ(CONFIRM_NOTIFICATIONSタイプ)を送ることによってトランザクション情報を取り出すことをあなたのアプリが確認をする。そして、受け取ったトランザクション情報に対して通知IDを規定する
9.Google PlayアプリはあなたのアプリにRESPONSE_CODEキー、REQUEST_IDキーとともにバンドルを送る。

Google Playからトランザクション情報を受け取ったとき、あなたは確認を送らなければならないことを覚えておくこと(図2のステップ8)。もしあなたが確認メッセージを送らないと、Google Playはあなたが確認をしなかったトランザクションに対するIN_APP_NOTIFYメッセージを送り続けることになる。ベストプラクティスとしては、あなたがユーザーに対してアイテムを届けている間は、決済アイテムに対するCONFIRM_NOTIFICATIONリクエストを送るべきである。このようにすれば、あなたのアプリがクラッシュ、または何かあなたのアプリに商品の付与ができない状態になっても、あなたのアプリは、商品付与をする必要があることを示しながらGoogle PlayからIN_APP_NOTIFYブロードキャスト目的を受け取ることになるだろう。その上、ベストプラクティスとして、あなたのアプリは複数注文を含むIN_APP_NOTIFYメッセージを管理することができるに違いない。

復元されたトランザクションリクエストに対するメッセージシーケンスは図3に示されている。各々のsendBillingRequest()メソッドに対するリクエストタイプは太字で示されており、ブロードキャスト目的はイタリックで示されている。明確にするために、図3はリクエスト毎に送られるRESPONSE_CODEブロードキャストインテントは表示していない。

このリクエストは3つのレスポンスのトリガーになる。初めのものは、RESPONSE_CODEキーとREQUEST_IDキーと一緒に戻されるバンドルである。次に、Google PlayアプリケーションはRESPONSE_CODEブロードキャスト目的を送る。これはステータス情報、もしくはリクエストに関するエラー情報を提供するものである。常に、RESPONSE_CODEメッセージは特定のリクエストIDに言及しており、だからあなたはどのリクエストがRESPONSE_CODEメッセージに紐づくのかを特定することができる。

RESTORE_TRANSACTIONSリクエストタイプはPURCHASE_STATE_CHANGEDブロードキャスト目的のトリガーにもなる。これは決済リクエスト中に送られたトランザクション情報が同じタイプも含んでいる。決済リクエストとは異なり、トランザクションは関連する通知IDなしで与えられることができ、あなたはCONFIRM_NOTIFICATIONメッセージと一緒にこの目的に対する反応をする必要がない。

ノート:あなたはRESTORE_TRANSACTIONSリクエストタイプを次の場合にのみ使うべきである。あなたのアプリがデバイス上で初めてインストールされた時か、あなたのアプリがデバイスから削除された後に再インストールされた場合。

in-app精算がサポートされているかどうかをチェックするためのメッセージシーケンスは図4で示されている。sendBillingRequest()メソッドに対するリクエストタイプは太字で示されている。

CHECK_BILLING_SUPPORTEDリクエストに対する動機レスポンスはサーバーレスポンスコードとともにバンドルを与える。RESULT_OKレスポンスコードはin-app精算がサポートされていることを示している。RESULT_BILLING_UNAVAILABLEレスポンスコードはin-app精算は使えないことを示している。その理由としてはあなたの規定しているAPIバージョンが認識されていない、もしくはユーザーがin-app決済を行うのに不適格であるからである(例えば、そのユーザーはin-app精算が許可されていない国に駐在しているとか)。SERVER_ERRORも返され、Google Playサーバーに問題があることを示している。


IN_APP_NOTIFY メッセージを操作する

通常あなたのアプリはREQUEST_PURCHASEメッセージに応えて、Google PlayからIN_APP_NOTIFYブロードキャスト目的を受け取る(図2参照)。IN_APP_NOTIFYブロードキャスト目的はあなたのアプリにリクエストした決済の状態が変わったことを知らせる。決済詳細を取り出すために、あなたのアプリはGET_PURCHASE_INFORMATIONリクエストを送る。Google PlayはPURCHASE_STATE_CHANGEDブロードキャスト目的とともにレスポンスを返す。この目的は決済状態の変更詳細を含んでいる。あなたのアプリはその後CONFIRM_NOTIFICATIONSメッセージを送り、Google Playにあなたが決済状態の変更情報を受け取ったことを知らせる。

いくつかの特別なケースでは、あなたは複数のIN_APP_NOTIFYメッセージを受け取るかもしれない。それが例え決済情報のレシートをあなたが確認していたとしても。または、あなたが決済の初期化を決してしていないとしても、決済変更に対するIN_APP_NOTIFYメッセージを受け取るかもしれない。あなたのアプリはこれら特別なケースの両方を操作しなければならない。


複数のIN_APP_NOTIFYメッセージを操作する

受け取ったPURCHASE_STATE_CHANGEDメッセージに対するCONFIRM_NOTIFICATIONSメッセージをGoogle Playが受け取ったとき、通常はPURCHASE_STATE_CHANGEDメッセージに対するIN_APP_NOTIFY目的を送るのをやめる。しかしときどき、Google PlayはPURCHASE_STATE_CHANGEDメッセージに対するIN_APP_NOTIFY目的を繰り返し送ることがある。それがたとえあなたのアプリがCONFIRM_NOTIFICATIONメッセージを送っていたとしてもである。これは、あなたがCONFIRM_NOTIFICATIONSメッセージを送っている間にデバイスのネットワーク接続が切れてしまった時に起きる。このケースではGoogle PlayはあなたのCONFIRM_NOTIFICATIONSメッセージを受け取ることができず、あなたがトランザクションメッセージを受け取ったことを認識する応答を受け取るまで、複数のIN_APP_NOTIFYメッセージが送られる。それ故、後続のIN_APP_NOTIFYメッセージは前に処理したトランザクションに対するものであることを、あなたのアプリは認識できなければならない。あなたはJSON文字列を含むorderIDをチェックすることでこれを行うことができる。なぜならすべてのトランザクションはユニークなorderIdを持っているからである。

refunds(返金)やその他未承諾のIN_APP_NOTIFYメッセージを操作する

あなたのアプリがREQUEST_PURCHASEメッセージを送っていないにもかかわらず、IN_APP_NOTIFYブロードキャスト目的を受け取る場合には2つのケースがある。図5はこれらのケースの両方に対するメッセージシーケンスを表している。それぞれのsendBillingRequest()メソッドに対するリクエストタイプは太字で示され、ブロードキャスト目的はイタリックで示されている。明確にするために図5はリクエスト毎に送られたRESPONSE_CODEブロードキャスト目的は示していない。

まず最初のケースでは、ユーザーがあなたのアプリを2つ以上のデバイスでインストールして、そのデバイスのうちの一つからin-app決済を行った際に、あなたのアプリはIN_APP_NOTIFYブロードキャスト目的を受け取るかもしれない。このケースでは、Google PlayはIN_APP_NOTIFYメッセージを2番めのデバイスに送り、決済状態が変更されたことをアプリケーションに知らせる。あなたのアプリはこのメッセージをアプリ初期化のREQUEST_PURCHASEメッセージからのレスポンスの操作と同じように操作できる。だから最終的に、あなたのアプリはPURCHASE_STATE_CHANGEDブロードキャスト目的メッセージを受け取る。このメッセージは決済されたアイテムに関する情報を含んでいる。これはユーザーアカウント毎にマネージドされたプロダクトタイプを持ったアイテムにのみ適用される。

次のケースでは、Google PlayがGoogleウォレットから返金通知を受け取った時、あなたのアプリがIN_APP_NOTIFYブロードキャスト目的を受け取ることができる。このケースでは、Google PlayはIN_APP_NOTIFYメッセージをあなたのアプリに送る。あなたのアプリは初期化されたREQUEST_PURCHASEメッセージからレスポンスを操作するのと同じやり方で、このメッセージを操作することができる。最終的にあなたのアプリが返金されたアイテムに関する情報を含むPURCHASE_STATE_CHANGEDメッセージを受け取るように。この返金情報はPURCHASE_STATE_CHANGEDブロードキャスト目的に付随するJSON文字列形式の中に含まれている。さらに、JSON文字列のpurchaseState文字列は2がセットされる。

重要:あなたはGoogleウォレットAPIをin-app精算トランザクションの返金やキャンセルを行うために使用することはできない。あなたはGoogleウォレット商人アカウントを通して手動で行わなければならない。しかしオーダー情報を取り出すためにGoogleウォレットAPIを使うことはできる。


セキュリティコントロール

アプリに対して送られたトランザクション情報の整合性を高めるために、Google PlayはPURCHASE_STATE_CHANGEDブロードキャスト目的の中に含まれるJSON文字列に署名をしている。Google Playは署名を作るためにアプリとひもづけられた秘密鍵を使っている。デベロッパーコンソールはそれぞれのアプリに対してRSAキーペアを生成する。あなたはアプリ発行詳細のデベロッパーコンソールの設定の下、ライセンスキーフィールドの中に、このキーペアの公開鍵部分を見つけることができる。

Google Playが精算レスポンスに署名をしたとき、精算レスポンスには署名済みJSON文字列(非暗号化)と署名が含まれている。あなたのアプリがこの署名済みレスポンスを受け取ったとき、署名の妥当性を確認するために、あなたはRSAキーペアの公開鍵部分を使うことができる。署名の妥当性チェックを行うことによって、あなたは改竄やなりすましが行われたレスポンスを見破ることができる。あなたはアプリの中で署名妥当性チェックを行うことができる。しかし、もしあなたのアプリがセキュアなリモートサーバーとつながっているのであれば、我々は署名の妥当性チェックをそのサーバー上で行うことを推奨する。

In-app精算はGoogle Playから返される決済情報の整合性をチェックするためにnonce(ワンタイムなランダム文字列)も使用する。あなたのアプリはnonceを生成し、GET_PURCHASE_INFOMATIONリクエストとRESTORE_TRANSACTIONSリクエストとともにnonceを送らなければならない。Google Playがリクエストを受け取ると、nonceにトランザクション情報を含んだJSON文字列を付加する。JSON文字列はその後署名され、あなたのアプリに返される。あなたのアプリがJSON文字列を受け取ったとき、あなたはJSON文字列の署名と同様、nonceも妥当性チェックを行う必要がある。

セキュリティと設計に対するベストプラクティスに関するより多くの情報を知りたい場合は、Security and Designを参照。


In-app精算要件と制約

in-app精算を始める前に、下記の要件と制約を再検討しておくこと。

・In-app精算はGoogle Playを通して発行されたアプリ内でのみ実装できる。
・あなたはGoogle Play In-app精算を使うためにGoogleウォレット商人アカウントを持たなければならない。
・In-app精算を使うにはAndroidマーケットアプリのバージョン2.3.4(もしくはそれ以上)が必要。定期購入をサポートするためには、Google Playアプリのバージョン3.5かそれ以上が必要。Android3.0でデバイスを動かすには、MyAppsアプリのバージョン5.0.12(もしくはそれ以上)が必要。
・デバイスがAndroid1.6(API level4)かそれ以上で動いている場合、アプリはin-app精算のみ使用することができる。
・あなたはin-app精算をデジタルコンテンツの販売にのみ使用出来る。あなたは物理的商品、個人サービス、そのた物理的な配送が必要になるなにかを売るためにin-app精算を使うことはできない。
・Google Playはコンテンツ付与のフォームは何も提供しない。あなたは自分のアプリ内で売るデジタルコンテンツの付与の責任を負っている。
・あなたはネットワークに接続されることが決してないデバイス上で、in-app精算を実装することはできない。in-app精算リクエストを完了させるには、デバイスはネットワーク越しにGoogle Playサーバーにアクセスできなければならない。











In-app Billing Version 2

In-app Billing Version 2 is superseded. Please migrate to Version 3 at your earliest convenience.
In-app Billing version 2 is the legacy version of the Google Play In-app Billing. Like Version 3, it lets you interact with the Google Play purchase flow and payments system indirectly, by means of IPC communication with the Play Store app installed on the device.
Unlike Version 3, the Version 2 API is asynchronous and uses service messages sent as broadcast intents, so it is more complicated than Version 3.
Version 2 supports both unmanaged and managed products, as well as supports subscriptions, where Version 3 does not yet offer support for subscriptions. If you want to sell subscriptions in your app, you should implement In-app Billing Version 2, rather than Version 3.
If you do not need to sell subscriptions, you should implement In-app Billing Version 3 instead.

Product Types


In-app Billing Version supports three different product types to give you flexibility in how you monetize your app. In all cases, you define your products using the Google Play Developer Console, including product type, SKU, price, description, and so on. For more information, see Administering In-app Billing.
  • Managed per user account — Items that can be purchased only once per user account on Google Play. When a user purchases an item that uses the "managed per user account" product type, Google Play permanently stores the transaction information for each item on a per-user basis. This enables you to later query Google Play to restore the state of the items a specific user has purchased. If a user attempts to purchase a managed item that has already been purchased, Google Play prevents the user from purchasing the item again and displays an "Item already purchased" error. The "managed" product type is useful if you are selling items such as game levels or application features. These items are not transient and usually need to be restored whenever a user reinstalls your application, wipes the data on their device, or installs your application on a new device.
  • Unmanaged — Items that do not have their transaction information stored on Google Play. This means that you cannot later query Google Play to retrieve transaction information for those items. For "unmanaged" purchases, you are responsible for managing the transaction information. Also, Google Play does not attempt to prevent the user from purchasing an item multiple times if it uses the "unmanaged" product type. It's up to you to control how many times an unmanaged item can be purchased.
    The "unmanaged" product type is useful if you are selling consumable items, such as fuel or magic spells. These items are consumed within your application and are usually purchased multiple times.
  • Subscriptions — Items that are sold with a developer-specified, recurring billing interval. When a user purchases a subscription, Google Play and its payment processor automatically bill the user's account at the specified interval and price, charging the amount to the original payment method. Once the user purchases a subscription, Google Play continues billing the account indefinitely, without requiring approval or action from the user. The user can cancel the subscription at any time. Subscriptions can only be sold using the "managed per user account" purchase type. As with in-app products, once the user has purchased an in-app product there is no refund window. Users desiring refunds must contact the developer directly. For more information about subscriptions and how to sell them in your apps, see the Subscriptions document.

Service Architecture


Your app accesses the In-app Billing service using an API that is exposed by the Google Play app installed on the device. The Google Play app then uses an asynchronous message loop to convey billing requests and responses between your application and the Google Play server. In practice, your application never directly communicates with the Google Play server (see figure 1). Instead, your application sends billing requests to the Google Play application over interprocess communication (IPC) and receives purchase responses from the Google Play application in the form of asynchronous broadcast intents. Your application does not manage any network connections between itself and the Google Play server or use any special APIs from the Android platform.

Figure 1. Your application sends and receives billing messages through the Google Play application, which handles all communication with the Google Play server.
Some in-app billing implementations may also use a private remote server to deliver content or validate transactions, but a remote server is not required to implement in-app billing. A remote server can be useful if you are selling digital content that needs to be delivered to a user's device, such as media files or photos. You might also use a remote server to store users' transaction history or perform various in-app billing security tasks, such as signature verification. Although you can handle all security-related tasks in your application, performing those tasks on a remote server is recommended because it helps make your application less vulnerable to security attacks.
A typical in-app billing implementation relies on three components:
  • A Service (named BillingService in the sample application), which processes purchase messages from the application and sends billing requests to the Google Play in-app billing service.
  • A BroadcastReceiver (named BillingReceiver in the sample application), which receives all asynchronous billing responses from the Google Play application.
  • A security component (named Security in the sample application), which performs security-related tasks, such as signature verification and nonce generation. For more information about in-app billing security, see Security controls later in this document.
You may also want to incorporate two other components to support in-app billing:
  • A response Handler (named ResponseHandler in the sample application), which provides application-specific processing of purchase notifications, errors, and other status messages.
  • An observer (named PurchaseObserver in the sample application), which is responsible for sending callbacks to your application so you can update your user interface with purchase information and status.
In addition to these components, your application must provide a way to store information about users' purchases and some sort of user interface that lets users select items to purchase. You do not need to provide a checkout user interface. When a user initiates an in-app purchase, the Google Play application presents the checkout user interface to your user. When the user completes the checkout process, your application resumes.

In-app Billing Messages


When the user initiates a purchase, your application sends billing messages to Google Play's in-app billing service (named MarketBillingService) using simple IPC method calls. The Google Play application responds to all billing requests synchronously, providing your application with status notifications and other information. The Google Play application also responds to some billing requests asynchronously, providing your application with error messages and detailed transaction information. The following section describes the basic request-response messaging that takes place between your application and the Google Play application.

In-app billing requests

Your application sends in-app billing requests by invoking a single IPC method (sendBillingRequest()), which is exposed by the MarketBillingService interface. This interface is defined in an Android Interface Definition Language file (IMarketBillingService.aidl). You can download this AIDL file with the in-app billing sample application.
The sendBillingRequest() method has a single Bundle parameter. The Bundle that you deliver must include several key-value pairs that specify various parameters for the request, such as the type of billing request you are making, the item that is being purchased and its type, and the application that is making the request. For more information about the Bundle keys that are sent with a request, see In-app Billing Service Interface.
One of the most important keys that every request Bundle must have is the BILLING_REQUEST key. This key lets you specify the type of billing request you are making. Google Play's in-app billing service supports the following five types of billing requests:
  • CHECK_BILLING_SUPPORTED This request verifies that the Google Play application supports in-app billing. You usually send this request when your application first starts up. This request is useful if you want to enable or disable certain UI features that are relevant only to in-app billing.
  • REQUEST_PURCHASE This request sends a purchase message to the Google Play application and is the foundation of in-app billing. You send this request when a user indicates that he or she wants to purchase an item in your application. Google Play then handles the financial transaction by displaying the checkout user interface.
  • GET_PURCHASE_INFORMATION This request retrieves the details of a purchase state change. A purchase changes state when a requested purchase is billed successfully or when a user cancels a transaction during checkout. It can also occur when a previous purchase is refunded. Google Play notifies your application when a purchase changes state, so you only need to send this request when there is transaction information to retrieve.
  • CONFIRM_NOTIFICATIONS This request acknowledges that your application received the details of a purchase state change. Google Play sends purchase state change notifications to your application until you confirm that you received them.
  • RESTORE_TRANSACTIONS This request retrieves a user's transaction status for managed purchases and subscriptions. You should send this request only when you need to retrieve a user's transaction status, which is usually only when your application is reinstalled or installed for the first time on a device.

In-app Billing Responses

The Google Play application responds to in-app billing requests with both synchronous and asynchronous responses. The synchronous response is a Bundle with the following three keys:
  • RESPONSE_CODE This key provides status information and error information about a request.
  • PURCHASE_INTENT This key provides a PendingIntent, which you use to launch the checkout activity.
  • REQUEST_ID This key provides you with a request identifier, which you can use to match asynchronous responses with requests.
Some of these keys are not relevant to every request. For more information, see Messaging sequence later in this document.
The asynchronous response messages are sent in the form of individual broadcast intents and include the following:
  • com.android.vending.billing.RESPONSE_CODE This response contains a Google Play server response code, and is sent after you make an in-app billing request. A server response code can indicate that a billing request was successfully sent to Google Play or it can indicate that some error occurred during a billing request. This response is not used to report any purchase state changes (such as refund or purchase information). For more information about the response codes that are sent with this response, see Server Response Codes for In-app Billing.
  • com.android.vending.billing.IN_APP_NOTIFY This response indicates that a purchase has changed state, which means a purchase succeeded, was canceled, or was refunded. This response contains one or more notification IDs. Each notification ID corresponds to a specific server-side message, and each messages contains information about one or more transactions. After your application receives an IN_APP_NOTIFY broadcast intent, you send a GET_PURCHASE_INFORMATION request with the notification IDs to retrieve message details.
  • com.android.vending.billing.PURCHASE_STATE_CHANGED This response contains detailed information about one or more transactions. The transaction information is contained in a JSON string. The JSON string is signed and the signature is sent to your application along with the JSON string (unencrypted). To help ensure the security of your in-app billing messages, your application can verify the signature of this JSON string.
The JSON string that is returned with the PURCHASE_STATE_CHANGED intent provides your application with the details of one or more billing transactions. An example of this JSON string for a subscription item is shown below:
{ "nonce" : 1836535032137741465,
  "orders" :
    [{ "notificationId" : "android.test.purchased",
       "orderId" : "transactionId.android.test.purchased",
       "packageName" : "com.example.dungeons",
       "productId" : "android.test.purchased",
       "developerPayload" : "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
       "purchaseTime" : 1290114783411,
       "purchaseState" : 0,
       "purchaseToken" : "rojeslcdyyiapnqcynkjyyjh" }]
}
For more information about the fields in this JSON string, see In-app Billing Broadcast Intents.

Messaging sequence

The messaging sequence for a typical purchase request is shown in figure 2. Request types for each sendBillingRequest() method are shown in bold, broadcast intents are shown in italic. For clarity, figure 2 does not show the RESPONSE_CODE broadcast intents that are sent for every request.
The basic message sequence for an in-app purchase request is as follows:
  1. Your application sends a purchase request (REQUEST_PURCHASE type), specifying a product ID and other parameters.
  2. The Google Play application sends your application a Bundle with the following keys: RESPONSE_CODE, PURCHASE_INTENT, and REQUEST_ID. The PURCHASE_INTENT key provides a PendingIntent, which your application uses to start the checkout UI for the given product ID.
  3. Your application launches the pending intent, which launches the checkout UI.
    Note: You must launch the pending intent from an activity context and not an application context.
  4. When the checkout flow finishes (that is, the user successfully purchases the item or cancels the purchase), Google Play sends your application a notification message (an IN_APP_NOTIFY broadcast intent). The notification message includes a notification ID, which references the transaction.
  5. Your application requests the transaction information by sending a GET_PURCHASE_STATE_CHANGED request, specifying the notification ID for the transaction.
  6. The Google Play application sends a Bundle with a RESPONSE_CODE key and a REQUEST_ID key.
  7. Google Play sends the transaction information to your application in a PURCHASE_STATE_CHANGED broadcast intent.
  8. Your application confirms that you received the transaction information for the given notification ID by sending a confirmation message (CONFIRM_NOTIFICATIONS type), specifying the notification ID for which you received transaction information.
  9. The Google Play application sends your application a Bundle with a RESPONSE_CODE key and a REQUEST_ID key.

Figure 2. Message sequence for a purchase request.
Keep in mind, you must send a confirmation when you receive transaction information from Google Play (step 8 in figure 2). If you don't send a confirmation message, Google Play will continue sending IN_APP_NOTIFY messages for the transactions you have not confirmed. As a best practice, you should not send a CONFIRM_NOTIFICATIONS request for a purchased item until you have delivered the item to the user. This way, if your application crashes or something else prevents your application from delivering the product, your application will still receive an IN_APP_NOTIFY broadcast intent from Google Play indicating that you need to deliver the product. Also, as a best practice, your application must be able to handle IN_APP_NOTIFY messages that contain multiple orders.
The messaging sequence for a restore transaction request is shown in figure 3. Request types for each sendBillingRequest() method are shown in bold, broadcast intents are shown in italic. For clarity, figure 3 does not show the RESPONSE_CODE broadcast intents that are sent for every request.

Figure 3. Message sequence for a restore transactions request.
The request triggers three responses. The first is a Bundle with a RESPONSE_CODE key and a REQUEST_ID key. Next, the Google Play application sends a RESPONSE_CODE broadcast intent, which provides status information or error information about the request. As always, the RESPONSE_CODE message references a specific request ID, so you can determine which request a RESPONSE_CODE message pertains to.
The RESTORE_TRANSACTIONS request type also triggers a PURCHASE_STATE_CHANGED broadcast intent, which contains the same type of transaction information that is sent during a purchase request. Unlike with a purchase request, however, the transactions are given without any associated notification IDs, so you do not need to respond to this intent with a CONFIRM_NOTIFICATIONS message.
Note: You should use the RESTORE_TRANSACTIONS request type only when your application is installed for the first time on a device or when your application has been removed from a device and reinstalled.
The messaging sequence for checking whether in-app billing is supported is shown in figure 4. The request type for the sendBillingRequest() method is shown in bold.

Figure 4. Message sequence for checking whether in-app billing is supported.
The synchronous response for a CHECK_BILLING_SUPPORTED request provides a Bundle with a server response code. A RESULT_OK response code indicates that in-app billing is supported; a RESULT_BILLING_UNAVAILABLE response code indicates that in-app billing is unavailable because the API version you specified is unrecognized or the user is not eligible to make in-app purchases (for example, the user resides in a country that does not allow in-app billing). A SERVER_ERROR can also be returned, indicating that there was a problem with the Google Play server.

Handling IN_APP_NOTIFY messages

Usually, your application receives an IN_APP_NOTIFY broadcast intent from Google Play in response to a REQUEST_PURCHASE message (see figure 2). The IN_APP_NOTIFY broadcast intent informs your application that the state of a requested purchase has changed. To retrieve the details of that purchase, your application sends a GET_PURCHASE_INFORMATION request. Google Play responds with a PURCHASE_STATE_CHANGED broadcast intent, which contains the details of the purchase state change. Your application then sends a CONFIRM_NOTIFICATIONS message, informing Google Play that you have received the purchase state change information.
In some special cases, you may receive multiple IN_APP_NOTIFY messages even though you have confirmed receipt of the purchase information, or you may receive IN_APP_NOTIFY messages for a purchase change even though you never initiated the purchase. Your application must handle both of these special cases.

Handling multiple IN_APP_NOTIFY messages

When Google Play receives a CONFIRM_NOTIFICATIONS message for a given PURCHASE_STATE_CHANGED message, it usually stops sending IN_APP_NOTIFY intents for that PURCHASE_STATE_CHANGED message. Sometimes, however, Google Play may send repeated IN_APP_NOTIFY intents for a PURCHASE_STATE_CHANGED message even though your application has sent a CONFIRM_NOTIFICATIONS message. This can occur if a device loses network connectivity while you are sending the CONFIRM_NOTIFICATIONS message. In this case, Google Play might not receive your CONFIRM_NOTIFICATIONS message and it could send multiple IN_APP_NOTIFY messages until it receives acknowledgement that you received the transaction message. Therefore, your application must be able to recognize that the subsequent IN_APP_NOTIFY messages are for a previously processed transaction. You can do this by checking the orderID that's contained in the JSON string because every transaction has a unique orderId.

Handling refunds and other unsolicited IN_APP_NOTIFY messages

There are two cases where your application may receive IN_APP_NOTIFY broadcast intents even though your application has not sent a REQUEST_PURCHASE message. Figure 5 shows the messaging sequence for both of these cases. Request types for each sendBillingRequest() method are shown in bold, broadcast intents are shown in italic. For clarity, figure 5 does not show the RESPONSE_CODE broadcast intents that are sent for every request.

Figure 5. Message sequence for refunds and other unsolicited IN_APP_NOTIFY messages.
In the first case, your application may receive an IN_APP_NOTIFY broadcast intent when a user has your application installed on two (or more) devices and the user makes an in-app purchase from one of the devices. In this case, Google Play sends an IN_APP_NOTIFY message to the second device, informing the application that there is a purchase state change. Your application can handle this message the same way it handles the response from an application-initiated REQUEST_PURCHASE message, so that ultimately your application receives a PURCHASE_STATE_CHANGED broadcast intent message that includes information about the item that has been purchased. This applies only to items that have their product type set to "managed per user account."
In the second case, your application can receive an IN_APP_NOTIFY broadcast intent when Google Play receives a refund notification from Google Wallet. In this case, Google Play sends an IN_APP_NOTIFY message to your application. Your application can handle this message the same way it handles responses from an application-initiated REQUEST_PURCHASE message so that ultimately your application receives a PURCHASE_STATE_CHANGED message that includes information about the item that has been refunded. The refund information is included in the JSON string that accompanies the PURCHASE_STATE_CHANGED broadcast intent. Also, the purchaseState field in the JSON string is set to 2.
Important: You cannot use the Google Wallet API to issue refunds or cancel in-app billing transactions. You must do this manually through your Google Wallet merchant account. However, you can use the Google Wallet API to retrieve order information.

Security Controls


To help ensure the integrity of the transaction information that is sent to your application, Google Play signs the JSON string that is contained in the PURCHASE_STATE_CHANGED broadcast intent. Google Play uses the private key that is associated with the app to create this signature. The Developer Console generates an RSA key pair for each app. You can find the public key portion of this key pair in the app's publishing details in the Developer Console, under Settings, in the License Key field.
When Google Play signs a billing response, it includes the signed JSON string (unencrypted) and the signature. When your application receives this signed response you can use the public key portion of your RSA key pair to verify the signature. By performing signature verification you can help detect responses that have been tampered with or that have been spoofed. You can perform this signature verification step in your application; however, if your application connects to a secure remote server then we recommend that you perform the signature verification on that server.
In-app billing also uses nonces (a random number used once) to help verify the integrity of the purchase information that's returned from Google Play. Your application must generate a nonce and send it with a GET_PURCHASE_INFORMATION request and a RESTORE_TRANSACTIONS request. When Google Play receives the request, it adds the nonce to the JSON string that contains the transaction information. The JSON string is then signed and returned to your application. When your application receives the JSON string, you need to verify the nonce as well as the signature of the JSON string.
For more information about best practices for security and design, see Security and Design.

In-app Billing Requirements and Limitations


Before you get started with in-app billing, be sure to review the following requirements and limitations.
  • In-app billing can be implemented only in applications that you publish through Google Play.
  • You must have a Google Wallet Merchant account to use Google Play In-app Billing.
  • In-app billing requires version 2.3.4 (or higher) of the Android Market application. To support subscriptions, version 3.5 or higher of the Google Play app is required. On devices running Android 3.0, version 5.0.12 (or higher) of the MyApps application is required.
  • An application can use in-app billing only if the device is running Android 1.6 (API level 4) or higher.
  • You can use in-app billing to sell only digital content. You cannot use in-app billing to sell physical goods, personal services, or anything that requires physical delivery.
  • Google Play does not provide any form of content delivery. You are responsible for delivering the digital content that you sell in your applications.
  • You cannot implement in-app billing on a device that never connects to the network. To complete in-app purchase requests, a device must be able to access the Google Play server over the network. 

Androidのインテントとは

Androidの英文マニュアルを読んでいて苦戦中なのだが、今までインテントを「目的」と
訳してた・・これ技術用語だったのか。意味が通らなくておかしいとは思っていたが。
http://k-tai.impress.co.jp/docs/column/keyword/20110118_420982.html

一言で言うとインテントとはアプリから別のアプリに橋渡しをする仕組みのことのようだ。
別のアプリのコマンドを呼び出す仕組みといったところか。

NHK番組API

個人的にメモ。
http://www2.nhk.or.jp/api/

APIは4つ。
PROGRAM LIST API:指定した地域、サービス(チャンネル)、日付の番組一覧を取得
PROGRAM GENRE API:指定した地域、ジャンル、日付の番組一覧を取得
PROGRAM INFO API:番組IDを指定して、その番組の詳細情報を取得
NOW ON AIR API:指定した地域、サービス(チャンネル)の放映中番組を取得

会員登録をすればAPIは使えて、1日300回まで使用可能。この回数を踏まえると、取得した情報を自分のサーバーに保存しておかないと、毎回ユーザーのアクセスが来る度にAPIを叩くような使い方はできないということか。

2013年5月29日水曜日

Google Play In-app Billingを訳してみる「In-app Billing Reference (IAB Version 3)」


In-app Billing レファレンス(IABバージョン3)

この文書はIn-app Billingバージョン3APIを使うための技術的レファレンス情報を提供するものである。

サーバーレスポンスコード

後述のテーブルはすべてのサーバーレスポンスコードを列記している。このレスポンスコードはGoogle Playからあなたのアプリへ送られるものである。Google Playはレスポンスコードを同期的に送る。レスポンスバンドル内でRESPONSE_CODEキーへマッピングされた整数値として。

レスポンスコード 値 詳細
BILLING_RESPONSE_RESULT_OK 0 成功
BILLING_RESPONSE_RESULT_USER_CANCELED 1 ユーザーが戻るボタンを押したかキャンセルダイアログを押した
BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE 3 Billing APIバージョンがこのタイプのリクエストをサポートしていない
BILLING_RESPONSE_RESULT_ITEM_unAVAILABLE 4 リクエストされた商品が決済で使えない
BILLING_RESPONSE_RESULT_DEVELOPER_ERROR 5 APIに不当な引数が与えられた。このエラーはアプリが正しく署名されていない、Google Play内のIn-app Billingに対して適切に設定されていない、マニュフェストに必要なパーミッションがないことも示している。
BILLING_RESPONSE_RESULT_ERROR 6 API挙動内での致命的エラー
BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED 7 アイテムが既に所持されていることによる決済エラー
BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED 8 アイテムが所持されていないことによる消費エラー


APIレファレンス

In-app Billingバージョン3APIはIInAppBillingService.aidlファイル内で定義されている。このファイルはバージョン3のサンプルアプリを含んでいる。

getSkuDetails()メソッド

このメソッドはプロダクトID一覧に対する商品詳細を返す。Google Playによって送られるレスポンスバンドル内で、クエリ結果はDETAILS_LISTキーにマッピングされたArrayList文字列内で保存される。詳細一覧内の各々の文字列はJSON形式の単体商品に対する商品詳細を含んでいる。商品詳細に伴うJSON文字列内のフィールドはtable2でまとめられている。

Table2。商品アイテム詳細に伴うJSONフィールドの詳細はgetSkudetailsリクエストから返される
キー 詳細
productId:商品に対するプロダクトID
type:値はin-app商品に対する"inapp"か定期購入に対する"subs"でなければならない
price:通貨単位を含む商品の定型化された価格。この価格は税を含まない
title:商品タイトル
description:商品の詳細


getBuyIntent()メソッド

このメソッドはRESPONSE_CODEキーでマッピングされたレスポンスコードの整数値を返す。またBUY_INTENTキーでマッピングされたin-appアイテムに対する決済フローを開始するためのPendingIntentを返す。PendingIntentを受け取ったとき、Google Playは決済注文に対するデータと共にレスポンスIntentを送る。レスポンスIntent内で返されたこのデータはtable 3でまとめられている。

Table 3.In-app Billinバージョン3決済リクエストからのレスポンスデータ

キー 詳細
RESPONSE_CODE もし決済が成功した場合は0、エラーはそれ以外
INAPP_PURCHASE_DATA JSON形式の文字列。JSONには決済注文に関する詳細を含んでいる。JSONフィールドの詳細に関してはtable4を参照。
INAPP_DATA_SIGNATURE 決済シグネチャーを含む文字列。この決済データはデベロッパーのプライベートキーで署名されている。データ署名はRSASSA-PKCS1-v1_5スキームを用いている

Table4は決済注文に対するレスポンスデータ内で返されるJSONフィールドについて述べている

Table4 INAPP_PURCHASE_DATAに対するJSONフィールドの詳細

フィールド 詳細
orderId:トランザクションに対するユニークなオーダー識別子。これはグーグルウォレットのOrderIDと一致する
packageName:決済が由来するアプリのパッケージ
productId:アイテム商品識別子。すべてのアイテムは商品IDを持っている。このIDはGoogle Playデベロッパーコンソール上でアプリ商品一覧内で定義しなければならない
purchaseTime:商品が決済された時間エポック(1970/1/1)からのミリセコンドで表記。
purchaseState:注文の決済状態。取りうる値は0(purchased),1(canceled),2(refunded)
developerPayload:デベロッパーが定義した文字列。この文字列は注文に関する追加情報を含んでいる。あなたはgetBuyIntentリクエストを生成した際にこのフィールドに対する値を規定することができる。
purchaseToken:付与されたアイテムとユーザーのペアに対する決済を一意に識別するトークン


getPurchases()メソッド

このメソッドはユーザーが所持している現在未消費の商品を返す。Table 5はバンドル内で返されたレスポンスデータを列挙している。

Table 5 getPurchaseリクエストからのレスポンスデータ

キー 詳細
RESPONSE_CODE:リクエストが成功なら0、エラーならそれ以外
INAPP_PURCHASE_ITEM_LIST:このアプリからの決済の商品ID一覧を含むStringArrayList
INAPP_PURCHASE_DATA_LIST:このアプリからの決済詳細を含むStringArrayList。一覧の各々のINAPP_PURCHASE_DATAアイテム内で保存された詳細情報の一覧を参照。
INAPP_DATA_SIGNATURE_LIST:このアプリの決済シグネチャーを含むStringArrayList
INAPP_CONTINUATION_TOKEN:ユーザーが所持しているin-app商品の次のセットを取り出すための連続トークンを含む文字列。ユーザーが所持している商品数がとても多い場合にこれはGoogle Playサービスによってのみセットされる。レスポンス内に連続トークンが存在する場合、あなたはgetPurchasesに対して別のコールを生成しなければならない。そしてあなたが取り出した連続トークンを通さなければならない。次のgetPurchasesコールはより多くの決済を返し、さらなる連続トークンを返すこともありうる。



In-app Billing Reference (IAB Version 3)

This documentation provides technical reference information for using the In-app Billing Version 3 API.

Server Response Codes


The following table lists all of the server response codes that are sent from Google Play to your application. Google Play sends the response code synchronously as an integer mapped to the RESPONSE_CODE key in the response Bundle. Your application must handle all of these response codes.
Table 1. Summary of response codes for In-app Billing Version 3 API calls.
Response Code Value Description
BILLING_RESPONSE_RESULT_OK 0 Success
BILLING_RESPONSE_RESULT_USER_CANCELED 1 User pressed back or canceled a dialog
BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE 3 Billing API version is not supported for the type requested
BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE 4 Requested product is not available for purchase
BILLING_RESPONSE_RESULT_DEVELOPER_ERROR 5 Invalid arguments provided to the API. This error can also indicate that the application was not correctly signed or properly set up for In-app Billing in Google Play, or does not have the necessary permissions in its manifest
BILLING_RESPONSE_RESULT_ERROR 6 Fatal error during the API action
BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED 7 Failure to purchase since item is already owned
BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED 8 Failure to consume since item is not owned

API Reference


The In-app Billing Version 3 API is defined in the IInAppBillingService.aidl file, which is included with the Version 3 sample application.

The getSkuDetails() method

This method returns product details for a list of product IDs. In the response Bundle sent by Google Play, the query results are stored in a String ArrayList mapped to the DETAILS_LIST key. Each String in the details list contains product details for a single product in JSON format. The fields in the JSON string with the product details are summarized in table 2.
Table 2. Description of JSON fields with product item details returned from a getSkuDetails request.
Key Description
productId The product ID for the product.
type Value must be “inapp” for an in-app product or "subs" for subscriptions.
price Formatted price of the item, including its currency sign. The price does not include tax.
title Title of the product.
description Description of the product.

The getBuyIntent() method

This method returns a response code integer mapped to the RESPONSE_CODE key, and a PendingIntent to launch the puchase flow for the in-app item mapped to the BUY_INTENT key. When it receives the PendingIntent, Google Play sends a response Intent with the data for that purchase order. The data that is returned in the response Intent is summarized in table 3.
Table 3. Response data from an In-app Billing Version 3 purchase request.
Key Description
RESPONSE_CODE 0 if the purchase was success, error otherwise.
INAPP_PURCHASE_DATA A String in JSON format that contains details about the purchase order. See table 4 for a description of the JSON fields.
INAPP_DATA_SIGNATURE String containing the signature of the purchase data that was signed with the private key of the developer. The data signature uses the RSASSA-PKCS1-v1_5 scheme.

Table 4 describes the JSON fields that are returned in the response data for a purchase order.
Table 4. Descriptions of the JSON fields for INAPP_PURCHASE_DATA.
Field Description
orderId A unique order identifier for the transaction. This corresponds to the Google Wallet Order ID.
packageName The application package from which the purchase originated.
productId The item's product identifier. Every item has a product ID, which you must specify in the application's product list on the Google Play Developer Console.
purchaseTime The time the product was purchased, in milliseconds since the epoch (Jan 1, 1970).
purchaseState The purchase state of the order. Possible values are 0 (purchased), 1 (canceled), or 2 (refunded).
developerPayload A developer-specified string that contains supplemental information about an order. You can specify a value for this field when you make a getBuyIntent request.
purchaseToken A token that uniquely identifies a purchase for a given item and user pair.

The getPurchases() method

This method returns the current un-consumed products owned by the user. Table 5 lists the response data that is returned in the Bundle.
Table 5. Response data from a getPurchases request.
Key Description
RESPONSE_CODE 0 if the request was successful, error otherwise.
INAPP_PURCHASE_ITEM_LIST StringArrayList containing the list of productIds of purchases from this app.
INAPP_PURCHASE_DATA_LIST StringArrayList containing the details for purchases from this app. See table 4 for the list of detail information stored in each INAPP_PURCHASE_DATA item in the list.
INAPP_DATA_SIGNATURE_LIST StringArrayList containing the signatures of purchases from this app.
INAPP_CONTINUATION_TOKEN String containing a continuation token to retrieve the next set of in-app products owned by the user. This is only set by the Google Play service if the number of products owned by the user is very large. When a continuation token is present in the response, you must make another call to getPurchases and pass in the continuation token that you received. The subsequent getPurchases call returns more purchases and possibly another continuation token.

Google Play In-app Billingを訳してみる「Implementing the API(Version 3 API)」

In-app Billingの実装(IABバージョン3)

Google PlayのIn-app Billingはわかりやすくシンプルなインターフェースを提供する。このインターフェースはIn-app Billingリクエストを起こったり、Google Playを使うIn-app Billingトランザクションを管理するのに使用される。下記の情報はどのようにしてあなたのアプリケーションからバージョン3APIを使ってin-app Billingサービスを呼び出すかに関する基本をカバーしている。

ノート:完璧な実装を見たり、どのようにあなたのアプリのテストするかを学んだりする場合はSelling In-app Productsトレーニングクラスを参照。このトレーニングクラスはIn-app Billing アプリケーションの完全なサンプルを提供している。サンプルには接続を行うのに関するキーとなるタスクを管理するクラスや、決済リクエストを送るクラス、Google Playからのレスポンスを管理するクラス、メイン操作からin-app Billingコールを生成できるよう、バックグラウンドのスレッドを管理するクラスなど、便利なクラスを含んでいる。

始める前に、必ずIn-app Billing Overviewを読んでおくこと。それをすることであなたはIn-app Billingを実装することを容易にするためのコンセプトに馴染みやすくすることができる。

In-app Billingをあなたのアプリに実装するために、あなたは以下のことをする必要がある。

1.あなたのプロジェクトにIn-app Billingライブラリを追加する
2.AndroidManifest.xmlファイルをアップデートする
3.ServiceConnectionを作り、IInAppBillingServiceをそこにバインドする
4.あなたのアプリからIInAppBillingServiceにIn-app Billingリクエストを送る
5.Google PlayからIn-app Billingレスポンスを管理する


AIDLファイルをあなたのプロジェクトに追加する

IInAppBillingService.aidlはアンドロイドインターフェース定義言語(AIDL)ファイルである。これはIn-app Billingバージョン3にインターフェースを定義するものである。あなたはIPCメソッドコールを呼び出すことによって決済リクエストを作るためのインターフェースを使うことができる。

AIDLファイルを取得するためには

1.Android SDK Managerを開く
2.SDKマネージャーでExtrasセクションを広げる
3.Google Play Billing Libraryを選択する
4.Install packagesをクリックし、ダウンロードを完了させる

これでIInAppBillingService.aidlファイルは<sdk>/extras/google/play_billing/にインストールされる。

AIDLをあなたのプロジェクトに追加するには

1.IInAppBillingService.aidlファイルをあなたのアンドロイドプロジェクトにコピーする
・あなたがEclipseを使っている場合は
a.あなたが既存のAndroidプロジェクトから始める場合は、プロジェクトをEclipseで開き。もしあなたが新しいAndroidプロジェクトを初めから作る場合は、File > New > Android Application Projectをクリックする。その後あなたのワークスペースに新しいプロジェクトを作るためのNew Android Applicationウィザードの指示に従う
b./srcディレクトリ内で、File > New > Packageをクリックする。そうするとcom.android.vending.billingという名前のパッケージが作られる。
c.<sdk>/extras/google/play_billing/からIInAppBillingService.aidlファイルをコピーし、あなたのワークスペース内のsrc/com.android.vending.billing/ フォルダに貼り付ける
・あなたが非Eclipse環境で開発をしている場合、/src/com/android/vending/billingディレクトリを作って、そこにIInAppBillingService.aidlをコピーする。AIDLファイルをあなたのプロジェクト内に置き、IInAppBillingService.javaファイルが作られるようにAntツールを使ってあなたのプロジェクトをビルドする
2.あなたのアプリケーションをビルドする。あなたはプロジェクトの/genディレクトリ内にIInAppBillingService.javaと名前の着いたファイルが生成されていることを確認する


あなたのアプリケーションManifestを更新する

In-app billingはGoogle Playアプリケーションに依存している。それはつまりあなたのアプリケーションとGoogle Playサーバー間のすべてのコミュニケーションはGoogle Playアプリケーションが管理している。Google Playアプリケーションを使うために、あなたのアプリケーションは適切なパーミッションをリクエストしなければならない。このリクエストはあなたのAndroidManifest.xmlファイルにcom.android.vending.BILLINGパーミッションを付加することで行うことができる。もしあなたのアプリがIn-app Billingパーミッションを宣言していないにもかかわらず決済リクエストを贈ろうとした場合、Google Playはそのリクエストを拒絶し、エラーのレスポンスを返す。

あなたのアプリに必要なパーミッションを与えるには、Android.xmlマニフェストファイルに以下の行を加える。
<uses-permission android:name="com.android.vending.BILLING" />


サービスコネクションを作る

あなたのアプリはアプリとGoogle Play間でメッセージのやり取りをするためのServiceConnectionを持たなくてはならない。最低限、あなたのアプリは下記のことを行わなければならない。

・IInAppBillingServiceをバインドする
・GooglePlayアプリに(IPCメソッドコールとしての)決済リクエストを送る
・各々の決済リクエストとともに返される同期レスポンスメッセージを管理する


IInAppBillingServiceをバインドする

Google Play上のIn-app Billingサービスと接続を確立するために、あなたのアクティビティとIInAppBillingServiceをつなぐServiceConnectionを実装する必要がある。接続が確立されたあとにIInAppBillingServiceインスタンスへのリファレンスを得るためのonServiceDisconnectedメソッドとonServiceConnectedメソッドをオーバーライドすること。

あなたのアクティビティのonCreateメソッドにおいて、bindServiceメソッドを呼ぶことでバインドを行う。メソッドにあなたが作成したServiceConnectionのインスタンスとIn-app Billingサービスを参照しているIntentを通す。

あなたはこれでGoogle Playサービスとコミュニケーションを取るmService参照を使うことができる。

重要:あなたがアクティビティを完了させたとき、In-app Billingサービスからバインドを外すことを覚えておくこと。もしバインドを外すことをしないと、オープンサービス接続があなたのデバイスのパフォーマンスを落とすことになる。この例は、アクティビティのonDestroyメソッドをオーバーライドすることによって、mServiceConnと呼ばれているIn-app Billingと接続しているサービス接続上でどうやってバインドを外すのかを示している。

IInAppBillingServiceにバインドするサービス接続の完全な実装に関しては、Selling In-app Productsトレーニングクラスと関連サンプルを参照。


In-app Billingリクエストを生成する

一度あなたのアプリをGoogle Playに接続させると、in-app商品に対する決済リクエストを初期化することができる。Google Playはユーザーが決済メソッドに入るための精算インターフェースを提供している。だから、あなたのアプリは決済トランザクションを直接操作する必要はない。アイテムが決済されたとき、Google Playはユーザーがアイテムの所有権を持つことを認識し、またそのアイテムが消費されるまで、同じプロダクトIDの他の商品を決済できないようにする。あなたはアプリ内でどうやってアイテムが消費されるかを管理することができ、またGoogle Playに再びそのアイテムの決済が可能であることを通知することができる。あなたはGoogle Playにユーザーによって行われた決済一覧を迅速に取り出す問い合わせをすることもできる。これは例えばユーザーがあなたのアプリを立ち上げた際にユーザー決済を復帰させたいときに便利だ。


決済に関する利用可能アイテムの問い合わせをする

あなたのアプリ内で、In-app Billingバージョン3APIを使うことでGoogle Playから商品詳細と問い合わせることができる。リクエストをIn-app Billingサービスに通すには、まず"ITEM_ID_LIST"キーとプロダクトIDの文字列配列を含むバンドルを作る。このリストの各々の文字列は決済可能アイテムに対するプロダクトIDである。

Google Playから情報を取り出すためにはgetSkuDetailsメソッドをIn-app Billingバージョン3PAI上で呼び、そのメソッドをIn-app BillingAPIバージョン3、あなたのコールしているアプリのパッケージネーム、決済タイプinapp、そしてあなたが作ったバンドルに通せばよい。

もしリクエストが成功した場合、返り値としてのバンドルはBILLING_RESPONSE_RESULT_OKのレスポンスコードを持っている。

警告:メインスレッドでgetSkuDetailsを呼んではいけない。このメソッドを呼ぶことはあなたのメインスレッドをブロックするネットワークリクエストのトリガーになる。その代わりとして、分離されたスレッドを生成し、そのスレッドの中からgetSkuDetailsメソッドを呼ぶ。

Google Playからすべての可能なレスポンスコードを見たい場合はIn-app Billing Referenceを参照。

問い合わせ結果はDETAILS_LISTキーとともに文字列配列の形で保存される。決済情報はJSON形式の文字列で保存される。帰ってくる商品詳細情報のタイプを見たい場合は、In-app Billing Referenceを参照。

この例では、あなたは前のコードの一部から返されるsku詳細バンドルからin-appアイテムに対する価格を取り出している。


アイテムの決済

あなたのアプリから決済リクエストを始めるためには、In-app Billingサービス上のgetBuyIntentメソッドを呼び出す。メソッドの中にIn-app Billing APIバージョン3、あなたの呼び出しアプリのパッケージネーム、決済アイテムのプロダクトID、決済タイプ(inappまたはsubs)、developerPayload文字列を通す。developerPayload文字列はGoogle Playに決済情報と一緒に返り値として送信してほしい追加の引数を規定したい場合に使われる。

リクエストが成功した場合、返り値としてのバンドルはBILLING_RESPONSE_RESULT_OK(0)のレスポンスコードと、決済フローを始めるために使用できるPendingIntentを持っている。Google Playから戻されうるレスポンスコードをすべて見たい場合は、In-app Billing Referenceを参照。次にBUY_INTENTキーと一緒にレスポンスバンドルからPendingIntentを抽出する。

PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");

決済トランザクションを完了させるためには、startIntentSenderForResultメソッドを呼び、生成したPendingIntentを使う。この例は、リクエストコードに対する1001の任意の値を使用している。

Google PlayはあなたのアプリのonActivityResultメソッドに対するPendingIntentに対するレスポンスを送る。onActivityResultメソッドはActivity.RESULT_OK(1)またはActivity.RESULT_CANCELED(0)の結果コードを持っている。Intentレスポンスで返される注文情報のタイプを見たい場合はIn-app Billing レファレンスを参照。

注文の決済データはIntentレスポンスの中でINAPP_PURCHASE_DATAキーにマッピングされたJSONフォーマットの文字列になっている。例が下記。

前の例から続ける場合は、あなたはレスポンスコード、決済データ、シグネチャーをIntentレスポンスから受け取る。

セキュリティ推奨:あなたが決済リクエストを送る際にはdeveloperPayloadの中でこのトークンを含み、また決済リクエストを一意に定義する文字列トークンを作る必要がある。あなたはトークンとして文字列をランダムに生成された文字列を使うことができる。Google Playからの決済レスポンスを受け取る際に、戻り値としてのデータシグネチャー、orderId、developerPayload文字列をチェックすること。さらにセキュリティを向上させるにはあなたはこのチェックをセキュアなサーバーで行うべきである。orderIdはあなたが前に処理していないユニークな値であること、そしてdeveloperPayload文字列は前に決済リクエストとともに送ったトークンとマッチすることを確かめる必要がある。


決済アイテムの問い合わせ

あなたのアプリからユーザーによってなされた決済情報を取り出すには、In-app Billingバージョン3サービスでgetPurchasesメソッドを呼び出せばよい。メソッドをIn-app Billing APIバージョン3、呼び出し元アプリのパッケージネーム、決済タイプ(inappまたはsubs)を通す。

Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);

Google Playサービスは現在デバイスにログが書き込まれているユーザーアカウントによって作られた決済のみを返す。リクエストが成功している場合、戻り値としてのバンドルは0のレスポンスコードを持っている。レスポンスバンドルはプロダクトIDの一覧、各々の決済の注文詳細の一覧、各々の決済のシグネチャーを含んでいる。

パフォーマンスを改善するために、getPurchaseが初めて呼ばれた際、in-app Billingサービスはユーザーが所持している700商品を上限に返す。ユーザーが大量の商品を所持している場合、Google Playは文字列トークンを含んでいる。その文字列トークンはINAPP_CONTINUATION_TOKENをキーにしてマッピングされている。そのキーはレスポンスバンドルの中にある。レスポンスバンドルは多くの商品が取り出せることを示すためのものである。あなたのアプリは次のgetPurchasesコールを作ることができるそして、このトークンの中で引数として通している。Google Playはレスポンスバンドルの中で継続的なトークンを返し続ける。それはユーザーが所持しているすべての商品があなたのアプリに送られるまでだ。

getPurchasesによって返されるより多くの情報を知りたい場合はin-app Billing Referenceを参照。次の例はどのようにあなたがレスポンスからこのデータを取り出すかを示している。


決済の消費

あなたはIn-app Billingバージョン3APIを使うことができる。Google Playでのin-app商品の決済オーナーを追うために。一度in-app商品が決済されると、それはownedとみなされ、Google Playから決済されることができない。あなたはin-app商品に関する消費リクエストを送らなければならない。Google Playがそれを再び決済可能にする前に。

重要:マネージドin-app商品は消費可能である。だが定期購入は消費可能ではない。

どのようにあなたがアプリ内で消費メカニズムを使うかはあなた次第である。基本的にはあなたあhin-app商品のために一時的な便益とともに消費を実装する。一時的な便益とはユーザーが複数回決済したいかもしれないものである(例えばゲーム内通貨や装備など)。あなたは基本的にin-app商品のために消費の実装をしたくないだろう。in-app商品は一度だけ決済ができ、恒久的な効果をもたらす(例えばプレミアムアップグレード)。

決済消費を記録するために、consumePurchaseメソッドをIn-app Billingサービスに送ること。また、決済が削除されたことを一意に示すpurchaseToken文字列の中に通すこと。purchaseTokenは決済の成功リクエストを追うためのGoogle PlayサービスによってINAPP_PURCHASE_DATA文字列の中に返されたデータの一部である。この例では、あなたは商品の消費を記録している。この商品はtoken変数の中でpurchaseTokenに一意に特定されている。

int response = mService.consumePurchase(3, getPackageName(), token);

警告:consumePurchaseメソッドをメインスレッド内で呼んではいけない。あなたのメインスレッドをブロックするネットワークリクエストのトリガーとなるメソッドを呼んでしまうからだ。その代わりにあなたは独立したスレッドを作り、その中でconsumePurchaseメソッドを呼ぶこと。

どのようにin-app商品をユーザーにプロビジョニングするを管理し、追跡することはあなたの責任である。例えば、もしユーザーがゲーム内通貨を決済する場合、あなたは決済された通貨量とともにプレイヤーの商品一覧を更新するべきである。

セキュリティ推奨:あなたは消費リクエストを送らなければならない。ユーザーに対して消費可能なin-app決済の便益をプロビジョニングする前に。あなたがアイテムをプロビジョニングする前に、Google Playから消費性向レスポンスを受け取っていることを必ず確認すること。


定期購入の実装

定期購入に対する決済フローを開始することはsubsにセットされなければならない商品タイプの例外とともに、商品に対する決済フローを開始するのと似ている。決済結果はあなたのアクティビティのonActivityResultメソッドによって運ばれる。in-app商品のケースと全く同様である。

アクティブな定期購入問い合わせをするためにはgetPurchasesメソッドを使い、再度subsでセットされた商品タイプパラメーターとともに使う。

このコールはユーザーが所持しているアクティブなすべての定期購入とともにバンドルを返す。一度定期購入が更新なしで期限切れになると、返されたバンドルの中にもはやそれは現れない。


あなたのアプリをセキュアにする

アプリへ送られたトランザクション情報の整合性を保証するのを助けるために、Google Playは決済注文に対するレスポンスデータを含むJSON文字列に署名をしている。Google Playはプライベートキーを使っている。そのプライベートキーは署名を作るためにデベロッパーコンソール内であなたのアプリケーションとひもづけられている。デベロッパーコンソールは各々のアプリに対してRSAキーペアを生成する。

ノート:このキーペアの公開鍵部分おw見つけるためにはデベロッパーコンソール内でアプリケーション詳細を開き、Service & APIsをクリックする。そしてYour License Key for This Applicationと書かれたフィールドを見る。

Base64でエンコードされたGoogle Playによってい生成されたRSA公開鍵はバイナリーエンコードされたX.509 subjectPublicKeyInfo DER SEQUENCE形式だ。Google Playライセンスで使われているものと同じ公開鍵だ。

あなたのアプリが署名済みのレスポンスを受けたとき、あなたは署名を照合したRSAキーペアの公開鍵部分を使用することができる。署名照合を行うことで、あなたはレスポンスがいたずらによるものなのか、調整されたものなのかを見破ることができる。あなたはアプリ内に署名照合段階を実行することができる。しかし、もしあなたのアプリがセキュアなリモートサーバーに接続している場合、我々はそのサーバー上で署名照合を行うことを推奨する。

セキュリティと設計に関するベストプラクティスに関する情報がもっと知りたい場合はSecurity and Designを参照。






Implementing In-app Billing (IAB Version 3)

In-app Billing on Google Play provides a straightforward, simple interface for sending In-app Billing requests and managing In-app Billing transactions using Google Play. The information below covers the basics of how to make calls from your application to the In-app Billing service using the Version 3 API.
Note: To see a complete implementation and learn how to test your application, see the Selling In-app Products training class. The training class provides a complete sample In-app Billing application, including convenience classes to handle key tasks related to setting up your connection, sending billing requests and processing responses from Google Play, and managing background threading so that you can make In-app Billing calls from your main activity.
Before you start, be sure that you read the In-app Billing Overview to familiarize yourself with concepts that will make it easier for you to implement In-app Billing.
To implement In-app Billing in your application, you need to do the following:
  1. Add the In-app Billing library to your project.
  2. Update your AndroidManifest.xml file.
  3. Create a ServiceConnection and bind it to IInAppBillingService.
  4. Send In-app Billing requests from your application to IInAppBillingService.
  5. Handle In-app Billing responses from Google Play.

Adding the AIDL file to your project


IInAppBillingService.aidl is an Android Interface Definition Language (AIDL) file that defines the interface to the In-app Billing Version 3 service. You will use this interface to make billing requests by invoking IPC method calls.
To get the AIDL file:
  1. Open the Android SDK Manager.
  2. In the SDK Manager, expand the Extras section.
  3. Select Google Play Billing Library.
  4. Click Install packages to complete the download.
The IInAppBillingService.aidl file will be installed to <sdk>/extras/google/play_billing/.
To add the AIDL to your project:
  1. Copy the IInAppBillingService.aidl file to your Android project.
    • If you are using Eclipse:
      1. If you are starting from an existing Android project, open the project in Eclipse. If you are creating a new Android project from scratch, click File > New > Android Application Project, then follow the instructions in the New Android Application wizard to create a new project in your workspace.
      2. In the /src directory, click File > New > Package, then create a package named com.android.vending.billing.
      3. Copy the IInAppBillingService.aidl file from <sdk>/extras/google/play_billing/ and paste it into the src/com.android.vending.billing/ folder in your workspace.
    • If you are developing in a non-Eclipse environment: Create the following directory /src/com/android/vending/billing and copy the IInAppBillingService.aidl file into this directory. Put the AIDL file into your project and use the Ant tool to build your project so that the IInAppBillingService.java file gets generated.
  2. Build your application. You should see a generated file named IInAppBillingService.java in the /gen directory of your project.

Updating Your Application's Manifest


In-app billing relies on the Google Play application, which handles all communication between your application and the Google Play server. To use the Google Play application, your application must request the proper permission. You can do this by adding the com.android.vending.BILLING permission to your AndroidManifest.xml file. If your application does not declare the In-app Billing permission, but attempts to send billing requests, Google Play will refuse the requests and respond with an error.
To give your app the necessary permission, add this line in your Android.xml manifest file:
<uses-permission android:name="com.android.vending.BILLING" />

Creating a ServiceConnection


Your application must have a ServiceConnection to facilitate messaging between your application and Google Play. At a minimum, your application must do the following:
  • Bind to IInAppBillingService.
  • Send billing requests (as IPC method calls) to the Google Play application.
  • Handle the synchronous response messages that are returned with each billing request.

Binding to IInAppBillingService

To establish a connection with the In-app Billing service on Google Play, implement a ServiceConnection to bind your activity to IInAppBillingService. Override the onServiceDisconnected and onServiceConnected methods to get a reference to the IInAppBillingService instance after a connection has been established.
IInAppBillingService mService;
ServiceConnection mServiceConn = new ServiceConnection() {
   @Override
   public void onServiceDisconnected(ComponentName name) {
       mService = null;
   }

   @Override
   public void onServiceConnected(ComponentName name, 
      IBinder service) {
       mService = IInAppBillingService.Stub.asInterface(service);
   }
};
In your activity’s onCreate method, perform the binding by calling the bindService method. Pass the method an Intent that references the In-app Billing service and an instance of the ServiceConnection that you created.
@Override
public void onCreate(Bundle savedInstanceState) {    
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);        
    bindService(new 
        Intent("com.android.vending.billing.InAppBillingService.BIND"),
                mServiceConn, Context.BIND_AUTO_CREATE);
You can now use the mService reference to communicate with the Google Play service.
Important: Remember to unbind from the In-app Billing service when you are done with your Activity. If you don’t unbind, the open service connection could cause your device’s performance to degrade. This example shows how to perform the unbind operation on a service connection to In-app Billing called mServiceConn by overriding the activity’s onDestroy method.
@Override
public void onDestroy() {
    super.onDestroy();
    if (mServiceConn != null) {
        unbindService(mServiceConn);
    }   }
For a complete implementation of a service connection that binds to the IInAppBillingService, see the Selling In-app Products training class and associated sample.

Making In-app Billing Requests


Once your application is connected to Google Play, you can initiate purchase requests for in-app products. Google Play provides a checkout interface for users to enter their payment method, so your application does not need to handle payment transactions directly. When an item is purchased, Google Play recognizes that the user has ownership of that item and prevents the user from purchasing another item with the same product ID until it is consumed. You can control how the item is consumed in your application, and notify Google Play to make the item available for purchase again. You can also query Google Play to quickly retrieve the list of purchases that were made by the user. This is useful, for example, when you want to restore the user's purchases when your user launches your app.

Querying for Items Available for Purchase

In your application, you can query the item details from Google Play using the In-app Billing Version 3 API. To pass a request to the In-app Billing service, first create a Bundle that contains a String ArrayList of product IDs with key "ITEM_ID_LIST", where each string is a product ID for an purchasable item.
ArrayList skuList = new ArrayList();
skuList.add("premiumUpgrade");
skuList.add("gas");
Bundle querySkus = new Bundle();
querySkus.putStringArrayList(“ITEM_ID_LIST”, skuList);
To retrieve this information from Google Play, call the getSkuDetails method on the In-app Billing Version 3 API, and pass the method the In-app Billing API version (“3”), the package name of your calling app, the purchase type (“inapp”), and the Bundle that you created.
Bundle skuDetails = mService.getSkuDetails(3, 
   getPackageName(), "inapp", querySkus);
If the request is successful, the returned Bundlehas a response code of BILLING_RESPONSE_RESULT_OK (0).
Warning: Do not call the getSkuDetails method on the main thread. Calling this method triggers a network request which could block your main thread. Instead, create a separate thread and call the getSkuDetails method from inside that thread.
To see all the possible response codes from Google Play, see In-app Billing Reference.
The query results are stored in a String ArrayList with key DETAILS_LIST. The purchase information is stored in the String in JSON format. To see the types of product detail information that are returned, see In-app Billing Reference.
In this example, you are retrieving the prices for your in-app items from the skuDetails Bundle returned from the previous code snippet.
int response = skuDetails.getInt("RESPONSE_CODE");
if (response == 0) {
   ArrayList responseList 
      = skuDetails.getStringArrayList("DETAILS_LIST");
   
   for (String thisResponse : responseList) {
      JSONObject object = new JSONObject(thisResponse);
      String sku = object.getString("productId");
      String price = object.getString("price");
      if (sku.equals("premiumUpgrade")) mPremiumUpgradePrice = price;
      else if (sku.equals("gas")) mGasPrice = price;
   }
}

Purchasing an Item

To start a purchase request from your app, call the getBuyIntent method on the In-app Billing service. Pass in to the method the In-app Billing API version (“3”), the package name of your calling app, the product ID for the item to purchase, the purchase type (“inapp” or "subs"), and a developerPayload String. The developerPayload String is used to specify any additional arguments that you want Google Play to send back along with the purchase information.
Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(),
   sku, "inapp", "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
If the request is successful, the returned Bundle has a response code of BILLING_RESPONSE_RESULT_OK (0) and a PendingIntent that you can use to start the purchase flow. To see all the possible response codes from Google Play, see In-app Billing Reference. Next, extract a PendingIntent from the response Bundle with key BUY_INTENT.
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
To complete the purchase transaction, call the startIntentSenderForResult method and use the PendingIntent that you created. In this example, you are using an arbitrary value of 1001 for the request code.
startIntentSenderForResult(pendingIntent.getIntentSender(),
   1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0),
   Integer.valueOf(0));
Google Plays sends a response to your PendingIntent to the onActivityResult method of your application. The onActivityResult method will have a result code of Activity.RESULT_OK (1) or Activity.RESULT_CANCELED (0). To see the types of order information that is returned in the response Intent, see In-app Billing Reference.
The purchase data for the order is a String in JSON format that is mapped to the INAPP_PURCHASE_DATA key in the response Intent, for example:
'{ 
   "orderId":"12999763169054705758.1371079406387615", 
   "packageName":"com.example.app",
   "productId":"exampleSku",
   "purchaseTime":1345678900000,
   "purchaseState":0,
   "developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
   "purchaseToken":"rojeslcdyyiapnqcynkjyyjh"
 }'

Continuing from the previous example, you get the response code, purchase data, and signature from the response Intent.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
   if (requestCode == 1001) {           
      int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
      String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
      String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
        
      if (resultCode == RESULT_OK) {
         try {
            JSONObject jo = new JSONObject(purchaseData);
            String sku = jo.getString("productId");
            alert("You have bought the " + sku + ". Excellent choice, 
               adventurer!");
          }
          catch (JSONException e) {
             alert("Failed to parse purchase data.");
             e.printStackTrace();
          }
      }
   }
}
Security Recommendation: When you send a purchase request, create a String token that uniquely identifies this purchase request and include this token in the developerPayload.You can use a randomly generated string as the token. When you receive the purchase response from Google Play, make sure to check the returned data signature, the orderId, and the developerPayload String. For added security, you should perform the checking on your own secure server. Make sure to verify that the orderId is a unique value that you have not previously processed, and the developerPayload String matches the token that you sent previously with the purchase request.

Querying for Purchased Items

To retrieve information about purchases made by a user from your app, call the getPurchases method on the In-app Billing Version 3 service. Pass in to the method the In-app Billing API version (“3”), the package name of your calling app, and the purchase type (“inapp” or "subs").
Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
The Google Play service returns only the purchases made by the user account that is currently logged in to the device. If the request is successful, the returned Bundle has a response code of 0. The response Bundle also contains a list of the product IDs, a list of the order details for each purchase, and the signatures for each purchase.
To improve performance, the In-app Billing service returns only up to 700 products that are owned by the user when getPurchase is first called. If the user owns a large number of products, Google Play includes a String token mapped to the key INAPP_CONTINUATION_TOKEN in the response Bundle to indicate that more products can be retrieved. Your application can then make a subsequent getPurchases call, and pass in this token as an argument. Google Play continues to return a continuation token in the response Bundle until all products that are owned by the user has been sent to your app.
For more information about the data returned by getPurchases, see In-app Billing Reference. The following example shows how you can retrieve this data from the response.
int response = ownedItems.getInt("RESPONSE_CODE");
if (response == 0) {
   ArrayList ownedSkus = 
      ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
   ArrayList purchaseDataList = 
      ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
   ArrayList signatureList = 
      ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE");
   String continuationToken = 
      ownedItems.getString("INAPP_CONTINUATION_TOKEN");
   
   for (int i = 0; i < purchaseDataList.size(); ++i) {
      String purchaseData = purchaseDataList.get(i);
      String signature = signatureList.get(i);
      String sku = ownedSkus.get(i);
  
      // do something with this purchase information
      // e.g. display the updated list of products owned by user
   } 

   // if continuationToken != null, call getPurchases again 
   // and pass in the token to retrieve more items
}

Consuming a Purchase

You can use the In-app Billing Version 3 API to track the ownership of purchased in-app products in Google Play. Once an in-app product is purchased, it is considered to be "owned" and cannot be purchased from Google Play. You must send a consumption request for the in-app product before Google Play makes it available for purchase again.
Important: Managed in-app products are consumable, but subscriptions are not.
How you use the consumption mechanism in your app is up to you. Typically, you would implement consumption for in-app products with temporary benefits that users may want to purchase multiple times (for example, in-game currency or equipment). You would typically not want to implement consumption for in-app products that are purchased once and provide a permanent effect (for example, a premium upgrade).
To record a purchase consumption, send the consumePurchase method to the In-app Billing service and pass in the purchaseToken String value that identifies the purchase to be removed. The purchaseToken is part of the data returned in the INAPP_PURCHASE_DATA String by the Google Play service following a successful purchase request. In this example, you are recording the consumption of a product that is identified with the purchaseToken in the token variable.
int response = mService.consumePurchase(3, getPackageName(), token);
Warning: Do not call the consumePurchase method on the main thread. Calling this method triggers a network request which could block your main thread. Instead, create a separate thread and call the consumePurchase method from inside that thread.
It's your responsibility to control and track how the in-app product is provisioned to the user. For example, if the user purchased in-game currency, you should update the player's inventory with the amount of currency purchased.
Security Recommendation: You must send a consumption request before provisioning the benefit of the consumable in-app purchase to the user. Make sure that you have received a successful consumption response from Google Play before you provision the item.

Implementing Subscriptions

Launching a purchase flow for a subscription is similar to launching the purchase flow for a product, with the exception that the product type must be set to "subs". The purchase result is delivered to your Activity's onActivityResult method, exactly as in the case of in-app products.
Bundle bundle = mService.getBuyIntent(3, "com.example.myapp",
   MY_SKU, "subs", developerPayload);
PendingIntent pendingIntent = bundle.getParcelable(RESPONSE_BUY_INTENT);
if (bundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {
   // Start purchase flow (this brings up the Google Play UI).
   // Result will be delivered through onActivityResult().
   startIntentSenderForResult(pendingIntent, RC_BUY, new Intent(),
       Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
}
To query for active subscriptions, use the getPurchases method, again with the product type parameter set to "subs".
Bundle activeSubs = mService.getPurchases(3, "com.example.myapp",
                   "subs", continueToken);
The call returns a Bundle with all the active subscriptions owned by the user. Once a subscription expires without renewal, it will no longer appear in the returned Bundle.

Securing Your Application


To help ensure the integrity of the transaction information that is sent to your application, Google Play signs the JSON string that contains the response data for a purchase order. Google Play uses the private key that is associated with your application in the Developer Console to create this signature. The Developer Console generates an RSA key pair for each application.

Note:To find the public key portion of this key pair, open your application's details in the Developer Console, then click on Services & APIs, and look at the field titled Your License Key for This Application.
The Base64-encoded RSA public key generated by Google Play is in binary encoded, X.509 subjectPublicKeyInfo DER SEQUENCE format. It is the same public key that is used with Google Play licensing.
When your application receives this signed response you can use the public key portion of your RSA key pair to verify the signature. By performing signature verification you can detect responses that have been tampered with or that have been spoofed. You can perform this signature verification step in your application; however, if your application connects to a secure remote server then we recommend that you perform the signature verification on that server.
For more information about best practices for security and design, see Security and Design.