ペイステーションとFirebase認証の組み合わせ使用について
Firebaseを使用してアプリケーションにユーザー認証を実装済みの場合、Firebase側で決済トークンを生成し、アプリケーションのクライアント側に渡して決済UIを開くことができます。
この統合オプションを使用すると、購入代金を支払うユーザーの国と通貨を決定するロジックを独自に実装する必要があります。
統合フロー:
- パブリッシャーアカウントに新規登録して、新しいプロジェクトを作成します。今後の手順で作成したプロジェクトのIDが必要です。
- カタログをセットアップします:
- エクソーラ側のアイテムカタログを作成します。アイテムを手動で追加するか、Google PlayまたはPlayFabからインポートすることができます。
Store ライブラリを使用して、アプリケーションのクライアント側でカタログを取得して表示する機能を実装します。
- アイテム購入をセットアップします:
- アプリケーションのクライアント側で、FirebaseのCloud Functionsを使って、ユーザーとアイテムのデータを含む注文を作成します。
Payments ライブラリを使用して、アプリケーションのクライアント側で決済UIを開くように実装します。
統合を完了し、実際の支払いを受け付けるようにするには、エクソーラとライセンス契約を結ぶ必要があります。
ライセンス契約はいつでも統合のどのステップでも署名できますが、審査プロセスには最大で3営業日かかる可能性があることを覚えておいてください。
ペイステーションとFirebase認証の組み合わせ使用例として、サンプルウェブアプリケーションを使用してください。サンプルウェブアプリケーションのソースコードはGitHubで利用可能です。
プロジェクトを作成する
パブリッシャーアカウントの新規登録
パブリッシャーアカウントは、エクソーラの機能を構成し、アナリティクスや取引を処理するための主要なツールです。
登録時に指定された会社とアプリケーションに関するデータは、エクソーラとのライセンス契約のドラフトを作成し、あなたに適したソリューションを提案するために使用されます。データは後で変更することができますが、新規登録時に正しいデータを提供することで、ライセンス契約締結までのプロセスが迅速化されます。
新規登録するには、パブリッシャーアカウントにアクセスし、アカウントを作成してください。
パブリッシャーアカウントのパスワードはラテン文字、数字、特殊文字で構成でき、少なくとも以下を含む必要があります:
- 8文字以上
- 1桁
- 大文字1つ
- 小文字1つ
パスワードのセキュリティを確保するために、以下をことを推奨します:
- 少なくとも90日に1回はパスワードを変更する
- アカウントの過去4回のパスワードと一致しない新しいパスワードを使用する
- 他の場所で使用されているパスワードと一致しない固有のパスワードを使用する
- 簡単にアクセスできる場所にパスワードを保存しない
- パスワードマネージャーを使用してパスワードを保存する
パブリッシャーアカウントでは2要素認証が使用され、認証を試行するたびに確認コードが送信されます。
パブリッシャーアカウントでのプロジェクト作成
複数のアプリケーションを所有している場合は、それぞれのアプリケーションに対して個別のプロジェクトを作成することをお勧めします。プロジェクト作成時に指定したデータに基づいて、エクソーラはあなたに適したソリューションを提案します。
新たしいプロジェクトを作成するには:
- パブリッシャーアカウントを開きます。
- サイドメニューで、「プロジェクトの作成」をクリックします。

- プロジェクト名を英語で入力してください(必須)。
- ゲームのリリースプラットフォームを1つまたは複数選択します(必須)。
- ゲームへのリンクを追加します。ゲームが独自のサイトを持っていない場合は、メインサイトまたはゲームがリストされているセクションへのリンクを提供してください(必須)。
- ゲームエンジンを選択します。
- 使用している、または使用する予定の収益化オプションを選択します。
- ゲームがすでにリリースされているかどうかを指定します。ゲームがまだリリースされていない場合は、予定公開日を指定します。
- 「プロジェクトを作成する」をクリックします。おすすめのエクソーラ製品のページが表示されます。
統合プロセスでは、パブリッシャーアカウントでプロジェクト名の横に表示されているプロジェクトIDを入力する必要があります。

カタログのセットアップ
パブリッシャーアカウントでのアイテム作成
エクソーラ側でカタログを作成する必要があります。アイテムを手動で追加するか、Google PlayまたはPlayFabからインポートすることができます。Google Playからインポートする場合、一度に最大100個のアイテムをインポートできます。
これらの説明は、仮想アイテムの基本設定手順を提供します。後で、カタログに他のアイテム(仮想通貨、バンドル、ゲームキー)を追加したり、アイテムグループを作成したり、プロモーションキャンペーンや地域価格などを設定したりすることができます。
基本設定の仮想アイテムをカタログに追加するには:
- パブリッシャーアカウントでプロジェクトを開きます。
- サイドメニューの「ストア」をクリックします。
- 「仮想アイテム」ペインで、「接続」をクリックします。
- ドロップダウンメニューで、「アイテムを作成する」を選択します。
- 以下のフィールドでアイテムの基本設定を行います:
- イメージ(任意)
- SKU(アイテムの一意のID)
- アイテム名
- 説明(任意)
- アイテム価格を指定します:
- 「実際通貨での価格」のトグルを「オン」に設定します。
- 「デフォルト通貨」フィールドで通貨を変更し(任意)、アイテム価格を指定します。
- 「デフォルト通貨」フィールドで通貨を変更した場合は、「実際通貨での価格」フィールドで同じ通貨を選択します。
- アイテムのステータスを「利用可能」に変更します。
- 「アイテムを作成」をクリックします。
アプリケーションのクライアント側にカタログの表示
Store ライブラリをプロジェクトに追加します。これを行うには、build.gradle
を開き、依存関係セクションに次の行を追加します:
1implementation("com.xsolla.android:store:latest.release")
- アプリケーションのクライアント側で、製品カタログを表示するUIを追加します。
- エクソーラサーバーからのアイテムカタログのリクエストを実装します。
XStore.getVirtualItems
メソッドを使用して仮想アイテムのリストを取得します。他の例(サンプルアプリケーションの
- kotlin
1package com.xsolla.androidsample
2
3import androidx.appcompat.app.AppCompatActivity
4import android.os.Bundle
5import android.widget.Toast
6import androidx.recyclerview.widget.LinearLayoutManager
7import androidx.recyclerview.widget.RecyclerView
8import com.xsolla.android.store.XStore
9import com.xsolla.android.store.callbacks.GetVirtualItemsCallback
10import com.xsolla.android.store.entity.response.items.VirtualItemsResponse
11import com.xsolla.androidsample.adapter.BuyItemAdapter
12
13class StoreActivity : AppCompatActivity() {
14
15 private lateinit var itemsView: RecyclerView
16
17 override fun onCreate(savedInstanceState: Bundle?) {
18 super.onCreate(savedInstanceState)
19 setContentView(R.layout.activity_store)
20
21 XStore.init(<projectId>)
22
23 initUI()
24 loadVirtualItems()
25 }
26
27 private fun initUI() {
28 itemsView = findViewById(R.id.buy_recycler_view)
29 itemsView.layoutManager = LinearLayoutManager(this)
30 }
31
32 private fun loadVirtualItems() {
33 val parentActivity = this
34 XStore.getVirtualItems(object : GetVirtualItemsCallback {
35 override fun onSuccess(response: VirtualItemsResponse) {
36 itemsView.adapter = BuyItemAdapter(parentActivity, response.items.filter { item -> item.virtualPrices.isEmpty() && !item.isFree })
37 }
38
39 override fun onError(throwable: Throwable?, errorMessage: String?) {
40 showNotificationMessage(errorMessage ?: throwable?.javaClass?.name ?: "Error")
41 }
42 })
43 }
44
45 private fun showNotificationMessage(message: String) {
46 Toast.makeText(
47 baseContext,
48 message,
49 Toast.LENGTH_SHORT,
50 ).show()
51 }
52}
スクリプトのXStore.init()
初期化ブロックで、パブリッシャーアカウントのプロジェクト名の横にあるプロジェクトIDを指定してください。

アイテム購入のセットアップ
Cloud Functionsを利用して注文を作成する
エクソーラ側でユーザーとアイテムのデータを使用して注文を作成するには、購入用の決済トークンを作成するAPIコールを使用するCloud Functionsをプロジェクトに追加します。このコールは決済UIを開き、購入を行うために必要な決済トークンを返します。
制限事項:
- 支払いトークンをリクエストする際に、ユーザーの国かIPアドレスを渡す必要があります。
- トークンに通貨を渡さなかった場合、通貨は国によって決定されます。
- トークンに通貨を渡すと、ユーザーはこの通貨で支払います。
プロジェクトにCloud Functionsを追加するには:
- Firebase CLI(コマンドラインインターフェース)をインストールします。これを行うには、CLIコマンドを実行します:
1npm install -g firebase-tools
- プロジェクトをFirebaseプロジェクトにリンクするには、CLIコマンドを実行してFirebaseプロジェクトを初期化します:
1firebase init functions
- インストーラーの指示に従って設定を構成します:
- 既存のコードベースを選択します。
- Cloud Functionsを作成する言語としてJavaScriptを指定します。
- 依存関係をインストールします。
functions/index.js
を開いて修正します:
- javascript
1// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
2const functions = require('firebase-functions/v1');
3
4const projectId = <projectId>;
5const apiKey = <apiKey>;
6
7exports.getXsollaPaymentToken = functions.https.onRequest((req, res) => {
8
9 const requestBody = req.body;
10 if (!requestBody) {
11 res.status(400).send('Request body is missing');
12 return;
13 }
14
15 const userId = requestBody.data.uid;
16 const email = requestBody.data.email;
17 const sku = requestBody.data.sku;
18 const returnUrl = requestBody.data.returnUrl;
19
20 const payload = {
21 user: {
22 id: {value: userId},
23 name: {
24 value: email
25 },
26 email: {
27 value: email
28 },
29 country: {
30 value: 'US',
31 allow_modify: false
32 }
33 },
34 purchase: {
35 items: [
36 {
37 sku: sku,
38 quantity: 1
39 }
40 ]
41 },
42 sandbox: true,
43 settings: {
44 language: 'en',
45 currency: 'USD',
46 return_url: returnUrl,
47 ui: {
48 theme: '63295aab2e47fab76f7708e3'
49 }
50 }
51 }
52
53 let url = "https://store.xsolla.com/api/v3/project/" + projectId.toString() + "/admin/payment/token";
54
55 fetch(
56 url,
57 {
58 method: "POST",
59 headers: {
60 'Content-Type': 'application/json',
61 Authorization: 'Basic ' + btoa(`${projectId}:${apiKey}`)
62 },
63 body: JSON.stringify(payload)
64 },
65 )
66 .then(xsollaRes => {
67 // Handle the response data
68 if (xsollaRes.ok) {
69 return xsollaRes.json();
70 } else {
71 throw new Error(`HTTP request failed with status ${xsollaRes.status} and statusText: ${xsollaRes.statusText}`)
72 }
73 })
74 .then(data => {
75 res.send(JSON.stringify(data));
76 })
77 .catch(error => {
78 res.send("Error = " + error);
79 });
80});
81
82exports.webhookFakeResponse = functions.https.onRequest((request, response) => {
83 response.status(200).send()
84})
- スクリプトの中で、変数の値を指定指定します:
projectId
— パブリッシャーアカウントのプロジェクト名の横にあるプロジェクトID。

apiKey
― APIキー。作成時に一度だけパブリッシャーアカウントに表示され、ユーザー側に保存する必要があります。次のセクションで新しいキーを作成できます:- 会社設定 > APIキー
- プロジェクト設定 > APIキー
- エミュレータでCloud Functionsをテストするには、CLIコマンドを実行します:
1firebase emulators:start
- Cloud Functionsを実行した後、アプリケーションのクライアント側で以下のメソッドを呼び出すことができます:
getXsollaPaymentToken
— 決済インターフェースを開くための決済トークンを返します。webhookFakeResponse
— 支払いウェブフックへの応答として、HTTPコード200
を送信します。このメソッドには購入検証ロジック(テスト用のみ)は含まれていません。ウェブフックの全リストと、ウェブフックの操作に関する一般的な情報については、ウェブフックのドキュメントを参照してください。
- メソッドをローカルで呼び出すには、
https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken
とhttps://localhost:5001/{firebase-project-id}/us-central1/webhookFakeResponse
のURLを使用します。{firebase-project-id}
はFirebaseプロジェクトID(Firebaseコンソール > プロジェクト設定 > プロジェクトID)です。
- 本番環境にCloud Functionsをデプロイするには、CLIコマンドを実行します:
1firebase deploy --only functions
- 本番環境にデプロイされた場合、
https://us-central1-{firebase-project-id}.cloudfunctions.net/getXsollaPaymentToken
とhttps://us-central1-{firebase-project-id}.cloudfunctions.net/webhookFakeResponse
のURLからメソッドを呼び出すことができます。{firebase-project-id}
はFirebaseのプロジェクトIDです(Firebaseコンソール > プロジェクト設定 > プロジェクトID)。本番環境での機能実行の詳細については、Firebaseのドキュメントを参照してください。
決済UI起動のセットアップ
Payments ライブラリをプロジェクトに追加します。これを行うには、build.gradle
を開き、依存関係セクションに次の行を追加します:
1implementation("com.xsolla.android:payments:latest.release")
AndroidManifest.xml
を開き、インターネットアクセスの権限を追加します:
- xml
1<uses-permission android:name="android.permission.INTERNET" />
- 注文作成(Cloud Functionsの
XStore.getXsollaPaymentToken
メソッドを呼び出す)と、受け取った支払いトークンで決済UIを開く(XPayments.createIntentBuilder()
クラス)ためのロジックを追加します。
getXsollaPaymentToken
メソッドを呼び出すには、{firebase-project-id}
はFirebaseプロジェクトID(Firebaseコンソール > プロジェクト設定 > プロジェクトID)で、以下のURLを提供してください:- ローカルアクセス用 —
https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken
- 本番環境でのアクセス用 —
https://us-central1-{firebase-project-id}.cloudfunctions.net/getXsollaPaymentToken
- ローカルアクセス用 —
例(サンプルアプリケーションの
- kotlin
1package com.xsolla.androidsample.adapter
2
3import android.R.attr.duration
4import android.os.Handler
5import android.os.Looper
6import android.view.LayoutInflater
7import android.view.ViewGroup
8import android.widget.Toast
9import androidx.recyclerview.widget.RecyclerView
10import com.bumptech.glide.Glide
11import com.xsolla.android.payments.XPayments
12import com.xsolla.android.payments.data.AccessToken
13import com.xsolla.android.store.entity.response.items.VirtualItemsResponse
14import com.xsolla.androidsample.R
15import com.xsolla.androidsample.StoreActivity
16import org.json.JSONObject
17import java.io.BufferedReader
18import java.io.BufferedWriter
19import java.io.OutputStream
20import java.io.OutputStreamWriter
21import java.net.HttpURLConnection
22import java.net.URL
23
24
25class BuyItemAdapter(private val parentActivity: StoreActivity, private val items: List<VirtualItemsResponse.Item>) :
26 RecyclerView.Adapter<BuyItemViewHolder>() {
27 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BuyItemViewHolder {
28 return BuyItemViewHolder( LayoutInflater.from(parent.context)
29 .inflate(R.layout.buy_item_sample, parent, false))
30 }
31
32 override fun onBindViewHolder(holder: BuyItemViewHolder, position: Int) {
33 val item = items[position]
34 Glide.with(holder.view).load(item.imageUrl).into(holder.itemImage)
35 holder.itemName.text = item.name
36 holder.itemDescription.text = item.description
37 var priceText: String
38 if(item.virtualPrices.isNotEmpty()) {
39 priceText = item.virtualPrices[0].getAmountRaw() + " " + item.virtualPrices[0].name
40 } else {
41 priceText = item.price?.getAmountRaw() + " " + item.price?.currency.toString()
42 }
43
44 holder.itemPrice.text = priceText
45
46 holder.itemButton.setOnClickListener {
47 Thread {
48 purchase(item.sku!!)
49 }.start()
50 }
51 }
52
53 private fun purchase(sku: String) {
54
55 val uid = parentActivity.intent.getStringExtra("uid")
56 val email = parentActivity.intent.getStringExtra("email")
57
58 val jsonBody = JSONObject()
59 jsonBody.put("data", JSONObject().apply {
60 put("uid", uid)
61 put("email", email)
62 put("sku", sku)
63 put("returnUrl", "app://xpayment." + parentActivity.packageName)
64 })
65
66 val connection = URL(https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken).openConnection() as HttpURLConnection
67 connection.requestMethod = "POST"
68 connection.setRequestProperty("Content-Type", "application/json")
69 connection.doOutput = true
70
71 val outputStream: OutputStream = connection.outputStream
72 val writer = BufferedWriter(OutputStreamWriter(outputStream))
73 writer.write(jsonBody.toString())
74 writer.flush()
75 writer.close()
76
77 val responseCode = connection.responseCode
78
79 if (responseCode == HttpURLConnection.HTTP_OK) {
80 val response = connection.inputStream.bufferedReader().use(BufferedReader::readText)
81 connection.disconnect()
82
83 val jsonObject = JSONObject(response)
84 val token = jsonObject.getString("token")
85 val orderId = jsonObject.getString("order_id")
86
87 val intent = XPayments.createIntentBuilder(parentActivity)
88 .accessToken(AccessToken(token))
89 .isSandbox(true)
90 .build()
91 parentActivity.startActivityForResult(intent, 1)
92 } else {
93 Handler(Looper.getMainLooper()).post {
94 showNotificationMessage("HTTP request failed with error: $responseCode")
95 }
96 }
97 }
98
99 override fun getItemCount() = items.size
100
101 private fun showNotificationMessage(message: String) {
102 Toast.makeText(
103 parentActivity,
104 message,
105 Toast.LENGTH_SHORT,
106 ).show()
107 }
108}
- 支払い結果を処理するために、
onActivityResult()
メソッドを追加します。
例(サンプルアプリケーションの
- kotlin
1override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
2 super.onActivityResult(requestCode, resultCode, data)
3 if (requestCode == 1) {
4 val (status, _) = XPayments.Result.fromResultIntent(data)
5 when (status) {
6 XPayments.Status.COMPLETED -> showNotificationMessage("Payment completed")
7 XPayments.Status.CANCELLED -> showNotificationMessage("Payment canceled")
8 XPayments.Status.UNKNOWN -> showNotificationMessage("Payment error")
9 }
10 }
11 }
注文状況追跡のセットアップ
注文状況の追跡は、支払いが成功したことを確認し、ユーザーにアイテムを付与するために必要です。
クライアント側で注文状況の取得
アプリケーションのクライアント側で注文状況の変更をサブスクライブするには、XStore.getOrderStatus
メソッドを呼び出し、以下のパラメータをメソッドに渡します:
listener
—OrderStatusListener
型のオーディエンスのオブジェクト。orderId
— ショッピングカート、ワンクリック購入、または仮想通貨での購入経由で受け取った注文ID。
メソッドの動作に関する詳細情報については、注文状況の追跡セクションを参照してください。
サーバー側で注文状況の取得
SDKはアプリケーションのクライアント側で注文状況を追跡することを可能にします。ただし、完了した購入の追加の検証を実装するために、アプリケーションのバックエンドで支払いウェブフックハンドラを設定することをお勧めします。これにより、注文情報を受け取ることができます
ウェブフックの完全なリストと、ウェブフックの操作に関する一般情報については、ウェブフックに関するドキュメントを参照してください。
エクソーラ側でウェブフックを構成するには:
- パブリッシャーアカウント内のプロジェクトで、プロジェクト設定 >ウェブフックセクションに移動します。
- 「ウェブフックサーバー」フィールドに、エクソーラがウェブフックを送信するURLを入力します。
テストの場合は、https://us-central1-{firebase-project-id}.cloudfunctions.net/webhookFakeResponse
を指定できます。ここで、{firebase-project-id}
はFirebaseプロジェクトIDです(Firebaseコンソール > プロジェクト設定 > プロジェクトID)。この場合、Firebaseはウェブフックの処理が成功したかのようにシミュレートします。実際のプロジェクトでは、購入の検証ロジックを追加する必要があります。
ウェブフックをテストするには、webhook.siteなどの専門サイトや、ngrokなどのプラットフォームを選択することもできます。
- 「秘密鍵」フィールドの値をコピーして保存します。このキーはデフォルトで生成され、ウェブフックの署名に使用されます。変更したい場合は、更新アイコンをクリックします。
- 「ウェブフックを有効にする」をクリックします。

誤字脱字などのテキストエラーを見つけましたか? テキストを選択し、Ctrl+Enterを押します。