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

这套结构可以直接复用。

相关推荐
swg32132121 小时前
Spring Boot 3.X Oauth2 认证服务与资源服务
java·spring boot·后端
gelald1 天前
SpringBoot - 自动配置原理
java·spring boot·后端
@yanyu6661 天前
07-引入element布局及spring boot完善后端
javascript·vue.js·spring boot
程序猿_极客1 天前
SpringBoot 三大参数注解详解:@RequestParam @RequestBody @PathVariable 区别及常用开发注解
java·spring boot·后端·面试八股文·springboot注释
小胖java1 天前
校园通衢公告枢纽系统
java·spring boot
Hadoop_Liang1 天前
构建Spring Boot项目Docker镜像
spring boot·后端·docker
Flittly1 天前
【SpringAIAlibaba新手村系列】(14)MCP 本地服务与工具集成
java·spring boot·笔记·spring·ai
Flittly1 天前
【SpringAIAlibaba新手村系列】(13)Tool Calling 函数工具调用技术
java·spring boot·spring·ai
my_styles1 天前
linux系统下安装 tengine / 宝兰德等国产信创中间件和闭坑
linux·运维·服务器·spring boot·nginx·中间件
coder阿龙1 天前
基于SpringAI+Qdrant+Ollama本地模型和向量数据库开发问答和RAG检索
java·数据库·spring boot·ai·数据库开发