ここではUnrealでアプリ内決済機能を使用するために必要な設定方法を説明します。 Gamebaseは、1つの統合された決済APIを提供し、ゲームから簡単に多くのストアのアプリ内決済を連携できるようにサポートします。
AndroidまたはiOSでアプリ内決済機能を設定する方法は、次の文書を参照してください。
[注意]
外部プラグインで決済関連処理がある場合、 Gamebase決済機能が正常に動作しない可能性があります。 * Unrealでデフォルトで有効になっているOnline SubSystemプラグインを無効化またはストア機能を利用できないように変更する必要があります。 * Online SubSystem GooglePlayプラグイン使用時 /Config/Android/AndroidEngine.iniファイルを編集します。
[OnlineSubsystemGooglePlay.Store]
bSupportsInAppPurchasing=False
* Online SubSystem iOSプラグイン使用時 /Config/IOS/IOSEngine.iniファイルを編集します。
[OnlineSubsystemIOS.Store]
bSupportsInAppPurchasing=False
アイテムの購入は大きく分けて決済フロー、消費フロー、再処理フローの3つがあります。 決済フローは、次のような順序で実装してください。
未消費決済履歴リストに値がある場合、次のような順序でConsume Flowを進行してください。
[注意]
アイテムの重複支給が発生しないように、ゲームサーバーで必ず重複支給の有無をチェックしてください。
購入したいアイテムのitemSeqを利用して次のAPIを呼び出し、購入をリクエストします。 ゲームユーザーが購入をキャンセルする場合、PURCHASE_USER_CANCELEDエラーが返されます。
API
Supported Platforms ■ UNREAL_IOS ■ UNREAL_ANDROID
void RequestPurchase(const FString& gamebaseProductId, const FGamebasePurchasableReceiptDelegate& onCallback);
void RequestPurchase(const FString& gamebaseProductId, const FString& payload, const FGamebasePurchasableReceiptDelegate& onCallback);
Example
void Sample::RequestPurchase(const FString& gamebaseProductId)
{
IGamebase::Get().GetPurchase().RequestPurchase(gamebaseProductId, FGamebasePurchasableReceiptDelegate::CreateLambda(
[](const FGamebasePurchasableReceipt* purchasableReceipt, const FGamebaseError* error)
{
if (Gamebase::IsSuccess(error))
{
UE_LOG(GamebaseTestResults, Display, TEXT("RequestPurchase succeeded. (gamebaseProductId= %s, price= %f, currency= %s, paymentSeq= %s, purchaseToken= %s)"),
*purchasableReceipt->gamebaseProductId, purchasableReceipt->price, *purchasableReceipt->currency,
*purchasableReceipt->paymentSeq, *purchasableReceipt->purchaseToken);
}
else
{
if (error->code == GamebaseErrorCode::PURCHASE_USER_CANCELED)
{
UE_LOG(GamebaseTestResults, Display, TEXT("User canceled purchase."));
}
else
{
// Check the error code and handle the error appropriately.
UE_LOG(GamebaseTestResults, Display, TEXT("RequestPurchase failed. (error: %d)"), error->code);
}
}
}));
}
void Sample::RequestPurchaseWithPayload(const FString& gamebaseProductId)
{
FString userPayload = TEXT("{\"description\":\"This is example\",\"channelId\":\"delta\",\"characterId\":\"abc\"}");
IGamebase::Get().GetPurchase().RequestPurchase(gamebaseProductId, userPayload, FGamebasePurchasableReceiptDelegate::CreateLambda(
[](const FGamebasePurchasableReceipt* purchasableReceipt, const FGamebaseError* error)
{
if (Gamebase::IsSuccess(error))
{
UE_LOG(GamebaseTestResults, Display, TEXT("RequestPurchase succeeded. (gamebaseProductId= %s, price= %f, currency= %s, paymentSeq= %s, purchaseToken= %s)"),
*purchasableReceipt->gamebaseProductId, purchasableReceipt->price, *purchasableReceipt->currency,
*purchasableReceipt->paymentSeq, *purchasableReceipt->purchaseToken);
FString payload = purchasableReceipt->payload;
}
else
{
if (error->code == GamebaseErrorCode::PURCHASE_USER_CANCELED)
{
UE_LOG(GamebaseTestResults, Display, TEXT("User canceled purchase."));
}
else
{
// Check the error code and handle the error appropriately.
UE_LOG(GamebaseTestResults, Display, TEXT("RequestPurchase failed. (error: %d)"), error->code);
}
}
}));
}
VO
USTRUCT()
struct FGamebasePurchasableReceipt
{
GENERATED_USTRUCT_BODY()
// 購入したアイテムの商品IDです。
UPROPERTY()
FString gamebaseProductId;
// itemSeqで商品を購入するLegacy API用の識別子です。
UPROPERTY()
int64 itemSeq;
// 購入した商品の価格です。
UPROPERTY()
float price;
// 通貨コードです。
UPROPERTY()
FString currency;
// 決済識別子です。
// purchaseTokenと一緒に「Consume」サーバーAPIを呼び出すのに使用する重要な情報です。
// Consume API : https://docs.toast.com/en/Game/Gamebase/en/api-guide/#purchase-iap
// 注意:Consume APIはゲームサーバーで呼び出してください!
UPROPERTY()
FString paymentSeq;
// 決済識別子です。
// paymentSeqと一緒に「Consume」サーバーAPIを呼び出すのに使用する重要な情報です。
// Consume APIでは「accessToken」という名前のパラメータで伝達する必要があります。
// Consume API : https://docs.toast.com/en/Game/Gamebase/en/api-guide/#purchase-iap
// 注意:Consume APIはゲームサーバーで呼び出してください!
UPROPERTY()
FString purchaseToken;
// Google、Appleなどのストアコンソールに登録された商品IDです。
UPROPERTY()
FString marketItemId;
// 次のような商品タイプがあります。
// * UNKNOWN:認識できないタイプ。 Gamebase SDKをアップデートするか、Gamebaseサポートへお問い合わせください。
// * CONSUMABLE:消費性商品。
// * AUTO_RENEWABLE:サブスクリプション型の商品。
// * CONSUMABLE_AUTO_RENEWABLE:サブスクリプション型の商品を購入したユーザーに、定期的に消費が可能な商品を支給したい場合に使用される「消費が可能なサブスクリプション商品」。
UPROPERTY()
FString productType;
// 商品を購入したUser ID
// 商品を購入していないUser IDでログインした場合、購入したアイテムを獲得できません。
UPROPERTY()
FString userId;
// ストアの決済識別子です。
UPROPERTY()
FString paymentId;
// サブスクリプション商品は更新するごとにpaymentIdが変更されます。
// このフィールドは、初めてサブスクリプション商品を決済した時のpaymentIdを伝えます。
// ストアや、決済サーバーの状態によって値が存在しない場合があるため
// 常に有効な値を保障するわけではありません。
UPROPERTY()
FString originalPaymentId;
// 商品を購入した時刻です。(epoch time)
UPROPERTY()
int64 purchaseTime;
// 購読が終了する時刻です。(epoch time)
UPROPERTY()
int64 expiryTime;
// Gamebase.Purchase.requestPurchase APIの呼び出し時にpayloadに伝達した値です。
//
// このフィールドは、例えば同じUser IDで購入したがゲームチャンネル、キャラクターなどに応じて
// 商品購入および支給を区分したい場合など
// ゲームで必要とするさまざまな追加情報を入れる目的で活用できます。
UPROPERTY()
FString payload;
};
アイテムリストを照会するには、次のAPIを呼び出します。 コールバックで返されるリスト内には、各アイテムの情報が含まれています。
API
Supported Platforms ■ UNREAL_IOS ■ UNREAL_ANDROID
void RequestItemListPurchasable(const FGamebasePurchasableItemListDelegate& onCallback);
Example
void Sample::RequestItemListPurchasable()
{
IGamebase::Get().GetPurchase().RequestItemListPurchasable(FGamebasePurchasableItemListDelegate::CreateLambda(
[](const TArray<FGamebasePurchasableItem>* purchasableItemList, const FGamebaseError* error)
{
if (Gamebase::IsSuccess(error))
{
UE_LOG(GamebaseTestResults, Display, TEXT("RequestItemListPurchasable succeeded."));
for (const FGamebasePurchasableItem& purchasableItem : *purchasableItemList)
{
UE_LOG(GamebaseTestResults, Display, TEXT(" - gamebaseProductId= %s, price= %f, itemName= %s, itemName= %s, marketItemId= %s"),
*purchasableItem.gamebaseProductId, purchasableItem.price, *purchasableItem.currency, *purchasableItem.itemName, *purchasableItem.marketItemId);
}
}
else
{
UE_LOG(GamebaseTestResults, Display, TEXT("RequestItemListPurchasable failed. (error: %d)"), error->code);
}
}));
}
VO
USTRUCT()
struct FGamebasePurchasableItem
{
GENERATED_USTRUCT_BODY()
// Gamebaseコンソールに登録された商品IDです。
// Gamebase.Purchase.requestPurchase APIで商品を購入する時に使用されます。
UPROPERTY()
FString gamebaseProductId;
// itemSeqで商品を購入するLegacy API用の識別子です。
UPROPERTY()
int64 itemSeq;
// 商品の価格です。
UPROPERTY()
float price;
// 通貨コードです。
UPROPERTY()
FString currency;
// Gamebaseコンソールに登録された商品名です。
UPROPERTY()
FString itemName;
// Google、Appleなどのストアコンソールに登録された商品IDです。
UPROPERTY()
FString marketItemId;
// 次のような商品タイプがあります。
// * UNKNOWN:認識できないタイプ。 Gamebase SDKをアップデートするか、Gamebaseサポートへお問い合わせください。
// * CONSUMABLE:消費性商品。
// * AUTORENEWABLE:サブスクリプション型の商品。
// * CONSUMABLE_AUTO_RENEWABLE:サブスクリプション型の商品を購入したユーザーに、定期的に消費が可能な商品を支給したい場合に使用される「消費が可能なサブスクリプション商品」。
UPROPERTY()
FString productType;
// 通貨記号が含まれたローカライズされた価格情報です。
UPROPERTY()
FString localizedPrice;
// ストアコンソールに登録されたローカライズされた商品名です。
UPROPERTY()
FString localizedTitle;
// ストアコンソールに登録されたローカライズされた商品説明です。
UPROPERTY()
FString localizedDescription;
// Gamebaseコンソールで該当商品の「使用状態」を表します。
UPROPERTY()
bool isActive;
};
アイテムを購入したが、正常にアイテムが消費(配送、支給)されていない未消費決済内訳をリクエストします。 未決済内訳がある場合は、ゲームサーバー(アイテムサーバー)にリクエストして、アイテムを配送(支給)するように処理する必要があります。
API
Supported Platforms ■ UNREAL_IOS ■ UNREAL_ANDROID
void RequestItemListOfNotConsumed(const FGamebasePurchasableReceiptListDelegate& onCallback);
Example
void Sample::RequestItemListOfNotConsumed()
{
IGamebase::Get().GetPurchase().RequestItemListOfNotConsumed(FGamebasePurchasableItemListDelegate::CreateLambda(
[](const TArray<FGamebasePurchasableItem>* purchasableItemList, const FGamebaseError* error)
{
if (Gamebase::IsSuccess(error))
{
// Should Deal With This non-consumed Items.
// Send this item list to the game(item) server for consuming item.
UE_LOG(GamebaseTestResults, Display, TEXT("RequestItemListOfNotConsumed succeeded."));
for (const FGamebasePurchasableItem& purchasableItem : *purchasableItemList)
{
UE_LOG(GamebaseTestResults, Display, TEXT(" - gamebaseProductId= %s, price= %f, itemName= %s, itemName= %s, marketItemId= %s"),
*purchasableReceipt.gamebaseProductId, purchasableItem.price, *purchasableItem.currency, *purchasableItem.itemName, *purchasableItem.marketItemId);
}
}
else
{
UE_LOG(GamebaseTestResults, Display, TEXT("RequestItemListOfNotConsumed failed. (error: %d)"), error->code);
}
}));
}
現在のユーザーID基準で有効になっている購読リストを照会します。 決済が完了した購読商品(自動更新型購読、自動更新型消費性購読商品)は、有効期限が切れる前まで照会できます。 ユーザーIDが同じ場合、AndroidとiOSで購入した購読商品が照会されます。
[注意]
Androidでは現在、Google Playストアでのみサブスクリプション商品をサポートしています。
API
Supported Platforms ■ UNREAL_IOS ■ UNREAL_ANDROID
void RequestActivatedPurchases(const FGamebasePurchasableReceiptListDelegate& onCallback);
Example
void Sample::RequestActivatedPurchases()
{
IGamebase::Get().GetPurchase().RequestActivatedPurchases(FGamebasePurchasableReceiptListDelegate::CreateLambda(
[](const TArray<FGamebasePurchasableReceipt>* purchasableReceiptList, const FGamebaseError* error)
{
if (Gamebase::IsSuccess(error))
{
UE_LOG(GamebaseTestResults, Display, TEXT("RequestActivatedPurchases succeeded."));
for (const FGamebasePurchasableReceipt& purchasableReceipt : *purchasableReceiptList)
{
UE_LOG(GamebaseTestResults, Display, TEXT(" - gamebaseProductId= %s, price= %f, currency= %s, paymentSeq= %s, purchaseToken= %s"),
*purchasableReceipt.gamebaseProductId, purchasableReceipt.price, *purchasableReceipt.currency, *purchasableReceipt.paymentSeq, *purchasableReceipt.purchaseToken);
}
}
else
{
UE_LOG(GamebaseTestResults, Display, TEXT("RequestActivatedPurchases failed. (error: %d)"), error->code);
}
}));
}
Error | Error Code | Description |
---|---|---|
PURCHASE_NOT_INITIALIZED | 4001 | Purchaseモジュールが初期化されませんでした。 gamebase-adapter-purchase-IAPモジュールをプロジェクトに追加したかを確認してください。 |
PURCHASE_USER_CANCELED | 4002 | ゲームユーザーがアイテムの購入をキャンセルしました。 |
PURCHASE_NOT_FINISHED_PREVIOUS_PURCHASING | 4003 | 購入ロジックがまだ完了していない状態でAPIが呼び出されました。 |
PURCHASE_NOT_ENOUGH_CASH | 4004 | 該当ストアのキャッシュが不足しているため決済できません。 |
PURCHASE_INACTIVE_PRODUCT_ID | 4005 | 該当商品が有効な状態ではありません。 |
PURCHASE_NOT_EXIST_PRODUCT_ID | 4006 | 存在しないGamebaseProductIDで決済をリクエストしました。 |
PURCHASE_LIMIT_EXCEEDED | 4007 | 月購入限度を超過しました。 |
PURCHASE_NOT_SUPPORTED_MARKET | 4010 | サポートしないストアです。 選択できるストアはAS(App Store)、GG(Google)、ONESTORE、GALAXYです。 |
PURCHASE_EXTERNAL_LIBRARY_ERROR | 4201 | IAPライブラリエラーです。 DetailCodeを確認してください。 |
PURCHASE_UNKNOWN_ERROR | 4999 | 定義されていない購入エラーです。 全てのログをサポートへご送付ください。迅速に対応いたします。 |
* エラーコードの一覧は、次の文書を参照してください。 | ||
* エラーコード |
PURCHASE_EXTERNAL_LIBRARY_ERROR
GamebaseError* gamebaseError = error; // GamebaseError object via callback
if (Gamebase::IsSuccess(error))
{
// succeeded
}
else
{
UE_LOG(GamebaseTestResults, Display, TEXT("code: %d, message: %s"), error->code, *error->message);
GamebaseInnerError* moduleError = gamebaseError.error; // GamebaseError.error object from external module
if (moduleError.code != GamebaseErrorCode::SUCCESS)
{
UE_LOG(GamebaseTestResults, Display, TEXT("moduleErrorCode: %d, moduleErrorMessage: %s"), moduleError->code, *moduleError->message);
}
}