207 lines
7.0 KiB
JavaScript
207 lines
7.0 KiB
JavaScript
import React, { useEffect, useState } from 'react';
|
||
import { useParams, useNavigate, useLocation } from 'react-router-dom';
|
||
import { Button, message, Result, Spin } from 'antd';
|
||
import { WechatOutlined, AlipayCircleOutlined, CheckCircleOutlined } from '@ant-design/icons';
|
||
import { QRCodeSVG } from 'qrcode.react';
|
||
import { getOrder, initiatePayment, confirmPayment, nativePay, queryOrderStatus } from '../api';
|
||
import './Payment.css';
|
||
|
||
const Payment = () => {
|
||
const { orderId: initialOrderId } = useParams();
|
||
const navigate = useNavigate();
|
||
const location = useLocation();
|
||
const [currentOrderId, setCurrentOrderId] = useState(location.state?.order_id || initialOrderId);
|
||
const [order, setOrder] = useState(location.state?.orderInfo || null);
|
||
const [codeUrl, setCodeUrl] = useState(location.state?.codeUrl || null);
|
||
const [loading, setLoading] = useState(!location.state?.orderInfo && !location.state?.codeUrl);
|
||
const [paying, setPaying] = useState(!!location.state?.codeUrl);
|
||
const [paySuccess, setPaySuccess] = useState(false);
|
||
const [paymentMethod, setPaymentMethod] = useState('wechat');
|
||
|
||
useEffect(() => {
|
||
if (codeUrl && !paying) {
|
||
setPaying(true);
|
||
}
|
||
}, [codeUrl]);
|
||
|
||
useEffect(() => {
|
||
console.log('Payment page state:', { currentOrderId, order, codeUrl, paying });
|
||
if (!order && !codeUrl) {
|
||
fetchOrder();
|
||
}
|
||
}, [currentOrderId]);
|
||
|
||
useEffect(() => {
|
||
if (paying && !codeUrl && order) {
|
||
handlePay();
|
||
}
|
||
}, [paying, codeUrl, order]);
|
||
|
||
// 轮询订单状态
|
||
useEffect(() => {
|
||
let timer;
|
||
if (paying && !paySuccess) {
|
||
timer = setInterval(async () => {
|
||
try {
|
||
const response = await queryOrderStatus(currentOrderId);
|
||
if (response.data.status === 'paid') {
|
||
setPaySuccess(true);
|
||
setPaying(false);
|
||
clearInterval(timer);
|
||
}
|
||
} catch (error) {
|
||
console.error('Check payment status failed:', error);
|
||
}
|
||
}, 3000);
|
||
}
|
||
return () => clearInterval(timer);
|
||
}, [paying, paySuccess, currentOrderId]);
|
||
|
||
const fetchOrder = async () => {
|
||
try {
|
||
const response = await getOrder(currentOrderId);
|
||
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;
|
||
}
|
||
|
||
if (codeUrl) {
|
||
setPaying(true);
|
||
return;
|
||
}
|
||
|
||
if (!order) {
|
||
message.error('正在加载订单信息,请稍后...');
|
||
return;
|
||
}
|
||
|
||
setPaying(true);
|
||
try {
|
||
const orderData = {
|
||
goodid: order.config || order.goodid,
|
||
quantity: order.quantity,
|
||
customer_name: order.customer_name,
|
||
phone_number: order.phone_number,
|
||
shipping_address: order.shipping_address,
|
||
ref_code: order.ref_code
|
||
};
|
||
|
||
const response = await nativePay(orderData);
|
||
setCodeUrl(response.data.code_url);
|
||
if (response.data.order_id) {
|
||
setCurrentOrderId(response.data.order_id);
|
||
}
|
||
message.success('支付二维码已生成');
|
||
} catch (error) {
|
||
console.error(error);
|
||
message.error('生成支付二维码失败,请重试');
|
||
setPaying(false);
|
||
}
|
||
};
|
||
|
||
if (loading) return <div style={{ padding: 50, textAlign: 'center' }}><Spin size="large" /><div style={{ marginTop: 20 }}>正在加载订单信息...</div></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' }}>订单 {currentOrderId} 已完成支付,我们将尽快为您发货。</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: {currentOrderId}</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', minWidth: 240, minHeight: 280 }}>
|
||
{codeUrl ? (
|
||
<>
|
||
<div style={{ background: '#fff', padding: '10px', borderRadius: '4px', display: 'inline-block' }}>
|
||
<QRCodeSVG value={codeUrl} size={200} />
|
||
</div>
|
||
<p style={{ color: '#000', marginTop: 15, fontWeight: 'bold', fontSize: 18 }}>请使用微信扫码支付</p>
|
||
<p style={{ color: '#666', fontSize: 14 }}>支付完成后将自动跳转</p>
|
||
</>
|
||
) : (
|
||
<div style={{ padding: '40px 0', textAlign: 'center' }}>
|
||
<Spin />
|
||
<div style={{ marginTop: 10 }}>正在生成支付二维码...</div>
|
||
</div>
|
||
)}
|
||
</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;
|