Amazon SP-API,授权封装、SDK 分层与 AAD 加密一致性设计

🛡️ Spring Boot 对接 Amazon SP-API 的工程化实践

------ 授权封装、SDK 分层与 AAD 加密一致性设计

在对接 Amazon SP-API 的过程中,"接口能跑"只是第一步

真正进入长期维护阶段后,你会迅速遇到几个现实问题:

  • SP-API SDK 多、接口多,代码开始重复
  • 授权信息需要加密,但解密失败问题偶发且致命
  • AAD(Additional Authenticated Data)一旦不一致,历史数据将全部失效
  • SDK 调用、业务逻辑、安全逻辑混在一起,难以维护

本文将结合一次真实的工程实践,完整讲解我是如何重构 SP-API 授权与 SDK 接入层的。


🎯 设计目标

在开始之前,先明确几个设计目标

  • 🔹 SDK 调用与业务逻辑彻底解耦
  • 🔹 授权信息安全存储,避免 AAD 不一致导致解密失败
  • 🔹 支持多个 SP-API(Sellers / Orders / Reports ...)
  • 🔹 一次解密,多 API 复用
  • 🔹 可扩展到 Temu / TikTok 等其他平台

🧱 一、整体分层设计

最终我采用了下面这套结构:

复制代码
Controller
   ↓
Service
   ↓
Manager(SP-API SDK)
   ↓
Amazon SDK

每一层只做一件事


🧩 二、核心模块职责划分

1️⃣ Service 层 ------ 业务裁判

  • 决定什么时候校验授权

  • 决定授权失败后的业务处理

  • 不直接接触 SDK

    AuthCheckService


2️⃣ Manager 层 ------ SDK 适配器

  • 只负责调用 Amazon SDK

  • 不操作数据库

  • 不解密、不拼 AAD

  • 不关心 storeCode

    SellerManager
    OrdersManager
    ReportsManager


3️⃣ Factory 层 ------ SDK 构建中心

复制代码
SpApiAuthContextFactory
SpApiClientFactory
  • 统一解密
  • 统一 endpoint 选择
  • 统一 SDK Client 创建

4️⃣ Crypto 层 ------ 安全核心(重点)

复制代码
CryptoKeyProvider
CryptoService
CryptoFieldEnum
CryptoUtil

👉 所有加解密规则只能从这里走


🔐 三、为什么 AAD 一定要统一?

在 SP-API 授权信息加密时,我使用了 AEAD 算法:

复制代码
CryptoUtil.encrypt(plainText, masterKey, aad);

其中:

  • masterKey:系统主密钥
  • aad:附加认证数据(AAD)

❗ AAD 的致命特点

加密和解密时的 AAD 必须完全一致

哪怕只是:

复制代码
storeCode:clientId
storeCode:client_id

都会导致:

  • ❌ 解密失败
  • ❌ 历史数据全部不可用
  • ❌ 无法补救

🧠 四、正确做法:字段级 AAD 枚举化

✅ 定义 AAD 唯一来源

复制代码
@Getter
@AllArgsConstructor
public enum CryptoFieldEnum {

    SP_API_CLIENT_ID("clientId"),
    SP_API_CLIENT_SECRET("clientSecret"),
    SP_API_REFRESH_TOKEN("refreshToken");

    private final String field;

    public String aad(String storeCode) {
        return storeCode + ":" + field;
    }
}

🔒 枚举一旦上线,不允许修改值


🔧 五、CryptoService:唯一加解密入口

复制代码
@Component
public class CryptoService {

    @Resource
    private CryptoKeyProvider cryptoKeyProvider;

    public String encryptSpApiField(
            String plainText,
            String storeCode,
            CryptoFieldEnum field
    ) {
        return CryptoUtil.encrypt(
                plainText,
                cryptoKeyProvider.getMasterKey(),
                field.aad(storeCode)
        );
    }

    public String decryptSpApiField(
            String cipherText,
            String storeCode,
            CryptoFieldEnum field
    ) {
        return CryptoUtil.decrypt(
                cipherText,
                cryptoKeyProvider.getMasterKey(),
                field.aad(storeCode)
        );
    }
}

📌 业务代码再也不需要知道 AAD 是什么


🧩 六、SpApiAuthContext:一次解密,多 API 复用

复制代码
public class SpApiAuthContext {

    private final LWAAuthorizationCredentials lwaCredentials;
    private final String endpoint;
}

创建 Context

复制代码
SpApiAuthContext ctx = authContextFactory.create(spStoreAuth);

使用 Context

复制代码
sellerManager.getMarketplaceParticipations(ctx);
ordersManager.listOrders(ctx);

🏭 七、ClientFactory:统一构建 SDK Client

复制代码
@Component
public class SpApiClientFactory {

    public SellersApi createSellersApi(SpApiAuthContext ctx) {
        return new SellersApi.Builder()
                .lwaAuthorizationCredentials(ctx.getLwaCredentials())
                .endpoint(ctx.getEndpoint())
                .build();
    }
}

🧭 八、类依赖关系图(核心)

复制代码
┌───────────────────────────┐
│        AuthCheckService   │
└─────────────┬─────────────┘
              ↓
┌───────────────────────────┐
│   SpApiAuthContextFactory │
└─────────────┬─────────────┘
              ↓
┌───────────────────────────┐
│        CryptoService      │
└─────────────┬─────────────┘
              ↓
┌───────────────────────────┐
│     CryptoKeyProvider     │
└───────────────────────────┘

┌───────────────────────────┐
│        SellerManager      │
└─────────────┬─────────────┘
              ↓
┌───────────────────────────┐
│     SpApiClientFactory    │
└─────────────┬─────────────┘
              ↓
┌───────────────────────────┐
│        Amazon SDK         │
└───────────────────────────┘

✅ 九、这种设计带来的收益

收益 说明
🔒 安全 AAD 绝对一致,历史数据安全
🔁 复用 一次解密,多 API
🧪 测试 Manager 可轻松 Mock
🧩 扩展 新平台只加 Manager
🧠 清晰 每层职责单一

📌 十、总结

在 SP-API 对接中,真正难的不是接口调用,而是长期演进能力

本文通过:

  • SDK 分层
  • 授权上下文封装
  • AAD 统一治理

构建了一套安全、可维护、可扩展的 SP-API 接入方案。

如果你也在做多平台对接(Amazon / Temu / TikTok),

这套结构可以直接复用。

相关推荐
一 乐5 小时前
婚纱摄影网站|基于ssm + vue婚纱摄影网站系统(源码+数据库+文档)
前端·javascript·数据库·vue.js·spring boot·后端
期待のcode8 小时前
前后端分离项目 Springboot+vue 在云服务器上的部署
服务器·vue.js·spring boot
ProgramHan9 小时前
Spring Boot 3.2 新特性:虚拟线程的落地实践
java·jvm·spring boot
源码获取_wx:Fegn089510 小时前
基于 vue智慧养老院系统
开发语言·前端·javascript·vue.js·spring boot·后端·课程设计
毕设源码_郑学姐10 小时前
计算机毕业设计springboot基于HTML5的酒店预订管理系统 基于Spring Boot框架的HTML5酒店预订管理平台设计与实现 HTML5与Spring Boot技术驱动的酒店预订管理系统开
spring boot·后端·课程设计
不吃香菜学java10 小时前
spring-依赖注入
java·spring boot·后端·spring·ssm
南部余额10 小时前
Spring Boot 整合 MinIO:封装常用工具类简化文件上传、启动项目初始化桶
java·spring boot·后端·文件上传·工具类·minio·minioutils
QQ196328847510 小时前
ssm基于Springboot+的球鞋销售商城网站vue
vue.js·spring boot·后端
太空眼睛11 小时前
【MCP】使用SpringBoot基于Streamable-HTTP构建MCP-Server
spring boot·sse·curl·mcp·mcp-server·spring-ai·streamable
幽络源小助理11 小时前
springboot校园车辆管理系统源码 – SpringBoot+Vue项目免费下载 | 幽络源
vue.js·spring boot·后端