1. 微信JSAPI支付的核心流程解析
第一次接触微信JSAPI支付的开发者,往往会被那一堆参数和签名搞得晕头转向。其实整个过程就像寄快递:后端准备好所有货物(参数)并贴上防伪标签(签名),前端只需要拿着这个包裹去快递点(微信客户端)寄出就行。让我们先看看这个"快递流程"的全貌:
- 用户在H5页面点击支付按钮
- 你的后端生成预支付订单(prepay_id)
- 后端计算支付签名(paySign)
- 前端拿到所有参数后调起微信支付
- 用户在微信客户端完成支付
这个过程中最关键的环节就是paySign的生成和验证。微信通过这个签名确保支付请求没有被篡改,就像快递单上的防伪码一样重要。我见过不少开发者在这个环节栽跟头,要么签名算法用错,要么参数拼接顺序不对,导致支付调不起来。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 后端签名生成全流程
2.1 必备参数详解
先来看看后端需要准备的五个核心参数:
- appId:公众号的唯一标识,相当于你的店铺ID
- timeStamp:当前时间戳(秒级),防止请求过期
- nonceStr:随机字符串,防止重放攻击
- package:格式固定为"prepay_id=xxx",携带预支付单号
- signType:签名算法类型(现在强制使用RSA)
这里有个坑我踩过:timeStamp在Java中通常用System.currentTimeMillis()获取,但这个返回的是毫秒时间戳,需要除以1000转换成秒级。微信服务端会校验这个时间戳,如果与服务器时间相差超过5分钟就会拒绝请求。
2.2 签名生成代码实现
签名生成的正确姿势应该是这样的:
java复制public String generatePaySign(String appId, String prepayId) throws Exception {
// 1. 准备基础参数
long timestamp = System.currentTimeMillis() / 1000;
String nonceStr = generateRandomString(32); // 32位随机字符串
String packageValue = "prepay_id=" + prepayId;
// 2. 构建待签名字符串
String message = buildSignMessage(appId, timestamp, nonceStr, packageValue);
// 3. 使用商户私钥进行签名
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(getPrivateKey());
signature.update(message.getBytes(StandardCharsets.UTF_8));
byte[] signBytes = signature.sign();
// 4. Base64编码后返回
return Base64.getEncoder().encodeToString(signBytes);
}
private String buildSignMessage(String appId, long timestamp,
String nonceStr, String packageValue) {
retu
