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

这套结构可以直接复用。

相关推荐
猫头虎12 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
MZ_ZXD00114 小时前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·vue.js·spring boot·python·django·php
invicinble15 小时前
springboot的核心实现机制原理
java·spring boot·后端
space621232715 小时前
在SpringBoot项目中集成MongoDB
spring boot·后端·mongodb
金牌归来发现妻女流落街头17 小时前
【从SpringBoot到SpringCloud】
java·spring boot·spring cloud
皮卡丘不断更17 小时前
手搓本地 RAG:我用 Python 和 Spring Boot 给 AI 装上了“实时代码监控”
人工智能·spring boot·python·ai编程
lucky670717 小时前
Spring Boot集成Kafka:最佳实践与详细指南
spring boot·kafka·linq
Coder_Boy_17 小时前
基于Spring AI的分布式在线考试系统-事件处理架构实现方案
人工智能·spring boot·分布式·spring
毕设源码-钟学长19 小时前
【开题答辩全过程】以 基于Springboot的扶贫众筹平台为例,包含答辩的问题和答案
java·spring boot·后端
Java水解20 小时前
Spring Boot 4 升级指南:告别RestTemplate,拥抱现代HTTP客户端
spring boot·后端