CDK

埋め込みフロー

CDKは、単一のインターフェース内で完全な検証可能な保護者の同意(VPC)フローを処理するエンドツーエンドウィジェットを提供し、年齢ゲート、VPC、データ通知、権限、設定を1つのシームレスなエクスペリエンスでカバーします。

モバイルでのウィジェットの利用

エンドツーエンドウィジェットと年齢ゲートウィジェットは、モバイルで完全にサポートされています。確認URLに使用するのと同じシステムブラウザサーフェスでウィジェットURLを表示し、redirectUrlコールバックを通じて結果を受け取ってください。表示方法については、モバイルアプリガイドを参照してください。

年齢ゲートと同意ステップについては、カスタムワークフローとCDK UXガイドラインを使用してUXをネイティブに構築することで、通常、最もシームレスでブランドに統合されたプレイヤーエクスペリエンスを実現できます。ウィジェットUIは現在モバイルで動作しており、そのモバイルUXは継続的に最適化されています。

エンドツーエンドウィジェットとは?

エンドツーエンドウィジェットは、単一のインターフェースで完全なコンプライアンスフローを処理する包括的なソリューションで、年齢ゲート、VPC、データ通知、権限、設定を1つのシームレスなエクスペリエンスでカバーします。このウィジェットは、子供のデバイスまたは親自身のデバイスで親が使用でき、同意プロセスに最大の柔軟性を提供します。

ウィジェットURLの生成

/widget/generate-e2e-url APIを呼び出して、完全なVPCフローを処理するエンドツーエンドウィジェットURLを作成します。これにより、ユーザーが年齢収集と保護者の同意プロセスを完了するための一意のURLが返されます。

リクエストの例

POST /api/v1/widget/generate-e2e-url
Content-Type: application/json
Authorization: Bearer your-api-key

{
  "jurisdiction": "US-CA"
}

設定フラグ

オプションのflagsパラメータを使用すると、スキップするフローの部分をカスタマイズできます:

  • skipDataNotices: データ通知と同意収集をスキップ
  • skipVerification: 確認ステップをスキップ
  • skipPermissions: 権限管理をスキップ
  • skipPreferences: 設定をスキップ

プラットフォーム年齢シグナルの送信(オプション)

ゲームがすでにプラットフォーム(Apple iOS、Google Play、Xbox、Meta Horizon、または以前のk-ID確認)からの年齢データを持っている場合、platformAgeSignalとしてリクエストボディに含めてください。ウィジェットはこのシグナルを内部の年齢ゲートチェックに転送するため、確認済みシグナルが成人を示す場合は年齢ゲートをスキップでき、別の確認手順なしに確認済み年齢権限を満たし、シグナルとプレイヤーが自己申告した年齢の矛盾を検出できます。

POST /api/v1/widget/generate-e2e-url
Content-Type: application/json
Authorization: Bearer your-api-key

{
  "jurisdiction": "US-CA",
  "platformAgeSignal": {
    "name": "apple-ios",
    "ageLow": 18,
    "ageHigh": 25,
    "declarationType": "governmentIDChecked"
  }
}

サポートされているプラットフォームとフィールド形式については、プラットフォーム年齢シグナルを参照してください。

レスポンスの例

{
  "id": "7854909b-9124-4bed-9282-24b44c4a3c97",
  "url": "https://family.k-id.com/widget?token=eyJhbGciOiJFUzM4NCIs..."
}

ウィジェットURLの表示

ウィジェットURLはホストされたWebページです。アプリケーションに適したサーフェスで開いてください:

  • Webアプリ: iframeに埋め込む(以下の例を参照)、ポップアップウィンドウで開く、または全画面リダイレクトする。
  • モバイルアプリ: ウィジェットURLをシステムブラウザサーフェス(AndroidではCustom Tabs、iOSではASWebAuthenticationSession)で開き、options.redirectUrlを渡して、結果をアプリに戻るディープリンクとして受け取ります。表示方法については、モバイルアプリクイックスタートを参照してください。最もブランドに統合されたエクスペリエンスを実現するには、代わりにカスタムワークフローで年齢ゲートと同意のUXをネイティブに構築することを検討してください。
  • コンソール (Switch、PlayStation、Xbox): コンソールブラウザは通常制限されているか存在しません。ウィジェットURLをQRコードとして表示し、プレイヤーがペアリングされたモバイルデバイスでフローを完了できるようにします。モバイルデバイスのリダイレクトはコンソールに戻れないため、結果はWebhookと/session/getポーリングで受信してください。

ウィジェット内で利用可能な方法は、ホストに関係なく管轄区域の要件に自動的に適応します。

Webの例

<div id="vpc-container">
  <iframe 
    id="vpc-widget"
    src="WIDGET_URL" 
    width="100%" 
    height="600"
    frameborder="0"
    allow="camera;payment;publickey-credentials-get;publickey-credentials-create">
  </iframe>
</div>

モバイルサーフェスの場合は、/widget/generate-e2e-urlを呼び出すときにoptions.redirectUrlを渡し、アプリでコールバックを処理してください。エンドツーエンドの例については、モバイルアプリクイックスタートを参照してください。

イベントの処理

DOMイベントが届く場所

以下のJavaScriptイベント(Widget.AgeGate.Result、Widget.AgeGate.Challenge、Widget.ExitReview)はpostMessageで配信されます。受信するには、ウィジェットのwindowに対するライブJavaScriptリスナーがホスト側に必要です。これにはiframeホスト、window.openで開かれたポップアップウィンドウ、JSブリッジを持つモバイルWebView / WKWebViewが含まれます(モバイルアプリクイックスタートを参照)。システムブラウザコンポーネント(ASWebAuthenticationSession、SFSafariViewController、Chrome Custom Tabs)と全画面トップレベルリダイレクトはリスナーを公開しないため、redirectUrlコールバックで結果を受け取り、/session/getまたはWebhooksでサーバーサイドで確認してください。

年齢ゲートフローが完了すると、プレイヤーの権限と年齢ステータスを保存するためにセッションが作成されます。フローがチャレンジを必要とするたびにチャレンジが作成されます。これは、確認可能な保護者の同意、またはプレイヤーが保護者の同意をスキップできる年齢を申告した場合のAutomatic age assuranceのためです。

ウィジェットは、リッスンできるJavaScriptイベントを発行します。Widget.AgeGate.Resultイベントをリッスンしてください。そのdata.statusはフローがどのように終了したかを示します:

  • PASS: プレイヤーが年齢ゲートを通過し、セッションが作成されました。data.sessionIdが存在します。
  • FAIL: 必要なチャレンジが通過しませんでした(たとえば、信頼できる大人が保護者の同意を拒否した、またはプレイヤーがAutomatic age assuranceを完了しなかった場合)。セッションは作成されません。
  • PROHIBITED: プレイヤーはこの管轄区域におけるプロダクトの最低年齢に達しておらず、続行できません。セッションは作成されず、data.ageに入力された年齢が含まれます。プレイヤーの続行をブロックしてください。

フロー中にチャレンジが作成された場合、イベントにはchallengeIdも含まれます。チャレンジ固有のイベントの詳細については、Widget.AgeGate.Challengeを参照してください。

UIを閉じる

ウィジェットUIをいつ閉じるかを判断するには、Widget.ExitReviewイベントをリッスンしてください。このイベントは、ユーザーが「完了」ボタンをクリックしたときに発行され、フローが完了し、iframeを閉じるか非表示にする必要があることを示します。

window.addEventListener('message', (event) => {
  if (!event.origin.endsWith('.k-id.com')) {
    return;
  }

  const message = event.data;

  if (message.eventType === 'Widget.AgeGate.Result') {
    if (message.data.status === 'PASS') {
      const sessionId = message.data.sessionId;

      // challengeId が存在する場合、フロー中にチャレンジが解決されました
      // (たとえば、保護者の同意または Automatic age assurance)。
      if (message.data.challengeId) {
        console.log('Challenge resolved, session issued:', sessionId);
      } else {
        console.log('Session created (no challenge required):', sessionId);
      }

      grantAccess(sessionId);
    } else if (message.data.status === 'FAIL') {
      // 必要なチャレンジが通過しませんでした(たとえば、保護者の同意が
      // 拒否された、または Automatic age assurance が完了しなかった)。セッションなし。
      console.log('Age gate not passed');
      restrictAccess();
    } else if (message.data.status === 'PROHIBITED') {
      // プレイヤーはプロダクトの最低年齢に達していません。
      // セッションは作成されません。続行をブロックします。
      console.log('Player below minimum age:', message.data.age);
      restrictAccess();
    }
  }

  // 必要に応じてチャレンジ固有のイベントを処理
  if (message.eventType === 'Widget.AgeGate.Challenge') {
    if (message.data.status === 'FAIL') {
      // 保護者が同意を拒否。アクセスを制限
      console.log('Consent denied');
      restrictAccess();
    }
  }

  if (message.eventType === 'Widget.ExitReview') {
    // ユーザーが「完了」をクリックしたときにウィジェットUIを閉じる
    closeWidget();
  }
});

リダイレクトURLで結果を受け取る

システムブラウザサーフェス(ASWebAuthenticationSession、SFSafariViewController、Chrome Custom Tabs)と全画面トップレベルリダイレクトはDOMリスナーを公開できないため、代わりにredirectUrlコールバックで年齢ゲートの結果を受け取ります。/widget/generate-e2e-urlまたは/widget/generate-age-gate-urlを呼び出すときにoptions.redirectUrlを渡してください。このURLはhttp(s)とカスタムスキームのモバイルディープリンク(たとえばmyapp://age-gate/return)を受け付けます。

年齢ゲートフローが完了すると、k-IDはWidget.AgeGate.Resultイベントが持つのと同じ結果フィールドをクエリパラメータとして追加し、プレイヤーをあなたのURLに遷移させます。リダイレクトURLの既存のクエリパラメータは保持されます。

パラメータ説明
statusPASS、FAIL、またはPROHIBITED(以下を参照)
sessionId新しく作成されたセッション。statusがPASSの場合にのみ存在します。
challengeIdフローに関与したチャレンジ(作成された場合)。
ageプレイヤーが入力した年齢。statusがPROHIBITEDの場合に存在します。

statusの値はDOMイベントと一致します:

  • PASS: プレイヤーが年齢ゲートを通過し、セッションが作成されました。sessionIdでアクセスを許可します。
  • FAIL: 必要なチャレンジが通過しませんでした(たとえば、保護者の同意が拒否された、またはAutomatic age assuranceが完了しなかった場合)。セッションは作成されません。
  • PROHIBITED: プレイヤーはこの管轄区域におけるプロダクトの最低年齢に達していません。セッションは作成されません。プレイヤーの続行をブロックしてください。

たとえば、最低年齢に達していないプレイヤーは次のURLに遷移します:

myapp://age-gate/return?status=PROHIBITED&age=8

リダイレクトのクエリパラメータは信頼できる結果ではなく、UXのヒントとして扱ってください。アクセスを許可する前に、Challenge.StateChange webhookまたは/session/getでサーバーサイドで結果を確認してください。

ウィジェットが処理する内容

ウィジェットは自動的に以下を処理します:

  • 年齢収集: 管轄区域に適した年齢収集方法
  • データ通知: Compliance Studioでのプロダクト設定に応じて受け入れるデータ通知
  • 権限: Compliance Studioでのプロダクト設定に応じて管理する権限
  • 保護者の同意チャレンジ: ユーザーが未成年者と判断された場合、信頼できる大人の承認のためにチャレンジが作成されます
  • Automatic age assurance: プロダクトが管轄区域で Automatic age assurance を有効化している場合、申告された年齢が保護者の同意をスキップできるほど高いプレイヤーは、セッションが発行される前にウィジェット内で申告した年齢を証明するよう求められます(顔年齢推定またはID書類)。

特定のフローは、管轄区域とCompliance Studioでのプロダクト設定によって異なります。

Automatic age assurance によるセッション作成タイミング

Automatic age assurance がエンドツーエンドウィジェット内でトリガーされる場合、セッションは年齢ゲート完了直後ではなく、プレイヤーが検証を通過した後に作成されます。フロー完了時に Widget.AgeGate.Result イベントは引き続き発火し、PASS の場合は sessionId を含みます。イベントが届くまでは、フローは進行中として扱ってください。

VPCの実装の詳細については、クイックスタートガイドを参照してください。

On this page