第4章:接入与认证

4.1 接入流程概述

WMS 对外 API 采用 Token 的安全认证机制。

客户系统在调用接口前,需要先向我司申请 API Key / Secret,并通过认证接口获取访问 Token。

后续所有业务接口调用时,均需在请求头中携带 Token。

系统目前支持两种访问模式:

模式说明
生产环境(Production)用于正式业务场景,数据真实、受权限控制。
测试环境(Sandbox)用于开发调试,接口逻辑与生产一致,但不产生真实业务数据。

4.2 凭证申请

在接入 WMS API 之前,开发者需向我司技术支持团队申请访问凭证。

申请时需提供以下信息:

参数说明
公司名称用于标识合作方身份
系统名称对接的 ERP / OMS / TMS 系统名称
联系人技术对接负责人姓名
联系邮箱接收 API Key / Secret 的邮箱地址
使用场景简要说明调用接口的目的与范围

说明:

  • 每个合作方将被分配独立的 API KeyAPI Secret
  • 以上信息审核通过后,我司将邮件发送认证信息。

4.3 Token 获取接口

获取 Token 是所有业务接口调用的前提。外部系统需要使用我司分配的 API KeyAPI Secret 来获取访问 Token。

请求地址: POST /ucauth/authc/account/createToken

请求头(Headers):

Header类型是否必填说明
X-Api-KeyString我司分配的应用标识(API Key)
X-Api-SecretString我司分配的应用密钥(API Secret)
Content-TypeString固定为 application/json

请求示例:

# 沙箱环境示例
curl -X POST "https://api.sandbox.onixportltl.com/ucauth/authc/account/createToken" \
  -H "X-Api-Key: 3F2504E04F8911D39A0C0305E82C3301" \
  -H "X-Api-Secret: L9Gf7bQ2xU3VjK1Yp8nR5wT0eXz6Hq2fAaJdKsLmQpU" \
  -H "Content-Type: application/json"

# 生产环境示例
curl -X POST "https://api.onixportsystem.com/ucauth/authc/account/createToken" \
  -H "X-Api-Key: your-api-key" \
  -H "X-Api-Secret: your-api-secret" \
  -H "Content-Type: application/json"

响应格式:

成功响应:

{
  "success": true,
  "errorCode": null,
  "errorMsg": null,
  "result": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expiresIn": 86400
  }
}

失败响应:

{
  "success": false,
  "errorCode": 1404,
  "errorMsg": "Email address or password is not valid."
}

响应字段说明:

字段类型说明
successBoolean请求是否成功
errorCodeInteger错误码。当 success=true 时,该字段为 null;当 success=false 时,该字段有值
errorMsgString错误信息。当 success=true 时,该字段为 null;当 success=false 时,该字段有值
resultObject成功时的响应数据
result.accessTokenString访问令牌,用于后续接口调用
result.expiresInLongToken 有效期(单位:秒),当前固定为 86400 秒(24小时)

说明:

  • expiresIn:Token 从当前时间开始的有效期,单位为秒,当前固定为 86400 秒(24小时)
  • 调用方应记录 Token 获取时间和 expiresIn 值,自行计算失效时间
  • 建议在 Token 失效前 1 分钟自动刷新,避免接口调用中断

常见错误码:

错误码说明
1404API Key 或 API Secret 无效
1405账户已被锁定,请联系系统管理员
1406账户邮箱需要验证
1412账户已被暂停,请联系销售获取更多信息
1440登录失败次数过多,请稍后再试

说明:

  • Token 有效期为 24 小时(86400 秒);
  • 建议将 Token 缓存到 Redis 或本地缓存中,缓存过期时间设置为 expiresIn - 5分钟(例如:86400 - 300 = 86100秒);
  • 当缓存过期时,说明 Token 即将失效,自动重新获取 Token;
  • Token 到期后需重新调用此接口获取新的 Token;
  • 所有业务接口均需在请求头中携带:Authorization: Bearer {accessToken}
  • 请妥善保管 API Key 和 API Secret,避免泄露。

4.4 业务接口请求头要求

获取 Token 后,调用业务接口时需在请求头中携带以下信息:

Header是否必填说明
Content-Type固定为 application/json
AuthorizationBearer {accessToken},其中 {accessToken} 为通过 createToken 接口获取的令牌

注意: 业务接口的请求头要求可能因具体接口而异,请参考各业务接口的详细文档。


4.5 Token 失效与续期

4.5.1 Token 失效时间

  • Token 有效期为 24 小时(86400 秒);
  • 创建 Token 时,响应中会返回 expiresIn 字段(单位:秒),表示 Token 的有效期;
  • 调用方应记录 Token 获取时间(Unix 时间戳)和 expiresIn 值,自行计算失效时间。

4.5.2 Token 刷新策略

建议实现:

1. 缓存 Token:将 Token 缓存到 Redis 或本地缓存中

2. 设置缓存过期时间:缓存过期时间应小于 expiresIn 值,例如提前 5 分钟失效

  • 缓存过期时间 = expiresIn - 5分钟(300秒)
  • 例如:expiresIn = 86400秒(24小时),则缓存过期时间 = 86100秒(23小时55分钟)

3. 自动刷新机制:当缓存过期时,说明 Token 即将失效,自动重新获取 Token

4. 缓存更新:获取新 Token 后,更新缓存并重新设置缓存过期时间

优势:

  • 利用缓存机制自动管理 Token 生命周期
  • 无需手动计算剩余时间,缓存过期即表示需要刷新
  • 支持分布式部署,多个服务实例共享同一个 Token

示例代码:

// 示例代码 - 使用 Redis 缓存
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.concurrent.TimeUnit;

public class TokenService {
    
    private static final String REDIS_KEY = "wms_api_token";
    private static final int CACHE_BUFFER = 5 * 60; // 提前5分钟失效(300秒)
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    @Autowired
    private TokenApiClient tokenApiClient;
    
    /**
     * 获取 Token,优先从缓存获取,缓存不存在或过期时重新获取
     */
    public String getToken() {
        // 1. 尝试从缓存获取 Token
        String token = redisTemplate.opsForValue().get(REDIS_KEY);
        
        if (token != null && !token.isEmpty()) {
            // 缓存中存在,直接返回
            return token;
        }
        
        // 2. 缓存不存在或已过期,重新获取 Token
        TokenResponse tokenResponse = tokenApiClient.getNewToken();
        token = tokenResponse.getAccessToken();
        Long expiresIn = tokenResponse.getExpiresIn();
        
        // 3. 计算缓存过期时间(提前5分钟失效)
        long cacheExpireTime = expiresIn - CACHE_BUFFER;
        
        // 4. 将 Token 存入缓存,设置过期时间
        redisTemplate.opsForValue().set(REDIS_KEY, token, cacheExpireTime, TimeUnit.SECONDS);
        
        return token;
    }
}

// 使用示例
@Autowired
private TokenService tokenService;

String token = tokenService.getToken();
// 使用 token 调用业务接口
// 示例代码 - 使用本地缓存(内存)
import java.util.concurrent.atomic.AtomicLong;

public class TokenCacheService {
    
    private static final int CACHE_BUFFER = 5 * 60; // 提前5分钟失效(300秒)
    
    private String token;
    private AtomicLong expireTime = new AtomicLong(0);
    private final Object lock = new Object();
    
    @Autowired
    private TokenApiClient tokenApiClient;
    
    /**
     * 获取 Token,优先从本地缓存获取,缓存过期时重新获取
     */
    public String getToken() {
        long now = System.currentTimeMillis() / 1000; // 当前时间戳(秒)
        
        // 1. 检查缓存是否有效
        if (token != null && now < expireTime.get()) {
            return token;
        }
        
        // 2. 缓存无效,重新获取 Token(加锁防止并发)
        synchronized (lock) {
            // 双重检查,避免重复获取
            if (token != null && now < expireTime.get()) {
                return token;
            }
            
            TokenResponse tokenResponse = tokenApiClient.getNewToken();
            Long expiresIn = tokenResponse.getExpiresIn();
            
            // 3. 计算缓存过期时间(提前5分钟失效)
            long cacheExpireTime = now + expiresIn - CACHE_BUFFER;
            
            // 4. 更新缓存
            this.token = tokenResponse.getAccessToken();
            this.expireTime.set(cacheExpireTime);
            
            return this.token;
        }
    }
}

// 使用示例
@Autowired
private TokenCacheService tokenCacheService;

String token = tokenCacheService.getToken();
// 使用 token 调用业务接口

4.5.3 Token 失效处理

  • 若接口返回 401 或业务码 10001(Token Invalid),说明 Token 已失效,需重新调用 /ucauth/authc/account/createToken 接口获取新 Token;
  • 旧 Token 失效后不可重复使用,必须重新获取;
  • 频繁重复调用将触发防刷机制,建议合理缓存 Token,避免频繁请求认证接口。

4.6 安全建议

  • 妥善保管 API Key 和 API Secret,严禁在前端或公共仓库中暴露;
  • 所有接口调用务必使用 HTTPS
  • 可在我司配置 IP 白名单 限制访问;
  • 建议服务端使用缓存机制保存 Token,以减少频繁认证请求;
  • Token 应存储在服务端,避免在客户端暴露。