refactor: 简化支付展示逻辑 - 有 payUrl 直接跳转,有 qrCode 显示二维码

移除 isRedirectPayment / mobileRedirectUrl 等支付类型判断,
前端只根据后端返回的字段决定行为:
- payUrl → 自动跳转,无需确认
- qrCode → 展示二维码 + 中心图标
- clientSecret → Stripe 嵌入式表单

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
erio
2026-03-06 19:13:06 +08:00
parent 7be0614c7d
commit 137a780269

View File

@@ -4,7 +4,6 @@ import { useEffect, useMemo, useState, useCallback, useRef } from 'react';
import QRCode from 'qrcode'; import QRCode from 'qrcode';
import { import {
isStripeType, isStripeType,
isRedirectPayment,
getPaymentMeta, getPaymentMeta,
getPaymentIconSrc, getPaymentIconSrc,
getPaymentChannelLabel, getPaymentChannelLabel,
@@ -78,32 +77,22 @@ export default function PaymentQRCode({
const [popupBlocked, setPopupBlocked] = useState(false); const [popupBlocked, setPopupBlocked] = useState(false);
const paymentMethodListenerAdded = useRef(false); const paymentMethodListenerAdded = useRef(false);
// alipay_direct 使用电脑网站支付payUrl 是跳转链接不是二维码内容 // 有 payUrl 就直接跳转,不需要确认
const isRedirect = isRedirectPayment(paymentType); const shouldAutoRedirect = !expired && !isStripeType(paymentType) && !!payUrl;
// 移动端可用的跳转链接:优先 payUrl其次尝试 qrCode微信 weixin:// 协议可直接唤起)
const mobileRedirectUrl = payUrl || (qrCode && /^(https?:|weixin:)/i.test(qrCode) ? qrCode : null);
// 自动跳转redirect 支付方式 或 移动端 H5
const shouldAutoRedirect = !expired && !isStripeType(paymentType) && ((isRedirect && payUrl) || (isMobile && mobileRedirectUrl));
useEffect(() => { useEffect(() => {
if (!shouldAutoRedirect || redirected) return; if (!shouldAutoRedirect || redirected) return;
const url = isRedirect ? payUrl! : mobileRedirectUrl!;
setRedirected(true); setRedirected(true);
// embedded iframe 不能 location.href 跳转,用 window.open
if (isEmbedded) { if (isEmbedded) {
window.open(url, '_blank'); window.open(payUrl!, '_blank');
} else { } else {
window.location.href = url; window.location.href = payUrl!;
} }
}, [shouldAutoRedirect, redirected, isRedirect, payUrl, mobileRedirectUrl, isEmbedded]); }, [shouldAutoRedirect, redirected, payUrl, isEmbedded]);
const qrPayload = useMemo(() => { const qrPayload = useMemo(() => {
if (isRedirect && !qrCode) return ''; return (qrCode || '').trim();
const value = (qrCode || payUrl || '').trim(); }, [qrCode]);
return value;
}, [qrCode, payUrl, isRedirect]);
useEffect(() => { useEffect(() => {
let cancelled = false; let cancelled = false;
@@ -476,7 +465,7 @@ export default function PaymentQRCode({
</span> </span>
</div> </div>
<a <a
href={isRedirect ? payUrl! : mobileRedirectUrl!} href={payUrl!}
target={isEmbedded ? '_blank' : '_self'} target={isEmbedded ? '_blank' : '_self'}
rel="noopener noreferrer" rel="noopener noreferrer"
className={`flex w-full items-center justify-center gap-2 rounded-lg py-3 font-medium text-white shadow-md ${meta.buttonClass}`} className={`flex w-full items-center justify-center gap-2 rounded-lg py-3 font-medium text-white shadow-md ${meta.buttonClass}`}
@@ -511,18 +500,7 @@ export default function PaymentQRCode({
</div> </div>
)} )}
{!qrDataUrl && payUrl && ( {!qrDataUrl && (
<a
href={payUrl}
target="_blank"
rel="noopener noreferrer"
className="rounded-lg bg-blue-600 px-8 py-3 font-medium text-white hover:bg-blue-700"
>
{TEXT_GO_PAY}
</a>
)}
{!qrDataUrl && !payUrl && (
<div className="text-center"> <div className="text-center">
<div <div
className={[ className={[