接口公共说明
S2S 接口地址
- TapTap -> 厂商,由厂商提供接口地址,由厂商提供接口地址,可前往
开发者中心 > 你的游戏 > 游戏服务 > 应用配置 > 直达礼包 > 直达礼包发送的接口地址
进行配置。 - 厂商 -> TapTap,https://cloud.tapapis.cn
公共参数
HTTP Request Method
- GET
- POST
HTTP Request Content-type
- application/json
HTTP Request Parameters
字段名 | 描述 | 类型 | 示例 |
---|---|---|---|
client_id | TapTap 开放平台 ID | string | s7ui6smunrk7tmt4m6 |
app_id | app_id:游戏在 TapTap 商店的唯一身份标识。 例如:https://www.taptap.cn/app/187168,其中 187168 是 app_id。 | uint64 | 58881 |
字段名 | 描述 | 类型 | 示例 |
---|---|---|---|
x-tap-ts | 请求时间,秒级时间戳 | uint64 | 1692347090 |
x-tap-nonce | 8 位随机字符串 | string | q1w2e3r4 |
x-tap-sign | 签算结果,不参与签算过程 | string | TZ76PQthw6mjaEPMbdyFjHyXvH7yAr2+IahMgX9ue8M= |
签名方法
构造待签名的请求内容 SignParts
{method}\n
{url_path_and_query}\n
{headers}\n
{body}\n
参数说明如下
字段名 | 描述 | 示例 |
---|---|---|
method | HTTP 方法,如 GET / POST (须为全部大写) | GET |
url_path_and_query | 完整请求路径及 QueryString | /apk/v1/upload-params?app_id=58881&file_name=xxx.apk&client_id=rfciqabirt4vqav7io |
headers | 所有以 x-tap- 为前缀的请求头(x-tap-sign 除外),将其 header keys 转小写并按 ANSII 排序后,key 和 value 以 : 分隔,各个 header 以换行符 \n 分隔,拼接成字符串 | x-tap-nonce:q1w2e3r4\nx-tap-ts:1692347090 |
body | 完整请求体 | {"key":"value"} |
计算签名
Signature = Base64Encode(HMAC-SHA256(Server Secret, SignParts))
HMAC-SHA256
方法的第一个参数是 key,第二个参数是待签名字符串Server Secret
为开放平台的服务端密钥,在 TapTap 开发者中心开通游戏服务后即可获取。SignParts
为第一步计算所得字符串
package tapsign
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"errors"
"fmt"
"io"
"net/http"
"sort"
"strings"
)
func Sign(req *http.Request, secret string) (string, error) {
// 获取 request method
methodPart := req.Method
// 获取完整 request
url + query urlPathAndQueryPart := req.URL.RequestURI()
// 获取 request headers
headersPart, err := getHeadersPart(req.Header)
if err != nil {
return "", err
}
// 获取 request body
bodyPart, err := io.ReadAll(req.Body)
if err != nil {
return "", err
}
// 计算签名
signParts := methodPart + "\n" + urlPathAndQueryPart + "\n" + headersPart + "\n" + string(bodyPart) + "\n"
fmt.Println(signParts)
h := hmac.New(sha256.New, []byte(secret))
h.Write([]byte(signParts))
rawSign := h.Sum(nil)
sign := base64.StdEncoding.EncodeToString(rawSign)
return sign, nil
}
func getHeadersPart(header http.Header) (string, error) {
var headerKeys []string
for k, v := range header {
k = strings.ToLower(k)
if !strings.HasPrefix(k, "x-tap-") {
continue
}
if k == "x-tap-sign" {
continue
}
if len(v) > 1 {
return "", errors.New(fmt.Sprintf("invalid header, %q has multiple values", k))
}
headerKeys = append(headerKeys, k)
}
sort.Strings(headerKeys)
headers := make([]string, 0, len(headerKeys))
for _, k := range headerKeys {
headers = append(headers, fmt.Sprintf("%s:%s", k, header.Get(k)))
}
return strings.Join(headers, "\n"), nil
}
验签方法
通过上述签算方法获取签名后和 Request header 中 x-tap-sign
对比,一致则验签通过。
Response 通用结构
{
"code": 0,
"msg": "OK",
"data": {
// response data
}
}
字段名 | 类型 | 描述 |
---|---|---|
code | uint64 | 业务返回状态码 0 表示请求成功,非 0 表示请求异常,参见错误码表 |
msg | string | 业务返回状态描述 "OK" 表示请求成功,其他表示请求异常,错误信息见字段内容 |
data | object | 成功时返回业务数据,失败时不读取 |
错误码表
自定义状态码 | 含义 | 复现场景 |
---|---|---|
510001 | 参数错误 | 发起请求的参数错误或者缺失部分必要参数 |
510002 | 发送道具失败 | 发送道具游戏方返回了失败结果 |
510003 | 该礼包码无效 | 异常兑换码的提交 |
510004 | 礼包码次数已达上限 | 通相同用户使用礼包中超过礼包设置的兑换数量 |
510005 | 找不到服务器列表 | 该用户在服务器下没有任何角色 |
510006 | 找不到角色列表 | 没有对应的角色 |
510007 | 点击过快,请稍候再试 | 用户连续点击获取角色或兑换礼包 |
510008 | 服务器故障 | 礼包系统出现通用性错误 |