ペイステーションとFirebase認証の組み合わせ使用について

Firebaseを使用してアプリケーションにユーザー認証を実装済みの場合、Firebase側で決済トークンを生成し、アプリケーションのクライアント側に渡して決済UIを開くことができます。

この統合オプションを使用すると、購入代金を支払うユーザーの国と通貨を決定するロジックを独自に実装する必要があります。

統合フロー:

  1. プロジェクトを作成します
  1. パブリッシャーアカウントに新規登録して、新しいプロジェクトを作成します。今後の手順で作成したプロジェクトのIDが必要です。

  1. カタログをセットアップします:
    • エクソーラ側のアイテムカタログを作成します。アイテムを手動で追加するか、Google PlayまたはPlayFabからインポートすることができます。
    • Storeライブラリを使用して、アプリケーションのクライアント側でカタログを取得して表示する機能を実装します。

  1. アイテム購入をセットアップします
    • アプリケーションのクライアント側で、FirebaseのCloud Functionsを使って、ユーザーとアイテムのデータを含む注文を作成します。
    • Paymentsライブラリを使用して、アプリケーションのクライアント側で決済UIを開くように実装します。

  1. 注文状況の追跡をセットアップします

注意

統合を完了し、実際の支払いを受け付けるようにするには、エクソーラとライセンス契約を結ぶ必要があります。

ライセンス契約はいつでも統合のどのステップでも署名できますが、審査プロセスには最大で3営業日かかる可能性があることを覚えておいてください。

ペイステーションとFirebase認証の組み合わせ使用例として、サンプルウェブアプリケーションを使用してください。サンプルウェブアプリケーションのソースコードはGitHubで利用可能です。

プロジェクトを作成する

パブリッシャーアカウントの新規登録

パブリッシャーアカウントは、エクソーラの機能を構成し、アナリティクスや取引を処理するための主要なツールです。

登録時に指定された会社とアプリケーションに関するデータは、エクソーラとのライセンス契約のドラフトを作成し、あなたに適したソリューションを提案するために使用されます。データは後で変更することができますが、新規登録時に正しいデータを提供することで、ライセンス契約締結までのプロセスが迅速化されます。

新規登録するには、パブリッシャーアカウントにアクセスし、アカウントを作成してください。

お知らせ

パブリッシャーアカウントのパスワードはラテン文字、数字、特殊文字で構成でき、少なくとも以下を含む必要があります:

  • 8文字以上
  • 1桁
  • 大文字1つ
  • 小文字1つ

パスワードのセキュリティを確保するために、以下をことを推奨します:

  • 少なくとも90日に1回はパスワードを変更する
  • アカウントの過去4回のパスワードと一致しない新しいパスワードを使用する
  • 他の場所で使用されているパスワードと一致しない固有のパスワードを使用する
  • 簡単にアクセスできる場所にパスワードを保存しない
  • パスワードマネージャーを使用してパスワードを保存する

パブリッシャーアカウントでは2要素認証が使用され、認証を試行するたびに確認コードが送信されます。

パブリッシャーアカウントでのプロジェクト作成

複数のアプリケーションを所有している場合は、それぞれのアプリケーションに対して個別のプロジェクトを作成することをお勧めします。プロジェクト作成時に指定したデータに基づいて、エクソーラはあなたに適したソリューションを提案します。

新たしいプロジェクトを作成するには:

  1. パブリッシャーアカウントを開きます。
  2. サイドメニューで、「プロジェクトの作成」をクリックします。

  1. プロジェクト名を英語で入力してください(必須)。

お知らせ
プロジェクトを作成した後、プロジェクト設定セクションで言語やローカライズされたプロジェクト名を追加することができます。

  1. ゲームのリリースプラットフォームを1つまたは複数選択します(必須)。
  2. ゲームへのリンクを追加します。ゲームが独自のサイトを持っていない場合は、メインサイトまたはゲームがリストされているセクションへのリンクを提供してください(必須)。
  3. ゲームエンジンを選択します。
  4. 使用している、または使用する予定の収益化オプションを選択します。
  5. ゲームがすでにリリースされているかどうかを指定します。ゲームがまだリリースされていない場合は、予定公開日を指定します。
  6. プロジェクトを作成する」をクリックします。おすすめのエクソーラ製品のページが表示されます。

統合プロセスでは、パブリッシャーアカウントでプロジェクト名の横に表示されているプロジェクトIDを入力する必要があります。

カタログのセットアップ

パブリッシャーアカウントでのアイテム作成

注意

エクソーラ側でカタログを作成する必要があります。アイテムを手動で追加するか、Google PlayまたはPlayFabからインポートすることができます。Google Playからインポートする場合、一度に最大100個のアイテムをインポートできます。

これらの説明は、仮想アイテムの基本設定手順を提供します。後で、カタログに他のアイテム(仮想通貨、バンドル、ゲームキー)を追加したり、アイテムグループを作成したり、プロモーションキャンペーンや地域価格などを設定したりすることができます。

基本設定の仮想アイテムをカタログに追加するには:

  1. パブリッシャーアカウントでプロジェクトを開きます。
  2. サイドメニューの「ストア」をクリックします。
  3. 仮想アイテム」ペインで、「接続」をクリックします。
  4. ドロップダウンメニューで、「アイテムを作成する」を選択します。

  1. 以下のフィールドでアイテムの基本設定を行います:
    • イメージ(任意)
    • SKU(アイテムの一意のID)
    • アイテム名
    • 説明(任意)

  1. アイテム価格を指定します:
    1. 実際通貨での価格」のトグルを「オン」に設定します。
    2. デフォルト通貨」フィールドで通貨を変更し(任意)、アイテム価格を指定します。
    3. デフォルト通貨」フィールドで通貨を変更した場合は、「実際通貨での価格」フィールドで同じ通貨を選択します。

お知らせ
カタログを取得するためのAPIコールが正しく機能するようにするには、デフォルト通貨と価格が指定されている通貨リストがすべてのアイテムで一致していることを確認してください。

  1. アイテムのステータスを「利用可能」に変更します。

  1. アイテムを作成」をクリックします。

アプリケーションのクライアント側にカタログの表示

  1. Storeライブラリをプロジェクトに追加します。これを行うには、build.gradleを開き、依存関係セクションに次の行を追加します:

Copy
Full screen
Small screen
    1implementation("com.xsolla.android:store:latest.release")
    

    1. アプリケーションのクライアント側で、製品カタログを表示するUIを追加します。
    2. エクソーラサーバーからのアイテムカタログのリクエストを実装します。

    お知らせ
    この例では、XStore.getVirtualItemsメソッドを使用して仮想アイテムのリストを取得します。他のStoreライブラリメソッドを使用してカタログアイテムの情報を取得することもできます。

    例(サンプルアプリケーションのStoreActivityクラス):

    Copy
    Full screen
    Small screen
     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アドレスを渡す必要があります。
    • トークンに通貨を渡さなかった場合、通貨は国によって決定されます。
    • トークンに通貨を渡すと、ユーザーはこの通貨で支払います。

    お知らせ
    まず、Firebaseプロジェクトを作成して初期化し、Firebaseを使用してユーザー認証を有効にする必要があります。これらの手順の詳細については、以下のFirebaseの説明を参照してください:

    プロジェクトにCloud Functionsを追加するには:

    1. Firebase CLI(コマンドラインインターフェース)をインストールします。これを行うには、CLIコマンドを実行します:

    Copy
    Full screen
    Small screen
      1npm install -g firebase-tools
      

      1. プロジェクトをFirebaseプロジェクトにリンクするには、CLIコマンドを実行してFirebaseプロジェクトを初期化します:

      Copy
      Full screen
      Small screen
        1firebase init functions
        

        1. インストーラーの指示に従って設定を構成します:
          1. 既存のコードベースを選択します。
          2. Cloud Functionsを作成する言語としてJavaScriptを指定します。
          3. 依存関係をインストールします。

        1. functions/index.jsを開いて修正します:

        Copy
        Full screen
        Small screen
         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})
        

        1. スクリプトの中で、変数の値を指定指定します:
          • projectId — パブリッシャーアカウントのプロジェクト名の横にあるプロジェクトID。

          • apiKey ― APIキー。作成時に一度だけパブリッシャーアカウントに表示され、ユーザー側に保存する必要があります。次のセクションで新しいキーを作成できます:
            • 会社設定 > APIキー
            • プロジェクト設定 > APIキー

        1. エミュレータでCloud Functionsをテストするには、CLIコマンドを実行します:

        Copy
        Full screen
        Small screen
          1firebase emulators:start
          

          1. Cloud Functionsを実行した後、アプリケーションのクライアント側で以下のメソッドを呼び出すことができます:
            • getXsollaPaymentToken — 決済インターフェースを開くための決済トークンを返します。
            • webhookFakeResponse支払いウェブフックへの応答として、HTTPコード200を送信します。このメソッドには購入検証ロジック(テスト用のみ)は含まれていません。ウェブフックの全リストと、ウェブフックの操作に関する一般的な情報については、ウェブフックのドキュメントを参照してください。

          1. メソッドをローカルで呼び出すには、https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentTokenhttps://localhost:5001/{firebase-project-id}/us-central1/webhookFakeResponseのURLを使用します。{firebase-project-id}はFirebaseプロジェクトID(Firebaseコンソール > プロジェクト設定 > プロジェクトID)です。

          1. 本番環境にCloud Functionsをデプロイするには、CLIコマンドを実行します:

          Copy
          Full screen
          Small screen
            1firebase deploy --only functions
            

            1. 本番環境にデプロイされた場合、https://us-central1-{firebase-project-id}.cloudfunctions.net/getXsollaPaymentTokenhttps://us-central1-{firebase-project-id}.cloudfunctions.net/webhookFakeResponseのURLからメソッドを呼び出すことができます。{firebase-project-id}はFirebaseのプロジェクトIDです(Firebaseコンソール > プロジェクト設定 > プロジェクトID)。本番環境での機能実行の詳細については、Firebaseのドキュメントを参照してください。

            決済UI起動のセットアップ

            1. Paymentsライブラリをプロジェクトに追加します。これを行うには、build.gradleを開き、依存関係セクションに次の行を追加します:

            Copy
            Full screen
            Small screen
              1implementation("com.xsolla.android:payments:latest.release")
              

              1. AndroidManifest.xmlを開き、インターネットアクセスの権限を追加します:

              Copy
              Full screen
              Small screen
              1<uses-permission android:name="android.permission.INTERNET" />
              

              1. 注文作成(Cloud FunctionsのXStore.getXsollaPaymentTokenメソッドを呼び出す)と、受け取った支払いトークンで決済UIを開く(XPayments.createIntentBuilder()クラス)ためのロジックを追加します。

              1. 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

              例(サンプルアプリケーションのBuyItemAdapterクラス):

              Copy
              Full screen
              Small screen
                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}
              

              1. 支払い結果を処理するために、onActivityResult()メソッドを追加します。

              例(サンプルアプリケーションのStoreActivityクラス):

              Copy
              Full screen
              Small screen
               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メソッドを呼び出し、以下のパラメータをメソッドに渡します:

              • listenerOrderStatusListener型のオーディエンスのオブジェクト。
              • orderId — ショッピングカート、ワンクリック購入、または仮想通貨での購入経由で受け取った注文ID。

              メソッドの動作に関する詳細情報については、注文状況の追跡セクションを参照してください。

              サーバー側で注文状況の取得

              注意

              SDKはアプリケーションのクライアント側で注文状況を追跡することを可能にします。ただし、完了した購入の追加の検証を実装するために、アプリケーションのバックエンドで支払いウェブフックハンドラを設定することをお勧めします。これにより、注文情報を受け取ることができます

              ウェブフックの完全なリストと、ウェブフックの操作に関する一般情報については、ウェブフックに関するドキュメントを参照してください。

              エクソーラ側でウェブフックを構成するには:

              1. パブリッシャーアカウント内のプロジェクトで、プロジェクト設定 >ウェブフックセクションに移動します。
              2. ウェブフックサーバー」フィールドに、エクソーラがウェブフックを送信するURLを入力します。

              お知らせ

              テストの場合は、https://us-central1-{firebase-project-id}.cloudfunctions.net/webhookFakeResponseを指定できます。ここで、{firebase-project-id}はFirebaseプロジェクトIDです(Firebaseコンソール > プロジェクト設定 > プロジェクトID)。この場合、Firebaseはウェブフックの処理が成功したかのようにシミュレートします。実際のプロジェクトでは、購入の検証ロジックを追加する必要があります。

              ウェブフックをテストするには、webhook.siteなどの専門サイトや、ngrokなどのプラットフォームを選択することもできます。

              1. 秘密鍵」フィールドの値をコピーして保存します。このキーはデフォルトで生成され、ウェブフックの署名に使用されます。変更したい場合は、更新アイコンをクリックします。
              2. ウェブフックを有効にする」をクリックします。

              この記事は役に立ちましたか?
              ありがとうございます!
              改善できることはありますか? メッセージ
              申し訳ありません
              この記事が参考にならなかった理由を説明してください。 メッセージ
              ご意見ありがとうございました!
              あなたのメッセージを確認し、体験を向上させるために利用させていただきます。
              最終更新日: 2025年7月9日

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

              問題を報告する
              当社は常にコンテンツを見直しています。お客様のご意見は改善に役立ちます。
              フォローアップ用のメールをご提供してください
              ご意見ありがとうございました!
              フィードバックを送信できませんでした
              後でもう一度お試しいただくか、doc_feedback@xsolla.comまでお問い合わせください。