• Like
  • Save
やろうぜ!アプリ内課金
Upcoming SlideShare
Loading in...5
×

やろうぜ!アプリ内課金

  • 11,970 views
Uploaded on

 

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
11,970
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
0
Comments
0
Likes
27

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Transcript

  • 1. やろうぜ!アプリ内課金 日本Androidの会 関西支部 ThreeColors 赤井 忠昭
  • 2. 自己紹介赤井 忠昭元Web系 デベロッパー(業界歴約10年)去年よりフリーランスプログラマTwitterアカウント:@akai_tAndroid 大好き
  • 3. Androidで稼ぐためには その1:広告収入 その2:有料アプリ その3:アプリ内課金 その4:月額課金 その5:その他
  • 4. 広告収入アプリ内に広告をはりつけるとユーザがその広告に興味を持ってクリッククリックした場合に収入がはいってくる金額は広告配信会社によって異なる1クリックあたりだいたい0.8円∼10円前後Admobなどが有名広告の表示数が多いとそれなりにクリックされる?
  • 5. 有料アプリアプリ自体に金額を設定する最低99円∼一回きりの課金Androidでは有料アプリは売れない傾向あり
  • 6. アプリ内課金アプリ内で課金する課金の方法には1回限りと何回でもできるパターンがあり最低99円∼アプリに組み込むのは多少面倒
  • 7. 月額課金毎月課金するモデル最低99円∼課金が継続されるときにはメールが送信される残念ながら今のところキャリア決済では使えない
  • 8. その他ユーザからはお金を貰わずに提携した企業からお金をもらうパターン等提携先を探さないといけないので敷居が高い自社ブランドの宣伝アプリとして売上は自社ブランド製品とするということもあるその他思いもつかない方法があるに違いない
  • 9. なぜアプリ内課金?広告はクリック率が低い+単価も低い有料アプリは売れない月額課金はアプリ内課金とほぼ同じ現在売上げランキングの上位はアプリ内課金で売上を上げているアプリが多いGoogle Play全体の売上の50%以上がアプリ内課金
  • 10. アプリ内課金を使うパターン ゲームアプリ内のものを買うパターン 課金した場合に広告を外すパターン 試用期限を指定して期限が過ぎた後も使用 する場合は課金するパターン あらかじめ機能を制限しておいて課金した 場合のみすべての機能を使えるようにする パターン
  • 11. アプリ内課金の仕組み アプリからPlay Storeアプリに対して課金要求 Play StoreアプリがMarket Serverと通信して課金 処理を実行 実行した結果をアプリに返す アプリで結果を受け取った通知をPlay Storeに 返す つまりPlay Storeが載っていない端末では使用 できない
  • 12. アプリ内課金の簡単なフロー Activityから課金用Serviceを開始してService内で 課金リクエストをMarket Serviceになげる 画面上ではPlay Storeの課金画面が表示 ユーザがアプリ内アイテムを購入 画面はアプリに戻る(購入は未完了) Google のMarket Serverが購入処理を実行(アプリ とは非同期で実行される) 購入情報変更通知がBroadCastで送信される アプリ内のBroadCastReceiverで変更通知を受信
  • 13. アプリ内課金の簡単なフロー 購入状態詳細内容をMarket Serviceに問い合わ せる 購入状態がJSON形式でBroadCastで送信される アプリで購入完了状態にする アプリは詳細内容を受けたという通知を Market Serviceに送信する
  • 14. アプリ内課金の簡単なフロー 課金リクエスト 同期レスポンス 購入画面表示指示 購入情報変更通知 アプリ 購入状態詳細内容リクエスト Marketアプリ 同期レスポンス 購入状態詳細内容送信 購入状態詳細内容受信確認 同期レスポンス
  • 15. アプリからのリクエスト 課金リクエスト 同期レスポンス 購入画面表示指示 購入情報変更通知 アプリ 購入状態詳細内容リクエスト Marketアプリ 同期レスポンス 購入状態詳細内容送信 購入状態詳細内容受信確認 同期レスポンス
  • 16. アプリからのリクエスト 各リクエストに送信するBundleのキー BILLING_REQUEST API_VERSION PACKAGE_NAME ITEM_ID NONCE NOTIFY_IDS DEVELOPER_PAYLOAD
  • 17. アプリからのリクエスト BILLING_REQUEST 必須項目 課金リクエストのタイプ 詳しくは後述 API_VERSION 必須項目 現在の最新バージョンは2を指定 バージョン2から月額課金が使用可能
  • 18. アプリからのリクエスト PACKAGE_NAME 必須項目 リクエストするアプリのパッケージ名 ITEM_ID 購入リクエスト(REQUEST_PURCHASE)の場合は 必須 購入するITEMのプロダクトID
  • 19. アプリからのリクエスト NONCE 購入状態詳細取得リクエスト (GET_PURCHASE_INFORMATION)とトランザク ション回復リクエスト (RESTORE_TRANSACTIONS)で必須 1回だけ利用できる値 Marketアプリからのトランザクションレス ポンスの整合性の検証で使用
  • 20. アプリからのリクエスト NOTIFY_IDS 購入状態詳細取得リクエスト (GET_PURCHASE_INFORMATION)とトランザク ション回復リクエスト (RESTORE_TRANSACTIONS)で必須 通知識別子の配列 DEVELOPER_PAYLOAD 開発者が自由につけれる値 結果に指定した値が返ってくるので開発 者が自由に使うことができる
  • 21. アプリからのリクエスト BILLING_REQUESTで指定するキー CHECK_BILLING_SUPPORTED REQUEST_PURCHASE GET_PURCHASE_INFORMATION CONFIRM_NOTIFICATIONS RESTORE_TRANSACTIONS
  • 22. アプリからのリクエスト CHECK_BILLING_SUPPORTED Marketアプリがアプリ内課金をサポートし ているかどうかを確認するリクエスト アプリ内課金はPlay Storeのversion 2.3.4 以上 月額課金はPlay Storeのversion 3.5 以上で対応 REQUEST_PURCHASE アプリ内課金の実施を依頼するリクエス ト
  • 23. アプリからのリクエスト GET_PURCHASE_INFORMATION 購入情報の変化の詳細を取得するリクエ スト 購入情報の変化があった時にリクエスト して内容の詳細を取得する CONFIRM_NOTIFICATIONS 購入情報の変化を取得できたことを通知 するリクエスト 購入情報詳細取得後は必ず行わなければ いけない
  • 24. アプリからのリクエスト RESTORE_TRANSACTIONS すでに購入されている情報を取得するた めのリクエスト ユーザごとに管理された商品のみ適用さ れる 現在の状況を確認するためにリクエスト するもので通常アプリがインストールさ れた時にすでに購入済みかどうかを チェックする場合に使用する
  • 25. アプリからのリクエストアプリ内課金サポート確認 CHECK_BILLING_SUPPORTED アプリ 同期レスポンス Marketアプリ課金リクエスト REQUEST_PURCHASE 同期レスポンス 購入画面表示指示 購入情報変更通知 アプリ GET_PURCHASE_INFORMATION Marketアプリ 同期レスポンス 購入状態詳細内容送信 CONFIRM_NOTIFICATIONS 同期レスポンス
  • 26. アプリからのリクエストトランザクション回復 RESTORE_TRANSACTIONS 同期レスポンス アプリ レスポンスコード送信 Marketアプリ 購入状態詳細内容送信
  • 27. 同期レスポンスアプリ内課金サポート確認 CHECK_BILLING_SUPPORTED アプリ 同期レスポンス Marketアプリ課金リクエスト REQUEST_PURCHASE 同期レスポンス 購入画面表示指示 購入情報変更通知 アプリ GET_PURCHASE_INFORMATION Marketアプリ 同期レスポンス 購入状態詳細内容送信 CONFIRM_NOTIFICATIONS 同期レスポンス
  • 28. 同期レスポンストランザクション回復 RESTORE_TRANSACTIONS 同期レスポンス アプリ レスポンスコード送信 Marketアプリ 購入状態詳細内容送信 すべてのリクエストには同期レスポンスが Bundleで返ってくる
  • 29. 同期レスポンス 返される可能性のあるレスポンス リクエストタイプ Bundleで返されるキー コード RESULT_OK, RESULT_BILLING_UNAVAILABLE,CHECK_BILLING_SUPPORTED RESPONSE_CODE RESULT_ERROR, RESULT_DEVELOPER_ERROR RESPONSE_CODE, PURCHASE_INTENT, RESULT_OK, RESULT_ERROR,REQUEST_PURCHASE REQUEST_ID RESULT_DEVELOPER_ERROR RESULT_OK, RESULT_ERROR,GET_PURCHASE_INFORMATION RESPONSE_CODE, REQUEST_ID RESULT_DEVELOPER_ERROR RESULT_OK, RESULT_ERROR,CONFIRM_NOTIFICATIONS RESPONSE_CODE, REQUEST_ID RESULT_DEVELOPER_ERROR RESULT_OK, RESULT_ERROR,RESTORE_TRANSACTIONS RESPONSE_CODE, REQUEST_ID RESULT_DEVELOPER_ERROR
  • 30. 返されるキー RESPONSE_CODE リクエストに関するステータス情報とエ ラー情報 PURCHASE_INTENT 購入画面のActivityを起動するために必要 とするPendingIntent REQUEST_ID 各リクエストの識別子 非同期応答を一致させるために使用
  • 31. レスポンスコード RESULT_OK 正常処理 RESULT_BILLING_UNAVAILABLE API_VERSIONが対応していない場合やアプリ 内課金が使用できない国で使用する場合 に返ってくる RESULT_ERROR 予期せぬサーバエラーなどで返ってくる
  • 32. レスポンスコード RESULT_DEVELOPER_ERROR デベロッパー側で何らかがおかしい場合 に返ってくる 考えられる原因はいくつかある Manifestファイルの権限付与がない 必須項目の値が入ってない 認識されないリクエストタイプ 月額課金済みITEMに再び月額課金リク エスト
  • 33. 同期レスポンスアプリ内課金サポート確認 CHECK_BILLING_SUPPORTED アプリ Bundle(RESPONSE_CODE) Marketアプリ課金リクエスト REQUEST_PURCHASE Bundle(RESPONSE_CODE, PURCHASE_INTENT, REQUEST_ID) 購入画面表示指示 購入情報変更通知 アプリ GET_PURCHASE_INFORMATION Marketアプリ Bundle(RESPONSE_CODE, REQUEST_ID) 購入状態詳細内容送信 CONFIRM_NOTIFICATIONS Bundle(RESPONSE_CODE, REQUEST_ID)
  • 34. 同期レスポンストランザクション回復 RESTORE_TRANSACTIONS Bundle(RESPONSE_CODE, REQUEST_ID) アプリ レスポンスコード送信 Marketアプリ 購入状態詳細内容送信
  • 35. 非同期通知課金リクエスト REQUEST_PURCHASE Bundle(RESPONSE_CODE, PURCHASE_INTENT, REQUEST_ID) 購入画面表示指示 購入情報変更通知 アプリ GET_PURCHASE_INFORMATION Marketアプリ Bundle(RESPONSE_CODE, REQUEST_ID) 購入状態詳細内容送信 CONFIRM_NOTIFICATIONS Bundle(RESPONSE_CODE, REQUEST_ID)
  • 36. 非同期通知トランザクション回復 RESTORE_TRANSACTIONS Bundle(RESPONSE_CODE, REQUEST_ID) アプリ レスポンスコード送信 Marketアプリ 購入状態詳細内容送信
  • 37. 非同期レスポンスコード すべてのリクエストには非同期でレスポン スコードが返ってくる レスポンスコードは同期レスポンス以外に 下記のものがある RESULT_USER_CANCELED RESULT_SERVICE_UNAVAILABLE RESULT_ITEM_UNAVAILABLE
  • 38. 非同期レスポンスコード RESULT_USER_CANCELED 購入画面で購入せずにBackボタンを押下 した時にくるコード 購入はされていない RESULT_SERVICE_UNAVAILABLE ネットワーク接続ができてない場合に 返ってくるコード RESULT_ITEM_UNAVAILABLE リクエストしたプロダクトIDがない場合 やまだ後悔されてない場合に返ってくる
  • 39. 非同期通知 各リクエストで送られてくる非同期通知 (BroadCast)は以下のとおり com.android.vending.billing.RESPONSE_CODE com.android.vending.billing.IN_APP_NOTIFY com.android.vending.billing.PURCHASE_STATE_CHANGED
  • 40. 非同期通知 com.android.vending.billing.RESPONSE_CODE 非同期通知を行う com.android.vending.billing.IN_APP_NOTIFY 購入情報変更通知を行う com.android.vending.billing.PURCHASE_STATE_CHANGED 購入情報の詳細情報通知を行う
  • 41. 非同期通知課金リクエスト REQUEST_PURCHASE Bundle(RESPONSE_CODE, PURCHASE_INTENT, REQUEST_ID) 購入画面表示指示 IN_APP_NOTIFY アプリ GET_PURCHASE_INFORMATION Marketアプリ Bundle(RESPONSE_CODE, REQUEST_ID) PURCHASE_STATE_CHANGED CONFIRM_NOTIFICATIONS Bundle(RESPONSE_CODE, REQUEST_ID)
  • 42. 非同期通知トランザクション回復 RESTORE_TRANSACTIONS Bundle(RESPONSE_CODE, REQUEST_ID) アプリ RESPONSE_CODE Marketアプリ PURCHASE_STATE_CHANGED
  • 43. PURCHASE_STATE_CHANGEDの値 PURCHASE_STATE_CHANGEDで下記の情報がJSONで 返ってくる nonce notificationId orderId packageName productId purchaseTime purchaseToken purchaseState developerPayload
  • 44. PURCHASE_STATE_CHANGEDの値 nonce GET_PURCHASE_INFORMATION等で指定したnonce の値が入っている notificationId IN_APP_NOTIFYと共にBroadCastで送信されて くるMarket Serverで一意な値 orderId トランザクション用の一意な値 Google Walletの注文IDに対応
  • 45. PURCHASE_STATE_CHANGEDの値 packageName 購入されたアプリのパッケージ名 productId itemのプロダクトID 自分で指定したプロダクトIDが入る purchaseTime プロダクトが購入された日時 1970年1月1日からのミリ秒単位の経過時 間
  • 46. PURCHASE_STATE_CHANGEDの値 purchaseToken ユーザ毎に管理された定期購入するアイ テムに一意に識別に与えられる このキーを用いて定期購入の有効性 チェックを行うことができる purchaseState 注文の購入状態 可能な値は 0 ( 購入済み ) 、1 ( キャンセ ル ) 、2 ( 払い戻し ) 、3(破棄)
  • 47. PURCHASE_STATE_CHANGEDの値 developerPayload 開発者が指定した値 REQUEST_PURCHASEで指定した値がそのまま 返ってくる
  • 48. キャンセルについて キャンセルはgoogle checkoutの画面より行う キャンセルされるとIN_APP_NOTIFYの通知が くるのであとは購入と同じフロー 月額課金のキャンセルについて アプリからはキャンセルできない Market アプリのアプリ画面でキャンセル ボタンを置く場合はMy App画面を開くIntent でキャンセル画面に誘導 キャンセル後も有効期限内なら使用可能
  • 49. 定期購読itemについて 定期購読したitemは継続中であれば自動的 に毎月引き落とされる 自動継続時は継続購入完了メールがユーザ に届く 現在の継続状態や有効期限や継続キャンセ ル処理はアプリ単独ではできない プログラムで行いたい場合はリモートサー バよりGoogle Play Android Developer APIを用いて行 う
  • 50. アプリ内課金のサンプルAndroid SDK Managerからダウンロードできるダウンロードしたサンプルは/SDK/extras/google/market_billing/に保存されている
  • 51. アプリ内課金のサンプル ダウンロードするとSecurity.javaのString base64EncodedPublicKey = "your public key here"; を書 き換える サンプルアプリのパッケージ名を変更する サンプルアプリをリリースバージョンで署 名してPlay Storeに非公開でアップロードする アップロードしたサンプルアプリのプロダ クトIDを公開モードで登録する サンプルではsword_001(管理されるアイテ ム),potion_001(管理されないアイテム)
  • 52. アプリ内課金のサンプル 月額課金ではsubscription_monthly(月額)、 subscription_yearly(年額) テストするアカウントを登録する(ただ し、アップロードしたアカウントとは別の ものとする) テストアカウントをプライマリアカウント とした端末でリリースバージョンのapkをイ ンストールして実行する
  • 53. アプリ内課金のサンプル その他詳しい内容についてはWeb上で色々と 解説がのってるのでそちらを参考に サンプルアプリを解析すると非常に仕組み がわかりやすい 解析する上で注意点があり
  • 54. サンプルアプリの注意点 プロダクトは早めに登録しないと公開まで1 時間ほどかかるのですぐに確認できない BillingService.javaのhandleCommandメソッドで CONFIRM_NOTIFICATIONSを実行する場所がある が、そこは通らない。 CONFIRM_NOTIFICATIONSはPURCHASE_STATE_CHANGEDの 処理が終わった後に実行する 月額課金の指示は一度実行するとキャンセ ルしても1ヶ月間は使用できなくなるので LOGなどを確認する場合は先に入れておく
  • 55. サンプルアプリの注意点 アプリ内課金の仕組みは独自サーバがなく ても使用可能なように設計されているが、 セキュリティ上独自サーバを用意するべき サンプルアプリをそのまま使うのはセキュ リティ上の観点から推奨されてない サンプルソースは仕組みを理解するために だけに使用すること
  • 56. セキュリティについて 署名認証はアプリ内で行わずにリモート サーバで行うようにするべき アプリ内課金で販売するコンテンツはapk ファイルに詰めずにサーバ上で配布する コンテンツをSDカード等に保存する場合は 暗号化を行う ソースコードはProguardなどを用いて難読化 する アプリ内課金のコードは他のメソッドにイ ンライン化する
  • 57. セキュリティについて 文字列は定数で作るのではなくその都度生 成する メソッドの呼び出しにJavaのリフレクショ ンを使用する サンプルコードは公開されている為、その まま使用すると比較的簡単にリバースエン ジニアリングされるので必ず変更する nonce(使い捨て乱数)は予測不能なものを 使用し、使い回しはしない
  • 58. セキュリティについて nonceの認証をサーバで行う場合はサーバ上 でnonceを生成すること ロックされていないコンテンツは廃止でき る仕組みを導入する Marketの公開キーはそのまま埋め込まずに実 行時にバラバラにしたものを文字列にした り、ビット操作をするなどして実際のキー を隠しておくこと
  • 59. In−app Billing Ver1からVer2へ Web上にあるドキュメントはVer1のものが多 い Ver2になって(Subscriptionが追加されて)何が変 わったか? 各リクエストに送信するAPI_VERSIONが2に 変更 PURCHASE_STATE_CHANGEDの戻り値に purchaseTokenが追加 PURCHASE_STATE_CHANGEDのpurchaseStateに3(破 棄)が追加
  • 60. アプリ内課金の注意点規約がすべてなのでよく読むこと購入したアプリ情報がこないことがあるのはアプリ側の対策が不十分な事が多いPURCHASE_STATE_CHANGEDが来た後はCONFIRM_NOTIFICATIONSを確実に送ることCONFIRM_NOTIFICATIONSが来るまでPURCHASE_STATE_CHANGEDが再送され続けるActivityがなくても動くように一旦受信したらそのデータを失われないように工夫する(一旦ファイルに書き込むなど)
  • 61. アプリ内課金の注意点アプリ内課金はキャンセルが多い場合あり キャリア決済の月額上限オーバー 「購入に失敗しました」で再挑戦チャージバックの件数はできるだけ減らす チャージバックが多いとクレジットカー ド会社からブラック認定?される エンドユーザからのクレーム・返金対応 は放置せずに確実に対応すること
  • 62. まとめお金を扱うのでセキュリティ対応は必須アプリ単体でも使用可能だがリモートサーバは必須と思ったほうがよいアプリ内課金はかなり面倒でも、お金を稼ぐなら必須?なのでぜひともマスターするべき
  • 63. ご清聴ありがとうございました