1. 微信支付Native扫码支付入门指南
第一次接触微信支付APIv3的Native扫码支付功能时,我完全理解那种面对官方文档时的迷茫感。作为过来人,我想用最直白的方式帮你理清整个流程。Native支付简单来说就是让用户在PC端扫描二维码完成支付,适用于网站、自助终端等场景。
要接入这个功能,你需要准备五个关键参数:
- APPID :微信开放平台或公众号的标识
- 商户号 :微信支付商户平台的唯一标识
- APIv3密钥 :32位随机字符串,用于数据加密
- 商户证书序列号 :从下载的证书文件中获取
- 私钥文件路径 :解压证书包得到的apiclient_key.pem
这些参数就像你进入微信支付大门的钥匙,缺一不可。特别提醒,证书文件一定要妥善保管,生产环境建议放在服务器安全目录下,千万别直接硬编码在代码里。
2. 环境配置与SDK集成
2.1 证书准备与解析
解压从微信支付平台下载的证书包后,你会看到三个文件:
- apiclient_cert.pem(证书文件)
- apiclient_key.pem(私钥文件)
- apiclient_cert.p12(PKCS#12格式证书)
重点处理私钥文件时,我推荐使用Java的
Files
类读取:
private static PrivateKey getPrivateKey(String filename) throws IOException {
String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s+", "");
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
}
2.2 依赖引入与配置
建议使用微信支付官方提供的Apache HttpClient扩展,它能自动处理签名和验签。在pom.xml中添加:
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.2</version>
</dependency>
创建wx_pay.properties配置文件:
# 商户号
wxpay.mch-id=1651xxx7xx
# appid
wxpay.appid=ww445bxxxxxx5a46bf1
# 私钥绝对路径
wxpay.private-key-path=D:\\MyAPP\\company_vxpay\\wx_pay\\apiclient_key.pem
# api_v3密码
wxpay.api-v3-key=xxxxxxxxxxxxxxx
# 商户API证书序列号
wxpay.mch-serial-no=2xxxxxxxxxxxxxDBF5245996A5E176A
3. 下单与二维码生成实战
3.1 构建支付请求
创建支付订单的核心是组装正确的请求参数。这里有个坑要注意:金额单位是分,需要将元转换为分:
Map<String, Object> amountMap = new HashMap<>();
amountMap.put("total", (int)(money * 100)); // 金额转换
amountMap.put("currency", "CNY");
完整的请求体示例:
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("appid", wxPayTestConfig.getAppid());
paramMap.put("mchid", wxPayTestConfig.getMchId());
paramMap.put("description", "在线充值"+money+"元");
paramMap.put("out_trade_no", orderNo);
paramMap.put("notify_url", NOTIFY_URL);
paramMap.put("amount", amountMap);
3.2 发送请求与处理响应
使用配置好的HttpClient发送请求时,有个大坑我踩过:SDK已经自动处理了签名,不需要再手动设置Authorization头:
HttpPost httpPost = new HttpPost(REQUEST_URL);
StringEntity se = new StringEntity(jsonParams, "utf-8");
httpPost.setEntity(se);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-Type", "application/json");
CloseableHttpResponse response = httpClient.execute(httpPost);
String res = EntityUtils.toString(response.getEntity());
JSONObject jsonObject = new JSONObject(res);
String codeUrl = jsonObject.getString("code_url");
3.3 二维码生成与展示
拿到code_url后,你可以使用任何二维码生成库(如ZXing)将其转为二维码图片。前端展示时要注意:
- 二维码有效期2小时,过期需重新生成
- 不支持相册识别,必须实时扫码
- 建议设置合适的二维码尺寸(不小于200×200像素)
4. 支付回调处理全解析
4.1 回调验证三部曲
回调处理是支付流程中最复杂的部分,总结为三个关键步骤:
- 证书验证 :比较请求头Wechatpay-Serial与本地证书序列号
String serial = request.getHeader("Wechatpay-Serial");
X509Certificate verifier = getVerifier();
String realSerial = verifier.getSerialNumber().toString(16).toUpperCase();
if (!realSerial.equals(serial)) {
return "验证平台序列号失败";
}
- 签名验证 :确保请求确实来自微信
String timestamp = request.getHeader("Wechatpay-Timestamp");
String nonce = request.getHeader("Wechatpay-Nonce");
String signature = request.getHeader("Wechatpay-Signature");
boolean isValid = verifySignature(verifier, timestamp, nonce, responseBody, signature);
- 数据解密 :使用APIv3密钥解密resource字段
AesUtil aesUtil = new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8));
String plainText = aesUtil.decryptToString(
associatedData.getBytes(StandardCharsets.UTF_8),
nonce.getBytes(StandardCharsets.UTF_8),
ciphertext
);
4.2 并发控制与幂等处理
支付回调可能会重复发送,必须做好并发控制:
if(lock.tryLock()) {
try {
// 处理业务逻辑
} finally {
lock.unlock();
}
}
建议在数据库中记录已处理的交易ID,防止重复处理。微信支付的订单号(transaction_id)和商户订单号(out_trade_no)都是幂等处理的依据。
5. 常见问题排查指南
5.1 证书自动更新机制
微信支付平台证书会定期更换,使用SDK的CertificatesManager可以自动更新:
CertificatesManager certificatesManager = CertificatesManager.getInstance();
certificatesManager.putMerchant(mchId,
new WechatPay2Credentials(mchId,
new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),
apiV3Key.getBytes(StandardCharsets.UTF_8));
5.2 回调地址注意事项
回调地址必须满足:
- 使用HTTPS协议
- 不能带查询参数(如?key=value)
- 必须外网可访问
- 返回HTTP 200/204表示成功接收
开发测试时可以使用内网穿透工具(如ngrok),但千万别在生产环境测试!
5.3 错误码速查表
| 错误码 | 含义 | 解决方案 |
|---|---|---|
| PARAM_ERROR | 参数错误 | 检查必填字段和格式 |
| NO_AUTH | 无权限 | 检查证书和IP白名单 |
| ORDERPAID | 订单已支付 | 检查订单状态 |
| OUT_TRADE_NO_USED | 商户订单号重复 | 更换out_trade_no |
6. 生产环境最佳实践
经过多个项目的实战检验,我总结了几条黄金法则:
- 证书安全 :私钥文件权限设置为600,定期轮换APIv3密钥
- 日志记录 :完整记录请求和响应,至少保存30天
- 监控报警 :设置支付成功率监控,低于阈值立即报警
- 对账机制 :每日定时下载账单,与本地订单核对
- 熔断设计 :当微信支付接口异常时,自动切换备用支付方式
最后提醒,微信支付文档虽然晦涩,但每个参数都有其作用。遇到问题时,先静下心来仔细阅读文档说明,往往能发现被忽略的细节。

217

被折叠的 条评论
为什么被折叠?



