玩家物品库
物品库是用户可在游戏中购买、赚取或消耗的物品集合。
艾克索拉玩家物品库允许合作伙伴:
- 同步用户在所有平台上的购买物和高级奖励。
- 使用艾克索拉API向用户物品库中发放或撤回物品和货币。
运行机制
玩家物品库通过用户ID来管理用户的物品库。用户的身份识别通过艾克索拉登录管理器实现。如果已配置自己的身份识别系统,可为客户端API方法使用支付中心访问令牌。
要使用玩家物品库API方法,必须配置认证。
用户物品库可包含消耗品和非消耗品。消耗品可通过游戏客户端多次购买并添加到物品库或从物品库中删除。非消耗品只能被购买并添加到物品库一次。取消购买和从物品库中删除的操作通过游戏服务器执行。
上图显示了玩家物品库操作的以下原则:
- 获取物品库
- 游戏通过用户的艾克索拉登录管理器帐户或您自己的身份识别方法来识别用户。
- 您的应用程序(客户端)调用获取当前用户物品库方法获取购买物及用户奖励列表,调用获取当前用户的虚拟余额方法获取虚拟货币的余额。
- 艾克索拉物品库服务器向客户端返回该用户当前拥有的购买物、奖励或余额。
- 通过艾克索拉商店进行游戏内购买
- 游戏通过用户的艾克索拉登录管理器帐户或您自己的身份识别方法来识别用户。
- 用户通过艾克索拉商店进行购买。
- 该内容购买事件发送到艾克索拉物品库服务器,然后购买物即自动发放到用户的物品库。
- 通过第三方发布平台(Steam、PlayStation等)进行应用内购买
- 用户使用平台帐户登录游戏。
- 用户通过平台的支付系统进行购买。
- 游戏服务器调用按购买项向用户发放商品方法通过发送用户在游戏内的唯一ID在艾克索拉物品库上发放购买物。
- 艾克索拉物品库服务器将购买物添加到指定ID的用户物品库。
- 向用户发放奖励
- 游戏通过用户的艾克索拉登录管理器帐户或您自己的身份识别方法来识别用户。
- 您的服务器调用向用户发放商品方法并发送用户在游戏内的唯一ID来发放奖励。
- 艾克索拉物品库服务器向指定ID的用户物品库添加奖励。
- 物品库同步
- 游戏通过用户的艾克索拉登录管理器帐户、您自己的身份识别方法或第三方平台帐户来识别用户。
- 游戏服务器同步用户帐户(如需要)。
- 游戏客户端调用获取当前用户物品库方法来检查哪些游戏内购买物可用并发送唯一用户ID。
- 艾克索拉物品库服务器返回指定ID的可用物品列表。
集成过程
要启用玩家物品库:
认证设置
为确保安全性,发放和撤回方法由游戏服务器调用。必须实现基本认证才能使用这些方法。
获取用户物品库和消耗品由游戏客户端通过SDK或API调用。以下是几种可用的认证方式:
- 如果连接了艾克索拉登录管理器,可使用艾克索拉登录管理器JWT来认证请求。
- 如果设置了自己的身份识别系统,可使用支付中心访问令牌来认证请求。
user.id
。该ID必须与支付中心访问令牌中使用的user.id
相同。通过艾克索拉登录管理器进行认证
如果用户数据保存在PlayFab数据存储中,请使用PlayFab高级诀窍。
如果用户数据保存在您自己一侧,请使用自定义存储高级诀窍。
通过支付中心访问令牌认证
认证过程:
- 应用程序(客户端)发送认证请求至您的服务器。
- 您的服务器发送商户ID和API密钥至艾克索拉服务器并请求access_token。
- 艾克索拉服务器发送access_token至您的服务器。
- 您的服务器发送access_token至客户端。
返回的access_token用作授权令牌,用于在
设置基本认证
向艾克索拉API物品库发放和撤回物品的服务器命令使用基本认证。所有发送到API的请求必须包含Authorization: Basic <your_authorization_basic_key>
头,其中<your_authorization_basic_key>
是按照Base64标准加密的商户ID:API密钥对。
前往发布商帐户找到以下参数:
- 商户ID在以下位置显示:
- 在项目设置 > Webhooks部分。
- 在公司设置 > 公司部分。
- 在发布商帐户任意页面的浏览器地址栏的URL中。URL的格式如下:
https://publisher.xsolla.com/商户ID/发布商帐户部分
。
- API密钥仅在创建它时在发布商帐户中显示一次,必须存储在己侧。您可以在以下部分中创建新的密钥:
- 公司设置 > API密钥
- 项目设置 > API密钥
关于使用API密钥的详细信息,请参阅API参考。
关于密钥的建议:
- 请在己侧保存生成的API密钥。您仅会在创建API密钥时在发布商帐户中看见它一次。
- 请妥善保管API不被泄露。它提供对您的个人帐户及您在发布商帐户中项目的访问权限。
- API密钥必须存储在您的服务器上,切勿保存在代码或前端中。
- http
- curl
- php
- C#
- python
- ruby
- java
- js
POST https://store.xsolla.com/api/v2/project/{project_id}/inventory/reward
Headers:
Authorization: Basic <your_authorization_basic_key>
curl --request POST \
--url 'https://store.xsolla.com/api/v2/project/{project_id}/inventory/reward' \
--header 'authorization: Basic <your_authorization_basic_key>'
<?php
$uri = 'https://store.xsolla.com/api/v2/project/{project_id}/inventory/reward';
$auth = base64_encode('your_merchant_id:your_merchant_api_key');
$headers = [
'Authorization: Basic ' . $auth,
'Content-Type: application/json',
'Accept: application/json',
];
$request = curl_init($uri);
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_POST, true);
curl_setopt($request, CURLOPT_POSTFIELDS, []);
curl_setopt($request, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($request);
print_r($response);
var client = new RestClient("https://store.xsolla.com/api/v2/project/{project_id}/inventory/reward");
var request = new RestRequest(Method.POST);
request.AddHeader("authorization", "Basic <your_authorization_basic_key>");
IRestResponse response = client.Execute(request);
import http.client
conn = http.client.HTTPSConnection("api.xsolla.com")
headers = { 'authorization': "Basic <your_authorization_basic_key>" }
conn.request("POST", "https://store.xsolla.com/api/v2/project/{project_id}/inventory/reward", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
url = URI("https://store.xsolla.com/api/v2/project/{project_id}/inventory/reward
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["authorization"] = 'Basic <your_authorization_basic_key>'
response = http.request(request)
puts response.read_body
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://store.xsolla.com/api/v2/project/{project_id}/inventory/reward")
.post()
.addHeader("authorization", "Basic <your_authorization_basic_key>")
.build();
Response response = client.newCall(request).execute();
var data = null;
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://store.xsolla.com/api/v2/project/{project_id}/inventory/reward");
xhr.setRequestHeader("authorization", "Basic <your_authorization_basic_key>");
xhr.send(data);
物品库管理方法
物品库管理方法包括以下几组方法:
向用户发放商品
实现向用户发放商品 API方法将指定物品添加到用户物品库或将虚拟货币添加到用户余额。
请求:
- php
<?php
$uri = 'https://store.xsolla.com/api/v2/project/44056/inventory/reward';
$body = '
[
{
"user": {
"id": "0125760a-6810-11e9-84c0-42010aa80029"
},
"comment": "Quest completed",
"platform": "xsolla",
"items": [
{
"sku": "boots_1",
"quantity": 5
},
{
"sku": "crystal_pack_1",
"quantity": 3
}
]
},
{
"user": {
"id": "a7d10a4e-3f68-43cc-a6b2-893d2c68fd14"
},
"comment": "Daily reward",
"platform": "xsolla",
"items": [
{
"sku": "helmet_1",
"quantity": 2
},
{
"sku": "minigun_1",
"quantity": 3
}
]
}
]';
$auth = base64_encode('44056:your_merchant_api_key');
$headers = [
'Authorization: Basic ' . $auth,
'Content-type: application/json'
];
$request = curl_init($uri);
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_POSTFIELDS, $body);
curl_setopt($request, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($request);
响应:
- php
{
"count": 2,
"operations": [
{
"user_id": "0125760a-6810-11e9-84c0-42010aa80029",
"platform": "xsolla",
"comment": "Quest completed",
"items": [
{
"sku": "boots_1",
"quantity": 5
},
{
"sku": "crystal_pack_1",
"quantity": 3
}
]
},
{
"user_id": "a7d10a4e-3f68-43cc-a6b2-893d2c68fd14",
"platform": "xsolla",
"comment": "Daily reward",
"items": [
{
"sku": "helmet_1",
"quantity": 2
},
{
"sku": "minigun_1",
"quantity": 3
}
]
}
]
}
撤回物品库商品
实现撤回物品库商品 API方法将指定物品从用户物品库中撤回或将虚拟货币从用户余额中撤回。
请求:
- php
<?php
$uri = 'https://store.xsolla.com/api/v2/project/44056/inventory/revoke';
$body = '
[
{
"user": {
"id": "0125760a-6810-11e9-84c0-42010aa80029"
},
"comment": "Remove from inventory",
"items": [
{
"sku": "boots_1",
"quantity": 5
},
{
"sku": "crystal_pack_1",
"quantity": 3
}
]
},
{
"user": {
"id": "a7d10a4e-3f68-43cc-a6b2-893d2c68fd14"
},
"comment": "Cheater",
"items": [
{
"sku": "helmet_1",
"quantity": 2
},
{
"sku": "minigun_1",
"quantity": 3
}
]
}
]';
$auth = base64_encode('44056:your_merchant_api_key');
$headers = [
'Authorization: Basic ' . $auth,
'Content-type: application/json'
];
$request = curl_init($uri);
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_POSTFIELDS, $body);
curl_setopt($request, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($request);
print_r($response);
响应:
- php
{
"count": 2,
"operations": [
{
"user_id": "0125760a-6810-11e9-84c0-42010aa80029",
"platform": "xsolla",
"comment": "Remove from inventory",
"items": [
{
"sku": "boots_1",
"quantity": 5
},
{
"sku": "crystal_pack_1",
"quantity": 3
}
]
},
{
"user_id": "a7d10a4e-3f68-43cc-a6b2-893d2c68fd14",
"platform": "xsolla",
"comment": "Cheater",
"items": [
{
"sku": "helmet_1",
"quantity": 2
},
{
"sku": "minigun_1",
"quantity": 3
}
]
}
]
}
按购买项向用户发放商品
实现按购买项向用户发放商品 API方法将用户在第三方平台购买的物品添加到用户物品库。
请求:
- php
<?php
$uri = 'https://store.xsolla.com/api/v2/project/44056/inventory/purchase';
$body = '
[
{
"user": {
"id": "0125760a-6810-11e9-84c0-42010aa80029"
},
"comment": "Purchase in App Store",
"platform": "app_store_ios",
"purchase": {
"amount": "3.99",
"currency": "USD",
"external_purchase_id": "MS6TGW7023",
"external_purchase_date": "2020-01-25T05:00:00+05:00"
},
"items": [
{
"sku": "boots_1",
"quantity": 5
},
{
"sku": "crystal_pack_1",
"quantity": 3
}
]
},
{
"user": {
"id": "a7d10a4e-3f68-43cc-a6b2-893d2c68fd14"
},
"comment": "Purchase in Google Play",
"platform": "google_play",
"purchase": {
"amount": "1.99",
"currency": "EUR",
"external_purchase_id": "GPA.3357-9348-5932-89841",
"external_purchase_date": "2020-02-14T05:00:00+05:00"
},
"items": [
{
"sku": "helmet_1",
"quantity": 2
},
{
"sku": "minigun_1",
"quantity": 3
}
]
}
]';
$auth = base64_encode('44056:your_merchant_api_key');
$headers = [
'Authorization: Basic ' . $auth,
'Content-type: application/json'
];
$request = curl_init($uri);
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_POSTFIELDS, $body);
curl_setopt($request, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($request);
print_r($response);
响应:
- php
{
"count": 2,
"operations": [
{
"user_id": "0125760a-6810-11e9-84c0-42010aa80029",
"platform": "app_store_ios",
"comment": "Purchase in App Store",
"items": [
{
"sku": "boots_1",
"quantity": 5
},
{
"sku": "crystal_pack_1",
"quantity": 3
}
],
"order_id": 4125,
"external_purchase_id": "MS6TGW7023",
"external_purchase_date": "2020-01-25T05:00:00+05:00",
"amount": "3.99",
"currency": "USD"
},
{
"user_id": "a7d10a4e-3f68-43cc-a6b2-893d2c68fd14",
"platform": "google_play",
"comment": "Purchase in Google Play",
"items": [
{
"sku": "helmet_1",
"quantity": 2
},
{
"sku": "minigun_1",
"quantity": 3
}
],
"order_id": 4126,
"external_purchase_id": "GPA.3357-9348-5932-89841",
"external_purchase_date": "2020-02-14T05:00:00+05:00",
"amount": "1.99",
"currency": "EUR"
}
]
}
获取当前用户物品库
实现获取当前用户物品库 API方法获取购买后添加到用户物品库的物品列表。
请求:
- js
var data = null;
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://store.xsolla.com/api/v2/project/44056/user/inventory/items");
xhr.setRequestHeader("authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE5NjIyMzQwNDgsImlzcyI6Imh0dHBzOi8vbG9naW4ueHNvbGxhLmNvbSIsImlhdCI6MTU2MjE0NzY0OCwidXNlcm5hbWUiOiJ4c29sbGEiLCJ4c29sbGFfbG9naW5fYWNjZXNzX2tleSI6IjA2SWF2ZHpDeEVHbm5aMTlpLUc5TmMxVWFfTWFZOXhTR3ZEVEY4OFE3RnMiLCJzdWIiOiJkMzQyZGFkMi05ZDU5LTExZTktYTM4NC00MjAxMGFhODAwM2YiLCJlbWFpbCI6InN1cHBvcnRAeHNvbGxhLmNvbSIsInR5cGUiOiJ4c29sbGFfbG9naW4iLCJ4c29sbGFfbG9naW5fcHJvamVjdF9pZCI6ImU2ZGZhYWM2LTc4YTgtMTFlOS05MjQ0LTQyMDEwYWE4MDAwNCIsInB1Ymxpc2hlcl9pZCI6MTU5MjR9.GCrW42OguZbLZTaoixCZgAeNLGH2xCeJHxl8u8Xn2aI");
xhr.send(data);
响应:
- js
{
"items": [
{
"description": "Conquer your foes with vindication using the Basic Blaster! ",
"image_url": "https://cdn.xsolla.net/img/misc/images/0c59a7698d4f66c1008b27ee752089b7.png",
"instance_id": null,
"long_description": "Conquer your foes with vindication using the Basic Blaster! Conquer your foes with vindication using the Basic Blaster! ",
"name": "Xsolla Basic Blaster 1",
"quantity": 22,
"sku": "gun_1",
"type": "virtual_good"
},
{
"description": "Protect your noggin' with style",
"image_url": "https://cdn.xsolla.net/img/misc/images/b79342cdf24f0f8557b63c87e8326e62.png",
"instance_id": null,
"long_description": "merchant_virtual_items_virtual_item_long_description_159429",
"name": "Xsolla Helmet",
"quantity": 18,
"sku": "helmet_1",
"type": "virtual_good"
}
]
}
获取当前用户的虚拟余额
实现获取当前用户的虚拟余额 API方法获取当前用户虚拟货币余额的信息。
请求:
- js
var data = null;
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://store.xsolla.com/api/v2/project/44056/user/virtual_currency_balance");
xhr.setRequestHeader("authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE5NjIyMzQwNDgsImlzcyI6Imh0dHBzOi8vbG9naW4ueHNvbGxhLmNvbSIsImlhdCI6MTU2MjE0NzY0OCwidXNlcm5hbWUiOiJ4c29sbGEiLCJ4c29sbGFfbG9naW5fYWNjZXNzX2tleSI6IjA2SWF2ZHpDeEVHbm5aMTlpLUc5TmMxVWFfTWFZOXhTR3ZEVEY4OFE3RnMiLCJzdWIiOiJkMzQyZGFkMi05ZDU5LTExZTktYTM4NC00MjAxMGFhODAwM2YiLCJlbWFpbCI6InN1cHBvcnRAeHNvbGxhLmNvbSIsInR5cGUiOiJ4c29sbGFfbG9naW4iLCJ4c29sbGFfbG9naW5fcHJvamVjdF9pZCI6ImU2ZGZhYWM2LTc4YTgtMTFlOS05MjQ0LTQyMDEwYWE4MDAwNCIsInB1Ymxpc2hlcl9pZCI6MTU5MjR9.GCrW42OguZbLZTaoixCZgAeNLGH2xCeJHxl8u8Xn2aI");
xhr.send(data);
响应:
- js
{
"items": [
{
"amount": 683,
"description": "Main in-game currency",
"image_url": "https://cdn3.xsolla.com/img/misc/images/91df536af4616519f639664854c13d75.png",
"name": "Crystals",
"sku": "crystal",
"type": "virtual_currency"
},
{
"amount": 450,
"description": "Money for in-store purchases",
"image_url": "https://cdn3.xsolla.com/img/misc/images/fda67a3feedaa706b4e4ae05a9edd6ab.png",
"name": "Gold",
"sku": "gold",
"type": "virtual_currency"
}
]
}
消耗商品
实现消耗商品 API方法消耗掉用户物品库中的相应物品。
请求:
- js
let data = JSON.stringify({
"sku": "gun_1",
"quantity": 1,
"instance_id": null
});
let xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://store.xsolla.com/api/v2/project/44056/user/inventory/item/consume");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE5NjIyMzQwNDgsImlzcyI6Imh0dHBzOi8vbG9naW4ueHNvbGxhLmNvbSIsImlhdCI6MTU2MjE0NzY0OCwidXNlcm5hbWUiOiJ4c29sbGEiLCJ4c29sbGFfbG9naW5fYWNjZXNzX2tleSI6IjA2SWF2ZHpDeEVHbm5aMTlpLUc5TmMxVWFfTWFZOXhTR3ZEVEY4OFE3RnMiLCJzdWIiOiJkMzQyZGFkMi05ZDU5LTExZTktYTM4NC00MjAxMGFhODAwM2YiLCJlbWFpbCI6InN1cHBvcnRAeHNvbGxhLmNvbSIsInR5cGUiOiJ4c29sbGFfbG9naW4iLCJ4c29sbGFfbG9naW5fcHJvamVjdF9pZCI6ImU2ZGZhYWM2LTc4YTgtMTFlOS05MjQ0LTQyMDEwYWE4MDAwNCIsInB1Ymxpc2hlcl9pZCI6MTU5MjR9.GCrW42OguZbLZTaoixCZgAeNLGH2xCeJHxl8u8Xn2aI");
xhr.send(data);
错误列表
用户或用户物品库管理错误:
代码 | 描述 | 操作 |
---|---|---|
0401-5002 | 添加商品至用户物品库的数据错误。 | 必须指定item_id,且instance_id或quantity的值必须为null。 |
0401-5003 | 未指定用户ID。 | 检查请求中是否包含了用户ID。 |
0401-5004 | 未在用户物品库中找到该物品。 | 确保该物品在物品库中。可通过Get user's inventory方法检查物品库状态。 |
0401-5006 | 虚拟货币不足,无法购买。 | - |
0401-5007 | 尝试消耗非消耗品。 | - |
0401-5008 | 找不到用户。 | - |
0401-5009 | 发放第三方平台购买物时未传入purchase。 | - |
物品管理错误:
代码 | 描述 | 操作 |
---|---|---|
0401-4001 | 找不到符合条件的物品。 | 通过调用Get user's inventory方法检查物品列表。 |
代码 | 描述 | 操作 |
---|---|---|
0401-1101 | 服务不可用(地址错误、连接问题)。 | 检查status.xsolla.com上的系统状态;联系艾克索拉客户支持团队或您的帐户经理。 |
0401-1102 | 请求项数据错误。 | 检查API规范。 |
0401-1016 | 某个请求参数的编码错误。 | 检查请求内容。 |
0401-1019 | 不支持该方法。 | 检查请求。可在响应中找到支持的方法。 |
0401-1020 | 使用商户的密钥散列时发生授权错误。 | 检查API密钥。 |
本文对您的有帮助吗?
为此页面评分
不想回答
感谢您的反馈!
发现了错别字或其他内容错误? 请选择文本,然后按Ctrl+Enter。