ペイステーションと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
を開き、依存関係セクションに次の行を追加します:
implementation("com.xsolla.android:store:latest.release")
- アプリケーションのクライアント側で、製品カタログを表示するUIを追加します。
- エクソーラサーバーからのアイテムカタログのリクエストを実装します。
XStore.getVirtualItems
メソッドを使用して仮想アイテムのリストを取得します。他の例(サンプルアプリケーションの
- kotlin
package com.xsolla.androidsample
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.xsolla.android.store.XStore
import com.xsolla.android.store.callbacks.GetVirtualItemsCallback
import com.xsolla.android.store.entity.response.items.VirtualItemsResponse
import com.xsolla.androidsample.adapter.BuyItemAdapter
class StoreActivity : AppCompatActivity() {
private lateinit var itemsView: RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_store)
XStore.init(<projectId>)
initUI()
loadVirtualItems()
}
private fun initUI() {
itemsView = findViewById(R.id.buy_recycler_view)
itemsView.layoutManager = LinearLayoutManager(this)
}
private fun loadVirtualItems() {
val parentActivity = this
XStore.getVirtualItems(object : GetVirtualItemsCallback {
override fun onSuccess(response: VirtualItemsResponse) {
itemsView.adapter = BuyItemAdapter(parentActivity, response.items.filter { item -> item.virtualPrices.isEmpty() && !item.isFree })
}
override fun onError(throwable: Throwable?, errorMessage: String?) {
showNotificationMessage(errorMessage ?: throwable?.javaClass?.name ?: "Error")
}
})
}
private fun showNotificationMessage(message: String) {
Toast.makeText(
baseContext,
message,
Toast.LENGTH_SHORT,
).show()
}
}
スクリプトのXStore.init()
初期化ブロックで、アドミンページのプロジェクト名の横にあるプロジェクトIDを指定してください。
アイテム購入のセットアップ
Cloud Functionsを利用して注文を作成する
エクソーラ側でユーザーとアイテムのデータを使用して注文を作成するには、購入用の決済トークンを作成するAPIコールを使用するCloud Functionsをプロジェクトに追加します。このコールは決済UIを開き、購入を行うために必要な決済トークンを返します。
制限事項:
- 支払いトークンをリクエストする際に、ユーザーの国かIPアドレスを渡す必要があります。
- トークンに通貨を渡さなかった場合、通貨は国によって決定されます。
- トークンに通貨を渡すと、ユーザーはこの通貨で支払います。
プロジェクトにCloud Functionsを追加するには:
- Firebase CLI(コマンドラインインターフェース)をインストールします。これを行うには、CLIコマンドを実行します:
npm install -g firebase-tools
- プロジェクトをFirebaseプロジェクトにリンクするには、CLIコマンドを実行してFirebaseプロジェクトを初期化します:
firebase init functions
- インストーラーの指示に従って設定を構成します:
- 既存のコードベースを選択します。
- Cloud Functionsを作成する言語としてJavaScriptを指定します。
- 依存関係をインストールします。
functions/index.js
を開いて修正します:
- javascript
// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const functions = require('firebase-functions/v1');
const projectId = <projectId>;
const apiKey = <apiKey>;
exports.getXsollaPaymentToken = functions.https.onRequest((req, res) => {
const requestBody = req.body;
if (!requestBody) {
res.status(400).send('Request body is missing');
return;
}
const userId = requestBody.data.uid;
const email = requestBody.data.email;
const sku = requestBody.data.sku;
const returnUrl = requestBody.data.returnUrl;
const payload = {
user: {
id: {value: userId},
name: {
value: email
},
email: {
value: email
},
country: {
value: 'US',
allow_modify: false
}
},
purchase: {
items: [
{
sku: sku,
quantity: 1
}
]
},
sandbox: true,
settings: {
language: 'en',
currency: 'USD',
return_url: returnUrl,
ui: {
theme: '63295aab2e47fab76f7708e3'
}
}
}
let url = "https://store.xsolla.com/api/v3/project/" + projectId.toString() + "/admin/payment/token";
fetch(
url,
{
method: "POST",
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic ' + btoa(`${projectId}:${apiKey}`)
},
body: JSON.stringify(payload)
},
)
.then(xsollaRes => {
// Handle the response data
if (xsollaRes.ok) {
return xsollaRes.json();
} else {
throw new Error(`HTTP request failed with status ${xsollaRes.status} and statusText: ${xsollaRes.statusText}`)
}
})
.then(data => {
res.send(JSON.stringify(data));
})
.catch(error => {
res.send("Error = " + error);
});
});
exports.webhookFakeResponse = functions.https.onRequest((request, response) => {
response.status(200).send()
})
- スクリプトの中で、変数の値を指定指定します:
projectId
— アドミンページのプロジェクト名の横にあるプロジェクトID。
apiKey
― APIキー。作成時に一度だけアドミンページに表示され、ユーザー側に保存する必要があります。次のセクションで新しいキーを作成できます:- 会社設定 > APIキー
- プロジェクト設定 > APIキー
- エミュレータでCloud Functionsをテストするには、CLIコマンドを実行します:
firebase 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コマンドを実行します:
firebase 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
を開き、依存関係セクションに次の行を追加します:
implementation("com.xsolla.android:payments:latest.release")
AndroidManifest.xml
を開き、インターネットアクセスの権限を追加します:
- xml
<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
package com.xsolla.androidsample.adapter
import android.R.attr.duration
import android.os.Handler
import android.os.Looper
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.xsolla.android.payments.XPayments
import com.xsolla.android.payments.data.AccessToken
import com.xsolla.android.store.entity.response.items.VirtualItemsResponse
import com.xsolla.androidsample.R
import com.xsolla.androidsample.StoreActivity
import org.json.JSONObject
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.OutputStream
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL
class BuyItemAdapter(private val parentActivity: StoreActivity, private val items: List<VirtualItemsResponse.Item>) :
RecyclerView.Adapter<BuyItemViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BuyItemViewHolder {
return BuyItemViewHolder( LayoutInflater.from(parent.context)
.inflate(R.layout.buy_item_sample, parent, false))
}
override fun onBindViewHolder(holder: BuyItemViewHolder, position: Int) {
val item = items[position]
Glide.with(holder.view).load(item.imageUrl).into(holder.itemImage)
holder.itemName.text = item.name
holder.itemDescription.text = item.description
var priceText: String
if(item.virtualPrices.isNotEmpty()) {
priceText = item.virtualPrices[0].getAmountRaw() + " " + item.virtualPrices[0].name
} else {
priceText = item.price?.getAmountRaw() + " " + item.price?.currency.toString()
}
holder.itemPrice.text = priceText
holder.itemButton.setOnClickListener {
Thread {
purchase(item.sku!!)
}.start()
}
}
private fun purchase(sku: String) {
val uid = parentActivity.intent.getStringExtra("uid")
val email = parentActivity.intent.getStringExtra("email")
val jsonBody = JSONObject()
jsonBody.put("data", JSONObject().apply {
put("uid", uid)
put("email", email)
put("sku", sku)
put("returnUrl", "app://xpayment." + parentActivity.packageName)
})
val connection = URL(https://localhost:5001/{firebase-project-id}/us-central1/getXsollaPaymentToken).openConnection() as HttpURLConnection
connection.requestMethod = "POST"
connection.setRequestProperty("Content-Type", "application/json")
connection.doOutput = true
val outputStream: OutputStream = connection.outputStream
val writer = BufferedWriter(OutputStreamWriter(outputStream))
writer.write(jsonBody.toString())
writer.flush()
writer.close()
val responseCode = connection.responseCode
if (responseCode == HttpURLConnection.HTTP_OK) {
val response = connection.inputStream.bufferedReader().use(BufferedReader::readText)
connection.disconnect()
val jsonObject = JSONObject(response)
val token = jsonObject.getString("token")
val orderId = jsonObject.getString("order_id")
val intent = XPayments.createIntentBuilder(parentActivity)
.accessToken(AccessToken(token))
.isSandbox(true)
.build()
parentActivity.startActivityForResult(intent, 1)
} else {
Handler(Looper.getMainLooper()).post {
showNotificationMessage("HTTP request failed with error: $responseCode")
}
}
}
override fun getItemCount() = items.size
private fun showNotificationMessage(message: String) {
Toast.makeText(
parentActivity,
message,
Toast.LENGTH_SHORT,
).show()
}
}
- 支払い結果を処理するために、
onActivityResult()
メソッドを追加します。
例(サンプルアプリケーションの
- kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1) {
val (status, _) = XPayments.Result.fromResultIntent(data)
when (status) {
XPayments.Status.COMPLETED -> showNotificationMessage("Payment completed")
XPayments.Status.CANCELLED -> showNotificationMessage("Payment canceled")
XPayments.Status.UNKNOWN -> showNotificationMessage("Payment error")
}
}
}
注文状況追跡のセットアップ
注文状況の追跡は、支払いが成功したことを確認し、ユーザーにアイテムを付与するために必要です。
クライアント側で注文状況の取得
アプリケーションのクライアント側で注文状況の変更をサブスクライブするには、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を押します。