import { useCallback, useEffect, useState } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; import type { WechatPayOrderResult } from '@dukang/shared-types'; import SubPageHeader from '../components/SubPageHeader'; import PhoneVerifySheet from '../components/PhoneVerifySheet'; import { request } from '../lib/api'; import { buildOrderConfirmUrl } from '../lib/navigation'; import { authorizeWechatForPay, fetchClientConfig, fetchUserProfile, isWechatAuthRequiredError, needsWechatAuthForPay, saveWechatLoginResult, } from '../lib/pay-wechat'; import { applyWechatLoginResult, handleWechatAuthCallback } from '../lib/wechat-auth'; import { isWechatEnv } from '../lib/weixin'; import { usePageView } from '../lib/usePageView'; import { track } from '../lib/analytics'; function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } async function waitOrderPaid(orderId: string, maxAttempts = 15) { for (let i = 0; i < maxAttempts; i += 1) { const order = await request<{ payStatus?: string }>('USER_H5', `/trade/orders/${orderId}`); if (order.payStatus === 'PAID') return true; await sleep(2000); } return false; } export default function PayPage() { const [params] = useSearchParams(); const orderId = params.get('orderId') || ''; usePageView('pay_page_view', { orderId }); const navigate = useNavigate(); const [loading, setLoading] = useState(false); const [authLoading, setAuthLoading] = useState(false); const [mockMode, setMockMode] = useState(true); const [needsWechatAuth, setNeedsWechatAuth] = useState(false); const [msg, setMsg] = useState(''); const [showBindPhone, setShowBindPhone] = useState(false); const [wxSessionKey, setWxSessionKey] = useState(null); const [orderNo, setOrderNo] = useState(''); const [deliveryType, setDeliveryType] = useState(''); const refreshPayReadiness = useCallback(async () => { try { const [config, profile] = await Promise.all([fetchClientConfig(), fetchUserProfile()]); setMockMode(config.mockPay); setNeedsWechatAuth(needsWechatAuthForPay(config, profile)); return profile; } catch { return null; } }, []); const handleWechatLoginResult = useCallback( async (result: Parameters[0]) => { if (result.needBindPhone && result.wxSessionKey) { setWxSessionKey(result.wxSessionKey); setShowBindPhone(true); setMsg(''); return; } if (saveWechatLoginResult(result)) { setMsg(''); await refreshPayReadiness(); } }, [refreshPayReadiness], ); useEffect(() => { refreshPayReadiness(); }, [refreshPayReadiness]); useEffect(() => { if (!orderId) { setOrderNo(''); return; } request<{ orderNo?: string; deliveryType?: string }>('USER_H5', `/trade/orders/${orderId}`) .then((order) => { setOrderNo(order.orderNo || ''); setDeliveryType(order.deliveryType || ''); }) .catch(() => { setOrderNo(''); setDeliveryType(''); }); }, [orderId]); useEffect(() => { if (!isWechatEnv()) return; handleWechatAuthCallback() .then((result) => { if (result) void handleWechatLoginResult(result); }) .catch((e) => setMsg(e instanceof Error ? e.message : '微信授权失败')); }, [handleWechatLoginResult]); function goBackConfirm() { navigate( buildOrderConfirmUrl({ productId: params.get('productId'), qty: params.get('qty'), addressId: params.get('addressId'), cross: params.get('cross'), }), ); } async function wechatAuthorize() { setAuthLoading(true); setMsg(''); try { if (!isWechatEnv()) { setMsg('请在微信内打开以授权微信支付'); return; } const result = await authorizeWechatForPay(); if (result) await handleWechatLoginResult(result); } catch (e) { setMsg(e instanceof Error ? e.message : '微信授权失败'); } finally { setAuthLoading(false); } } async function pay() { if (needsWechatAuth) { setMsg('请先完成微信授权后再支付'); return; } setLoading(true); setMsg(''); try { const result = await request('USER_H5', `/trade/orders/${orderId}/pay`, { method: 'POST', }); if (result.mode === 'jsapi' && result.prepay) { setMockMode(false); const { weixinSdk } = await import('../lib/weixin'); await weixinSdk.pay(result.prepay); const paid = await waitOrderPaid(orderId); if (!paid) { alert('支付结果确认中,请稍后在订单列表查看'); } navigate( deliveryType === 'ON_SITE_PICKUP' ? '/orders?tab=completed' : '/orders?tab=paid', ); return; } navigate(deliveryType === 'ON_SITE_PICKUP' ? '/orders?tab=completed' : '/orders?tab=paid'); } catch (e) { if (isWechatAuthRequiredError(e)) { setNeedsWechatAuth(true); setMsg('微信支付需要先完成微信授权'); return; } setMsg(e instanceof Error ? e.message : '支付失败'); track('pay_fail', { orderId, failReason: e instanceof Error ? e.message : '支付失败', pagePath: '/pay', }); } finally { setLoading(false); } } return (
account_balance_wallet

{needsWechatAuth ? '授权微信后可支付' : mockMode ? (isWechatEnv() ? '微信支付' : 'Mock 微信支付') : '微信支付'}

{needsWechatAuth ? '使用微信支付前,需先授权微信账号以完成付款' : mockMode ? 'preV1 Mock 模式:点击确认即完成;开启真实支付后将调起微信收银台' : '请在微信内完成支付,支付成功后自动跳转'}

{needsWechatAuth && (

尚未授权微信

授权后可安全调起微信支付,不会重复扣款

)} {msg &&

{msg}

} {orderNo &&

订单号 {orderNo}

}
{ setShowBindPhone(false); setWxSessionKey(null); }} onSuccess={() => { void refreshPayReadiness(); }} />
); }