Combo Game
后端对接

用户钱包变动回调

用户消费、获得收益、获得额外奖励、退款时调用

注意

消费订单不会重试,收益、额外奖励和退款订单如果调用失败会自动重试,商户端需要根据orderUid进行去重,避免数据异常。同一个 App 内 orderUid 唯一。

请求格式

请求方式: POST

编码格式: Content-Type: application/json;charset=UTF-8

参数类型说明
appIdint商户 App ID
amountlong本次变动余额,消费类型为负数,其余类型为正数
gameIdintCombo Game 游戏 ID
orderUidstring订单唯一 ID,格式为 UUID 字符串,同一个 App 内唯一
payloadstring额外信息 JSON 格式化后的字符串,退款时为{"relatedOrderUid":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}包含被退款的原订单 ID,其余类型为{}
roundUidstring本局游戏 UID,格式为 UUID 字符串,部分游戏可能为空字符串
typeint订单类型,1 消费,2 收益,3 额外奖励,4 退款;商户消费订单返回时间较长时可能会导致本局已结束,此时会进行退款
userIdstring用户 ID
tokenstringApp 加载游戏时携带的商户提供的用户鉴权 token,不能为空
tslong当前时间戳毫秒
signstringMD5 小写字符串
示例<消费>订单商户回调请求数据
{
  "amount": -1000,
  "gameId": 1001,
  "orderUid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "payload": "{}",
  "roundUid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "token": "xxxx",
  "type": 1, 
  "userId": "1234556",
  "ts": 1750151429551,
  "sign": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
示例<收益>订单商户回调请求数据
{
  "amount": 2000,
  "gameId": 1001,
  "orderUid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "payload": "{}",
  "roundUid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "token": "xxxx",
  "type": 2, 
  "userId": "1234556",
  "ts": 1750151429551,
  "sign": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
示例<额外奖励>订单商户回调请求数据
{
  "amount": 2000,
  "gameId": 1001,
  "orderUid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "payload": "{}",
  "roundUid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "token": "xxxx",
  "type": 3, 
  "userId": "1234556",
  "ts": 1750151429551,
  "sign": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
示例<退款>订单商户回调请求数据
{
  "amount": 2000,
  "gameId": 1001,
  "orderUid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "payload": "{\"relatedOrderUid\":\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"}", 
  "roundUid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "token": "xxxx",
  "type": 4, 
  "userId": "1234556",
  "ts": 1750151429551,
  "sign": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

签名算法

sign = MD5(amount + appId + gameId + orderUid + payload + roundUid + token + ts + type + userId + appKey)

示例代码

public static String sign(long amount, int appId, int gameId, String orderUid, String payload, String roundUid, String token, long ts, int type, String userId, String appKey) {
    try {
        MessageDigest digest = MessageDigest.getInstance("MD5");
        String sourceString = String.format(Locale.CHINA, "%d%d%d%s%s%s%s%d%d%s%s", amount, appId, gameId, orderUid, payload, roundUid, token, ts, type, userId, appKey);
        return bytesToHex(digest.digest(sourceString.getBytes(StandardCharsets.UTF_8)));
    } catch (Exception e) {
        System.out.println("加密失败");
    }
    return null;
}

private static final byte[] HEX_ARRAY = "0123456789abcdef".getBytes(StandardCharsets.US_ASCII);

public static String bytesToHex(byte[] bytes) {
    byte[] hexChars = new byte[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars, StandardCharsets.UTF_8);
}
h := md5.New()
h.Write([]byte(fmt.Sprintf("%d%d%d%s%s%s%s%d%d%s%s", amount, appId, gameId, orderUid, payload, roundUid, token, ts, Type, userId, appKey)))
sign := hex.EncodeToString(h.Sum(nil))

返回格式

编码格式: Content-Type: application/json;charset=UTF-8

字段类型说明
codeint错误码,详见错误码页
msgstring错误信息,若无错误可以传空字符串或者 OK
dataobject数据体
data.balancelong用户钱包余额
示例商户回调返回数据
{
  "code": 0,
  "msg": "OK",
  "data": {
    "balance": 88888888
  }
}

Token 补充说明

  1. 游戏过程中一直使用 token 进行交互,用户 token 要保证在游戏过程中有效。如果需要强制让用户退出游戏 APP 服务器也可以直接让 token 失效;
  2. 由于有一些多人游戏,需要延迟开奖。也就是玩家在参与游戏后,需要等一段时间后才能知道结果。如果这用户离线或强制退出 APP,APP 服务器也不能马上回收 token,每次游戏方调用用户钱包变动回调后,商户方需要保持 token 有效最少 3 分钟,这样才能保证该用户在游戏结果后也能正常获得奖励。