沉默是金,总会发光
大家好,我是沉默
“支付这件事,就像点外卖——用户只看到‘付款成功’,
背后其实跑了几十个接口、几道签名验证、还有一堆安全校验。”
今天,我们用 Spring Boot + 微信支付 V3,从 0 到 1 打造一个可落地的支付系统,完整覆盖下单、回调、退款、查询全流程。
不废话,干货直接上。
**-**01-
每个系统都绕不开“支付”?
电商下单、会员充值、票务系统、小程序商城……
只要涉及钱,支付模块就是灵魂。
但开发者最怕的就是:
文档晦涩、签名复杂、回调老失败。
于是今天这篇文章,帮你一口气搞清楚:
-
如何发起微信统一下单(生成二维码)
-
如何正确处理微信回调
-
如何实现退款与查询逻辑
-
如何封装成模块,方便复用
- 02-
微信支付接入前的准备
就像打游戏前先打补丁,微信支付也得先办好“通行证”。
1️⃣ 注册商户号
前往 微信商户平台(pay.weixin.qq.com/)
完成认证后,你将拿到四个关键凭证:
| 项目 | 说明 |
|---|---|
mchid | 商户号 |
apiV3Key | API V3 密钥 |
privateKey | 商户私钥 |
certSerialNo | 证书序列号 |
2️⃣ 官方文档入口
微信支付 API V3 文档(pay.weixin.qq.com/wiki/doc/ap…
- 03-
项目准备
核心支付流程图
项目配置与依赖
Maven 依赖
<dependencies> <!-- Spring Boot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 微信支付 SDK --> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-java</artifactId> <version>0.2.11</version> </dependency> <!-- 日志 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency></dependencies>
application.yml 配置
wechat: mchid: '1234567890' appid: 'wx1234567890abcdef' apiV3Key: 'your_api_v3_key' privateKeyPath: 'classpath:/cert/apiclient_key.pem' certSerialNo: 'XXXXXX' notifyUrl: 'https://yourdomain.com/wechat/pay/notify' refundNotifyUrl: 'https://yourdomain.com/wechat/refund/notify'
**-**04-
实战代码详解
统一下单接口(Native 模式)
@Servicepublic class WechatPayService { @Autowired private WechatPayHttpClient wechatClient; @Value("${wechat.notifyUrl}") private String notifyUrl; public String unifiedOrder(String orderNo, BigDecimal amount, String description) throws Exception { Map<String, Object> params = new HashMap<>(); params.put("appid", wechatClient.getAppId()); params.put("mchid", wechatClient.getMchId()); params.put("description", description); params.put("out_trade_no", orderNo); params.put("notify_url", notifyUrl); Map<String, Object> amountMap = new HashMap<>(); amountMap.put("total", amount.multiply(new BigDecimal(100)).intValue()); amountMap.put("currency", "CNY"); params.put("amount", amountMap); HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native"); httpPost.setEntity(new StringEntity(new ObjectMapper().writeValueAsString(params), "UTF-8")); httpPost.setHeader("Content-Type", "application/json"); HttpResponse response = wechatClient.getClient().execute(httpPost); String body = EntityUtils.toString(response.getEntity()); JsonNode jsonNode = new ObjectMapper().readTree(body); return jsonNode.get("code_url").asText(); }}
支付回调接口
@RestController@RequestMapping("/wechat/pay")public class WechatPayCallbackController { @PostMapping("/notify") public ResponseEntity<String> payNotify(@RequestBody String body, @RequestHeader Map<String, String> headers) { System.out.println("支付回调数据:" + body); // TODO: 验签、解密、订单状态更新 return ResponseEntity.ok("{"code":"SUCCESS","message":"成功"}"); }}
回调逻辑流程图
退款与查询接口
public String refund(String orderNo, String refundNo, BigDecimal refundAmount) throws Exception { Map<String, Object> params = new HashMap<>(); params.put("out_trade_no", orderNo); params.put("out_refund_no", refundNo); params.put("notify_url", "https://yourdomain.com/wechat/refund/notify"); Map<String, Object> amountMap = new HashMap<>(); amountMap.put("refund", refundAmount.multiply(new BigDecimal(100)).intValue()); amountMap.put("total", 100); amountMap.put("currency", "CNY"); params.put("amount", amountMap); HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds"); httpPost.setEntity(new StringEntity(new ObjectMapper().writeValueAsString(params), "UTF-8")); httpPost.setHeader("Content-Type", "application/json"); HttpResponse response = wechatClient.getClient().execute(httpPost); return EntityUtils.toString(response.getEntity());}
系统架构视图
常见问题排查表
问题 解决方案回调未触发 检查 notify_url 是否公网可访问且为 HTTPS
签名失败 确认 V3 密钥、私钥加载正确
退款失败 确认订单状态为已支付、退款金额 ≤ 原金额
商户号无效 检查 appid 与 mchid 是否匹配
-05-
总结
支付接入不难,难的是稳定与信任
支付系统的本质是「信任传递」——
从用户到平台,从平台到银行,从银行再到商户。
你写的每一行代码,其实都在参与一次真实的金钱流转。
所以,别怕麻烦,多一步验证、多一层日志、多一个签名,
都是在为用户的“信任安全”买保险。
进阶建议
支持小程序 / H5 / APP 多端支付
用 MQ 异步化处理支付回调
持久化支付日志,防止重复通知
封装成 SDK 模块供多个项目共用
**-**05-
粉丝福利
点点关注,送你互联网大厂面试题库,如果你正在找工作,又或者刚准备换工作。可以仔细阅读一下,或许对你有所帮助!