Java+Vue+微信小程序对接微信支付全流程
🔥干货预警,收藏备用🔥
最近在开发一个前后端分离的在线课程平台,接入了微信支付功能,把整个流程整理出来分享给大家,避免踩坑~
🎯 项目架构
-
后端:Java + Spring Boot
-
前端:Vue.js
-
移动端:微信小程序
-
支付方式:微信支付
💡 微信支付接入流程
1️⃣ 前期准备
-
申请微信支付商户号
-
获取商户API密钥
-
配置支付授权目录和域名
2️⃣ 后端核心实现(Java)
生成预支付订单
java
@RestController
@RequestMapping("/api/pay")
public class PaymentController {
@Autowired
private WechatPayService wechatPayService;
@PostMapping("/createOrder")
public Map<String, String> createPaymentOrder(@RequestBody OrderRequest request) {
// 创建商户订单
String outTradeNo = generateOrderNo();
// 调用微信统一下单API
Map<String, String> paymentParams = wechatPayService.createPrepayOrder(
request.getCourseId(),
request.getAmount(),
outTradeNo,
request.getOpenId()
);
return paymentParams;
}
}
微信支付服务封装
java
@Service
public class WechatPayService {
public Map<String, String> createPrepayOrder(String courseId, BigDecimal amount,
String outTradeNo, String openId) {
// 构造请求参数
Map<String, String> params = new HashMap<>();
params.put("appid", wechatConfig.getAppId());
params.put("mch_id", wechatConfig.getMchId());
params.put("nonce_str", generateNonceStr());
params.put("body", "课程购买-" + courseId);
params.put("out_trade_no", outTradeNo);
params.put("total_fee", amount.multiply(new BigDecimal("100")).intValue() + "");
params.put("spbill_create_ip", "123.207.151.100");
params.put("notify_url", wechatConfig.getNotifyUrl());
params.put("trade_type", "JSAPI");
params.put("openid", openId);
// 生成签名
String sign = generateSignature(params);
params.put("sign", sign);
// 调用微信支付统一下单接口
String response = httpClient.post(WEIXIN_UNIFIED_ORDER_URL, mapToXml(params));
Map<String, String> result = xmlToMap(response);
// 返回前端调起支付所需参数
return buildPaymentParams(result.get("prepay_id"));
}
private Map<String, String> buildPaymentParams(String prepayId) {
Map<String, String> paymentParams = new HashMap<>();
paymentParams.put("appId", wechatConfig.getAppId());
paymentParams.put("timeStamp", System.currentTimeMillis() / 1000 + "");
paymentParams.put("nonceStr", generateNonceStr());
paymentParams.put("package", "prepay_id=" + prepayId);
paymentParams.put("signType", "RSA");
paymentParams.put("paySign", generatePaySign(paymentParams));
return paymentParams;
}
}
支付结果回调处理
java
@PostMapping("/notify")
public String paymentNotify(HttpServletRequest request) {
try {
// 解析微信支付回调数据
String xmlData = getRequestBody(request);
Map<String, String> notifyData = xmlToMap(xmlData);
// 验证签名
if (!verifySignature(notifyData)) {
return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
}
// 处理业务逻辑
if ("SUCCESS".equals(notifyData.get("return_code"))) {
String outTradeNo = notifyData.get("out_trade_no");
String transactionId = notifyData.get("transaction_id");
// 更新订单状态
orderService.updateOrderStatus(outTradeNo, OrderStatus.PAID, transactionId);
// 更新用户课程权限
courseService.grantCourseAccess(outTradeNo);
}
return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
} catch (Exception e) {
log.error("支付回调处理失败", e);
return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
}
}
3️⃣ 前端调用实现(Vue + 微信小程序)
Vue组件中调起支付
vue
<template>
<div class="payment-page">
<button @click="handlePayment" class="pay-btn">立即支付</button>
</div>
</template>
<script>
import { createPaymentOrder } from '@/api/payment'
export default {
data() {
return {
courseId: '',
orderInfo: null
}
},
methods: {
async handlePayment() {
try {
// 创建支付订单
const response = await createPaymentOrder({
courseId: this.courseId,
amount: this.amount
})
// 调起微信支付
await this.wechatPay(response.data)
this.$message.success('支付成功!')
this.$router.push('/learning')
} catch (error) {
this.$message.error('支付失败:' + error.message)
}
},
wechatPay(paymentParams) {
return new Promise((resolve, reject) => {
if (typeof WeixinJSBridge === 'undefined') {
reject(new Error('微信环境不支持'))
return
}
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
{
appId: paymentParams.appId,
timeStamp: paymentParams.timeStamp,
nonceStr: paymentParams.nonceStr,
package: paymentParams.package,
signType: paymentParams.signType,
paySign: paymentParams.paySign
},
res => {
if (res.err_msg === 'get_brand_wcpay_request:ok') {
resolve()
} else {
reject(new Error('支付取消或失败'))
}
}
)
})
}
}
}
</script>
微信小程序支付调用
javascript
// 小程序支付
wx.request({
url: 'https://your-domain.com/api/pay/createOrder',
method: 'POST',
data: {
courseId: '123',
amount: 99.00
},
success: function(res) {
const paymentParams = res.data
wx.requestPayment({
timeStamp: paymentParams.timeStamp,
nonceStr: paymentParams.nonceStr,
package: paymentParams.package,
signType: paymentParams.signType,
paySign: paymentParams.paySign,
success: (res) => {
console.log('支付成功', res)
wx.navigateTo({
url: '/pages/learning/learning'
})
},
fail: (err) => {
console.error('支付失败', err)
wx.showToast({
title: '支付失败',
icon: 'none'
})
}
})
}
})
⚠️ 注意事项
-
签名验证:一定要做好签名验证,防止数据篡改
-
重复通知:微信可能会多次发送支付通知,需要做好幂等处理
-
金额单位:微信支付金额单位为分,记得转换
-
超时处理:设置合理的支付超时时间
-
异常处理:做好网络异常、用户取消等情况的处理
🔧 故障排查
-
支付签名失败:检查参数顺序和签名算法
-
无法调起支付:确认支付授权目录配置正确
-
回调接收不到:检查notify_url是否外网可访问
这个流程在我们项目中运行稳定,希望对大家有帮助!有问题的欢迎在评论区讨论~
#技术干货 #微信支付 #前后端分离 #Java #Vue #微信小程序
更多推荐


所有评论(0)