服务端 REST API
服务端开发指南
服务端 REST API
URL | HTTP | 功能 |
---|---|---|
/open/payment/v1/orders/<order_id> | GET | 查询订单信息 |
/open/payment/v1/orders/<order_id>/verify | POST | 核销订单 |
/open/payment/v1/orders/<order_id>/refund | POST | 订单退款 |
/open/payment/v1/orders/unconfirmed | GET | 查询未核销的订单列表 |
查询订单
通过一个订单 ID 可以查询到订单的详细信息并确定当前的支付状态
curl -X GET \
-H 'X-LC-Id: {{client_id}}' \
-H 'X-LC-Key: {{server_secret}},master' \
https://tds-tapsdk0.intl.tapapis.com/open/payment/v1/orders/1670731970469806082
返回值是一个订单的 JSON 对象
{
"data" : {
"amount" : 299,
"client_id" : "UeTShOwxDrAsf232WN",
"currency" : "USD",
"extra" : "648ff2d31a81c",
"goods_open_id" : "game-11190",
"minor_unit" : 2,
"order_id" : "1670680390026510338",
"order_token" : "2cf31318c6f4939d5eaf2e9431bf45f2",
"region_id" : "HK",
"status" : "refund.succeeded",
"user_id" : 3173821787,
"verified" : false
},
"success" : true
}
核销订单
当支付成功后,核销订单表示已经确认支付结果并会对买家完成发货,订单状态也会从 charge.succeeded
变为 charge.confirmed
curl -X POST \
-H 'X-LC-Id: {{client_id}}' \
-H 'X-LC-Key: {{server_secret}},master' \
-H 'Content-Type: application/json; charset=utf-8'
-d '{"token": "2cf31318c6f4939d5eaf2e9431bf45f2"}'
https://tds-tapsdk0.intl.tapapis.com/open/payment/v1/orders/1670731970469806082/verify
返回值是一个订单的 JSON 对象
{
"data" : {
"amount" : 299,
"client_id" : "UeTShOwxDrAsf232WN",
"currency" : "USD",
"extra" : "648ff2d31a81c",
"goods_open_id" : "game-11190",
"minor_unit" : 2,
"order_id" : "1670680390026510338",
"order_token" : "2cf31318c6f4939d5eaf2e9431bf45f2",
"region_id" : "HK",
"status" : "refund.succeeded",
"user_id" : 3173821787,
"verified" : false
},
"success" : true
}
游戏服务端使用 REST API 应该只有「查询订单」以及「核销订单」的场景。异常响应示例如下所示:
// 1004 - 订单不存在 1018 - 验证订单错误
{
"data" : {
"code" : 1004,
"error" : "order_not_found",
"error_description" : "订单不存在",
"msg" : "订单不存在"
},
"success" : false
}
订单退款
对一个订单进行退款
curl -X GET \
-H 'X-LC-Id: {{client_id}}' \
-H 'X-LC-Key: {{server_secret}},master' \
https://tds-tapsdk0.intl.tapapis.com/open/payment/v1/orders/1670731970469806082/refund
查询未核销的订单
查询当前为核销的订单列表,正常情况下在用户支付成功后,应通过 verify 接口核销订单并同时保证对用户发货成功。如果因异常原因没有完成核销,可以通过这个接口查询并重新 verify 并完成发货。
订单对象字段
字段 | 含义 |
---|---|
client_id | 应用 Client ID |
user_id | 用户 OpenID |
order_id | 订单 ID |
order_token | 用于核销的 token |
goods_open_id | 商品 ID |
amount | 订单金额 |
currency | 货币 |
monior_unit | 货币精度 |
region_id | 买家区域 |
status | 订单状态 |
verified | 之前是否已经核销过 |
extra | 业务附加数据 |
订单状态
状态 | 含义 |
---|---|
charge.pending | 待支付 |
charge.succeeded | 支付成功 |
charge.confirmed | 已核销 |
charge.overdue | 支付超时关闭 |
refund.pending | 退款中 |
refund.succeeded | 退款成功 |
refund.failed | 退款失败 |
refund.rejected | 退款被拒绝 |
角色信息
(必配)
路由地址
游戏可自定义
请求方式
POST-application/json
入参 |参数|类型|含义|是否必须 |:----- |:----- |:----- |:----- | |open_id|string|用户唯一ID|Y |language|string|展示label的语言|Y
出参如下
示例一:适合通过"角色"确定一个充值对象
{
"data": {
"depth_title": [
{
"label": "角色",
"value": "role"
}
],
"player": [
{
"label": "冒险者A",
"value": "a"
},
{
"label": "冒险者B",
"value": "b"
}
]
},
"success": true
}
示例二:适合通过"服务器","角色"确定一个充值对象
{
"data": {
"depth_title": [
{
"label": "服务器",
"value": "server"
},
{
"label": "角色",
"value": "role"
}
],
"player": [
{
"label": "服务器S1",
"value": "S1",
"children": [
{
"label": "冒险者A",
"value": "a"
},
{
"label": "冒险者B",
"value": "b"
}
]
},
{
"label": "服务器S2",
"value": "S2",
"children": [
{
"label": "冒险者C",
"value": "c"
}
]
}
]
},
"success": true
}
`
示例三:适合通过"地区","服务器","角色"确定一个充值对象
```json
{
"data": {
"depth_title": [
{
"label": "地区",
"value": "region"
},
{
"label": "服务器",
"value": "server"
},
{
"label": "角色",
"value": "role"
}
],
"player": [
{
"label": "美东",
"value": "ae",
"children": [
{
"label": "服务器S1",
"value": "S1",
"children": [
{
"label": "冒险者A",
"value": "a"
}
]
},
{
"label": "服务器S2",
"value": "S2",
"children": [
{
"label": "冒险者C",
"value": "c"
}
]
}
]
}
]
},
"success": true
}
购买配置 API
(选配)
路由地址
游戏可自定义
请求方式
POST-application/json
入参
示例一
参数 | 类型 | 含义 | 是否必须 |
---|---|---|---|
role | string | 角色ID | Y |
示例二
参数 | 类型 | 含义 | 是否必须 |
---|---|---|---|
server | string | 服务器ID | Y |
role | string | 角色ID | Y |
示例三
参数 | 类型 | 含义 | 是否必须 |
---|---|---|---|
region | string | 地区ID | Y |
server | string | 服务器ID | Y |
role | string | 角色ID | Y |
出参
参数 | 类型 | 含义 | 是否必须 |
---|---|---|---|
type | string | 规则类型:blacklist-商品黑名单,whitelist-商品白名单 | Y |
list | string | 商品唯一ID | Y |
{
"data": {
"type": "blacklist",
"list": [
"com.gooplin.il.GiftPackOrcTask",
"com.gooplin.il.ActivityPack006"
]
},
"success": true
}
到账通知
(必配)
路由地址
游戏可自定义
请求方式
POST-application/json
入参
参数 | 类型 | 含义 | 是否必须 |
---|---|---|---|
id | long | 订单唯一ID | Y |
client_id | string | DC应用ID | Y |
user_id | long | 用户的TapTapId | Y |
open_id | long | 用户的开放平台ID | Y |
user_region | string | 用户地区 | Y |
merchant_order_id | string | 商户订单唯一ID | Y |
payment_provider | string | 支付方式 | Y |
payment_channel | string | 支付渠道 | Y |
goods_id | string | 商品唯一ID | Y |
goods_name | string | 商品名称 | Y |
status | string | 订单状态 | Y |
amount | string | 金额 | Y |
tax | string | 税 | Y |
fee | string | 费 | Y |
currency | string | 币种 | Y |
create_time | long | 创建时间 | Y |
pay_time | long | 支付时间 | Y |
extra | string | 自定义信息,如服务器、角色信息 | Y |
order_refund | object | 退款信息,默认空 | Y |
{
"order":{
"id":1721791738662895617,
"client_id":"3l5b2phi8k2snze3hs",
"user_id":3173820362,
"open_id":"I1LEuujBQMqM4d9CWpVQug==",
"user_region":"CL",
"merchant_order_id":"f84f6778-9357-413c-b503-066900667ff5",
"payment_provider":"STRIPE",
"payment_channel":"CARD",
"goods_id":"com.gooplin.il.goods1030",
"goods_name":"test20230920-name",
"status":"charge.confirmed",
"amount":"990",
"tax":"0",
"fee":"0",
"currency":"CLP",
"create_time":1699342114,
"pay_time":1699342118,
"extra":"{\"server\":\"S1\",\"role\":\"b\"}",
"order_refund":{}
},
"event_type":"charge.succeeded"
}
出参如下 成功则输出字符串:success 失败输出其他任意字符串
TapPay-Signature header规则
通过 TapPay-Signature header 传递签名信息。格式 时间戳,签名 如: TapPay-Signature: 1687224754,4dd293a514223c052513c1db449106f13710c733855d2af6654948675e1624e7 根据上面的 header ,得到 ts = 1687224754 ,首先可以确认一下跟当前系统时间是否差异过大,确保不是被重用的旧请求。 请求的 request body ,是一个 JSON 字符串,定义为 payload
{"open_id":"4tPbsDs1EHHt33c9HMFOjg=="}
sign = HmacSHA256(secret, ts + "." + payload )
Webhook 回调
Webhook 说明
目前 Webhook 仅监听「退款成功」事件: refund.succeeded
,对于支付成功建议采取主动核销订单
,根据订单状态完成发货。
Webhook 验签
Webhook 是一个 HTTP POST 请求,通过 TapPay-Signature
header 传递签名信息。格式 时间戳,签名
如:
TapPay-Signature: 1687224754,4dd293a514223c052513c1db449106f13710c733855d2af6654948675e1624e7
根据上面的 header ,得到 ts = 1687224754
,首先可以确认一下跟当前系统时间是否差异过大,确保不是被重用的旧请求。
请求的 request body ,是一个 JSON 字符串,定义为 payload
{
"event_type": "refund.succeeded"
"order": {
"amount" : 299,
"client_id" : "UeTShOwxDrAsf232WN",
"currency" : "USD",
"extra" : "648ff2d31a81c",
"goods_open_id" : "game-11190",
"minor_unit" : 2,
"order_id" : "1670680390026510338",
"order_token" : "2cf31318c6f4939d5eaf2e9431bf45f2",
"region_id" : "HK",
"status" : "refund.succeeded",
"user_id" : 3173821787,
"verified" : false
}
}
此外,还需要将在 TapTap 开发者中心后台配置的 API 密钥
作为 HmacSHA256 算法的 secret 最终得到
sign = HmacSHA256(secret, ts + "." + payload )
比对计算结果 sign 和 TapPay-Signature
的签名部分是否相同
Webhook 内容
Webhook 内容包含 event_type
和 订单信息,目前支持的 event_type
有:
event_type | 含义 |
---|---|
refund.succedded | 退款成功 |
{
"event_type": "refund.succeeded"
"order": {
"amount" : 299,
"client_id" : "UeTShOwxDrAsf232WN",
"currency" : "USD",
"extra" : "648ff2d31a81c",
"goods_open_id" : "game-11190",
"minor_unit" : 2,
"order_id" : "1670680390026510338",
"order_token" : "2cf31318c6f4939d5eaf2e9431bf45f2",
"region_id" : "HK",
"status" : "refund.succeeded",
"user_id" : 3173821787,
"verified" : false
}
}