Bitget APIBitget API
统一账户经典账户
旧文档
  • 概览
  • API 文档
  • WebSocket
  • Agent Hub
  • SDK
  • 更新日志
Copied to clipboard
快速开始
统一账户快速开始最佳实践指南rToken 交易指南CFD 交易指南带单 API 交易指南
经纪商接入指南
    API 经纪商FastAPI 接入指南
历史数据下载指南
模拟盘
限频规则
API 参考
API 文档枚举
错误码
经纪商接入指南

FastAPI 接入指南

背景

欢迎与 Bitget 交易所合作,您作为 Broker 在接入我们的 FastAPI 时,需要按照我们给出的标准进行接入。在本文档中,我们将为您介绍如何接入到 Bitget 的 FastAPI。

接入准备

该功能需要联系您的 Bitget BD(Business Development)进行申请。请联系 BD 并提交以下资料:

信息说明
name平台名称
contact联系方式 — 邮箱或手机号
ip服务器 IP — Broker 平台调用 Bitget API 接口的常用 IP 地址
logo(AI)平台 Logo — 文件格式为 Adobe Illustrator
logo(PNG)平台 Logo — 文件格式为 PNG,像素要求为 64 × 64
callbackUrl回调地址 — 用于 Broker 用户信息回传
rsaPublicKey(2048 bit)公钥 — 基于 RSA 算法;格式规则为 RSA PKCS8 2048 位

申请成功后,BD 会提供以下信息:

参数名称参数类型说明
clientIdStringBroker 平台 ID — 由 Bitget 分配的唯一标识

技术实现

下面涉及到的一些属性信息,主要用于对接功能实现。

参数名称参数类型提供方描述
clientIdStringBitgetBroker 平台 ID — 申请成功后由 BD 提供
callbackUrlStringBroker 客户回调地址 — 作为 BD 申请材料的一部分提交给 Bitget;用于 Broker 用户信息回传
rsaPublicKey(2048 bit)StringBroker 客户公钥 — 作为 BD 申请材料的一部分提交给 Bitget;基于 RSA 算法,格式规则为 RSA PKCS8 2048 位
rsaPrivateKey(2048 bit)StringBroker 客户私钥 — 基于 RSA 算法;格式规则为 RSA PKCS8 2048 位;由 Broker 自行保管,无需提供给 Bitget

请妥善保管私钥

rsaPrivateKey 必须由 Broker 一方安全保存,切勿提供给 Bitget 或任何第三方。一旦私钥泄露,他人可解密用户的 API Key 信息并伪造签名。

代码示例(Java)

下面是签名和 RSA 加密解密的代码示例,均基于 Java 实现。

工具类

签名以及 RSA 加密/解密都基于下面的工具类实现。

Code
package xxx; import org.springframework.util.Base64Utils; import javax.crypto.Cipher; import java.nio.charset.StandardCharsets; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeSet; public class RsaUtil { // 使用公钥进行 RSA 加密 public static String encryptRSA(String plaintext, String publicKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKey)); byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)); return Base64Utils.encodeToString(encryptedBytes); } // 使用私钥进行 RSA 解密 public static String decryptRSA(String encryptedData, String privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey)); byte[] encryptedBytes = Base64Utils.decodeFromString(encryptedData); byte[] decryptedBytes = cipher.doFinal(encryptedBytes); return new String(decryptedBytes, StandardCharsets.UTF_8); } /** * 解码 PublicKey * * @param key * @return */ public static PublicKey getPublicKey(String key) throws Exception { byte[] byteKey = org.apache.commons.codec.binary.Base64.decodeBase64(key); X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(x509EncodedKeySpec); } /** * 解码 PrivateKey * * @param key * @return */ public static PrivateKey getPrivateKey(String key) throws Exception { byte[] byteKey = org.apache.commons.codec.binary.Base64.decodeBase64(key); PKCS8EncodedKeySpec x509EncodedKeySpec = new PKCS8EncodedKeySpec(byteKey); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(x509EncodedKeySpec); } public static boolean verify(Map<String, String> map, String publicKey, String sign) throws Exception { String srcData = getSignData(map); byte[] keyBytes = getPublicKey(publicKey).getEncoded(); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey key = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance("SHA256withRSA"); signature.initVerify(key); signature.update(srcData.getBytes()); return signature.verify(Base64Utils.decodeFromString(sign)); } /** * 签名 * * @param data 待签名数据 * @param privateKey 私钥 * @return 签名 */ public static String sign(String data, String privateKey) throws Exception { byte[] keyBytes = getPrivateKey(privateKey).getEncoded(); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey key = keyFactory.generatePrivate(keySpec); Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(key); signature.update(data.getBytes()); return Base64Utils.encodeToString(signature.sign()); } /** * 得到签名 * * @param params 参数集合,不含 secretKey * @return */ public static String getSignData(Map<String, String> params) { StringBuilder sb = new StringBuilder(); // step1:先对请求参数排序 Set<String> keyset = params.keySet(); TreeSet<String> sortSet = new TreeSet<String>(); sortSet.addAll(keyset); Iterator<String> it = sortSet.iterator(); // step2:把参数的 key value 链接起来,secretKey 放在最后面,得到要加密的字符串 while (it.hasNext()) { String key = it.next(); String value = params.get(key); sb.append(key).append(value); } return sb.toString(); } static String publicKey = "*****"; static String privateKey = "*****"; }

签名使用示例

Code
public static void main(String[] args) throws Exception { // 生成签名 Map<String, String> map = new HashMap<>(); long l = System.currentTimeMillis(); map.put("timestamp", String.valueOf(l)); map.put("clientId", "1"); map.put("clientUserId", "123"); String sign = RsaUtil.sign(RsaUtil.getSignData(map), RsaUtil.privateKey); System.out.println(sign); }

RSA 加密和解密使用示例

Code
public static void main(String[] args) throws Exception { String xxStr = "hello world"; // encrypt String encrypted = RsaUtil.encryptRSA(xxStr, RsaUtil.publicKey); System.out.println("encrypt by publicKey: " + encrypted); // decrypt System.out.println("decrypt by privateKey: " + RsaUtil.decryptRSA(encrypted, RsaUtil.privateKey)); }

功能实现

下面是功能实现的具体过程,其中涉及到了接口、参数、签名生成规则等 OAuth 授权流程细节。

整体流程分为三步:Broker 跳转 Bitget 授权页面、Bitget 携带用户 API Key 回调 Broker 接口、Bitget 携带授权结果跳转回 Broker 页面。

1. Broker 跳转 Bitget 授权页面

从 Broker 平台跳转到 Bitget 的授权页面时,需要 Broker 在 URL 中携带以下参数。

Bitget 授权页面链接为 https://www.bitget.com/account/oauth。

参数名参数类型描述
clientUserIdStringBroker 用户 ID — 客户自定义
timestampString时间戳 — Unix 毫秒格式;请传入当前时间前后 5 分钟内的时间戳,超出范围会被认为无效请求;用户在 Bitget 页面点击授权时会校验该时间戳
clientIdStringBroker 平台 ID
signString签名 — 格式规则为 clientId[]clientUserId[]timestamp[];实际使用请参考代码示例(Java)
redirectUrlString重定向地址 — 授权完成后自动跳转的 Broker 平台链接
serialNoString随机序列号 — 1)在回调接口中,Broker 需要通过此参数校验回调接口请求的合法性;2)出于安全考虑,请将 serialNo 与 clientUserId 关联,不要在多个账户间混用;3)出于安全考虑,建议为 serialNo 设置有效期,例如 10 分钟

示例 URL(请将参数进行 URL 编码,防止参数在传输过程中转译丢失):

Code
https://www.bitget.com/account/oauth?clientUserId=123&timestamp=1691117744470&clientId=1&redirectUrl=https://broker-domain/callback/url&sign=F9zeG9oUYzqwN94kSfoFy...&serialNo=123

补充说明(可选配置)

为帮助提升用户注册转化,Bitget 支持在 OAuth 跳转链接中携带邀请码(Referral Code)。当用户通过 OAuth 跳转至 Bitget 页面后点击注册,系统会自动识别链接中携带的邀请码,并在注册页面自动填充,无需用户手动输入。

配置方式:

  1. 联系 Broker 运营或 BD,在后台配置邀请链接(长链接),例如 https://www.bitget.com/test?channelCode=abcde&vipCode=1234&languageType=1。
  2. 从邀请链接中获取邀请码参数,例如 vipCode=1234。
  3. 将该邀请码参数追加至 Bitget OAuth 跳转链接后,即可完成配置。
Code
https://www.bitget.com/account/oauth?clientUserId=123&timestamp=1691117744470&clientId=1&redirectUrl=https://broker-domain/callback/url&sign=F9zeG9oUYzqwN94kSfoFy...&serialNo=123&channelCode=abcde&vipCode=1234

2. Bitget 回调 Broker 接口

一旦用户在页面完成授权,Bitget 将自动请求 Broker 回调接口。

  • 请求类型:POST
  • 请求 URL:双方商议
  • Content-Type:application/x-www-form-urlencoded
参数名参数类型描述
openIdString加密后的 Bitget user ID
userIdStringBitget user ID — 仅白名单用户返回,非白名单用户返回为空
clientUserIdStringBroker 用户 ID
timestampString时间戳 — Unix 毫秒格式;请验证该时间与当前时间的差值是否超过 5 分钟,如超出范围请视作无效请求
signString签名 — 请通过 privateKey 解密,解密后可获得 serialNo
dataString加密后的 API Key 信息 — 请通过 privateKey 解密,解密后可获得用户 apiKey、passphrase 及 secret

其他说明

  1. 请使用 privateKey 对 sign 进行解密,并校验结果是否与 serialNo 一致,若不一致则说明请求不合法。
  2. 请使用 privateKey 对 data 进行解密,解密结果为 JSON 格式的用户 API Key 信息:
Code
{ "apiKey": "bg_xxxxxxxxxx", "passphrase": "***", "secret": "xxxxxxxxxxxxxxxxxxxxxxx" }

请妥善保管 API Key 信息

解密后得到的 apiKey、passphrase、secret 可用于操作用户的 Bitget 账户交易权限,请安全存储(如加密存储),切勿在日志、前端代码或错误信息中暴露这些信息。

Bitget 请求后,Broker 需按照如下格式返回响应参数:

Code
{ "code": "00000", "msg": "success", "requestTime": "1671258739383" }

3. Bitget 跳转回 Broker 页面

授权结果无论成功还是失败,Bitget 都会将下列参数添加至 URL,并跳转到 Broker 页面。

参数名参数类型描述
clientUserIdStringBroker 平台的用户 ID
signString签名 — 通过 publicKey 加密后的 serialNo,需要进行解密
stateString授权状态 — 通过 publicKey 加密后的 state,需要进行解密;SUCCESS 表示授权成功,FAIL 表示授权失败

示例:

Code
https://broker-domain/callback/url?sign=sahkduhas1237hkNAQGS&clientUserId=123&state=DHJSAshaj

其他说明

  1. 请使用 privateKey 对 sign 进行解密,并校验结果是否与 serialNo 一致,若不一致则说明请求不合法。
  2. 建议通过 serialNo 查询 clientUserId,并判断是否与当前 URL 中的 clientUserId 一致,若不一致则说明请求不合法。
API 经纪商历史数据下载指南
On this page
  • 背景
  • 接入准备
    • 技术实现
    • 代码示例(Java)
  • 功能实现
    • 1. Broker 跳转 Bitget 授权页面
    • 2. Bitget 回调 Broker 接口
    • 3. Bitget 跳转回 Broker 页面