跳到主要内容

OAuth接入文档

欢迎使用 WEEX OAuth服务。本指南旨在帮助第三方平台(以下简称“平台方”)安全、高效地接入WEEX 用户授权系统。您的平台可以在获得用户授权后,获取用户特定的API 密钥,从而代替用户进行行情查询、现货及合约交易等操作。

流程概览

整个接入流程主要分为三个步骤:

  1. 平台注册:联系 WEEX 商务注册您的平台信息,获取唯一的clientIdsecret并配置回调地址等信息。
  2. 用户授权:引导 WEEX 用户登录并授权,获取临时的授权码(code)。
  3. 换取密钥:在后端使用 code 换取 access_token,再通过 access_token 获取最终的 API Key、Secret Key、Passphrase,用于后续的 API 调用。

接入准备

向WEEX提供以下信息完成平台注册:

配置项说明示例
平台名称您的平台名称,将在用户授权页显示,只支持英文名称MyTrading
WEEX UID平台方关联的 WEEX 用户ID,用于身份关联123456
隐私条款您的平台隐私条款地址https://www.mytrading.com/en/privacy-policy
服务条款您的平台隐私条款地址https://www.mytrading.com/en/terms-of-use
平台Logo将显示在用户授权页的Logo图片
联系人技术或商务联系人
邮箱联系人的邮箱地址[email protected]
电话联系人的电话号码
回调地址关键配置
用户授权后,WEEX OAuth 服务器将重定向至此地址,并携带授权码。支持配置多个回调地址,但请求时必须完全匹配其中之一
https://api.mytrading.com/oauth/callback
https://sandbox.mytrading.com/oauth/callback
出口 IP为了确保通信安全,您需要提供平台服务器访问 WEEX 接口时的公网出口 IP 地址。WEEX 运维团队将为您配置白名单,未授权的 IP 将无法调用接口。47.100.1.1, 47.100.1.2

接入步骤

1.拼接授权页面

# OAuth 授权页面示例
https://www.weex.com/oauth?
clientId={clientId}&
responseType=code&
scope=create:apikey&
redirectUri={redirectUri}&
state={state}&
codeChallenge={codeChallenge}&
codeChallengeMethod={codeChallengeMethod}

请求参数:

参数说明备注
clientId商户身份标识商户初始化完成后获得
responseType响应类型固定值:code
scope权限范围create:apikey
state状态参数随机字符串,防 CSRF 攻击
redirectUri回调地址必须在管理后台配置
codeChallengePKCE 挑战值PKCE 挑战值,RFC 7636 规定格式:43-128 位的 [A-Z, a-z, 0-9, -, ., _, ~]
codeChallengeMethodPKCE 方法PKCE 方法,当前仅支持 S256

注: 由于服务端强制PKCE,所以客户端需要生产pkce参数。

第一步:生成 Code Verifier (代码验证码)

客户端生成一个高熵的随机字符串 code_verifier。

  • 要求:由 [A-Z, a-z, 0-9, -, ., _, ~] 组成。
  • 长度:建议使用 43 位或以上(最大 128 位)。

第二步:生成 Code Challenge (代码挑战值)

对 code_verifier 进行 SHA256 哈希,然后进行 Base64URL 编码(且不得包含末尾的 = 填充符)。 code_challenge = Base64URL(SHA256(code_verifier))

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import java.security.SecureRandom;

public class PKCEUtils {
public static void main(String[] args) throws Exception {
// 1. 生成 code_verifier (随机字符串)
SecureRandom sr = new SecureRandom();
byte[] codeValue = new byte[32];
sr.nextBytes(codeValue);
String codeVerifier = Base64.getUrlEncoder().withoutPadding().encodeToString(codeValue);

// 2. 生成 code_challenge (S256)
byte[] bytes = codeVerifier.getBytes(StandardCharsets.US_ASCII);
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte[] digest = messageDigest.digest(bytes);
String codeChallenge = Base64.getUrlEncoder().withoutPadding().encodeToString(digest);

System.out.println("code_verifier: " + codeVerifier);
System.out.println("code_challenge: " + codeChallenge);
}
}

2. 授权成功回调

用户完成授权后,页面将会301重定向至 redirectUri 回调地址

# 假設 redirect_uri = https://www.example.com/callback
# 回調後的 URL:
https://www.example.com/callback/?
code=sS38ddda0ddPC342342hhfuiu&
state=1234abc

3.获取 access_token

接口信息:

请求参数:

参数类型是否必须参数描述
grantTypestring授权类型,可选值:authorization_code、refresh_token
codestring返回的授权码,grantType=authorization_code 时需传
redirectUristring回调地址,必须与授权时一致,grantType=authorization_code 时需传
codeVerifierstringPKCE 原始值,grantType=authorization_code 时需传
refresh_tokenstring刷新令牌,grantType=refresh_token 时需传

请求示例:

curl -v -X POST {url} \
-H 'Client-Id: weex123456' \
-H 'Sign: *******' \
-H 'Timestamp: 1735689600000' \
-H 'Nonce: Nonce' \
-d '{
"grantType": "authorization_code",
"code": "auth_code_xxx",
"redirectUri": "https://api.wundertrading.com/oauth/callback",
"codeVerifier": "code-verifier-demo"
}'

返回参数:

参数类型参数描述
accessTokenString访问令牌
refreshTokenString刷新令牌
tokenTypeString令牌类型,固定为 Bearer
expiresInintaccess token 剩余有效期,单位秒
refreshExpiresInintrefresh token 剩余有效期,单位秒
scopeString授权范围

返回示例:

{
"code": "00000",
"msg": "success",
"requestTime": 1774621008941,
"data": {
"accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI3NzU0MDkwNjQwIiwiYXVkIjoiY2FnZSIsInNjb3BlIjoiY3JlYXRlOmFwaWtleSIsImlzcyI6Imh0dHBzOi8vd2VleC5jb20iLCJleHAiOjE3NzQ2MjQ2MDgsImlhdCI6MTc3NDYyMTAwOCwianRpIjoiMzkifQ.mMVGvW0EeVO5TMxRiUDAyGmf64bcyEFXy0kz8xjv3wRp2pjsxpQUdT1Jn2V2SD0I6LhsCCRDp9Rhl6UuKnHYESBrqKWQONwf1nXTwIFB8Fmw_MqWFWVpi9nlaYBUIGiayuybllYZB1vN06fXRm5yq068UJFD_lSWMkrHJfUu5I7dD-JpwN9UNTsi5NY2a5vUc0WyBSPOnfnPBPr8x5PNB7uc9fr1Uew9QrmO2WnLuDCcDnZ2XGulzvmKC3b2ZXADDBKleuXAAgYzq-t-M4NBI2EjNP1wvpMGeTKyNTBKrXY4Wo0MQdipLGlKsr3cnpKdNqGWi9SzBSp-KctcGrpGew",
"refreshToken": "o_3ubYfLM9zaqbwF_Xo9Jb13vyq-KPP6sVlGEAL3TjrBmbzao-xuT82VDVRFA-bCGuim2V-A_6vCbIiZsvdbjIefaGKaskNubXM9Wk3--7QwoSDqtpsUyD9KnJtoqToe",
"tokenType": "Bearer",
"expiresIn": 3600,
"refreshExpiresIn": 36000,
"scope": "create:apikey"
}
}

4.获取Apikey

接口信息:

注:

  1. 同一个用户只能创建一个用户绑定三方的apikey,即只有用户不存在已绑定该三方的apikey时,接口才能调用成功。需重新绑定时,用户需要先删除原先已绑定的apikey。
  2. 调用创建api key成功后,需要妥善保存apikey、secret、passphrase,只有在第一次调用成功后才会返回以上3个参数
  3. 如果用户当前API状态不是正常,创建的APIKEY存在不能立马使用的情况。

请求示例:

curl {url} \
-H "Authorization: Bearer {access_token}"

返回示例:

{
"code": "00000",
"data": {
"apiKey": "ak_xxxxxxxxx",
"secret": "sk_xxxxxxxxx",
"passphrase": "pp_xxxxxxxxx"
},
"msg": "success",
"requestTime": "1768529101682"
}

错误示例

{
"code": "80000",
"msg": "param error",
"requestTime": "1768529101682"
}

响应码列表

响应码响应信息响应描述
00000success请求成功
40400resource not found接口路径不存在或资源不存在
80000param error请求参数错误
80002client invalidclient 无效
80003client auth failed客户端签名验证失败
80004PKCE code_verifier verification failed客户端 PKCE 校验失败
80005client mismatchclient 不匹配
80006expired request请求已过期
80007replay request重放请求
80008uid duplicate该 uid 已绑定 client
80009client unauthorizedclient 无权限
80010user invaliduser 无效
80100code invalid授权码无效
80200redirect uri invalidredirect uri 无效
80201redirect uri mismatchredirect uri 不匹配
80300access token invalidaccess token 无效
80301access token auth failaccess token 鉴权失败
80400refresh token invalidrefresh token 无效
80500grant type invalidgrant_type 无效
80600scope invalidscope 无效
80601scope insufficientscope 权限不足
80700unsupported response type不支持的 response type
80800state invalidstate 无效
80900code challenge invalidPKCE code_challenge 无效
80901code challenge method invalidPKCE code_challenge_method 无效
81000api key permission invalidAPI Key 权限无效
81001api key already boundAPI Key 已绑定
81002user api key num exceeds max limit用户 API Key 数量超过最大限制

安全与规范

保护密钥:

client_secret、code_verifier 以及最终获取的 secret_key 和 passphrase 都必须存储在后端,严禁放在前端代码或移动应用中。

验证 State:

严格验证回调中的 state 参数,防止 CSRF 攻击,建议使用随机字符串。

使用 HTTPS:

所有 API 请求必须通过 HTTPS 发起。