Ecom Web APIs

RESTful端点在不使用SDK的情况下执行所有权验证

Epic Games Store
阅读时间10分钟

Epic在线服务 (EOS) 提供多种方式来验证帐户的目录项所有权。首选的方法是通过Ecom Interface使用EOS SDK API。本文是针对那些偏好通过RESTful终端访问所有权信息的标题和服务而提供的。EOS拥有用于直接在线所有权验证的RESTful服务终端,从而创建并验证可在客户端、服务与权利服务之间传递的所有权令牌,进而查询,枚举和使用 权利 记录。

所有权验证所使用的方法取决于具体用例。游戏客户端或游戏服务器可通过直接与我们的终端集成来使用在线方法。所有权验证令牌方法提供令牌,其中包括游戏客户端、用户和授权相关信息以及可供游戏客户端或任何其他服务验证的签名。若与执行所有权验证的第三方服务集成,最好使用所有权验证令牌校验来避免授予它们访问用户数据的权利。

所有权校验将遍历整个结构来确定用户是否有访问给定catalogItemId的权利。权利对于确认已发生的特定交易很有用。例如,若用户购买了含季票的豪华版游戏,而季票本身就包含对DLC1的访问权利,则对于DLC1,所有权校验将返回TRUE,而权利校验将不包含DLC1。

开始前,必须与身份验证服务集成以获得访问令牌。如需与身份验证有关的更多信息,请查看Epic账号服务入门

直接所有权验证

终端将检查用户是否拥有项或一系列项。

https://api.epicgames.dev/epic/ecom/v1/platforms/EPIC/identities/{{currentAccountId}}/ownership?nsCatalogItemId={{sandboxId:catalogItemId}}

此端点适用于通过SDK 1.5+获取或通过使用配置 'https://api.epicgames.dev/epic/oauth/v1/.well-known/openid-configuration' 实现的OAuth OpenID Connect交换获取的身份验证令牌。

你需要使用Bearer授权在授权标头中传递访问令牌。

此终端支持下列查询参数:

参数描述
nsCatalogItemId使用 {{sandboxId:catalogItemId}} 格式,可重复此参数来检查多个sandboxId和catalogItem组合。
sandboxId该参数可用于获取指定沙盒中所拥有的 catalogItemIds 完整列表。

以下片段展示了一个用于获取所有权信息的请求示例:

GET /epic/ecom/v1/platforms/EPIC/identities/12abc3de456f78901a2bc345dd6789e0/ownership HTTP/1.1
Host: api.epicgames.dev
Authorization: Bearer 1fe59d629cda497b9f65dbdbee7d468e
nsCatalogItemId=fn:ff150af93c9a4fb99fee12f5db49fa5b&nsCatalogItemId=fn:94egdb6df476d45199f6be940aa1337c0
[
{
"namespace": "fn",
"itemId": "94egdb6df476d45199f6be940aa1337c0",
"owned": false
},
{
"namespace": "fn",
"itemId": "ff150af93c9a4fb99fee12f5db49fa5b",
"owned": true
}
]

基于令牌的所有权验证

所有权验证令牌是已签署的JWT,有效期为五分钟。它是使用RS512(RSA PKCS#1签名,包含SHA-512,RSA密钥大小2048)签署的。

执行基于令牌的所有权验证包含两个步骤:

  1. 请求所有权验证令牌

  2. 用公钥验证令牌是否真实

游戏客户端/服务器获得所有权验证令牌,可将其传递给需执行所有权验证的任何集成。验证令牌的集成需解压缩JWT提取kid(密钥ID),然后获取该密钥ID的公钥来验证签名。

此令牌包含以下声明::

声明描述
jti此令牌的唯一辨识符。
sub用于请求此令牌的帐户的帐户ID。
clid用于请求此令牌的客户端的客户端ID。
ent针对此令牌验证的一系列权利所有权。若此值为空,则该帐户无权享有请求权利
iat令牌发出的时间,使用Unix时间戳。
exp令牌到期的时间,使用Unix时间戳。

请求所有权验证令牌

要请求所有权验证令牌,客户端将向所有权令牌终端发出HTTP POST请求。

要请求所有权验证令牌的终端为:

https://api.epicgames.dev/epic/ecom/v1/platforms/\{platform}/identities/\{identityId}/ownershipToken

需用Bearer授权在授权标头中传递访问令牌。

此终端支持下列请求正文参数:

注意:内容类型需为 "application/x-www-form-urlencoded",且此参数需位于请求正文中。

参数描述
nsCatalogItemId使用 {{sandboxId:catalogItemId}} 格式,可重复此参数来检查多个sandboxId和catalogItem组合。

下列片段展示一个用于获取验证令牌的请求示例:

POST /epic/ecom/v1/platforms/EPIC/identities/{{currentAccountId}}/ownershipToken HTTP/1.1
Host: api.epicgames.dev
Authorization: Bearer 1fe59d629cda497b9f65dbdbee7d468e
nsCatalogItemId=fn:c204662afac64acd8a2117590be477da
{
"token": "egoc1~eyJraWQiOiJWbWdpMDFoQ2V2dXVEbUtWZFZubXphWnhpT2lBa0dEZWdRQmdDdWc4dkRZIiwiYWxnIjoiUlM1MTIifQ.eyJzdWIiOiI5NGVkYjZkZjQ3NmQ0NTE5OWY2YmU5NDBhYTEzMzdjMCIsImlwIjoiNTAuOTguMjI2LjEwIiwiY2xpZCI6IjI5Y2VlNDJlNzExNzQ2ZTFiYmNhZmI2MjkyOWU0OGZkIiwiZW50IjpbeyJjYXRhbG9nSXRlbUlkIjoiYzIwNDY2MmFmYWM2NGFjZDhhMjExNzU5MGJlNDc3ZGEiLCJvd25lZCI6dHJ1ZSwibmFtZXNwYWNlIjoiY2F0bmlwIn1dLCJleHAiOjE1Njk5Nzg1NjUsImlhdCI6MTU2OTk3ODI2NSwianRpIjoiMzgzN2FjODhlNDJjNDE1OTlmMzI5OTNjMmViYzBhOWQifQ.CX4yEEsZph9qPaVvtpnS0sLe_9YGLic5jIOQhhk3tG88GfNLp10w5y9DbYXocDlMXdEoAsAt-33G1JOPIFzrktrOxpR_FNdQ_ozCbBCF1aTQFTYKtvrbYkpA5AIGHmy_J9jSKMq-jN4TQxoSbR0LnowiWoKp_ntibmx0titFQ0kOYBQMvwwTlLgTzUv55I6VlFl8gMBSEw1_oRIUbdNbdHJO4UwnHTeUbcUUvuAWm13BpI2P39vRjU1xx4t51kUj_yY9ISWFBSGsLgEAhH13Mm1CilaeiPsLanE1sA5B3mRMjq8KcLtkkp8JvlIrgD4e-xo_tnRSLkRyKuU0GoqNKw"
}

egoc1~ 为前缀,表示Epic游戏所有权校验。解码令牌时请将其去除。

令牌包括三个base64编码的JSON对象,它们分别对应JWT标头、有效负载和签名。请参见JWT 文档了解详情。

下面是JWT标头示例:

{
"kid": "tFC2UIhFpTM_Ea3qcOd_MqQT1cBBm9kFLSDfeJhsRG8",
"alg": "RS512"
}

下面是JWT正文示例:

{
"jti" : "a19c3f03edf84c0a9621ee44ff36566f",
"sub" : "d144285abee343df98c4e84572c576bb",
"clid": "44c39619da304266855c9646e1081ab5",
"iat" : 1547675438,
"exp" : 1547704238,
"ent" : [{
"catalogItemId": "c204662afac64acd8a2117590be477da",
"owned": true,
"namespace": "catnip"
}]
}

验证所有权验证令牌

要验证令牌中的签名,需获取公钥。要获取密钥,需密钥ID(JWT中的kid声明)。回复将包括JSON Web Key (JWK),可用于验证JWT中的签名。

要请求公钥,客户端/服务将向公钥终端发出HTTP请求。

公钥终端为:

https://ecommerceintegration-public-service-ecomprod02.ol.epicgames.com/ecommerceintegration/api/public/publickeys/{kid}.

下列片段展示用于获取公钥的请求示例:

GET /ecommerceintegration/api/public/publickeys/Vmgi01hCevuuDmKVdVnmzaZxiOiAkGDegQBgCug8vDY HTTP/1.1
Host: ecommerceintegration-public-service-ecomprod02.ol.epicgames.com
{
"kty": "RSA",
"e": "AQAB",
"kid": "Vmgi01hCevuuDmKVdVnmzaZxiOiAkGDegQBgCug8vDY",
"n": "k-LHmLHW5bbiqYLmPxC77ciG4N7IuF1SUOSsnDBLneKH3ZAU9kXRkq5MYjmRjxt8g3HpXmmhi_sHe4_g-VnSrM7jP6ntMiJ5t0d5J9ERkSEUSY4w_LS_YECavTr76GiutV_xPT-9jpHJWdVYqk68tiqR42xPFHEFUkYYsb_t6gONhth85ICnVY8Mjg6F0hFvvaMvOJcDVYfQbdjWY8-mzvIF9DmvyVkWaZSQYBaVuNCNKkSiSnkyCtbrynneayugwW0R-rNP5lEcp8UwXpBnep6sRf8nQEsByCnR91RdRXjuvrCSl7fOxpFX82t2WjWTYEOkOgb6yGc_ft-sJidSIQ"
}

直接权利枚举

需获取帐户的直接权利列表时,终端将进行校验。

https://api.epicgames.dev/epic/ecom/v1/identities/{identityId}/entitlements

若只需校验所有权,请使用上文的所有权校验API,Epic推荐此方法。)

需用Bearer授权在授权标头中传递访问令牌。

此终端支持下列查询参数:

参数描述
sandboxId游戏标题的命名空间。
entitlementName可选。权利的名称。若未提供,将返回sandboxId下的所有权利。可重复此参数来校验多个权利。
includeRedeemed可选。该参数指定了是否包含已经兑换的权利。默认为 false。如果不是 true,返回结果将只包含 未被 兑换的权利。

下列片段展示用于获取用户和沙盒的所有权利的请求示例:

GET /api.epicgames.dev/epic/ecom/v1/identities/12abc3de456f78901a2bc345dd6789e0/entitlements HTTP/1.1
Host: api.epicgames.dev
Authorization: Bearer 1fe59d629cda497b9f65dbdbee7d468e
[{
"id": "8894469f1120432095eff043a4529433",
"entitlementName": "942e8a7133464f0ea83179030536505e",
"namespace": "buffalo",
"catalogItemId": "942e8a7133464f0ea83179030536505e",
"entitlementType": "AUDIENCE",
"grantDate": "2019-01-04T21:34:24.826Z",
"consumable": false,
"status": "ACTIVE",
"useCount": 0,
"entitlementSource": "AppEpicgamesCom"
},
{
"id": "e21aa0b339ae4e778971058c9395b2b7",
"entitlementName": "25ed76af7816430cbfc0f5e6d3195d56",
"namespace": "badger",
"catalogItemId": "25ed76af7816430cbfc0f5e6d3195d56",
"entitlementType": "AUDIENCE",
"grantDate": "2019-01-16T04:42:06.270Z",
"consumable": false,
"status": "ACTIVE",
"useCount": 0,
"entitlementSource": "LauncherWeb"
}]

基于令牌的权利验证

权利验证令牌是已签署的JWT,有效期为五分钟。它是使用RS512(RSA PKCS#1签名,包含SHA-512,RSA密钥大小2048)签署的。

执行基于令牌的权利验证包含两个步骤:

  1. 请求权利验证令牌

  2. 用公钥验证令牌是否真实

游戏客户端/服务器获得权利验证令牌,可将其传递给需执行所有权验证的任何集成。验证令牌的集成需解压缩JWT提取kid(密钥ID),然后获取该密钥ID的公钥来验证签名。

此令牌包含以下声明:

权利验证令牌声明
jti此令牌的唯一辨识符。
sub用于请求此令牌的帐户的帐户ID。
clid用于请求此令牌的客户端的客户端ID。
ent针对此令牌验证的一系列权利所有权。若此值为空,则该帐户无权享有请求的权利或者任何用于该sandboxId的权利。
iat令牌发出的时间,使用Unix时间戳。
exp令牌到期的时间,使用Unix时间戳。

请求权利验证令牌

要请求权利验证令牌,客户端将向权利令牌终端发出HTTP POST请求。

要请求所有权验证令牌的终端为 https://api.epicgames.dev/epic/ecom/v1/platforms/{platform}/identities/{identityId}/entitlementToken

需用Bearer授权在授权标头中传递访问令牌。

此终端支持下列请求参数:

请求参数
sandboxId游戏标题的命名空间。
entitlementName可选。权利的名称。若未提供,将返回sandboxId下的所有权利。可重复此参数来校验多个权利。

下列片段展示用于获取用户和沙盒的所有权利的请求示例:

POST
/epic/ecom/v1/platforms/EPIC/identities/94edb6df476d45199f6be940aa1337c0/entitlementToken HTTP/1.1
Host: api.epicgames.dev
Authorization: Bearer 1fe59d629cda497b9f65dbdbee7d468e
sandboxId=2bd59d629cda497b9f65dbdbee7d443s
{
"token": "egoc1~eyJraWQiOiJ0RkMyVUloRnBUTV9FYTNxY09kX01xUVQxY0JCbTlrRkxTRGZlSmhzUkc4IiwiYWxnIjoiUlM1MTIifQ. eyJqdGkiOiJhMTljM2YwM2VkZjg0YzBhOTYyMWVlNDRmZjM2NTY2ZiIsInN1YiI6ImQxNDQyODVhYmVlMzQzZGY5OGM0ZTg0NTcyYzU3NmJiIiwiY2xpZCI6IjQ0YzM5NjE5ZGEzMDQyNjY4NTVjOTY0NmUxMDgxYWI1IiwiaWF0IjoxNTQ3Njc1NDM4LCJleHAiOjE1NDc3MDQyMzgsImVudCI6W3siaWF0IjoxNTQ3Njc1MDAwLCJuYmYiOjE1NDc2NzkwMDAsInNyYyI6IkVQSUMiLCJucyI6InNuYXBkcmFnb24iLCJpdGVtIjoiMTJmYjdkNTBiYmJhNGQwNTlkNWJhYzJlOGUyNzZkMmYiLCJ0eXBlIjoiRU5USVRMRU1FTlQiLCJuYW1lIjoiNDNlZDI4ZTU3N2FiNGMyYThjZWEyN2Q2YjQ0YmJhMTgiLCJjb25zIjoxLCJ1c2NudCI6MH1dfQ.JHFFCjxmcKQDBGWaas53PsvaqeobK_kLZDgw3Je9Btwx5AzmmnW8TGUQGgr-FdZEkpdP2N_TMYV2UBO91QG1ApvwCYrvW3IYBwtl3_9e3NA1QrNLqw2qxG9X8LPiowh0gRO7rpJJ4BwbrYBwImcyf0KPhmCEKkHI9XiDsZDkoD8"
}

注意: egoc1~ 为前缀,表示Epic游戏所有权校验。解码令牌时请将其去除

令牌包括三个base64编码的JSON对象,它们分别对应于JWT标头、有效负载和签名。请参见JWT文档了解详情。

下面是JWT标头示例:

{
"kid": "tFC2UIhFpTM_Ea3qcOd_MqQT1cBBm9kFLSDfeJhsRG8",
"alg": "RS512"
}

下面是JWT正文示例:

{
"jti" : "a19c3f03edf84c0a9621ee44ff36566f",
"sub" : "d144285abee343df98c4e84572c576bb",
"clid": "44c39619da304266855c9646e1081ab5",
"iat" : 1547675438,
"exp" : 1547704238,
"ent" : [{
"grantDate" : 1547375000,
"startDate" : 1547375000,
"endDate" : (timestamp, optional),
"platformType" : "EPIC",
"namespace" : "tbd",
"catalogItemId" : "tbd",
"entitlementType" : "AUDIENCE",
"entitlementName" : "43ed28e577ab4c2a8cea27d6b44bba18",
"consumable" : false,
"useCount" : 0
}]
}

验证权利验证令牌

要验证令牌中的签名,需获取公钥。要获取密钥,需密钥ID(JWT中的kid声明)。回复将包括JSON Web Key (JWK),可用于验证JWT中的签名。

要请求公钥,客户端/服务将向公钥终端发出HTTP请求。

公钥终端为 https://ecommerceintegration-public-service-ecomprod02.ol.epicgames.com/ecommerceintegration/api/public/publickeys/{kid}

下列片段展示用于获取公钥的请求示例:

GET /ecommerceintegration/api/public/publickeys/Vmgi01hCevuuDmKVdVnmzaZxiOiAkGDegQBgCug8vDY HTTP/1.1
Host: ecommerceintegration-public-service-ecomprod02.ol.epicgames.com
{
"kty": "RSA",
"e": "AQAB",
"kid": "Vmgi01hCevuuDmKVdVnmzaZxiOiAkGDegQBgCug8vDY",
"n": "k-LHmLHW5bbiqYLmPxC77ciG4N7IuF1SUOSsnDBLneKH3ZAU9kXRkq5MYjmRjxt8g3HpXmmhi_sHe4_g-VnSrM7jP6ntMiJ5t0d5J9ERkSEUSY4w_LS_YECavTr76GiutV_xPT-9jpHJWdVYqk68tiqR42xPFHEFUkYYsb_t6gONhth85ICnVY8Mjg6F0hFvvaMvOJcDVYfQbdjWY8-mzvIF9DmvyVkWaZSQYBaVuNCNKkSiSnkyCtbrynneayugwW0R-rNP5lEcp8UwXpBnep6sRf8nQEsByCnR91RdRXjuvrCSl7fOxpFX82t2WjWTYEOkOgb6yGc_ft-sJidSIQ"
}

查询商品

如需为某个用户请求可用的商品(Offer)列表,客户端需要向商品端点发出一个HTTP GET请求。

在请求由Epic在线服务定义的商品列表时,目标端点如下所示:

https://api.epicgames.dev/epic/ecom/v1/identities/{identityId}/namespaces/{sandboxID}/offers/

该API提供的数据和SDK API EOS_Ecom_QueryOffers 提供的数据相同。请参见EOS API 参考文档,了解更多关于如何使用SDK API的信息。

你需要在使用Bearer验证,在验证标头中传入一个访问令牌。

以下代码演示了如何为某个用户和沙盒请求商品(Offer):

GET
/ecom/v1/identities/12abc3de456f78901a2bc345dd6789e0/namespaces/8894469f1120432095eff043a4529433/offers/
Host: api.epicgames.dev
Authorization: Bearer 1fe59d629cda497b9f65dbdbee7d468e

以下是一段服务器响应示例代码(虚拟货币商品):

{
"elements": [
{
"id": "123ca45c67a8487895811a1234567890",
"namespace": "tbd",
"title": "1500 Coins",
"description": "1500 Coins",
"longDescription": "",
"availableForPurchase": true,
"purchaseLimit": 1,
"purchasedCount": 0,
"priceInfo": {
"currencyCode": "USD",
"discountPrice": 0,
"originalPrice": 0,
"discountPercentage": 0,
"decimals": 2
},
"releaseDate": "2099-02-01T08:00:00.000Z",
"effectiveDate": "2099-02-01T08:00:00.000Z",
"keyImages": [
{
"type": "OfferImage",
"url": "https://offer/image/url",
"md5": "tbd",
"width": 1200,
"height": 1600,
"size": 651591,
"uploadedDate": "2022-05-12T22:29:48.971Z"
},
{
"type": "ProductLogo",
"url": "https://product/logo/url",
"md5": "tbd",
"width": 400,
"height": 400,
"size": 42030,
"uploadedDate": "2022-06-07T19:48:31.668Z"
}
],
"items": [
{
"id": "12c3f456f7bf89e0bbc1234c567d890d",
"namespace": "tbd",
"title": "1500 Coins Audience",
"itemType": "CONSUMABLE",
"entitlementName": "12c3f456f7bf89e0bbc1234c567d890d",
"description": "1500 Coins Audience",
"developer": "Epic Games",
"keyImages": [],
"releaseInfo": []
}
],
"offerType": "VIRTUAL_CURRENCY"
}
],
"paging": {
"count": 100,
"start": 0,
"total": 17
}
}

如何读取 priceInfo 结构体中的货币数据取决于 decimals 字段中的值。如果 decimals 的值为 2 (例如美元、加元、欧元等),则 discountPriceoriginalPrice 字段的值以“分”表示。所以,如果要将数值转换为美元,请将数值除以100(例如,350就是3.50美元)。

如果 decimals 字段的值可能是 0,(例如日元、韩元等),则其他字段的值就是其指定的货币值。无需任何转换。

取回/使用权利

终端将取回/使用权利。取回权利后,权利状态将更改为未激活。

https://api.epicgames.dev/epic/ecom/v1/identities/{identityId}/entitlements/redeem

你需要使用Bearer授权在授权标头中传递访问令牌。

此终端支持下列请求正文:

{
"entitlementIds": [
"8894469f1134432095eff043a4529433",
"25ed76af9816430cbfc0f5e6d3195d56"
],
"sandboxId": "8894469f1120432095eff043a4529433"
}

下列片段展示用于补偿用户和沙盒的多种权利的示例请求:

PUT
/ecom/v1/identities/94edb6df476d45199f6be940aa1337c0/entitlements/redeem
Host: api.epicgames.dev
Authorization: Bearer 1fe59d629cda497b9f65dbdbee7d468e
Content-Type: application/json
Request body:
{
"entitlementIds": [
"8894469f1134432095eff043a4529433",
"25ed76af9816430cbfc0f5e6d3195d56"
],
"sandboxId": "8894469f1120432095eff043a4529433"
}