ドキュメント

Webshop を Unity ゲームに統合する

認証されたプレイヤー セッションで Unity ゲームから Webshop を開きます。
読み終わるまでの所要時間 21 分最終更新 3ヶ月前

UnityゲームからWebshopを開き、プレイヤーがアプリ内課金(IAP)カタログから製品を購入できるようにします。
Web ショップは、すでに設定した IAP カタログと支払いプロバイダーを使用します。プレイヤーは、ゲーム内のストアで別途購入しなくても、ウェブで購入を完了できます。
ショップを開くには、ボタンなどのゲーム内アクションを追加します。これにより、プレイヤーの認証済みセッションがアタッチされたショップURLが開きます。セッションは Webshop に対してプレイヤーを識別します。

前提条件

開始する前に、以下の前提条件を満たしていることを確認します。
  • アプリ内課金を統合するUnityプロジェクト。
  • プロジェクト内のAuthentication SDK(バージョン3.7.1以降)。
  • ターゲット環境内の Webshop。
ライブショップを開くには、Webshop を公開して
shop.unity.com/{studio}/game/{slug}
で利用できるようにします。ドラフトをテストするには、ターゲット環境に作成された Webshop だけが必要です。
詳細については、「 最初の Webshop の作成と公開 」を参照してください。

ゲームからウェブショップを開く

SDK ヘルパーの使用

Unity Iap SDK には、必要なパラメータとコンプライアンスチェックを使用して Webshop を開くための
RedirectToWebshop
が用意されています。
支払いプロバイダーの
IPaymentProvidersExtendedPurchaseService
経由で
RedirectToWebshop
を呼び出します。
catalogListingId
を空のままにすると Webshop 正面ページが開きます。リスト ID を渡すとプロダクトページが直接開きます。
// Open the front page UnityIAPServices.StoreController(PaymentProvider.Name).PaymentProvidersExtendedPurchaseService.RedirectToWebshop();// Open a specific product page UnityIAPServices.StoreController(PaymentProvider.Name).PaymentProvidersExtendedPurchaseService.RedirectToWebshop(catalogListingId: "your-listing-id");

オープン前にコンプライアンス承認が必要

コンプライアンス チェックで Webshop をゲートするには、
RedirectToWebshop
を呼び出す前に
SetComplianceCheck
にコールバックを登録します。コールバックは各リダイレクトの前に実行されます。
false
を返すとリダイレクトがキャンセルされ、購入は
PurchasingUnavailable
で失敗します。
StoreController(PaymentProvider.Name).PaymentProvidersExtendedPurchaseService .SetComplianceCheck(async context => await ShowComplianceDialog(context));

Webshop を開く方法をコントロール

デフォルトでは、SDK は外部ブラウザーで Webshop を開きます。これを変更するには、リダイレクトする前に支払いプロバイダーの
IPaymentProvidersExtendedPurchaseService
で
SetWebshopPresentationMode(CheckoutPresentationMode)
を呼び出します。この設定は
SetCheckoutPresentationMode
とは無関係です。

手動での統合

SDK ヘルパーを使用できない場合は、Webshop URL を直接作成して開きます。
ボタンやその他のゲーム内アクションから Webshop を開くには、Webshop サービスからショップ URL を解決し、
Application.OpenURL
で URL を開きます。
ランタイムに URL を解決すると、同じビルドでパブリッシュされたショップまたは環境ドラフトプレビューを開くことができます。これにより、公開前にドラフトをテストできます。
URL を解決するには、
storefront-link
エンドポイントに
GET
リクエストを送信します。
https://webshop.services.api.unity.com/v1/projects/{projectId}/environments/{environmentId}/storefront-link
デフォルトでは、サービスは環境の状態に基づいて URL を自動的に返します。
  • 公開された本番環境では、公開中のストアフロント URL が返されます。ライブ URL は匿名で解決します。
  • 非本番環境または未公開の本番環境では、短期間の下書きプレビュー URL が返されます。
ライブショップの未公開の変更をプレビューするには、
source=draft
クエリパラメーターを追加します。これは、パブリッシュされた本番環境であってもドラフトプレビュー URL を返します。
https://webshop.services.api.unity.com/v1/projects/{projectId}/environments/{environmentId}/storefront-link?source=draft
インテグレーションは以下のAuthentication SDKトークンを使用します。
  • アクセストークンは、ドラフトプレビューの解決時に
    storefront-link
    リクエストを承認します。
    Authorization: Bearer
    ヘッダーでアクセストークンを送信します。
  • セッショントークンはブラウザーでプレイヤーを認証します。ショップを開く直前に、短期間の、1回限りの使用に制限されたトークンを
    GenerateRestrictedTokenAsync
    で除外し、そのセッショントークンを
    sessionToken
    クエリパラメーターとして解決済みURLに追加します。
URL を解決したら、セッショントークン、プロジェクト ID、および環境を追加して、正しいプレイヤー用のショップを開きます。
各クエリパラメーターの詳細と、パラメーターがない場合のショップの動作については、「 ゲームから Webshop を開く 」を参照してください。
using System;using System.Collections;using System.Collections.Generic;using Unity.Services.Authentication;using UnityEngine;using UnityEngine.Networking;public class WebshopLauncher :MonoBehaviour{ // Replace these with the values from your Unity Cloud project and webshop configuration. const string ProjectId = "<your-project-id>"; const 文字列 EnvironmentId = "<your-environment-id>"; // API リクエストパスで使用 const 文字列 EnvironmentName = "production"; // ショップ URL で使用 const string StorefrontLinkEndpoint = "https://webshop.services.api.unity.com/v1/projects/{0}/environments/{1}/storefront-link"; // draftPreview: request source=draft to preview unpublished changes even on a live env. public void OpenShop(string locale, string currency, bool draftPreview = false) { StartCoroutine(OpenShopRoutine(locale, currency, draftPreview)); } IEnumerator OpenShopRoutine(string locale, string currency, bool draftPreview) { var signedIn = AuthenticationService.Instance.IsSignedIn; // The access token is required for draft previews; live storefronts open anonymously // and ignore any token sent.プレイヤーがサインインするたびに送信します。 if (draftPreview && !signedIn) { Debug.LogWarning("WebshopLauncher: draft preview requires the player to be signed in."); yield break; } // 1.Webshop サービスにストアフロント URL を問い合わせます。 var endpoint = string.Format(StorefrontLinkEndpoint, ProjectId, EnvironmentId); if (draftPreview) endpoint += "?source=draft"; using var request = UnityWebRequest.Get(endpoint); request.SetRequestHeader("Accept", "application/json"); if (signedIn) request.SetRequestHeader("Authorization", $"Bearer {AuthenticationService.Instance.AccessToken}"); yield return request.SendWebRequest(); if (request.result != UnityWebRequest.Result.Success) { デバッグ.LogError($"WebshopLauncher: storefront-linkリクエストが失敗しました" + $"({request.responseCode}): {request.error}"); yield break; } var link = JsonUtility.FromJson<StorefrontLinkResponse>(request.downloadHandler.text); if (link == null || string.IsNullOrEmpty(link.storefrontUrl)) { Debug.LogError("WebshopLauncher: storefront-link response did not contain a storefrontUrl."); yield break; } // 2.Webshop リダイレクト用の短期間の、1 回限りの使用制限付きトークンを最小にします。 var tokenOptions = new RestrictedTokenOptions { Services = new リスト<string> { "no-svc" }, // ID トークンは実際のサービスに対して使用できません SingleUse = true、 // 最初の更新時に Webshop によって消費されます TtlSeconds = 60, // リダイレクト直前に発生 }; var tokenTask = AuthenticationService.Instance.GenerateRestrictedTokenAsync(tokenOptions); yield return new WaitUntil() => tokenTask.IsCompleted); if (tokenTask.IsFaulted) { Debug.LogError($"WebshopLauncher: failed to generate restricted token: {tokenTask.Exception}"); yield break; } // 3.店を開けろ var sessionToken = tokenTask.Result.SessionToken; var shopUrl = BuildShopUrl(link.storefrontUrl, sessionToken, locale, currency); Application.OpenURL(shopUrl); } 静的文字列 BuildShopUrl(文字列 storefrontUrl、文字列 sessionToken、文字列ロケール、文字列通貨) { var url = storefrontUrl; url = AppendParam(url, "sessionToken", sessionToken); url = AppendParam(url, "projectId", ProjectId); url = AppendParam(url, "environment", EnvironmentName); url = AppendParam(url, "locale", locale); url = AppendParam(url, "currency", currency); return url; } 静的 文字列 AppendParam(文字列 URL, 文字列 キー, 文字列 value) { if (string.IsNullOrEmpty(value)) return url; var separator = url.Contains("?") ? '&' : '?'; return $"{url}{separator}{key}={UnityWebRequest.EscapeURL(value)}"; } Serializable class StorefrontLinkResponse { public string storefrontUrl; public bool live; }}
ショップを開いた後、URL からこれらのパラメータを削除し、ブラウザーでプレイヤーのセッションを維持します。セッションと持続性の詳細については、ゲームから Webshop を開く を参照してください。
注意
子供のプライバシー児童オンラインプライバシー保護法 (COPPA) をはじめとする児童データ保護法では、制限年齢に満たないユーザー (適用法に応じて 13 歳、16 歳、または 18 歳未満の児童など) からのデータの収集とその使用に関して、各種の制限が設けられています。Unity のサービス規約 で説明されている適用法を遵守しない限り、年齢制限ユーザーに属する「個人情報」を Unity に送信することはできません。
渡すロケールまたは通貨がない場合は、これらのパラメーターを省略します。デフォルトでは、IAP カタログはプレイヤーのブラウザーロケールを使用し、デフォルトは米ドル (USD) です。カタログのロケール処理の詳細については、「 カタログと Web ショップでの支払い 」を参照してください。
Webshop に Deeplink URL を設定すると、ショップはそのカスタム URL スキームを通じてプレイヤーをゲームに戻します。ショップは、購入後、およびプレイヤーが未認証のランディングページでConnect to game(ゲームに接続)を選択した場合に、返品ディープリンクを使用します。
リターン ディープ リンクを受信するには、デバイスにカスタム URL スキームを登録し、ランタイムに着信リンクをハンドルします。ショップが戻り URL を構築する方法の詳細については、「 ゲームから Webshop を開く 」を参照してください。
注
Connect to game フローでは、Unity Iap SDK によって Webshop が自動的に開き直されます。このリンクは自分でハンドルする必要はありません。
以下の要件が満たされていることを確認します。
  • プレイヤーは IAP を初期化する前に Unity Authentication にサインインします。
  • PaymentProvider ストアが接続されています。
購入後の返品処理には、標準のプラットフォーム カスタムURLスキーム処理が使用され、Unity固有のSDKは必要ありません。
注
ディープリンクを返します。Unity エディターや WebGL では解決されず、ビルドされたプレイヤーでのみ解決されます。エディタはカスタムスキームのハンドラーとして登録されていないため、ブラウザーから開いたリンクは再生モードにならず、WebGL の構築はカスタムスキームではなくページ URL を使用します。デバイス (iOS または Android) またはスタンドアロンビルドでリターンフローをテストします。プラットフォーム サポートと登録の詳細については、Unityのディープ リンクマニュアルを参照してください。

URL スキームの登録

ダッシュボードの Deeplink URL フィールドで設定したのと同じスキームを宣言します。オペレーティング システムは、このスキームを使用してリンクをゲームにルートします。
  • iOS と macOS:編集> プロジェクト設定> プレイヤー> その他の設定> サポートされる URL スキーム でスキームを追加します。Unity は、ビルド時にそれをビルドしたアプリケーションの
    Info.plist
    (
    CFBundleURLTypes
    ) に書き込みます。ビルドごとに再生成される生成された
    Info.plist
    を手動で編集するよりも優先してください。
  • Androidカスタムのメインマニフェストまたは Gradle マニフェストテンプレートを使用して、
    <data android:scheme="mygame" />
    エントリーを持つ
    intent-filter
    をアクティビティに追加します。
スキームは Deeplink URL 値と正確に一致する必要があります。Android マニフェストを変更したら、ゲームを再インストールして OS に新しいスキームを適用します。
ゲームの実行中に到着するリンクの
Application.deepLinkActivated
をサブスクライブします。起動時に、ディープリンクがゲームを起動するコールドスタートのハンドルにも
Application.absoluteURL
します。
void Awake(){ // Links that arrive while the game is running. Application.deepLinkActivated += OnReturnFromWebshop; // Cold start: the deep link launched the game. if (!string.IsNullOrEmpty(Application.absoluteURL)) OnReturnFromWebshop(Application.absoluteURL);}void OnReturnFromWebshop(string url){ // Handle the post-purchase return: the shop appends ?status=success // (and playerId when available) after a completed purchase. if (new Uri(url).Query.Contains("status=success")) { // Purchase completed on the web — refresh the player's entitlements. } // The Connect to game sign-in link is reopened by the SDK automatically, // so it needs no handling here.}
ショップは
status=success
しか送信しないため、その場合はここでハンドルします。前の注で説明したように、SDK は Connect to game sign-in (ゲームサインインに接続) リンクを自動的に開きます。

テストオープン

公開する前にドラフトプレビューをテストし、公開中のショップに対してテストを繰り返します。ドラフトをテストするには、
draftPreview: true
を使用して
OpenShop
を呼び出し、プレイヤーがサインインしていることを確認します。非本番環境をターゲットにするか、
source=draft
を使用して本番環境で未公開の変更をプレビューできます。
インテグレーションを検証するには、次の手順に従います。
  1. モバイルデバイスにゲームをビルドおよびインストールします。
  2. OpenShop
    を呼び出してデバイスのシステムブラウザーを起動するゲーム内ボタンをトリガー。
  3. ブラウザーで解決済みのストアフロントURLが開き、URLにロケールと通貨が入力されていることを確認します。下書きにすると、環境スコープのプレビュー URL が開きます。ライブ ショップが
    shop.unity.com/{studio}/game/{slug}
    オープンします。
  4. ショップが、未認証のランディングページではなく、認証済み製品リストを開くことを確認します。
  5. サンドボックスの購入を完了します。テスト認証情報については、該当する IAP 支払いプロバイダーのサンドボックスのドキュメントを参照してください。
  6. ドラフトが期待通りに機能したら、
    draftPreview: false
    で
    OpenShop
    を呼び出し、公開中のショップに対してテストを繰り返します。
プロダクト リストではなく未認証のランディング ページにショップが開いた場合は、ゲームにURLの有効な
sessionToken
と
projectId
が渡されたことを確認してください。Webshop のトラブルシューティング を参照してください。