以下是PC端前端实现扫码支付及支付状态判定的技术实现详解,结合支付宝/微信支付等常见场景:
一、支付二维码的生成方式
1. 支付宝(前置模式)
// 1. 请求后端接口获取支付数据
async function getAlipayQRCode(orderId) {
const res = await axios.post('/api/alipay/create', { orderId });
// 返回的form数据示例: <form action="https://openapi.alipay.com/..." method="POST">...</form>
return res.data.formHTML;
}
// 2. 通过iframe渲染支付宝返回的form数据
function renderAlipayQRCode(formHTML) {
const iframe = document.createElement('iframe');
iframe.srcdoc = formHTML; // 关键:将form数据嵌入iframe
iframe.style.width = '300px';
iframe.style.height = '300px';
document.getElementById('qrcode-container').appendChild(iframe);
}
2. 微信支付(模式二)
// 1. 调用统一下单接口获取code_url
async function getWechatPayCodeUrl(orderId) {
const res = await axios.post('/api/wechatpay/unifiedorder', { orderId });
return res.data.code_url; // 示例: weixin://wxpay/bizpayurl?pr=xxxxx
}
// 2. 使用qrcode.js生成二维码
function generateWechatQRCode(codeUrl) {
const qrcode = new QRCode(document.getElementById('qrcode-container'), {
text: codeUrl,
width: 200,
height: 200
});
}
二、支付状态轮询逻辑
1. 通用轮询方案(以支付宝为例)
let pollInterval;
function startPaymentPolling(orderId) {
pollInterval = setInterval(async () => {
const res = await axios.get(`/api/payment/status?orderId=${orderId}`);
if (res.data.status === 'SUCCESS') {
clearInterval(pollInterval);
alert('支付成功');
// 后续业务逻辑(如订单状态更新)
} else if (res.data.status === 'CLOSED') {
clearInterval(pollInterval);
alert('支付超时');
}
}, 3000); // 每3秒轮询一次
}
// 页面卸载时清除轮询
window.addEventListener('beforeunload', () => {
clearInterval(pollInterval);
});
2. WebSocket实时通知(优化方案)
javascriptCopy Code
const socket = new WebSocket('wss://your-api/payment-ws');
socket.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.event === 'payment_success') {
console.log('支付成功', data.orderId);
// 更新UI状态
}
};
三、关键实现细节
-
二维码有效期处理
-
微信支付的
code_url有效期通常为2小时,超时需重新生成6 -
前端可通过
setTimeout自动刷新:javascriptCopy Code setTimeout(() => { if (!paymentCompleted) { refreshQRCode(); } }, 7200000); // 2小时
-
-
安全注意事项
- 所有支付相关接口必须使用HTTPS
- 禁止前端直接处理支付金额等敏感数据
-
移动端适配
-
可通过
navigator.userAgent识别移动端,自动切换为H5支付方案:if (/Mobile|Android/i.test(navigator.userAgent)) { redirectToMobilePayment(); }
-
四、完整流程示例(微信支付)
// 1. 生成二维码
const codeUrl = await getWechatPayCodeUrl('ORDER123');
generateWechatQRCode(codeUrl);
// 2. 启动轮询
startPaymentPolling('ORDER123');
// 3. 支付成功后的处理
function onPaymentSuccess() {
// 更新订单状态、跳转成功页等
window.location.href = '/payment/success';
}
以上方案可根据实际业务需求调整轮询频率、超时时间等参数。对于高并发场景,推荐使用WebSocket替代轮询以降低服务器压力。