商业化接入
服务器上架后,可通过官方商业化接口向玩家收费——卖会员、卖道具、卖特权。这篇基于官方《商业化接入文档》与《商城商品上架更新流程》完整说明接入方式。
商业化架构
商业化系统里,第三方服主需要接入三个环节:
| 步骤 | 通信方式 | 作用 |
|---|---|---|
| 4 | Plugin Message | 启动器账号购买后,对首个进入游戏的角色自动触发发货 |
| 5 | HTTP | 查询玩家未发货订单 |
| 6 | HTTP | 通知网易服务器发货成功 |
推荐主动触发
Plugin Message 的自动发货可以不用。官方建议改用游戏内输入指令、点击 NPC 或界面按钮的方式,由玩家在游戏内主动触发订单查询与发货——更可控、便于排查。
接入前置
正式调接口前,必须先备齐这几样:
- IP 白名单:接口有 IP 白名单机制,只有白名单内的机器能访问。接入前务必先把服务器 IP 提供给工作人员加入白名单,否则请求返回 404
- SecretKey:签名用的密钥,由网易提供。PC 和 PE 的 key 不同,即使部署互通服务器也要分别申请两个 key
- gameid:游戏 ID。PC 游戏用 PC 侧注册的 gameid,PE 用 PE 侧的
- 测试服:首次接入需搭测试服联调,接口地址用测试环境(见下文接口地址表)
先加白名单再调接口
没加白名单直接调接口会 404。排查时用 curl -i -X POST 接口地址,返回 404 就是 IP 没加白名单,联系工作人员添加。
商品上架流程
网络游戏正式上架后,在**开发者 Launcher 左侧「商品管理」**进入商品编辑界面。
一、分类编辑
「橱窗编辑」标签 → 「分类编辑」按钮,可添加/重命名/删除分类,确认后保存。分类信息会显示在启动器商城上。
二、商品编辑
「库存编辑」标签 → 「添加商品」,填写各字段:
| 字段 | 说明 |
|---|---|
| 商品名称 | 商城显示的名称 |
| 商品定价 | 商城定价,单位钻石 |
| 购买次数 | 限制单账号购买次数,达到后商城隐藏该商品;不限填 -1 |
| 商品分类 | 归属的分类位置 |
| 商品简介 | 简单介绍 |
| 实现指令 | 向服务端传输的指令信息,即接口里的 cmd(商品唯一标识,服务器据此判断玩家买了什么) |
| 付费类型 | 第三方服务器商品统一选 server commodity |
| 付费备注 | 审核备注,暂无实际作用 |
| 详情信息 | 富文本商品详情(购买页显示,富文本格式可能显示异常,谨慎用) |
| 图片 | 商城界面图(橱窗显示)、商城介绍图(购买页显示) |
cmd 不能为空字符串
cmd(实现指令)是服务器判断商品类型的唯一依据。官方预留的 cmd 为空字符串,服务器自己设置的 cmd 不允许为空字符串。上架时填的实现指令会作为订单里的 cmd 返回给服务器。
三、自测 → 审核 → 上架
- 商品信息填完 → 保存
- 点自测:开发者自行在测试服测试发货是否正常
- 提交审核(审核中 → 审核通过)
- 审核通过 → 点更新到橱窗 → 上架设置
上架设置与下架
- 橱窗编辑可改商品分类与位置,排序编号越小越靠前
- 保存并提交审核后,商城信息同步到测试服
- 测试服接入测试环境地址后,用测试版启动器自测,发货无问题、通过审核后点更新橱窗列表
- 下架:橱窗编辑选商品点下架,或库存编辑直接下架
- 修改商品信息必须先下架,改完重新提交审核才能再上架
Plugin Message 接口
- Channel 名:
storemod - 参考附件的
storeplugin示例工程 - 用途:启动器账号购买商城物品后,对首个进入游戏的角色自动触发发货逻辑
- 可不使用,改用游戏内主动触发
HTTP 接口
所有 HTTP 接口通用约定:
- 方法:
POST Content-Type: application/json、Accept: application/json- 请求头:
Netease-Server-Sign(SecretKey 签名,见签名方法)
1. 查询未发货订单 get-mc-item-order-list
向网易服务器查询指定玩家的未发货订单,mc 游戏服对这些订单发货。
请求参数:
{
"gameid": <你的游戏 gameid>,
"uuid": "8a0886b5-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}响应:
{
"code": 0,
"message": "正常返回",
"details": "",
"entities": [
{
"item_id": 90027446413343740,
"uuid": "8a0886b5-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"item_num": 1,
"orderid": 1234,
"cmd": "vip_30day",
"buy_time": 1230782400,
"group": 1,
"type": "",
"extra": {}
}
]
}| 字段 | 说明 |
|---|---|
item_id | 商品 ID,仅记录用 |
uuid | 玩家唯一编号 |
item_num | 购买数量 |
orderid | 订单编号 |
cmd | 商品唯一标识,据此判断玩家买了什么(空字符串为官方预留) |
buy_time | 购买时间戳 |
group | 道具分类 |
type / extra | 保留字段,官方活动奖励用到(见礼包) |
三条重要提醒
- 别重复发货:如果 mc 游戏已发货,但网易仍返回该订单,不要重复发货,要再调
ship-mc-item-order通知网易改状态 - 排队处理:强烈建议对订单发货排队处理,避免并发时重复发货
- 上限 100:返回订单列表上限 100 条,超出部分下次请求返回
2. 通知发货成功 ship-mc-item-order
发货成功后通知网易服务器修改订单状态。
请求参数:
{
"gameid": <你的游戏 gameid>,
"uuid": "8a0886b5-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"orderid_list": [98431742905470976, 98431742905470976]
}响应:
{ "code": 0, "message": "正常返回", "details": "", "entities": [] }3. uid + name → uuid uuid-xuid-from-uid-name
用玩家 uid 和昵称获取 uuid。
请求:{ "uid": 100, "name": "test" }
响应:
{ "code": 0, "entity": { "uuid": "098f6bcd-4621-4373-8ade-4e836bedca9f", "xuid": "6bedca9f" } }4. uuid → uid uid-from-uuid
用 uuid 获取 uid。
请求:{ "uuid": "098f6bcd-4621-4373-8ade-4e836bedca9f" }
响应:
{ "code": 0, "entity": { "uid": 100 } }PC 和 PE 的 uuid/uid 不同
PC 玩家和 PE 玩家的 id 体系不一样,接口地址和 gameid 也分 PC/PE。本系列是 PC Java,用 PC 侧地址。
签名方法
所有带签名的接口统一用以下方式计算:
1. 拼接待签名串
str2sign = HTTP_METHOD + PATH_QS + HTTP_BODYHTTP_METHOD:请求方法(GET、POST 等)PATH_QS:URL 中除协议、域名端口外的部分,如/get-mc-item-order?orderid=123&gameid=12HTTP_BODY:请求体内容,可为空
2. 获取签名 key:由网易提供(PC/PE 不同)
3. 计算签名:HMAC_SHA256,结果用 hex 格式、字母小写
sign = HMAC_SHA256(key, str2sign)4. 放入请求头:Netease-Server-Sign: <sign>
示例(POST)
原始请求: curl -X POST -d '{"uid": "123"}' 'http://127.0.0.1:10100/apps/app1/login'
待签名串: POST/apps/app1/login{"uid": "123"}
key: appkey123
sign: fc905b4d6c5e585bba32c439f924890d46c129f3a0fe7279ac6648fcaaa9e6dc
curl -X POST -H 'Netease-Server-Sign: fc905b4d...' -d '{"uid": "123"}' 'http://...'错误码
| code | 含义 | 处理 |
|---|---|---|
| 0 | 成功返回 | — |
| 4 | 参数为空 | 对照接口文档修改参数 |
| 12 | 参数错误 | 对照接口文档修改 |
| 18 | 数据库内部错误 | 反馈给服务端程序排查 |
| 52 | 订单不存在 | — |
| 53 | 签名错误 | 对照签名算法排查计算过程 |
| 54 | 订单状态错误 | 该订单未扣费或 mc 已发过货,核实订单信息 |
| 55 | 玩家未购买该网络游戏 | 用户必须先购买网络游戏,才能买游戏内商品 |
| 56 | 秘钥未分配 | 在平台申请网络游戏秘钥 |
接口地址
商业化 4 个接口(get-mc-item-order-list、ship-mc-item-order、uuid-xuid-from-uid-name、uid-from-uuid)均分测试环境与正式环境两套地址;PC 与 PE 地址不同,正式环境还按机房机器型号(如 2630/2637 与 2690)对应不同地址。
具体地址向官方获取
接口的具体域名、端口、路径属于官方内部信息,请以官方最新《商业化接入文档》为准,或向工作人员获取。首次接入用测试环境地址联调,通过审核后再切正式环境地址。注意区分 http 与 https,并按你所在机房机器型号选对应正式地址。
玩家登录认证接口
认证接口地址见认证接入(同样以官方文档为准)。
发货流程与代码示例
完整链路:玩家触发(指令/NPC/按钮)→ 查未发货订单 → 按 cmd 发货 → 通知 ship → 通知玩家。
cmd 映射配置
# 服务器配置:cmd → 发货动作
products:
vip_30day:
action: grant_vip
duration: 30
coin_100:
action: deposit_coins
amount: 100
sword_skin_a:
action: give_item
item: sword_skin_a发货逻辑示例
// 玩家输入 /delivery 指令时触发
public void deliver(Player player) {
UUID uuid = player.getUniqueId();
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
// 1. 查未发货订单
OrderListResp resp = queryOrders(gameId, uuid); // POST get-mc-item-order-list
if (resp.code != 0) return;
List<Long> shipped = new ArrayList<>();
for (Order o : resp.entities) {
// 2. 幂等:本地已发货的跳过(但 ship 仍要通知网易)
if (localShipped(o.orderid)) {
shipped.add(o.orderid);
continue;
}
// 3. 按 cmd 发货
dispatch(player, o); // 按 o.cmd 执行 grant_vip / deposit_coins / give_item
markLocalShipped(o.orderid);
shipped.add(o.orderid);
}
// 4. 通知网易发货成功(即使之前已发过,只要网易还返回就要通知)
if (!shipped.isEmpty()) {
shipOrders(gameId, uuid, shipped); // POST ship-mc-item-order
}
// 5. 回主线程通知玩家
Bukkit.getScheduler().runTask(plugin, () ->
player.sendMessage(ChatColor.GREEN + "发货完成,共 " + shipped.size() + " 笔订单"));
});
}并发与幂等
- 排队处理:高并发时多个请求同时查订单会重复发货,建议单玩家发货请求串行排队
- 本地幂等记录:用
orderid去重,已发过的别重复发物品 - ship 必须调:即使本地已发货,只要网易接口还返回该订单,就要再调
ship-mc-item-order通知网易改状态,否则下次还返回
签名计算示例
public static String sign(String key, String method, String pathQs, String body) throws Exception {
String str2sign = method + pathQs + (body == null ? "" : body);
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"));
byte[] raw = mac.doFinal(str2sign.getBytes("UTF-8"));
return HexFormat.of().formatHex(raw); // 小写 hex
}
// 调用:sign(key, "POST", "/get-mc-item-order-list", jsonBody)
// 放入头:conn.setRequestProperty("Netease-Server-Sign", sign);礼包 type/extra
官方活动奖励订单的 cmd 为空字符串,用 type 和 extra 区分:
| 礼包 | type | extra | 说明 |
|---|---|---|---|
| 会员季度礼包 | vip_season | {"season": "201810"} | 开通会员每月领一次,season 表示季度(2018Q4=201810,2019Q1=201901) |
服务器处理时若 cmd 为空,再查 type 判断是哪种官方礼包。
测试服联调
- 测试服接入网易测试服认证接口(地址向官方获取,见认证接入)
- 商业化接口用测试环境地址(向官方获取)
- 上传商品、自测发货
- 用测试版启动器进测试服,游戏内触发发货指令,验证全链路
- 确认商品上传成功、认证接入无误、商业化地址正确、发货逻辑无问题后,联系工作人员审核
- 通过后切正式环境地址、正式上架
无法发货排查
- 白名单:
curl -i -X POST 接口地址,返回 404 = IP 没加白名单,联系工作人员添加 - 白名单正常:在请求处加日志,打印请求参数和接口响应,按错误码处理
- 反馈给服务端程序时,务必同时提供请求参数和接口响应信息
商业化接入完成,商品配好、发货跑通,只差最后一步——正式上架与开服运营。回到Java 网络游戏首页。
