1. 利用例
注: このセクションは規範的ではありません。
1.1. サービスインスタンスの取得
window.getDigitalGoodsService()
の呼び出しから始まります。このメソッドは特定のコンテキスト(例:HTTPS、アプリ、ブラウザ、OS)でのみ利用可能な場合があります。
利用できる場合、メソッドはサービスプロバイダーのURLを指定して呼び出すことができます。
指定したサービスプロバイダーが利用不可の場合、このメソッドはPromiseをリジェクトします。
if ( window. getDigitalGoodsService=== undefined ) { // このコンテキストではデジタル商品APIはサポートされていません。 return ; } try { const digitalGoodsService= await window. getDigitalGoodsService( "https://example.com/billing" ); // ここでサービスを利用します。 ... } catch ( error) { // 希望するサービスプロバイダーが利用できませんでした。 // 通常のウェブベースの決済フローを利用してください。 console. error( "サービスの取得に失敗:" , error. message); return ; }
1.2. アイテム情報の取得
const details= await digitalGoodsService. getDetails([ 'shiny_sword' , 'gem' , 'monthly_subscription' ]); for ( itemof details) { const priceStr= new Intl. NumberFormat( locale, { style: 'currency' , currency: item. price. currency} ). format( item. price. value); AddShopMenuItem( item. itemId, item. title, priceStr, item. description); }
getDetails()
メソッドは特定のアイテムのサーバー側情報を返します。これはユーザーに購入オプションや価格を表示するためのもので、購入フローを実行することなくメニューで表示できます。
返される ItemDetails
シーケンスの順序は任意であり、入力リストと出力が1:1で対応しない場合(サーバにアイテムが無い場合は含まれません)もあります。
アイテムIDはストアサーバで設定された主キーを表す文字列です。アイテムID一覧を取得する関数は無いため、クライアント側でハードコードするか、開発者自身のサーバから取得する必要があります。
アイテムの価格は PaymentCurrencyAmount
であり、ユーザーの現在の地域・通貨での価格が格納されます。ユーザーのロケールに合わせてIntl.NumberFormatでフォーマットできます(上記例参照)。
ItemDetails
オブジェクトの各フィールドについては、下記[ItemDetails 辞書]セクションを参照してください。
1.3. Payment Request APIでの購入
const details= await digitalGoodsService. getDetails([ 'monthly_subscription' ]); const item= details[ 0 ]; new PaymentRequest( [{ supportedMethods: 'https://example.com/billing' , data: { itemId: item. itemId}}]);
購入フロー自体にはPayment Request API
を利用します。ここでは完全な支払いリクエストのコードは省略していますが、ユーザーが購入を選択したアイテムのIDは、メソッドデータ内のdataフィールドにストアごとの形式で渡すことができます。
1.4. 既存購入の確認
purchases= await digitalGoodsService. listPurchases(); for ( pof purchases) { VerifyOnBackendAndGrantEntitlement( p. itemId, p. purchaseToken); }
listPurchases()
メソッドは、ユーザーが現在所有・購入しているアイテムの一覧を取得するためのものです。エンタイトルメント(例:サブスクリプションやプロモコード、有料アップグレードの有効性確認)や、途中で通信エラーが発生した場合の復旧(例:購入済みだがバックエンド未確認の場合)などに必要となる場合があります。メソッドはアイテムIDと購入トークンを返し、エンタイトルメント付与前に開発者-プロバイダー間のAPIで検証されるのが一般的です。
1.5. 過去の購入履歴の確認
const purchaseHistory= await digitalGoodsService. listPurchaseHistory(); for ( pof purchaseHistory) { DisplayPreviousPurchase( p. itemId); }
listPurchaseHistory()
メソッドは、ユーザーがこれまで購入した各アイテム種別の最新購入を一覧取得するためのものです。期限切れまたは消費済み購入も含まれることがあります。ストアによっては購入履歴を保存しない場合もあり、その場合はlistPurchases()
と同じデータになります。
1.6. 購入の消費
digitalGoodsService. consume( purchaseToken);
複数回購入可能な商品は、再度購入する前に「消費済み」にする必要があります。例として、ゲーム内でプレイヤーを一時的に強化する消耗アイテムなどがあります。これはconsume()
メソッドで実現できます。
より確実に消費を保証するために、可能な場合は開発者-プロバイダー間のAPIで消費処理することが推奨されます。
1.7. サブドメインiframeとの利用
< iframe src= "https://sub.origin.example" allow= "payment" > < /iframe>
サブドメインのiframeからデジタル商品APIを利用可能にするには、iframe要素のallow属性に"payment"キーワードを指定します。クロスオリジンiframeでは本APIの呼び出しはできません。詳細や例についてはPermissions Policy仕様を参照してください。
2. API定義
2.1. Windowインターフェースの拡張
partial interface Window { [SecureContext ]Promise <DigitalGoodsService >getDigitalGoodsService (DOMString ); };serviceProvider
Window
オブジェクトは getDigitalGoodsService()
メソッドを公開してもよい(MAY)。デジタル商品をサポートしないユーザーエージェントはgetDigitalGoodsService()を
Window
インターフェース上に公開すべきではありません(SHOULD NOT)。
注: 上記の記述は機能検出を許容するためのものです。getDigitalGoodsService()
が存在すれば、少なくとも1つのサービスプロバイダーで動作することが期待されます。
2.1.1. getDigitalGoodsService() メソッド
注: getDigitalGoodsService()
メソッドは指定したserviceProvider
が現在のコンテキストでサポートされているかどうかを判定するために呼び出されます。メソッドは
DigitalGoodsService
オブジェクトでPromiseを解決(resolve)しますが、serviceProviderが非対応や何らかのエラーの場合は例外でリジェクト(reject)します。
serviceProvider
には通常URLベースの決済手段識別子を指定します。
getDigitalGoodsService(serviceProvider)
メソッドが呼ばれたとき、以下の手順を実行する:
-
document を 現在の設定オブジェクトの 関連グローバルオブジェクト の関連付けられた
Documentとする。 -
もし document が 完全にアクティブ でなければ、a promise rejected with を返し、
"InvalidStateError"DOMExceptionとする。 -
もし document の オリジン がトップレベルオリジンと同一オリジンでなければ、 a promise rejected with を返し、
"NotAllowedError"DOMExceptionとする。 -
もし document が "payment" パーミッションを利用可能でなければ、 a promise rejected with を返し、
"NotAllowedError"DOMExceptionとする。 -
もし serviceProvider が undefined か null か空文字列なら、a promise rejected with を返し、
TypeErrorとする。 -
result を、デジタル商品サービス作成可否アルゴリズム(serviceProviderとdocumentを渡す)を実行した結果とする。
-
result が false なら a promise rejected with を返し、
OperationErrorとする。
2.1.2. デジタル商品サービス作成可否アルゴリズム
-
ユーザーエージェントはserviceProviderやdocument、あるいは外部要因に応じて true または false を返してよい(MAY)。
注: これによりユーザーエージェントは異なるコンテキストで異なるサービスプロバイダーをサポートできます。
2.2. DigitalGoodsService インターフェース
[Exposed =Window ,SecureContext ]interface {DigitalGoodsService Promise <sequence <ItemDetails >>getDetails (sequence <DOMString >);itemIds Promise <sequence <PurchaseDetails >>listPurchases ();Promise <sequence <PurchaseDetails >>listPurchaseHistory ();Promise <undefined >consume (DOMString ); };purchaseToken dictionary {ItemDetails required DOMString ;itemId required DOMString ;title required PaymentCurrencyAmount ;price ItemType ;type DOMString ;description sequence <DOMString >;iconURLs DOMString ;subscriptionPeriod DOMString ;freeTrialPeriod PaymentCurrencyAmount ;introductoryPrice DOMString ; [introductoryPricePeriod EnforceRange ]unsigned long long ; };introductoryPriceCycles enum {ItemType ,"product" , };"subscription" dictionary {PurchaseDetails required DOMString ;itemId required DOMString ; };purchaseToken
2.2.1. getDetails() メソッド
getDetails(itemIds)
メソッドが呼び出されたとき、次の手順を実行する:
-
itemIds が空の場合、a promise rejected with を返し、
TypeErrorとする。 -
result をデジタル商品サービスから指定された itemIds の情報をリクエストした結果とする。
注: これによりユーザーエージェント内でサービスプロバイダーごとの動作が可能になる。
-
result がエラーの場合、 a promise rejected with を返し、
OperationErrorとする。 -
result 内の各 itemDetails について:
-
itemDetails.itemId は空文字列であってはならない(SHOULD NOT)。
-
itemIds は itemDetails.itemId を 含むべき(SHOULD)。
-
itemDetails.title は空文字列であってはならない(SHOULD NOT)。
-
itemDetails.price は 正規 PaymentCurrencyAmount でなければならない(MUST)。
-
存在する場合、itemDetails.subscriptionPeriod は iso-8601 期間でなければならない(MUST)。
-
存在する場合、itemDetails.freeTrialPeriod はiso-8601 期間でなければならない(MUST)。
-
存在する場合、itemDetails.introductoryPrice は 正規 PaymentCurrencyAmount でなければならない(MUST)。
-
存在する場合、itemDetails.introductoryPricePeriod は iso-8601 期間でなければならない(MUST)。
-
-
a promise resolved with result を返す。
注: result の項目の順序が itemIds の順序と一致する必要はない。これは無効・欠落したアイテムを出力リストから省略可能にするため。
2.2.2. listPurchases() メソッド
listPurchases() メソッドが呼び出されたとき、次の手順を実行する:
-
result をデジタル商品サービスからユーザーの購入情報をリクエストした結果とする。
注: これによりユーザーエージェント内でサービスプロバイダーごとの動作が可能になる。
-
result がエラーの場合、 a promise rejected with を返し、
OperationErrorとする。 -
result 内の各 itemDetails について:
-
itemDetails.itemId は空文字列であってはならない(SHOULD NOT)。
-
itemDetails.purchaseToken は空文字列であってはならない(SHOULD NOT)。
-
-
a promise resolved with result を返す。
2.2.3. listPurchaseHistory() メソッド
listPurchaseHistory()
メソッドが呼び出されたとき、次の手順を実行する:
-
result をユーザーがこれまで購入した各アイテム種別の最新購入情報のリクエスト結果とする。
-
result がエラーの場合、 a promise rejected with を返し、
OperationErrorとする。 -
result 内の各 itemDetails について:
-
itemDetails.itemId は空文字列であってはならない(SHOULD NOT)。
-
itemDetails.purchaseToken は空文字列であってはならない(SHOULD NOT)。
-
-
a promise resolved with result を返す。
2.2.4. consume() メソッド
注: この文脈での「消費」は購入を使い切ることを意味します。消費後はユーザーにその購入品の権利はなくなると想定されます。
consume(purchaseToken)
メソッドが呼び出されたとき、次の手順を実行する:
-
purchaseToken が空文字列の場合、 a promise rejected with を返し、
TypeErrorとする。 -
result をデジタル商品サービスに purchaseToken を消費として記録するようリクエストした結果とする。
注: これによりユーザーエージェント内でサービスプロバイダーごとの動作が可能になる。
-
result がエラーの場合、 a promise rejected with を返し、
OperationErrorとする。
2.3. ItemDetails 辞書
このセクションは規範的ではありません。
ItemDetails
辞書は、serviceProvider
から取得したデジタルアイテムの情報を表します。
-
itemIdは現在のアプリ内の特定のデジタルアイテムを識別します。アプリ内で一意であることが期待されますが、すべてのアプリ間で一意であるとは限りません。 -
titleはユーザーに表示するためのアイテム名です。これはserviceProviderによってユーザー向けにローカライズされていることが期待されます。 -
priceはアイテムの価格であり、上記§ 1.2 アイテム情報の取得例のようにユーザー向けにフォーマットして表示できます。これはserviceProviderによってユーザー向けにローカライズされていることが期待されます。 -
descriptionはユーザーに表示するためのアイテムの詳細説明です。これはserviceProviderによってユーザー向けにローカライズされています。 -
iconURLsはそのアイテムのビジュアル説明のためのアイコン一覧です。 -
subscriptionPeriodは、ISO 8601 期間で指定される期間であり、その間だけユーザーに権利が付与されます。この期間が経過した後は権利が更新または消失すると想定されます(この制御はDigital Goods API外)。これはサブスクリプションのみに設定される想定であり、単体購入には設定されません。 -
freeTrialPeriodは、ISO 8601 期間で指定され、ユーザーが支払いをせずに特典を受けられる期間です。この期間後は有償となるか権利消失と想定されます(Digital Goods API外で制御)。このフィールドもサブスクリプション専用です。 -
introductoryPriceはアイテムの初期価格であり、§ 1.2 アイテム情報の取得例のようにユーザー向けに表示できます。これはserviceProviderによってローカル化されていることが期待されます。 -
introductoryPricePeriodは ISO 8601 期間で指定され、その間のみintroductoryPriceで購入できます。その後はprice価格が適用される想定です。 -
introductoryPriceCyclesは、introductoryPriceが適用されるサブスクリプションの回数です。
2.4. PurchaseDetails 辞書
このセクションは規範的ではありません。
PurchaseDetails
辞書は、ユーザーが何らかの時点で購入した
serviceProvider
のデジタルアイテムについての情報を表します。
-
itemIdは現在のアプリ内の特定アイテムを識別します。アプリ内で一意であることが期待されますが、すべてのアプリ間で一意とは限りません。これはitemId(getDetails()メソッドで使用)と同等であることが想定されます。 -
purchaseTokenはserviceProviderにより生成された購入を表す任意のトークンです。 このトークンは(Digital Goods API外で)サービスプロバイダーへ直接問い合わせて購入確認などに使用することを想定しています。
3. Permissions Policy との統合
本仕様は、"ポリシー制御機能" を "payment" という文字列で定義します。その デフォルト許可リストは 'self' です。
注: document の
permissions policy により、そのドキュメント内のコンテンツが
DigitalGoodsService
インスタンスを取得できるか決まります。どこかで無効化されていれば、その document 内のいかなるコンテンツも allowed to use
getDigitalGoodsService()
メソッドは利用できません(呼び出すと例外がスローされます)。
4. 追加定義
"payment" パーミッションは [permissions-policy] のフィーチャーであり、 payment-request仕様で定義されています。
正規化された
PaymentCurrencyAmount
とは、PaymentCurrencyAmount
の amount が 正規化(check and
canonicalize amount)の手順を実行してもエラーにも変更も発生しないものです。
iso-8601 は日付・時刻表現の標準規格です。