トランザクション
このガイドでは、トランザクションの統合について説明します。保護者が確認できるように購入を報告すること、請求の前に保護者に購入の承認を求めること、そして完了したカード決済を保護者の同意の代わりとして使えるようにすることを扱います。
トランザクションとは何か、k-IDとプロダクトの責任の境界がどこにあるかについては、先にトランザクションの概念を読んでください。支払いによる確認には専用の概念ページがあります。
始める前に
- 組織でトランザクションが利用可能か確認する。 この機能を組織で有効にするには、k-IDにお問い合わせください。
- 利用する部分を有効にする。 トランザクションは既定では無効で、Compliance StudioのTransactionsセクションでプロダクトごとに設定します。Transactionsは他の2つが依存するスイッチです。エンドポイントが必要とするスイッチが有効になるまで、そのエンドポイントは
FEATURE_DISABLEDを返します。3つのスイッチとそれぞれが制御する対象については、機能フラグを参照してください。 - Webhookのエンドポイントを設定する(購入の承認を使う場合)。承認の結果はWebhookとして届きます。プロダクトのDeveloper SettingsでURLとシークレットを設定し、Webhooksの概要の説明に従って署名を検証してください。
- 処理するイベントを購読する。 エンドポイントは購読しているイベントタイプのみを受信し、k-IDはそれ以外を配信の試行もエラーもなく破棄します。プロダクトのDeveloper Settingsページで、エンドポイントに対して
Transaction.PurchaseApprovalResultを選択してください。
購入の報告
/transaction/pushは、完了した購入をセッションに対して記録します。購入が完了した後に、定期購入が更新されるたびを含めて呼び出してください。
各イベントは、冪等性のためのid、保護者にそのまま表示されるtitleと任意のdescription、通貨の最小単位でのamount、currency、完了したtimestamp、保護者がそれを管理できる任意のurl、そしてstatusを持ちます。
| フィールド | 内容 |
|---|---|
id | プロダクトが生成するUUID。sessionIdと合わせて冪等性キーとなります。すでに受理されたidを再送しても、二重に記録されることなく再びacceptedとなります。 |
type | purchase。 |
title、description | 保護者にそのまま表示されます。titleは必須で、descriptionは任意です。 |
amount | 通貨のISO 4217最小単位での整数。499はUSDでは4.99、JPYでは499です。無料アイテムのためにゼロも許容されます。 |
currency | ISO 4217コード。大文字が正規形で、小文字も受け入れられ正規化されます。 |
timestamp | RFC 3339のUTC。過去7日以内で、未来ではないこと。 |
url | 保護者が購入を管理するために開ける任意のHTTPSリンク。たとえばサブスクリプションの解約用です。 |
status | successful、または試みられたが完了しなかった請求にはfailed。failedを報告することで、成立した購入と成立しなかった購入とを保護者が見分けられます。 |
1回の呼び出しで最大100件のイベントを受け取ります。
{
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"events": [
{
"id": "9d4e2f81-7a3b-4c56-8e90-1f2a3b4c5d6e",
"type": "purchase",
"title": "Starter Pack",
"description": "500 coins and a cosmetic item",
"amount": 499,
"currency": "USD",
"timestamp": "2026-06-24T09:00:00Z",
"status": "successful",
"url": "https://your-webstore.example.com/manage?ref=order-4455667"
}
]
}
イベントは個別に処理されるため、バッチ全体が成功したと想定せず、イベントごとのステータスを読んでください。
{
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"accepted": 1,
"rejected": 0,
"events": [
{ "id": "9d4e2f81-7a3b-4c56-8e90-1f2a3b4c5d6e", "status": "accepted" }
]
}
拒否されたイベントのreasonがinvalid_inputの場合、そのイベントは検証ルールに違反しており、そのまま再送しても再び失敗します。reasonがinternal_errorの場合は一時的なもので、再送して問題ありません。セッションが存在しないか取り消されている場合は、イベントごとではなくバッチ全体が拒否されます。
報告された購入は、Family Connectの子どもごとの購入ビューとしてリンクされた保護者に提示され、その金額は、信頼できる大人がそこで、また定期的なダイジェストメールで読むアクティビティにも反映されます。
承認のリクエスト
請求の前に保護者の決定を求めたい場合、/transaction/request-purchaseが承認リクエストを開きます。請求の前に求め、approvedの結果が届いてから初めて購入を完了してください。
{
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"id": "9d4e2f81-7a3b-4c56-8e90-1f2a3b4c5d6e",
"title": "Starter Pack",
"description": "500 coins and a cosmetic item",
"amount": 499,
"currency": "USD"
}
レスポンスには送信したidとexpiresAtが含まれます。idを保存してください。結果のWebhookと対応付けるためのものです。
{
"id": "9d4e2f81-7a3b-4c56-8e90-1f2a3b4c5d6e",
"expiresAt": "2026-06-25T16:00:00Z"
}
k-IDはセッションに登録された保護者にリクエストをメールで送り、保護者はFamily Connectで承認または拒否します。結果はapproved、denied、またはexpiredを伴うTransaction.PurchaseApprovalResultのWebhookとして届き、data.idで対応付けられます。
このフローの以下の性質を前提に設計してください。
- 請求の前に承認を求めてください。 リクエストは購入の前に置くゲートであり、購入の記録ではありません。
approvedで請求し、deniedとexpiredは「請求しない」として扱ってください。 - リクエストは24時間後に有効期限切れとなります。 有効期限切れは
status: "expired"でWebhookを発行し、失敗ではなく通常の結果です。プレイヤーには改めてその購入を提示できます。Webhookを無期限に待つのではなく、expiresAtを期限として扱ってください。 - リクエストは
idごとに冪等です。 まだ決定を待っているidを再送すると、2件目を開いたり保護者に2度促したりせず、保留中のリクエストをそのまま返します。 - 1人のプレイヤーが保持できる保留中のリクエストは最大20件です。 それを超えると、1件が解決するまで呼び出しは
INVALID_INPUTで拒否されます。 - 保護者に促すには、プレイヤーにリンクされた保護者が必要です。 リクエストはセッションに登録された承認者に送られます。保護者がリンクされていないプレイヤーに対してリクエストを開いても、通知する相手がいません。そのため先に保護者のリンクを確立してください。検証済み保護者リンクを参照してください。
ペイロードとすべてのステータスについては、Transaction.PurchaseApprovalResultを参照してください。
支払いによる確認
セッションの管轄区域でクレジットカード確認方法が有効な場合、完了したクレジットカード決済は、別途の確認の代わりに保護者の同意ステップを満たすことができます。何が条件を満たすか、そしてその理由については支払いによる確認の概念を読んでください。このセクションは統合です。
支払いによる確認は、標準の保護者同意チャレンジに付随します。/challenge/send-emailで同意メールを送るところを、代わりに/challenge/send-email-with-payment-verificationで送り、paymentVerificationのアテステーションを追加します。チャレンジのそれ以外の点はすべて変わりません。
アテステーションは、どのプロバイダーを使う場合でも、支払いをk-IDのフィールドで記述します。
| フィールド | 内容 |
|---|---|
provider | 支払いを処理した記録上の販売者。invoiceIdのスコープを定めます。 |
invoiceId | 記録上の販売者における支払いの識別子。k-IDはこれを不透明なものとして扱います。 |
payerEmail | 支払いを行ったメールアドレス。 |
instrument | 支払いに使われたもの。card、wallet、またはother。 |
funding | カードの資金タイプ。credit、debit、prepaid、またはunknown。条件を満たすのはcreditだけです。プロバイダーが資金タイプを報告しない場合はunknownを送ってください。 |
他の同意メールと同じ方法でチャレンジ上に送り、アテステーションをpaymentVerificationに入れます。
{
"challengeId": "ae6d4729-af32-42ea-8ef2-ff46c7664802",
"email": "parent@example.com",
"paymentVerification": { "...": "the normalized attestation from your merchant of record" }
}
k-IDは支払いを処理も直接確認もしないため、実際に完了した支払いだけをアテステーションとしてください。
プロバイダーの支払いの正規化
記録上の販売者は、それぞれ異なる形で支払いを報告します。任意で/transaction/lookup-providerを使って、記録上の販売者からの生の支払いシグナルを標準のアテステーションの形に正規化できます。
たとえばXsollaの場合、生のpayment Webhookの本文を送ります。これにはカードのBINが含まれている必要があります。
{
"provider": "xsolla",
"data": { "...": "the raw Xsolla payment webhook body" }
}
同意メールのpaymentVerificationに入れる、正規化されたアテステーションを返します。
{
"provider": "xsolla",
"invoiceId": "2110445753",
"payerEmail": "parent@example.com",
"instrument": "card",
"funding": "credit"
}
機能フラグ
トランザクションには3つのスイッチがあり、Transactionsは他の2つが必要とするスイッチです。
| スイッチ | 有効になる機能 | 対象のエンドポイント |
|---|---|---|
| Transactions | 購入の報告とプロバイダーの支払いの正規化 | /transaction/push、/transaction/lookup-provider |
| Purchase Controls | 保護者に購入の承認を求めること | /transaction/request-purchase |
| Payment-as-verification | 条件を満たすカード決済が同意の代わりになること | /challenge/send-email-with-payment-verification |
スイッチが無効なエンドポイントはFEATURE_DISABLEDを返します。Purchase ControlsとPayment-as-verificationはどちらもTransactionsも必要とするため、Transactionsだけを有効にしたプロダクトは購入を報告し支払いを正規化できますが、承認をリクエストすることはできず、どれも有効でないプロダクトはいずれのエンドポイントも呼び出せません。
公開前チェックリスト
- すべての
/transaction/pushが、バッチが成功したと想定せずにイベントごとのステータスを読み、internal_errorのイベントのみを再送している。 - 購入が
failedの請求を含めて実際のstatusとともに報告されており、保護者が実際に起きたことを見られる。 - 購入の承認が請求の前に求められており、
deniedとexpiredの両方が「請求しない」として処理されている。 - プロダクトのWebhookが
Transaction.PurchaseApprovalResultを購読しており、ハンドラがdata.idについて冪等で、署名を検証している。 - プロダクトが承認リクエストを開く前に、プレイヤーにリンクされた保護者がいる。