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

这套结构可以直接复用。

相关推荐
大学生资源网4 小时前
基于springboot的万亩助农网站的设计与实现源代码(源码+文档)
java·spring boot·后端·mysql·毕业设计·源码
q_19132846954 小时前
基于SpringBoot2+Vue2的诗词文化传播平台
vue.js·spring boot·mysql·程序员·计算机毕业设计
五阿哥永琪5 小时前
RedisTemplate、StringRedisTemplate、RedisIndexedSessionRepository之间的区别?
spring boot
计算机毕设指导66 小时前
基于微信小程序的鸟博士系统【源码文末联系】
java·spring boot·mysql·微信小程序·小程序·tomcat·maven
QQ_21696290966 小时前
Spring Boot大学生社团管理平台 【部署教程+可完整运行源码+数据库】
java·数据库·spring boot·微信小程序
是席木木啊7 小时前
Spring Boot 中 @Async 与 @Transactional 结合使用全解析:避坑指南
数据库·spring boot·oracle
阿拉斯攀登7 小时前
自定义 Spring Boot 自动配置
java·spring boot
appearappear7 小时前
Mac 上重新安装了Cursor 2.2.30,重新配置 springboot 过程记录
java·spring boot·后端
鹿角片ljp8 小时前
Spring Boot Web入门:从零开始构建web程序
前端·spring boot·后端