支付sdk应封装signer工具类统一签名验签、requestexecutor处理http请求与异常、paymentclient聚合业务操作,并将验签严格前置到通知处理最外层。

把签名逻辑抽成独立工具类
签名生成是支付 SDK 最核心的封装点。不同平台(如微信、支付宝)签名规则差异大,但共性在于:需要对参数按规则排序、拼接、加签(RSA/SHA256withRSA/HMAC-SHA256 等)。不要把签名代码散落在每个请求方法里。
建议封装一个 Signer 工具类,构造时传入商户私钥、平台公钥(验签用)、签名算法等配置,提供两个核心方法:
-
String sign(Map
params) :输入业务参数 Map,返回 base64 编码的签名字符串 -
boolean verify(Map
params, String signature) :用平台公钥校验响应中的签名是否合法
内部统一处理参数过滤(剔除空值、sign 字段)、字典序排序、键值拼接(如 key1=value1&key2=value2)、编码(UTF-8)、摘要与加签全流程。这样后续新增支付渠道,只需继承或实现新 Signer 即可。
用统一 RequestExecutor 封装 HTTP 请求与异常处理
发送请求不只是调用 HttpClient。第三方支付接口有固定要求:Content-Type、超时时间、SSL 证书信任(尤其微信需加载 apiclient_cert.p12)、重试机制(部分接口幂等性弱)、日志脱敏(不打敏感字段如密钥、银行卡号)。
封装一个 RequestExecutor,暴露类似这样的方法:
T executePost(String url, Map params, Class responseType) T executeGet(String url, Map queryParams, Class responseType)
内部自动完成:参数签名注入(调用 Signer)、构建标准 HttpEntity、设置连接/读取超时、捕获 IOException/SSLException/HttpStatusException、解析 JSON 响应并做基础字段校验(如检查 return_code、result_code)。错误时抛出自定义异常(如 PayException),携带原始响应体和 HTTP 状态码,便于上层区分失败原因。
用 PaymentClient 统一入口聚合业务操作
避免让业务方直接拼参数、调 Signer、再调 RequestExecutor。应提供语义清晰的客户端,比如 WechatPaymentClient 或通用 PaymentClient。
- 每个支付动作对应一个方法:pay(OrderRequest req)、refund(RefundRequest req)、query(String outTradeNo)、notifyVerify(InputStream inputStream)
- 每个方法内部组合调用 Signer 和 RequestExecutor,并处理协议细节:微信下单要补全 body、appid、mch_id;支付宝要组装 biz_content;异步通知验签要先解析 form 表单或 JSON,再剔除 sign/sign_type 后验签
- 返回统一结果包装类 Result
,含 success、code、msg、data 字段,屏蔽底层协议差异
这样业务代码就变成:Result
验签必须放在最外层且严格隔离
验签不是“顺手做一下”,而是安全边界。所有异步通知(微信 notify、支付宝 callback)必须在解析业务参数前,先完成完整验签。常见错误是先转 JSON 再取字段,导致字段被篡改未被发现。
- 收到通知请求后,第一件事是原样读取 request.getInputStream() 的原始字节流(不能用 getParameterMap,会丢失顺序和编码)
- 对原始字符串(微信是 XML 字符串,支付宝是 form 表单字符串)做签名验证,确认来源可信
- 验签通过后,才解析为对象,再执行业务逻辑(更新订单状态、发消息等)
- 验签失败必须立即返回失败响应(微信要求 return_code=FAIL),且不记录业务日志,防止被刷量攻击
可以把验签逻辑下沉到 Filter 或 Spring MVC 的 HandlerInterceptor 中,强制所有通知接口都经过同一道门禁。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











