Files
market_page/frontend/src/pages/Payment.jsx
jeremygan2021 b2f9545fdd
All checks were successful
Deploy to Server / deploy (push) Successful in 25s
sms
2026-02-16 20:15:26 +08:00

207 lines
7.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;