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),

这套结构可以直接复用。

相关推荐
vx-程序开发21 小时前
springboot旅游推介平台---附源码24175
java·spring boot·python·spring cloud·eclipse·django·idea
小蒜学长21 小时前
“喵汪联盟”宠物领养系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·宠物
xbgRS1 天前
springboot的自动装配
java·spring boot
嘻哈∠※1 天前
0061基于 SpringBoot 的投稿与稿件处理系统设计与实现
java·spring boot·后端
zhougl9962 天前
Java Spring Boot 爬虫技术全面介绍
java·spring boot·爬虫
用户3126874877202 天前
@Async 加了没生效?Spring Boot 异步编程全链路拆解:从线程池到自调用陷阱
java·spring boot
阿图灵2 天前
Agentic AI 架构完整学习手册(课程精华全收录)
架构设计·ai agent·智能体·agentic ai·完整手册
云烟成雨TD2 天前
Micrometer 系列【25】Spring Boot Actuator | Spring MVC、Spring WebFlux 指标
java·spring boot·micrometer
xbgRS2 天前
springBoot项目配置加载优先级
java·spring boot
云烟成雨TD2 天前
Micrometer 系列【61】统一观测:基于 Spring Boot 的生产级演示案例 | 指标集成
spring boot·云原生·链路追踪