[https://github.com/magape-official/sdk/blob/main/java/JAVA_SDK_EN.md]
sequenceDiagram
participant 游戏厂商
participant magape
participant 玩家
游戏厂商 ->> magape: 1、通过sdk上传支持导出的道具列表(接口1)
magape -> magape: 2、审核
玩家 ->> magape: 3、执行导入
magape ->> 游戏厂商: 4、查询可以导出的道具列表以及玩家个人导入限制,可选(接口2)
magape ->> 游戏厂商: 5、检查玩家是否还有余额可以导入(case:特殊道具每人只能购买一次)(接口3)
游戏厂商 ->> magape: 5、返回结果,库存足够,可以执行导入
magape ->> blockChain: 6、调用合约
blockChain ->> magape: 7、监听合约事件
magape ->> 游戏厂商: 8、调用游戏厂商接口给玩家新增道具(接口4)
接口1: - 上传可导出道具元数据http(uploadOrUpdateProp) | - 上传可导出道具元数据SDK(uploadOrUpdateProp)
接口2: - 查询可以导出的道具列表及个人限制
接口3: - 检查游戏对应道具库存
接口4: - 在游戏中新增玩家道具
sequenceDiagram
participant 游戏厂商
participant magape
participant 玩家
游戏厂商 ->> magape: 1、通过sdk上传支持导出的道具列表(接口1)
magape -> magape: 2、审核
玩家 ->> magape: 3、在magape市场可以看到自己在不同游戏支持导入导出的道具以及限制(接口2)
玩家 ->> magape: 4、执行导出
magape ->> 游戏厂商: 5、调用游戏厂商接口删除玩家道具(接口3)
magape ->> blockChain: 6、调用合约
blockChain ->> magape: 7、监听合约事件
接口1: - 上传可导出道具元数据http(uploadOrUpdateProp) | - 上传可导出道具元数据SDK(uploadOrUpdateProp)
接口2: - 查询玩家可导出数量
接口3: - 删除玩家道具
如果没有提供,则默认在magape页面不展示导入导出限制数量
# 请求
POST https://game.com/assetConfig
--header 'Content-Type: application/json' \
--header 'signature:xxxx'
--data '{
"reqId":'xxxx',
"operate":'buy|sell'
}'
# 返回
{
"code":200,
"data":[
{
"propId":"游戏道具id",
"quantity":10
}
],
"err":""
}
request
类型 | 位置 | 描述 | 是否必填 | |
---|---|---|---|---|
header | signature | header | 请求签名,游戏平台使用私钥解签 | 是 |
Content-Type | string | header | 请求类型application/json | 是 |
reqId | string | body | 本次请求的唯一id | 是 |
operate | string | body | 操作描述(buy or sell),buy表示查询玩家在平台可以购买的游戏道具库存数量,查询纬度是游戏厂商(例如有的道具是每个玩家只能购买一次),sell表示查询玩家可以卖出的游戏道具库存数量,查询纬度是玩家 | 是 |
response
类型 | 描述 | 是否必填 | |
---|---|---|---|
code | int | 相应码,200 成功,401 未授权,500 错误 | 是 |
err | string | 错误信息,有则不用填 | |
data | array | 玩家可导出的道具合集 | 是 |
data[0].propId | string | 游戏道具id | 是 |
data[0].quantity | int | 玩家最多可以买入或卖出多少个道具(-1表示道具可以无限购买/卖出) | 是 |
# 请求
POST https://game.com/deleteAsset
--header 'signature:xxxx'
--header 'Content-Type: application/json' \
--data '{
"reqId":"xxx",
"address": xxxx,
"assets":[
{
"propId": "游戏道具id",
"quantity": 10
}
]
}'
# 返回
{
"code":200|400|401|500 // 返回状态码
"data":"success" | "fail",
"err":""
}
request
类型 | 位置 | 描述 | 是否必填 | |
---|---|---|---|---|
signature | string | header | 请求签名,游戏平台使用私钥解签 | 是 |
Content-Type | string | header | 请求类型application/json | 是 |
reqId | string | body | 本次请求的唯一id | 是 |
address | string | body | 玩家地址 | 是 |
assets | array | body | 受影响的资产 | 是 |
assets[].propId | string | body | 游戏道具id | 是 |
assets[].quantity | int | body | 要删除的数量 | 是 |
response
类型 | 描述 | 是否必填 | |
---|---|---|---|
code | int | 相应码,200 成功,401 未授权,500 错误 | 是 |
err | string | 错误信息,有则不用填 | 否 |
data | string | "success" | "fail | 是 |
# 请求
POST https://game.com/queryStorage
--header 'signature:xxxx'
--header 'Content-Type: application/json' \
--data '{
"reqId":"xxx",
"address": xxxx,
"operate": "buy | sell",
"queryIds": [1, 2, 3]
}'
# 返回
{
"code":200,
"data":[
{
"propId": 1,
"quantity": 100
},
{
"propId": 2,
"quantity": 200
}
],
"msg":""
}
request
类型 | 位置 | 描述 | 是否必填 | |
---|---|---|---|---|
signature | string | header | 请求签名,游戏平台使用私钥解签 | 是 |
Content-Type | string | header | 请求类型application/json | 是 |
reqId | string | body | 本次请求的唯一id | 是 |
address | string | body | 玩家地址 | 是 |
operate | string | body | 操作描述(buy or sell),buy表示查询玩家在平台可以购买的游戏道具库存数量,查询纬度是游戏厂商(例如有的道具是每个玩家只能购买一次),sell表示查询玩家可以卖出的游戏道具库存数量,查询纬度是玩家 | 是 |
queryIds | string[] | body | 游戏道具id | 否 |
response
类型 | 描述 | 是否必填 | |
---|---|---|---|
code | int | 相应码,200 成功,401 未授权,500 错误 | 是 |
err | string | 错误信息,有则不用填 | 否 |
data | object[] | 返回对象 | 是 |
data[].propId | string | 道具id | 是 |
data[].quantity | string | 剩余库存数量(operate为buy)或玩家拥有数量(operate为sell) | 是 |
# 请求
POST https://game.com/checkEnough
--header 'signature:xxxx'
--header 'Content-Type: application/json' \
--data '{
"reqId":"xxx",
"address": xxxx,
"operate": "buy | sell",
"assets":[
{
"propId": "游戏道具id",
"quantity": 10
}
]
}'
# 返回
{
"code":200,
"data":{
"enough":true | false
},
"err":""
}
request
类型 | 位置 | 描述 | 是否必填 | |
---|---|---|---|---|
signature | string | header | 请求签名,游戏平台使用私钥解签 | 是 |
Content-Type | string | header | 请求类型application/json | 是 |
reqId | string | body | 本次请求的唯一id | 是 |
address | string | body | 玩家地址 | 是 |
operate | string | body | 操作描述(buy or sell),buy表示查询玩家在平台可以购买的游戏道具库存数量,查询纬度是游戏厂商(例如有的道具是每个玩家只能购买一次),sell表示查询玩家可以卖出的游戏道具库存数量,查询纬度是玩家 | 是 |
assets[].propId | string | body | 游戏道具id | 是 |
assets[].quantity | int | body | 要购买的数量 | 是 |
response
类型 | 描述 | 是否必填 | |
---|---|---|---|
code | int | 相应码,200 成功,401 未授权,500 错误 | 是 |
err | string | 错误信息,有则不用填 | 否 |
data | object | 返回对象 | 是 |
data.enough | bool | 库存是否足够去买或者卖 | 是 |
# 请求
POST https://game.com/increaseAsset
--header 'signature:xxxx'
--header 'Content-Type: application/json' \
--data '{
"reqId":"xxx",
"address": xxxx,
"assets":[
{
"propId": "游戏道具id",
"quantity": 10
}
]
}'
# 返回
{
"code":200,
"data":"success" ,
"err":""
}
request
类型 | 位置 | 描述 | 是否必填 | |
---|---|---|---|---|
signature | string | header | 请求签名,游戏平台使用私钥解签 | 是 |
Content-Type | string | header | 请求类型application/json | 是 |
reqId | string | body | 本次请求的唯一id | 是 |
address | string | body | 玩家地址 | 是 |
assets | array | body | 受影响的资产 | 是 |
assets[].propId | string | body | 游戏道具id | 是 |
assets[].quantity | int | body | 要删除的数量 | 是 |
response
类型 | 描述 | 是否必填 | |
---|---|---|---|
code | int | 相应码,200 成功,401 未授权,500 错误 | 是 |
err | string | 错误信息,有则不用填 | 否 |
data | string | "success" | "fail | 是 |
# 请求
POST https://game.com/callback/buyMerchandise
--header 'signature:xxxx'
--header 'Content-Type: application/json' \
--data '{
"reqId": "1720160554482100200",
"address": "0xA34357486224151dDfDB291E13194995c22Df505",
"items": [
{
"username": "magape",
"id": 43,
"telephone": "+61 88888888",
"remark": "Hello!",
"quantity": 3,
"deliveryAddress": "moon"
}
]
}'
# 返回
{
"code": 200,
"err": "",
"data": "success"
}
request
类型 | 位置 | 描述 | 是否必填 | |
---|---|---|---|---|
reqId | int | body | 请求的唯一ID | 是 |
address | string | body | 用户钱包地址 | 是 |
items | array | body | 购买的商品列表 | 是 |
items[].id | int | body | 商品ID | 是 |
items[].quantity | int | body | 购买数量 | 是 |
items[].username | string | body | 收件人名称 | 是 |
items[].telephone | string | body | 收件人号码 | 是 |
items[].deliveryAddress | string | body | 收件地址 | 是 |
items[].remark | string | body | 备注 | 否 |
response
类型 | 描述 | 是否必填 | |
---|---|---|---|
code | int | 响应码,200 成功,401 未授权,500 错误 | 是 |
err | string | 错误信息,若无错误则为空字符串 | 是 |
data | string | 操作结果,"success"表示成功 | 是 |
https://github.com/magape-official/sdk/blob/main/java/HTTP_EN.md(参考uploadOrUpdateProp方法)
sequenceDiagram
participant 游戏厂商
participant magape
participant 玩家A
participant 玩家B
游戏厂商 ->> magape: 1、通过sdk上传支持导出的道具列表(接口1)
magape -> magape: 2、审核
玩家A ->> magape: 3、上架要卖的道具,货币为mac
magape ->> 游戏厂商: 4、调用game厂商接口删除游戏道具(接口2)
magape -> magape: 5、生成一条道具上架记录
玩家B ->> magape: 6、购买玩家A的道具
magape ->> blockChain: 7、调用合约扣除玩家B mac数量
blockChain ->> magape: 8、监听合约事件
magape ->> 游戏厂商: 9、调用游戏厂商接口给玩家新增道具(接口3)
sequenceDiagram
participant 游戏厂商
participant magape
participant 玩家A
游戏厂商 ->> magape: 1、通过sdk上传支持导出的道具列表(接口1)
magape -> magape: 2、审核
玩家A ->> magape: 3、上架要卖的道具,货币为mac
magape ->> 游戏厂商: 4、调用game厂商接口删除游戏道具(接口2)
magape -> magape: 5、生成一条道具上架记录
玩家A ->> magape: 6、下架要卖的道具
magape ->> 游戏厂商: 7、调用游戏厂商接口给玩家恢复道具(接口3)
接口1: - 上传可导出道具元数据http(uploadOrUpdateProp) | - 上传可导出道具元数据SDK(uploadOrUpdateProp)
接口2: - 在游戏中删除玩家道具
接口3: - 在游戏中新增玩家道具
sequenceDiagram
participant 游戏厂商
participant magape
participant 玩家
玩家 ->> magape: mint、transfer、merge、dust、upgrade、buy
magape -->> magape: 查询这个用户在那些游戏上面有账号
magape ->> 游戏厂商: 通过回调地址通知游戏玩家nft资产发生变化(接口1)
游戏厂商 ->> magape: 使用http或者sdk拉取玩家最新的nft详情(接口2)
接口1: - 提醒游戏用户nft发生变化
接口2: - 获取用户所有nft
# 请求
POST https://game.com/nftNotify
--header 'Content-Type: application/json' \
--header 'signature:xxxx'
--data '{
"reqId":'xxxx',
"address':'xxxx'
}'
# 返回
{
"code":200,
"data":"success",
"err":""
}
request
类型 | 位置 | 描述 | 是否必填 | |
---|---|---|---|---|
signature | string | header | 请求签名,游戏平台使用私钥解签 | 是 |
Content-Type | string | header | 请求类型 | 是 |
reqId | string | body | 本次请求唯一id | 是 |
address | string | body | 玩家地址 | 是 |
response
类型 | 描述 | 是否必填 | |
---|---|---|---|
code | int | 相应码,200 成功,401 未授权,500 错误 | 是 |
err | string | 错误信息,有则不用填 | 否 |
data | string | "success" | "fail | 是 |
5.1.2.1、根据玩家地址查询所有nft列表,sdk中getPopList函数,返回的NFT属性为A(1-10)、B(1-10)、C(1-10)、D(1-10),属性在5、NFT在游戏中的影响中有详细描述
{
"code": 200,
"data": {
"data": [
{
"attrList": [
{
"displayType": "boost_percentage",
// 不需要处理,属于nft market市场展示
"traitType": "D2",
// 属性名
"value": 60
// 属性值,百分比
},
{
"displayType": "boost_percentage",
"traitType": "D1",
"value": 20
},
{
"displayType": "boost_percentage",
"traitType": "D9",
"value": 30
},
{
"displayType": "boost_percentage",
"traitType": "D5",
"value": 40
},
{
"traitType": "Rank",
"value": "Epic"
},
{
"traitType": "Ape Type",
"value": "Sky"
}
],
"attrs": "[{\"display_type\":\"boost_percentage\",\"trait_type\":\"D2\",\"value\":60},{\"display_type\":\"boost_percentage\",\"trait_type\":\"D1\",\"value\":20},{\"display_type\":\"boost_percentage\",\"trait_type\":\"D9\",\"value\":30},{\"display_type\":\"boost_percentage\",\"trait_type\":\"D5\",\"value\":40},{\"trait_type\":\"Rank\",\"value\":\"Epic\"},{\"trait_type\":\"Ape Type\",\"value\":\"Sky\"}]",
"category": "Sky",
"createTime": 1714109254000,
"erc721ContractAddress": "0x3FB236F17054c24DB20FDf6135Ce334DE7451928",
"fromAddress": "0x0000000000000000000000000000000000000000",
"imageUrl": "https://testnet-api.magape.io/ipfs/QmeSRVY7786EZTEQivowaPakjjSPg3BRyMdWk8dHWroDFL",
"imgCid": "ipfs://QmeSRVY7786EZTEQivowaPakjjSPg3BRyMdWk8dHWroDFL",
"level": "Epic",
"name": "Mappy #306",
"nftCidUrl": "https://testnet-api.magape.io/ipns/null",
"status": 2,
"toAddress": "0x4d11df920e0e48c7e132e5a9754c7e754cd6ebfb",
"tokenId": 306
}
],
"hasNext": true,
"pageNo": 1,
"pageSize": 20,
"totalPage": 2,
"totalRecord": 38
},
"message": "success"
}
5.2.1、游戏厂商在生成sk的时候,magape平台会同步生成一个公钥,在magape给游戏厂商发送数据时会对数据进行加密,游戏方拿到数据之后可以通过sk进行解密。避免接口暴露导致恶意攻击
InputStream inputStream = request.getInputStream();
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int n;
while(-1!=(n =inputStream.
read(buffer))){
output.
write(buffer, 0,n);
}
String payload = output.toString(StandardCharsets.UTF_8);
String sigHeader = request.getHeader("signature");
String accessKeyStr = "magape平台公钥";
byte[] accessKeyBytes = Base64.decodeBase64(accessKeyStr);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(accessKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("Ed25519");
PublicKey accessKey = keyFactory.generatePublic(keySpec);
Signature signDecode = Signature.getInstance("Ed25519");
signDecode.
initVerify(accessKey);
signDecode.
update(source.getBytes(StandardCharsets.UTF_8));
boolean verifyResult = signDecode.verify(Base64.decodeBase64(rsaData));
System.out.
println("Verify Result: "+verifyResult);
在magape页面设置游戏支持的nft类型,目前分为4类"City", "Jungle", “Ocean", "Sky",每一种类型下面有不同的属性。
游戏厂商可以选择任意一种类型的nft进行游戏人物增强,每一个nft的属性只会属于其中一种类型,比如NFT不会同时拥有City下面的属性和Jungle下面的属性
游戏方可以自行设定游戏功能使用哪一种属性(例如:攻击力 -> City的A1),并设置在游戏中影响的最大值和最小值
nft等级决定了具体影响数值。目前magape的nft有5个等级(Common、Uncommon、Rare、Epic、Legendary)
magape平台可以提供接口计算这些NFT最终加成,游戏平台也可以获取所有的NFT自行计算这些属性加成
6.1.1.1、获取游戏支持的属性,方便玩家可以准确的知道自己拥有的nft能对游戏的加成
# 请求
POST https://game.com/attrDefinition
--header 'Content-Type: application/json' \
--header 'signature:xxxx' \
--data '{
"reqId":"xxxxx"
}'
# 返回
{
"code":200
"data": {
"category": "City",
"attrs": [
{
"attr":"A1",
"min":10,
"max":100,
"description":"Power Enhancement"
}
]
},
"err":""
}
request
类型 | 位置 | 描述 | 是否必填 | |
---|---|---|---|---|
signature | string | header | 请求签名,游戏平台使用私钥解签 | 是 |
Content-Type | string | header | 请求类型 |
| | reqId | string | body | 本次请求唯一id | |
response
类型 | 描述 | 是否必填 | |
---|---|---|---|
code | int | 相应码,200 成功,401 未授权,500 错误 | 是 |
err | string | 错误信息,有则不用填 | 否 |
category | string | 游戏支持的nft类型(City, Jungle, Ocean, Sky) | 是 |
attrs | array | 游戏支持的属性 | 是 |
attrs[0].attr | string | 属性名称 | 是 |
attrs[0].min | int | 属性最小值,百分比 | 是 |
attrs[0].max | int | 属性最大值,百分比 | 是 |
attrs[0].description | string | 属性描述 | 是 |
6.1.1.2.1、游戏获取用户所有nft总的加成,算法参考上述表格
# 请求
curl --location 'https://{url}/api/v1/nft/overallPerformance' \
--header 'signature: xxxx' \
--header 'requestId: 123123127' \
--header 'X-Access-Key: xxx' \
--header 'Content-Type: application/json' \
--data '
{
"address":"xxxx",
"networkId":56
}
'
# 返回
{
"code": 200,
"data": {
"enhancedAttrs": [
{
"enhancedPercentage": "80",// nft enhanced percentage 80%
"enhancedVal": 16.84,// the value that calculated according to configuretion in magape platform
"id": 6,
"level": "Common", // nft level
"name": "A6",// game define attribute
"nfName": "Mappy #106" // the NFT that provide this capability
}
]
},
"message": "success"
}
request
位置 | 描述 | 是否必填 | |
---|---|---|---|
requestId | header | 唯一的traceId,不能重复 | Yes |
signature | header | 签名信息 | Yes |
X-Access-Key | header | magape平台上游戏厂商的访问密钥 | Yes |
NFTOverallPerformanceReq | body | 请求参数 | Yes |
类型 | 描述 | Required | |
---|---|---|---|
networkId | int | 链id(97 bsc testnet,56 mainnet) | yes |
address | string | 玩家地址 | yes |
response
类型 | 描述 | 是否必填 | |
---|---|---|---|
code | int | 相应码,200 成功,401 未授权,500 错误 | 是 |
err | string | 错误信息,有则不用填 | 否 |
address | string | 玩家地址 | 是 |
enhancedAttrs | array | 增益 | 是 |
enhancedAttrs[0].enhancedPercentage | string | 属性增幅比例 | 是 |
enhancedAttrs[0].enhancedVal | int | 属性加成值 | 是 |
enhancedAttrs[0].id | int | 属性id | 是 |
enhancedAttrs[0].level | int | nft 等级 | 是 |
enhancedAttrs[0].name | int | 游戏定义属性 | 是 |
enhancedAttrs[0].nfName | int | nft 名称 | 是 |
玩家先登入magape平台进行签名,在进入游戏的时候带上magape平台生成的token信息。游戏厂商可以直接使用token操作sdk方法,也可以直接传入玩家地址,区别是token可以让玩家退出游戏,address不存在退出
sequenceDiagram
participant A as 玩家
participant B as magape平台
participant C as 游戏厂商
A ->> B: 登入magape平台
Note left of A: 对象A的描述(提示)
B -->> A: Fine, Thank you.
Note right of B: 对象B的描述
A -x B: 我走了
游戏需要提供入口让玩家和钱包地址进行绑定,绑定之后在调用magape平台接口时会自动在magape平台中保存玩家和游戏的关联关系
通过本地钱包执行登入验证签名,或者输入设置好的密码执行登入,调用签名访问进行认证授权。返回认证结果和用户钱包地址
通过开源钱包或者magape随机生成一个钱包公私钥,并让用户设定好密码。返回认证结果和用户钱包地址
# 请求
curl --location 'https://{url}/api/v1/game/exit' \
--header 'signature: xxxx' \
--header 'requestId: 123123127' \
--header 'X-Access-Key: xxx' \
--header 'Content-Type: application/json' \
--data '
{
"token":"xxxx"
}
'
# 返回
{
"code": 200,
"data": {"succcess"},
"message": "success"
}
request
位置 | 描述 | 是否必填 | |
---|---|---|---|
requestId | header | 唯一的traceId,不能重复 | Yes |
signature | header | 签名信息 | Yes |
X-Access-Key | header | magape平台上游戏厂商的访问密钥 | Yes |
GameExitReq | body | 请求参数 | Yes |
类型 | 描述 | Required | |
---|---|---|---|
token | string | 登入游戏的token | yes |
response
类型 | 描述 | 是否必填 | |
---|---|---|---|
code | int | 相应码,200 成功,401 未授权,500 错误 | 是 |
data | string | 正常返回success,错误返回对应错误信息 | 否 |
可以查询用户所有的nft,以及代币余额