Questアプリ内購入のサーバー実装でつまづいたところ

こんにちは!クラスター株式会社でソフトウェアエンジニアをしているえんじです。

クラスター株式会社には昨年10月頃に入社し、前職ではモバイルアプリのサーバサイドエンジニアとしてAPIの開発や社内ツールの開発などを行っていました。
転職後の初めてのepic ownerとしてQuestアプリ内でアプリ内購入(以後IAP)の実装を任せていただいたのですが、その際につまづいた箇所を紹介していければと思います。

QuestでのIAPについて

clusterでは「クラスターコイン」を購入することで、バーチャルイベント上での投げ銭や、clusterで活動するクリエイターたちが制作した、cluster内でワールドをつくる機能「ワールドクラフト」で使えるアイテムを購入したり、自分のアバターにつけるアクセサリーを入手することができます。

www.youtube.com

クラスターコイン はQuest上で 購入することが可能で、その際にMeta社のOculusプラットフォームが提供しているIAPの仕組みを利用しています。
ユーザーがアプリ上で決済を行い、サーバー上でクラスターコインが反映されるまでのざっくりとした流れを図化すると以下のようになります。

このうち、今回はclusterのサーバーとOculusプラットフォーム間で通信を行っている部分の実装でつまづいたポイントを紹介していきます。
IAP自体の詳細な話は以下の公式ドキュメントに記載されていますので、そちらを御覧ください。
アプリ内購入サーバー間API

以降はサーバーがやり取りしている箇所をServer to serverの略でS2S、Oculusプラットフォーム側のAPIをS2S APIと呼称します。

ポイント1 : S2S APIのデータ利用申請の審査時間にばらつきがある

まず、S2S APIを利用するためには、 データの使用状況(DUC)の確認の実施 を行う必要があります。DUCの提出はStore/AppLabの公開状況にかかわらず実施する必要があり、また毎年更新が必要です。
有効期限は「DUC審査通過から1年」かつ期間中に再提出が可能なので、余裕を持って更新を行うようにしましょう。

なお、DUCの審査終了までの所要時間にはばらつきがあります。
実際に実装前の調査で利用した検証用のアプリの場合は申請と同時に利用許可が出たのですが、別のアプリでは審査に2~3週間かかった、ということがありました。
どういった要因で所要時間が変わるのかについてはMetaのみぞ知るというところなので、スケジュール的な制約がある場合や環境ごとに申請を行う必要がある場合は、十分な余裕を持った状態で申請を行うことをおすすめします。

ポイント2 : S2S APIを叩く時トークンの取り扱い

S2S API経由で特定ユーザーに対して操作をする場合、ユーザーを特定するためにトークンを渡す必要があります。
この情報を渡す方法は2種類用意されています。これらは公式ドキュメントのサーバー間APIの基本 に記載はされているのですが、公式ドキュメントのサンプルとして記載されているトークンの形式が実情と異なっていてつまづきました。

アプリ認証情報

公式ドキュメントの こちらに記載されている方法です。
ダッシュボードから取得してきたアプリ認証情報と、クライアント側で取得したMetaプラットフォーム上のユーザーIDを一緒に渡す方法になります。
公式ドキュメント の例に沿って、「consume_entitlement」のAPIを叩くサンプルを記載すると以下のとおりです。

$ curl -d "access_token=OC|$APP_ID|$APP_SECRET" -d "sku=$SKU" -d "user_id=$USER_ID" https://graph.oculus.com/$APP_ID/consume_entitlement

ユーザーアクセストークン

公式ドキュメントの こちらに記載されている方法です。こちらはシンプルにクライアント側で取得したユーザーアクセストークンのみを渡します。
ドキュメント上でユーザーアクセストークンは OCxxxx と記載されていますが、実際は FLRxxxx といった別のprefixのものが飛んでくる場合もあるので、バリデーションなどを仕込む場合は注意が必要です。
こちらも公式ドキュメント の例に沿って、「consume_entitlement」のAPIを叩くサンプルを記載すると以下のとおりです。

$ curl -d "access_token=$USER_ACCESS_TOKEN" -d "sku=$SKU" https://graph.oculus.com/$APP_ID/consume_entitlement

ポイント3 : Organizationに所属したユーザーが、すべてのIAPアイテムを1円で購入できてしまう。

アプリ配信元のOrganizationに所属したユーザーは、権限設定に関係なくすべてのIAPアイテムを元の金額に関わらず1円で購入できる仕様となっています。
この仕様をOculusプラットフォーム側の設定でOFFにする方法は現状ありませんでした。

なのでこの挙動を許容できない場合はOrganizationに所属したユーザーがIAPアイテムを購入できなくなる対策を入れる必要があります。
弊社においては開発メンバーが意図せず1円でIAPアイテムを購入できてしまう状態を防ぐため対策を導入することとしました。

弊社では、アプリ配信元のOrganization内でユーザーを一意に識別するIDである OrgScopedIDを用いて以下の仕組みでIAPアイテムの購入を制限しています。

  1. Organizationにユーザーを追加する際、社内アプリ経由で該当ユーザーのOrgScopedIDを取得する
  2. OrgScopedIDをDBに登録する
  3. 該当するOrgScopedIDのユーザーが購入可能なIAPアイテム一覧を取得しようとした際、購入可能なアイテムを返さないようにする

おわりに

初めてOculusプラットフォームの機能を利用した開発を行ったのですが、Oculusプラットフォームを用いた開発は他のモバイルプラットフォームと比較してインターネット上に前例が公開されておらず、調査しながらベストな方法を模索する経験ができてよかったです。
今後実装する人が同じように苦戦しないための指標になればと思い、今回つまづいた箇所をブログとして公開させていただきました。

また、本記事のようなOculusプラットフォームの機能を利用した開発に興味がある方、クラスター社で一緒に働きませんか?
まずはカジュアル面談だけでも是非ご検討ください!

recruit.cluster.mu