Appearance
全局接口说明
CHANGELOG
查阅 API 更新日志
错误码定义
查阅 错误码说明
金额参数
OP 和 2J服务器之间接口交互中涉及到的金额参数都以厘为单位,数据类型为int64。
1元 = 1000厘
1分 = 10厘
游戏类型
游戏分为Slots、百人类、对战类、捕鱼类、休闲类,不同类型对应不同游戏ID范围,适用不同的下注和派彩接口,具体如下:
游戏类型 | 游戏ID范围 | 适用下注/结算接口 |
---|---|---|
Slots | 1000~1999 | /order/transfer |
百人类 | 2000~2999 | /order/batch_transfer |
对战类 | 3000~3999 | /order/batch_transfer |
捕鱼类 | 4000~4999 | /order/transfer |
休闲类 | 6000~6999 | /order/transfer |
接口签名
OP 和 2J 服务器之间每个请求 querystring 中都必须携带参数,参照如下案例:
/seamless/launch?mch=108&ts=1710230433000&sign=f764e34bb223966caf66d88e8e1c817f
Query 参数说明:
- mch 是 2J分配给接入OP的标识id(通常为三位id)
- ts 时间戳, milisecond
- sign, sign的生成规则为MD5(httpjsonbody+ts+key), OP 接入前需要向 2J 申请一个 key
计算sign的示例代码如下:
Python
python
import hashlib
def compute_md5(jsonbody, ts_str, key):
m = hashlib.md5()
m.update(jsonbody.encode('utf-8'))
m.update(ts_str.encode('utf-8'))
m.update(key.encode('utf-8'))
return m.hexdigest()
# 假如调用url最终为: /open/seamless/create?mch=xxx&ts=1718675696497&sign=your_sign
jsonbody = '''{"brd": "wl", "op_id": "60095050427", "user_info": {"cnt": "ph", "gender": 0, "lan": "en", "nickname": "60095050427"}}'''
ts_str = "1718675696497"
key = "example_key"
your_sign = compute_md5(jsonbody, ts_str, key)
# cbc16eea6ad1af1f63955d24b314e13a
print(your_sign)
Go
go
import "crypto/md5"
func ComputeMd5(dataStr []byte, key []byte) string {
h := md5.New()
h.Write(dataStr)
if len(key) > 0 {
h.Write(key)
}
return fmt.Sprintf("%x", h.Sum(nil))
}
body := `{"brd": "wl", "op_id": "60095050427", "user_info": {"cnt": "ph", "gender": 0, "lan": "en", "nickname": "60095050427"}}`
ts := "1718675696497"
key := "example_key"
part1 := []byte(body + ts)
part2 := []byte(key)
// cbc16eea6ad1af1f63955d24b314e13a
your_sign := ComputeMd5(part1, part2)
响应结构体
json
content-type: application/json
{
"header": {
"code": 0, // 错误编码,0表示正常, 非0表示异常
"msg": "", // 错误提示
"timestamp": 1709716095516
},
"data": xxx
}
2J 提供接口
POST /open/seamless/create 用户注册
用于在 2J 服务器上注册用户信息。
json
content-type: application/json
{
"op_id": "xxx-xxx-aaa", // op侧用户的唯一标识, required
"user_info": {
"nickname": "player01", // op 玩家昵称。注意:不支持 emoji 特殊字符
"gender": 0, // 0-unknow, 1-famale, 2-male
"cnt": "ph", // 默认国家
"lan": "en" // 默认语言
}
}
Response:
json
content-type: application/json
{
"header": {
"code": 0,
"trace_id": "9cd0bfd22447bf607d20a3c2ac4e304a",
"msg": "",
"timestamp": 1710310573038
}// 通用响应header
}
POST /open/seamless/launch 登录游戏
获取游戏链接接口。
json
content-type: application/json
{
"op_id": "xxx-xxx-aaa", // 必填。op侧用户的唯一标识
"balance": 666, // 必填。op用户余额
"game_id": 65005, // 必填。游戏id
"lang": "en-US",
"backlink": "http://xxxxx.com?a=ss", // 返回 OP 地址
"cur": "$", // 可选。货币符号
"device_type": 2, // 可选。玩家客户端类型 1: h5, 2: android, 3: ios
"device_id": "AD19939", // 可选。玩家客户端设备唯一id
"ret_lobby_btn": false, // 可选。是否显示返回大厅按钮
"full_screen": 1, // 可选。控制在使用浏览器情况下,是否自动进入全屏 1: 不进入全屏 2: 自动进入全屏,该参数未传由2j服务器控制是否自动进入全屏
}
参数说明:
- game_id 详细清单可参考这里
- lang 参考:https://zh.wikipedia.org/wiki/ISO_639-1
- backlink: 控制游戏中退出游戏按钮执行的逻辑
- 如果传 about:blank 或者为空 触发代码:
window.close()
- 如果传链接 触发代码:
window.location.href=backlink
- 如果是用Iframe的方式打开游戏,可以使用设置backlink参数为脚本的方式使用,例如:javascript:window.parent.postMessage({ type: 'exit_customer_page'}, '*'), 这样会触发父页面的onmessage事件,然后父页面可以根据type参数做相应的处理。
- 如果传 about:blank 或者为空 触发代码:
Response:
json
content-type: application/json
{
"header": {
"code": 0,
"trace_id": "9cd0bfd22447bf607d20a3c2ac4e304a",
"msg": "",
"timestamp": 1710310573038
},
"url": "http://abc.zzz?brd=default&chn=&lang=en-US&launch=blackjack&mch=108&opid=demo10087&token=6defed39fd6a4e98add31a4e1ead5172&version=1"
}
POST /open/seamless/evict 踢出用户
提供给 OP 用于踢出用户, 如果玩家在游戏中,会被强制退出游戏。
注意:这里玩家被踢出后,会收到一个弹窗通知告知玩家被踢出,但如果 OP 在调用
/open/seamless/launch
时没有提供backlink
参数,会导致玩家无法返回 OP 端。
json
content-type: application/json
{
"op_id": "xxx-xxx-aaa", // 必填。op侧用户的唯一标识
}
Response:
json
content-type: application/json
{
"header": {
"code": 0,
"trace_id": "9cd0bfd22447bf607d20a3c2ac4e304a",
"msg": "",
"timestamp": 1710310573038
},
"game_info": {
"game_id": 1006, // 游戏id
"join_at": 1720686368, // 加入时间
"leave_at": 1720686368, // 离开时间
}
}
OP 需要提供的接口
POST /balance/get 查询用户余额接口
json
content-type: application/json
{
"op_id": "xxx-xxx-aaa", // op侧用户的唯一标识, required
"game_id": 1006, // 游戏ID,表示是从哪个游戏中请求过来的,可选
}
Response:
json
content-type: application/json
{
"header": {
"code": 103, // 错误编码,0表示正常, 非0表示异常
"msg": "user not exist",
"timestamp":1709716095516,
},
"result":
{
"op_id": "111444", // op侧用户的唯一标识
"availableAmount": 998, // op用户当前可用余额
},
}
POST /order/transfer 用户下注/结算
该接口适用于单人游戏:用于OP用户下注和派彩,至少一次的调用,OP需要保持该接口的 幂等。
下注撤销发生在用户下注时,2J 调用 OP 的接口失败 (超时,异常错误) 时,2J 会调用此接口并指定 action=3 表示撤销下注。
注意⚠️:投注撤销
的请求参数中,amount
为正数,值等于之前的下注金额(负数)的绝对值;action
为 3
。 其余参数和下注请求一致(包括 trans_no
和 draw_id
)。
json
content-type: application/json
{
"action":1, // 1:下注,2:派彩, 3:下注撤销
"op_id": "xxx-xxx-aaa", // op侧用户的唯一标识, required
"order":
{
"trans_no":"101156966-1170920125564673-1006-2-1726-1709201163-0",//本次变更唯一凭证
"draw_id":"1006-2-1726-1709201163-0", // 牌局唯一标识
"game_id": 1006, // 游戏ID
"amount": -5000, // 金额变动
"room_kind": 1, //房间场次
"extra_business": // 可选。不同游戏额外的业务数据
{
"win_crash_bet": 1000, // 在捕鱼类中每轮结算周期内输赢为负的累计金额
"total_bet": 5000, // 退出捕鱼类时本次下注金额
"total_award": 0, // 退出捕鱼类时本次总派彩金额
}
}
}
参数说明:
参数 | 类型 | 说明 | 备注 |
---|---|---|---|
action | int | 请求行为 | 1: 下注 , 2: 奖励, 3: 下注撤销 |
op_id | string | OP 的玩家id | |
order | object | 订单结构体 | |
order.trans_no | string | 订单唯一凭证,可以此做幂等操作 | |
order.draw_id | string | 牌局唯一标识 | |
order.game_id | int | 游戏id | |
order.amount | int64 | 金额变动 | 捕鱼类游戏下注时是预扣值,并非玩家实际下注 |
order.extra_business | object | 不同游戏额外的业务数据 | 捕鱼类游戏结算时玩家的实际下注和奖励在该字段体现 |
捕鱼类游戏中额外的业务数据说明:
参数 | 类型 | 说明 | 备注 |
---|---|---|---|
extra_business.win_crash_bet | int | 在捕鱼类游戏中每轮结算周期内输赢为负的累计金额 | |
extra_business.total_bet | int | 退出捕鱼类游戏时本次实际下注金额 | |
extra_business.total_award | int | 退出捕鱼类游戏时本次实际派彩金额 | |
Response: |
json
// content-type: application/json
{
"header": {
"code": 0, // 错误编码,0表示正常, 非0表示异常
"msg": "",
"timestamp":1709716095516,
},
"result":
{
"op_id": "111444", // required op侧用户的唯一标识
"availableAmount": 998, // required op用户当前可用余额
},
}
POST /order/batch_transfer 用户批量下注/结算
该接口适用于百人类和对战类游戏:用于OP多个用户下注和派彩,至少一次的调用,OP需要保持该接口的 幂等。
下注撤销发生在用户下注时,2J 调用 OP 的接口失败 (超时,异常错误) 时,2J 会调用此接口并指定 action=3 表示撤销下注。
注意⚠️:投注撤销
的请求参数中,amount
为正数,值等于之前的下注金额(负数)的绝对值;action
为 3
。 其余参数和下注请求一致(包括 trans_no
和 draw_id
)。
json
content-type: application/json
{
"action": 1, // 1:下注,2:派彩,3:下注撤销
"trans_no": "101156966-1170920125564673-1006-2-1726-1709201163-0",//本次变更唯一凭证
"draw_id": "1006-2-1726-1709201163-0", // 牌局唯一标识
"game_id": 1006, // 游戏ID
"room_kind": 0, // 房间类型
"orders": [
{
"trans_no": "101156966-1170920125564673-1006-2-1726-1709201163-0",
"op_id": "xxx-xxx-aaa", // op侧用户的唯一标识, required
"amount": -5000, // 金额变动
"extra_business": {"total_bet":6000,"total_award":1000},
},
{
"trans_no": "101156966-1170920125564673-1006-2-1726-1709201163-0",
"op_id": "xxx-xxx-aaa", // op侧用户的唯一标识, required
"amount": -5000, // 金额变动
"extra_business": {"total_bet":6000,"total_award":1000},
}
]
}
参数说明:
参数 | 类型 | 说明 | 备注 |
---|---|---|---|
action | int | 请求行为 | 1: 下注 , 2: 奖励, 3: 下注撤销 |
trans_no | string | 本次订单的唯一标识 | |
draw_id | string | 牌局唯一标识 | |
game_id | int | 游戏ID | |
room_kind | int | 房间类型 | |
orders | object | 订单结构体 | |
order.trans_no | string | 订单唯一凭证,可以此做幂等操作 | |
order.op_id | string | op用户唯一标识 | |
order.amount | int64 | 金额变动 | 并非玩家的真实下注和奖励 |
order.extra_business | object | 不同游戏额外的业务数据 | 包含本局玩家实际的下注和奖励等业务信息 |
注意⚠️:order.amount为流水记录,并非实际下注和派彩,对于对战类和输金可能超过下注金额的百人类游戏,order.amount额外包含了预扣金额和预扣返还金额。
预扣:处理玩家快速下注和未知输赢金额时的余额不足问题时,提前质押玩家部分余额的行为,对局结束后即会返还,目前捕鱼类、对战类、百人类,均会使用预扣。
比如:游戏Mythical Animals,玩家下注100$,下注时order.amount则是-1300$,本局结束玩家额外再输掉了300$,奖励时order.amount则是900$。
百人类和对战类游戏中额外的业务数据说明:
参数 | 类型 | 说明 |
---|---|---|
extra_business.total_bet | int | 玩家在本局游戏里的实际下注 |
extra_business.total_award | int | 玩家在本局游戏里的实际奖励 |
Response:
json
// content-type: application/json
{
"header": {
"code": 0, // 错误编码,0表示正常, 非0表示异常
"msg": "not allowed bet",
"reason":"not allowed bet",
},
"result":
{
"data":[
{
"code": 0, // 错误编码,0表示正常, 非0表示异常
"op_id": "111444", // required op侧用户的唯一标识
"availableAmount": 998, // required op用户当前可用余额
},
{
"code": 0, // 错误编码,0表示正常, 非0表示异常
"op_id": "111445", // required op侧用户的唯一标识
"availableAmount": 998, // required op用户当前可用余额
}
]
}
}
POST /member/profile 用户信息查询
说明:用于即时获取用户信息
json
content-type: application/json
{
"op_id": "xxx-xxx-aaa", // op侧用户的唯一标识, required
}
参数说明:
参数 | 类型 | 说明 | 备注 |
---|---|---|---|
op_id | string | OP 的玩家id |
Response:
json
content-type: application/json
{
"header": {
"code": 0, // 错误编码,0表示正常, 非0表示异常
"msg": "",
"timestamp":1709716095516,
},
"result":
{
"nickname": "player01", // op 玩家昵称 required
"gender": 1 , // op 玩家性别 0-unknown, 1-famale, 2-male
}
}
POST /order/business 业务数据推送
说明:该接口为非必需接口,用于将一些游戏的业务信息即时的推送到OP侧,比如捕鱼类游戏玩家的开火和击杀数据。
json
content-type: application/json
{
"game_id": 4001, // 游戏ID
"room_kind": 1, // 场次编号
"businesses":Object // 不同游戏自身的业务数据
}
参数说明:
参数 | 类型 | 说明 | 备注 |
---|---|---|---|
game_id | int | 游戏ID | |
room_kind | int | 场次编号 | |
businesses | Object | 游戏的业务数据 | Fishdom |
Response:
json
content-type: application/json
{
"header": {
"code": 0, // 错误编码,0表示正常, 非0表示异常
"msg": "",
"timestamp":1709716095516,
}
}