Skip to content

商业化接入 ​

服务器上架后,可通过官方商业化接口向玩家收费——卖会员、卖道具、卖特权。这篇基于官方《商业化接入文档》与《商城商品上架更新流程》完整说明接入方式。

商业化架构 ​

商业化系统里,第三方服主需要接入三个环节:

步骤通信方式作用
4Plugin Message启动器账号购买后,对首个进入游戏的角色自动触发发货
5HTTP查询玩家未发货订单
6HTTP通知网易服务器发货成功

推荐主动触发

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 返回给服务器。

三、自测 → 审核 → 上架 ​

  1. 商品信息填完 → 保存
  2. 点自测:开发者自行在测试服测试发货是否正常
  3. 提交审核(审核中 → 审核通过)
  4. 审核通过 → 点更新到橱窗 → 上架设置

上架设置与下架 ​

  • 橱窗编辑可改商品分类与位置,排序编号越小越靠前
  • 保存并提交审核后,商城信息同步到测试服
  • 测试服接入测试环境地址后,用测试版启动器自测,发货无问题、通过审核后点更新橱窗列表
  • 下架:橱窗编辑选商品点下架,或库存编辑直接下架
  • 修改商品信息必须先下架,改完重新提交审核才能再上架

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 游戏服对这些订单发货。

请求参数:

json
{
  "gameid": <你的游戏 gameid>,
  "uuid": "8a0886b5-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

响应:

json
{
  "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保留字段,官方活动奖励用到(见礼包)

三条重要提醒

  1. 别重复发货:如果 mc 游戏已发货,但网易仍返回该订单,不要重复发货,要再调 ship-mc-item-order 通知网易改状态
  2. 排队处理:强烈建议对订单发货排队处理,避免并发时重复发货
  3. 上限 100:返回订单列表上限 100 条,超出部分下次请求返回

2. 通知发货成功 ship-mc-item-order ​

发货成功后通知网易服务器修改订单状态。

请求参数:

json
{
  "gameid": <你的游戏 gameid>,
  "uuid": "8a0886b5-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "orderid_list": [98431742905470976, 98431742905470976]
}

响应:

json
{ "code": 0, "message": "正常返回", "details": "", "entities": [] }

3. uid + name → uuid uuid-xuid-from-uid-name ​

用玩家 uid 和昵称获取 uuid。

请求:{ "uid": 100, "name": "test" }

响应:

json
{ "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" }

响应:

json
{ "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_BODY
  • HTTP_METHOD:请求方法(GET、POST 等)
  • PATH_QS:URL 中除协议、域名端口外的部分,如 /get-mc-item-order?orderid=123&gameid=12
  • HTTP_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 映射配置 ​

yaml
# 服务器配置: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

发货逻辑示例 ​

java
// 玩家输入 /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 通知网易改状态,否则下次还返回

签名计算示例 ​

java
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 区分:

礼包typeextra说明
会员季度礼包vip_season{"season": "201810"}开通会员每月领一次,season 表示季度(2018Q4=201810,2019Q1=201901)

服务器处理时若 cmd 为空,再查 type 判断是哪种官方礼包。

测试服联调 ​

  1. 测试服接入网易测试服认证接口(地址向官方获取,见认证接入)
  2. 商业化接口用测试环境地址(向官方获取)
  3. 上传商品、自测发货
  4. 用测试版启动器进测试服,游戏内触发发货指令,验证全链路
  5. 确认商品上传成功、认证接入无误、商业化地址正确、发货逻辑无问题后,联系工作人员审核
  6. 通过后切正式环境地址、正式上架

无法发货排查 ​

  1. 白名单:curl -i -X POST 接口地址,返回 404 = IP 没加白名单,联系工作人员添加
  2. 白名单正常:在请求处加日志,打印请求参数和接口响应,按错误码处理
  3. 反馈给服务端程序时,务必同时提供请求参数和接口响应信息

商业化接入完成,商品配好、发货跑通,只差最后一步——正式上架与开服运营。回到Java 网络游戏首页。