java微信支付封装需统一配置敏感信息、封装带签名的http客户端、分场景实现支付服务、严格验签解密回调。使用@configurationproperties绑定yml配置,wechatpayhttpclient自动处理签名头与json序列化,wechatpayservice接口模板化jsapi/app/native等场景,wechatpaynotifyvalidator校验并解密aes通知。

在 Java 项目中封装微信支付调用逻辑,核心是把签名生成、HTTP 请求、参数校验、结果解析等重复操作抽离成可复用、易维护的模块,同时兼顾安全性(如密钥不硬编码)、可扩展性(支持 JSAPI/APP/NATIVE/H5 等不同场景)和可观测性(日志、异常处理)。
统一配置管理
避免在业务代码中散落 appId、mchId、APIv3 密钥、证书路径等敏感信息:
- 使用 @ConfigurationProperties 绑定 yml 配置,例如 wechat.pay.app-id、wechat.pay.mch-id、wechat.pay.api-v3-key
- APIv3 秘钥用于平台证书解密和回调验签,必须严格保密;私钥(apiclient_key.pem)应通过 Spring 的 Resource 加载,不读取绝对路径
- 将微信支付网关地址(如 https://api.mch.weixin.qq.com)也作为配置项,便于多环境切换(沙箱/正式)
封装签名与 HTTP 客户端
微信支付 V3 接口强制要求使用平台证书 + APIv3 密钥 + HTTP 签名(RFC 2104 HMAC-SHA256),不能简单用 RestTemplate 发请求:
- 基于官方 weixin-java-pay SDK(推荐 v4.5+)或自行封装 Apache HttpClient + Bouncy Castle 实现签名逻辑
- 封装一个 WechatPayHttpClient 类,内部自动完成:时间戳生成、随机字符串、签名头(Authorization)构造、JSON 请求体序列化、响应自动 JSON 解析
- 关键签名字段包括:请求方法、路径、请求时间戳、随机串、请求体哈希(空体为空字符串 SHA256),示例签名头:WECHATPAY2-SHA256-RSA2048 mchid="1900000100",nonce_str="5K8264ILTKCH16CQ2502SI8JEPOEM6AL",timestamp="1712345678",serial_no="XXXXXX...",signature="base64..."
分场景抽象支付服务
不同支付方式(JSAPI、APP、NATIVE、H5、小程序)入参和返回结构不同,但共性明显,适合模板化:
- 定义顶层接口 WechatPayService,含 createOrder(WechatPayOrderRequest) 和 queryOrder(String outTradeNo) 方法
- 按场景实现子类,如 JsapiWechatPayService 负责拼装 openid、sub_mch_id(如有)、trade_type=JSAPI;NativeWechatPayService 返回 code_url 供生成二维码
- 所有请求对象继承 AbstractWechatPayRequest,统一携带 notifyUrl、attach、detail 等通用字段;响应对象统一包装为 Result
,含 success、code、message、data
安全处理回调与验签
支付结果异步通知(notify URL)是高危入口,必须严格验签并幂等处理:
- 提供工具类 WechatPayNotifyValidator,使用平台证书公钥验证通知头中的 Wechatpay-Timestamp、Wechatpay-Nonce、Wechatpay-Signature
- 通知体为 AES-256-GCM 加密,需用 APIv3 密钥解密;解密后 JSON 中的 resource.associated_data、resource.nonce、resource.ciphertext 缺一不可
- 业务层收到解密后的通知后,先查库判断该 out_trade_no 是否已处理(防重复通知),再更新订单状态、发消息、扣库存等,整个过程加数据库行锁或 Redis 分布式锁
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











