client_id和app_secretclient_id和app_secret以B站侧提供的信息为准;| 名称 | 类型 | 是否必填 | 描述 |
|---|---|---|---|
| Accept | String | 是 | 接受的返回结果的类型。目前只支持JSON类型。取值:application/json |
| Content-Type | String | 是 | 当前请求体(Request Body)的数据类型。取值:application/json或multipart/form-data |
| x-bili-content-md5 | String | 是 | 请求体的编码值,根据请求体计算所得(全小写字母)。 算法说明:将body的请求体内容(除文件外)当作字符串进行MD5编码。 如果为GET请求或者请求的body为空,x-bili-content-md5的值请直接使用空字符串(string.Empty)进行求md5。 |
| x-bili-timestamp | String | 是 | unix时间戳,单位是秒。请求时间戳不能超过当前时间10分钟,否则请求会被丢弃。 |
| x-bili-signature-method | String | 是 | 签名方式。取值:HMAC-SHA256 |
| x-bili-signature-nonce | String | 是 | 全网签名唯一随机数。用于防止网络重放攻击,建议您每一次请求都使用不同的随机数,例如GUID。 |
| x-bili-accesskeyid | String | 是 | B站侧给出的Access Key(申请应用时获得的client_id) |
| x-bili-signature-version | String | 是 | 如无单独说明,请取值2.0 |
| access-token | String | 否 | x-bili-signature-version为2.0时必填,为通过OAuth2授权获取到的access_token |
| Authorization | String | 是 | 请求签名。关于请求签名的计算方法,请参见签名机制。 |
\nGET请求或者请求的body为空,x-bili-content-md5的值请直接使用空字符串(string.Empty)进行求md5"x-bili-accesskeyid:$accesskeyidValue"
"x-bili-content-md5:$contentMd5Value"
"x-bili-signature-method:HMAC-SHA256"
"x-bili-signature-nonce:$signatureNonceValue"
"x-bili-signature-version:2.0"
"x-bili-timestamp:$timestamp""x-bili-accesskeyid:$accesskeyidValue"
"x-bili-content-md5:$contentMd5Value"
"x-bili-signature-method:HMAC-SHA256"
"x-bili-signature-nonce:$signatureNonceValue"
"x-bili-signature-version:2.0"
"x-bili-timestamp:$timestamp"x-bili-accesskeyid:xxxx
x-bili-content-md5:fa6837e35b2f591865b288dfd859ce9d
x-bili-signature-method:HMAC-SHA256
x-bili-signature-nonce:ad184c09-095f-91c3-0849-230dd3744045
x-bili-signature-version:2.0
x-bili-timestamp:1624594467Authorization字段中package main
import (
"crypto/hmac"
"crypto/md5"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/monaco-io/request"
"sort"
"strconv"
"strings"
"time"
)
type BaseResp struct {
Code int64 `json:"code"`
Message string `json:"message"`
RequestId string `json:"request_id"`
Data interface{} `json:"data"`
}
const (
ClientIdProd = "yourclientid"
AppSecretProd = "yoursecret"
AccessTokenProd = "youraccesstoken"
)
const (
AcceptHeader = "Accept"
ContentTypeHeader = "Content-Type"
AuthorizationHeader = "Authorization"
JsonType = "application/json"
HmacSha256 = "HMAC-SHA256"
BiliTimestampHeader = "x-bili-timestamp"
BiliSignatureMethodHeader = "x-bili-signature-method"
BiliSignatureNonceHeader = "x-bili-signature-nonce"
BiliAccessKeyIdHeader = "x-bili-accesskeyid"
BiliSignVersionHeader = "x-bili-signature-version"
BiliContentMD5Header = "x-bili-content-md5"
AccessToken = "access-token"
BiliVersionV2 = "2.0"
MainOpenPlatformHttpHost = "https://member.bilibili.com"
)
type CommonHeader struct {
ContentType string
ContentAcceptType string
Timestamp string
SignatureMethod string
SignatureVersion string
Authorization string
Nonce string
AccessKeyId string
ContentMD5 string
X1BilispyColor string
AccessToken string
}
// ApiRequestV2 http request demo方法
func ApiRequestV2(reqJson, requestUrl string) (resp BaseResp, err error) {
resp = BaseResp{}
header := &CommonHeader{
AccessToken: AccessTokenProd,
ContentType: JsonType,
ContentAcceptType: JsonType,
Timestamp: strconv.FormatInt(time.Now().Unix(), 10),
SignatureMethod: HmacSha256,
SignatureVersion: BiliVersionV2,
Authorization: "",
Nonce: strconv.FormatInt(time.Now().UnixNano(), 10), //用于幂等,记得替换
AccessKeyId: ClientIdProd,
ContentMD5: Md5(reqJson),
//X1BilispyColor: model.Color,
}
header.Authorization = CreateSignature(header, AppSecretProd)
cli := request.Client{
Method: "POST",
URL: fmt.Sprintf("%s%s", MainOpenPlatformHttpHost, requestUrl),
Header: ToMap(header),
String: reqJson,
}
// 打印请求的cURL命令
fmt.Println("cURL Command:")
cli.PrintCURL()
var respTest interface{}
cliResp := cli.Send().Scan(&respTest)
if !cliResp.OK() {
err = fmt.Errorf("[error] req:%+v resp:%+v err:%+v", reqJson, resp, cliResp.Error())
}
// 使用json.MarshalIndent来格式化JSON数据
jsonData, err := json.MarshalIndent(respTest, "", " ")
if err != nil {
fmt.Println("Error marshaling JSON:", err)
return
}
// 打印格式化后的JSON字符串
fmt.Println(string(jsonData))
return
}
// CreateSignature 生成Authorization加密串
func CreateSignature(header *CommonHeader, accessKeySecret string) string {
sStr := ToSortedString(header)
return HmacSHA256(accessKeySecret, sStr)
}
// Md5 md5加密
func Md5(str string) (md5str string) {
data := []byte(str)
has := md5.Sum(data)
md5str = fmt.Sprintf("%x", has)
return md5str
}
// HmacSHA256 HMAC-SHA256算法
func HmacSHA256(key string, data string) string {
mac := hmac.New(sha256.New, []byte(key))
mac.Write([]byte(data))
return hex.EncodeToString(mac.Sum(nil))
}
// ToMap 所有字段转map<string, string>
func ToMap(h *CommonHeader) map[string]string {
return map[string]string{
BiliTimestampHeader: h.Timestamp,
BiliSignatureMethodHeader: h.SignatureMethod,
BiliSignatureNonceHeader: h.Nonce,
BiliAccessKeyIdHeader: h.AccessKeyId,
BiliSignVersionHeader: h.SignatureVersion,
BiliContentMD5Header: h.ContentMD5,
AuthorizationHeader: h.Authorization,
ContentTypeHeader: h.ContentType,
AcceptHeader: h.ContentAcceptType,
AccessToken: h.AccessToken,
}
}
// ToSortMap 参与加密的字段转map<string, string>
func ToSortMap(h *CommonHeader) map[string]string {
return map[string]string{
BiliTimestampHeader: h.Timestamp,
BiliSignatureMethodHeader: h.SignatureMethod,
BiliSignatureNonceHeader: h.Nonce,
BiliAccessKeyIdHeader: h.AccessKeyId,
BiliSignVersionHeader: h.SignatureVersion,
BiliContentMD5Header: h.ContentMD5,
}
}
// ToSortedString 生成需要加密的文本
func ToSortedString(h *CommonHeader) (sign string) {
hMap := ToSortMap(h)
var hSil []string
for k := range hMap {
hSil = append(hSil, k)
}
sort.Strings(hSil)
for _, v := range hSil {
sign += v + ":" + hMap[v] + "\n"
}
sign = strings.TrimRight(sign, "\n")
return
}| 名称 | 类型 | 是否必填 | 例子 | 描述 |
|---|---|---|---|---|
| code | int | 是 | 0 | 返回码,业务错误码参考下方。 |
| message | string | 是 | success | 返回信息,业务错误信息参考下方。 |
| data | object | 是 | 业务信息。 | |
| request_id | string | 是 | abcd123456 | 每次请求生成的唯一id,用于问题排查。 |
| 错误码 | 含义 |
|---|---|
| 4000 | 参数错误(一般是缺少参数) |
| 4001 | 配置无效 |
| 4002 | 签名异常 |
| 4003 | 请求过期 |
| 4004 | 重复请求 |
| 4005 | 签名method异常 |
| 4006 | 签名版本异常 |
| 4007 | Content-Type不为application/json |
| 4008 | MD5校验失败 |
| 4009 | Accept不为application/json |
| 4010 | 服务异常 |
| 4011 | 内部错误 |
| 4012 | BizCode不支持该方法 |
| 错误码 | 含义 |
|---|---|
| 122000 | client_id错误 |
| 122001 | client_secret 错误 |
| 122002 | code未找到 |
| 122007 | refreshToken不合法 |
| 122008 | app_id不匹配 |
| 122009 | 系统繁忙,获取用户数据失败,请稍后再试 |
| 122010 | 系统异常,相关用户操作失败 |
| 错误码 | 含义 |
|---|---|
| 127000 | 缺少鉴权参数 |
| 127001 | access_token验证错误 |
| 127002 | sign验证错误 |
| 127003 | 缺少mid或mid不匹配 |
| 127004 | client_id验证错误 |
| 127005 | 机构认证未通过 |
| 127006 | 应用认证未通过 |
| 127007 | 应用无该接口权限 |
| 127008 | mid验证失败 |
| 127009 | 接口请求次数达到上限 |
| 127010 | sign白名单验证错误 |
| 127011 | 该接口用户未授权 |
| 127022 | upload_token验证错误 |
| 127023 | client_token校验错误 |
| 错误码 | 含义 |
|---|---|
| 127009 | 接口繁忙,请稍后再试 |
| 127304 | 接口访问受限,请确认应用已申请相关权限,且授权账号状态正常 |
| 127305 | 白名单限制 |
| 127306 | 接口请求频率过高,请确保请求量正常。如果使用量大请联系运营进行相关业务咨询 |
| 错误码 | 含义 |
|---|---|
| 123001 | 账号无权限操作 |
| 123002 | 服务不可用 |
| 123003 | 该类型不支持投稿 |
| 123004 | 不存在该稿件 |
| 123005 | 稿件已经被删除 |
| 123006 | 异常视频提交 |
| 123007 | 当前稿件已锁定 |
| 123008 | 参数错误 |
| 123009 | 该分区不存在 |
| 123010 | 该稿件类型不合法 |
| 123011 | 该活动不存在 |
| 123012 | Tag参数不合法 |
| 123013 | 标题不合法 |
| 123014 | 描述信息不合法 |
| 123015 | 新增稿件同一个标题短时间内不能重复提交 |
| 123016 | 稿件转载来源不能为空 |
| 123017 | 稿件描述长度为零 |
| 123018 | 稿件描述长度太长,已超过限制 |
| 123019 | 稿件描述类型不存在或者不匹配 |
| 123020 | 稿件描述类型和对应的分区类型不匹配 |
| 123021 | 稿件描述类型和对应的创作类型不匹配 |
| 123022 | 第(%d)个Tag已被封印 |
| 123023 | 投稿暂不可用 |
| 123024 | 当前输入有敏感信息,请修正 |
| 123026 | 您投稿的频率过快,请稍等30秒 |
| 123027 | 转载类型稿件不支持活动参加哦~ |
| 123028 | 稿件后台处理中,请10秒后再尝试 |
| 123029 | 当前总提交视频个数已经超过上限 |
| 123030 | 稿件标题过长,已经超过80个字符 |
| 123033 | 第(%d)个视频的标题过长,已经超过80个字符 |
| 123034 | 开放联合投稿权限前的稿件,不可编辑为合作稿件 |
| 123035 | 当前稿件已开放,不允许再次设置定时发布,请刷新列表查看 |
| 123036 | 非正式会员单日只能投递五个稿件,赶紧去答题转正吧 |
| 123037 | 您当前等级太低,无法投稿,请先答题到1级,谢谢 |
| 123038 | 封面不允许使用gif |
| 123039 | 网络繁忙 请稍后再试 |
| 123040 | 不存该视频 |
| 123041 | 该视频已经被UP主删 除 |
| 123042 | 视频提交需要二次确认 |
| 123043 | 稿件任务已被取消 |
| 123044 | 新人单P 系统升级中,敬请谅解 |
| 123045 | 定时发布设置错误 |
| 123046 | 视频章节内容含有非法字符 |
| 123047 | 当前话题和分区不匹配,请重新选择话题或者分区 |
| 123048 | 活动话题不允许修改 |
| 123049 | 当前话题无效 |
| 123050 | 投稿需要图片验证 |
| 123051 | 投稿图片验证失败 |
| 123052 | 您投稿的内容不符合平台社区规范 |
| 123053 | 稿件批量提交时mtime校验失败 |
| 123054 | 稿件提交时mtime校验失败 |
| 123055 | 稿件审核机器提交时mtime校验失败 |
| 123056 | 稿件审核人工提交时mtime校验失败 |
| 错误码 | 含义 |
|---|---|
| 129000 | 相同标题的专栏短时间内不能重复提交 |
| 129001 | 专栏不存在 |
| 129002 | 分类错误 |
| 129003 | 标签错误 |
| 129004 | 封面图地址错误 |
| 129005 | 专栏标题含有特殊文字或者标题长度大于40 |
| 129006 | 正文要超过200字以上或者超过三张图哦 |
| 129009 | 创建失败,文集数量达到上限 |
| 129010 |