fix: 3D Show
This commit is contained in:
183
frontend/src/pages/Payment.jsx
Normal file
183
frontend/src/pages/Payment.jsx
Normal file
@@ -0,0 +1,183 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { Button, message, Result, Spin, QRCode } from 'antd';
|
||||
import { WechatOutlined, AlipayCircleOutlined, CheckCircleOutlined } from '@ant-design/icons';
|
||||
import { getOrder, initiatePayment, confirmPayment } from '../api';
|
||||
import './Payment.css';
|
||||
|
||||
const Payment = () => {
|
||||
const { orderId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [order, setOrder] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [paying, setPaying] = useState(false);
|
||||
const [paySuccess, setPaySuccess] = useState(false);
|
||||
const [paymentMethod, setPaymentMethod] = useState('wechat');
|
||||
|
||||
useEffect(() => {
|
||||
fetchOrder();
|
||||
}, [orderId]);
|
||||
|
||||
const fetchOrder = async () => {
|
||||
try {
|
||||
const response = await getOrder(orderId);
|
||||
setOrder(response.data);
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch order:', error);
|
||||
// Fallback if getOrder API fails (404/405), we might show basic info or error
|
||||
// Assuming for now it works or we handle it
|
||||
message.error('无法获取订单信息,请重试');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePay = async () => {
|
||||
if (paymentMethod === 'alipay') {
|
||||
message.info('暂未开通支付宝支付,请使用微信支付');
|
||||
return;
|
||||
}
|
||||
|
||||
setPaying(true);
|
||||
try {
|
||||
// 1. 获取微信支付参数
|
||||
const response = await initiatePayment(orderId);
|
||||
const payData = response.data;
|
||||
|
||||
if (typeof WeixinJSBridge === 'undefined') {
|
||||
message.warning('请在微信内置浏览器中打开以完成支付');
|
||||
setPaying(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 调用微信支付
|
||||
const onBridgeReady = () => {
|
||||
window.WeixinJSBridge.invoke(
|
||||
'getBrandWCPayRequest', {
|
||||
"appId": payData.appId, // 公众号名称,由商户传入
|
||||
"timeStamp": payData.timeStamp, // 时间戳,自1970年以来的秒数
|
||||
"nonceStr": payData.nonceStr, // 随机串
|
||||
"package": payData.package,
|
||||
"signType": payData.signType, // 微信签名方式:
|
||||
"paySign": payData.paySign // 微信签名
|
||||
},
|
||||
function(res) {
|
||||
setPaying(false);
|
||||
if (res.err_msg == "get_brand_wcpay_request:ok") {
|
||||
message.success('支付成功!');
|
||||
setPaySuccess(true);
|
||||
// 这里可以再次调用后端查询接口确认状态,但通常 JSAPI 回调 ok 即可认为成功
|
||||
// 为了保险,可以去轮询一下后端状态,或者直接展示成功页
|
||||
} else if (res.err_msg == "get_brand_wcpay_request:cancel") {
|
||||
message.info('支付已取消');
|
||||
} else {
|
||||
message.error('支付失败,请重试');
|
||||
console.error('WeChat Pay Error:', res);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
if (typeof window.WeixinJSBridge == "undefined") {
|
||||
if (document.addEventListener) {
|
||||
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
|
||||
} else if (document.attachEvent) {
|
||||
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
|
||||
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
|
||||
}
|
||||
} else {
|
||||
onBridgeReady();
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
if (error.response && error.response.data && error.response.data.error) {
|
||||
message.error(error.response.data.error);
|
||||
} else {
|
||||
message.error('支付发起失败,请稍后重试');
|
||||
}
|
||||
setPaying(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) return <div style={{ padding: 50, textAlign: 'center' }}><Spin size="large" /></div>;
|
||||
|
||||
if (paySuccess) {
|
||||
return (
|
||||
<div className="payment-container" style={{ borderColor: '#00b96b' }}>
|
||||
<Result
|
||||
status="success"
|
||||
icon={<CheckCircleOutlined style={{ color: '#00b96b' }} />}
|
||||
title={<span style={{ color: '#fff' }}>支付成功</span>}
|
||||
subTitle={<span style={{ color: '#888' }}>订单 {orderId} 已完成支付,我们将尽快为您发货。</span>}
|
||||
extra={[
|
||||
<Button type="primary" key="home" onClick={() => navigate('/')}>
|
||||
返回首页
|
||||
</Button>,
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="payment-container">
|
||||
<div className="payment-title">收银台</div>
|
||||
|
||||
{order ? (
|
||||
<>
|
||||
<div className="payment-amount">¥{order.total_price}</div>
|
||||
<div className="payment-info">
|
||||
<p><strong>订单编号:</strong> {order.id}</p>
|
||||
<p><strong>商品名称:</strong> {order.config_name || 'AI 硬件设备'}</p>
|
||||
<p><strong>收货人:</strong> {order.customer_name}</p>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="payment-info">
|
||||
<p>订单 ID: {orderId}</p>
|
||||
<p>无法加载详情,但您可以尝试支付。</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ color: '#fff', marginBottom: 15, textAlign: 'left' }}>选择支付方式:</div>
|
||||
<div className="payment-method">
|
||||
<div
|
||||
className={`payment-method-item ${paymentMethod === 'wechat' ? 'active' : ''}`}
|
||||
onClick={() => setPaymentMethod('wechat')}
|
||||
>
|
||||
<WechatOutlined style={{ color: '#09BB07', fontSize: 24, verticalAlign: 'middle', marginRight: 8 }} />
|
||||
微信支付
|
||||
</div>
|
||||
<div
|
||||
className={`payment-method-item ${paymentMethod === 'alipay' ? 'active' : ''}`}
|
||||
onClick={() => setPaymentMethod('alipay')}
|
||||
>
|
||||
<AlipayCircleOutlined style={{ color: '#1677FF', fontSize: 24, verticalAlign: 'middle', marginRight: 8 }} />
|
||||
支付宝
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{paying && (
|
||||
<div style={{ margin: '20px 0', padding: 20, background: '#fff', borderRadius: 8, display: 'inline-block' }}>
|
||||
<QRCode value={`mock-payment-${orderId}`} bordered={false} />
|
||||
<p style={{ color: '#000', marginTop: 10 }}>请扫码支付 (模拟)</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!paying && (
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
block
|
||||
onClick={handlePay}
|
||||
style={{ height: 50, fontSize: 18, background: paymentMethod === 'wechat' ? '#09BB07' : '#1677FF' }}
|
||||
>
|
||||
立即支付
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Payment;
|
||||
Reference in New Issue
Block a user