fix sub distributor payment feedback

This commit is contained in:
abingyyds committed 2026-04-26 21:50:05 +08:00
1 parent b850a5d709
commit dae5c121b7
3 files changed
+83 -6

No files matched your search

+9
View File
@@ -135,6 +135,15 @@
"subDist.fillRequired": "Please fill in the site name, slug, and payment method",
"subDist.selectPayment": "Please select a payment method",
"subDist.createFailed": "Failed to create order",
"subDist.paymentPageOpened": "Order created. Please complete payment on the opened payment page.",
"subDist.paymentPageFailed": "Failed to open the payment page. Please try again later or contact the site administrator.",
"subDist.popupBlocked": "The browser blocked the payment window. Please allow pop-ups and try again.",
"subDist.cryptoOrderCreated": "Crypto order created. Please complete the transfer using the details on this page.",
"subDist.confirmingPayment": "Confirming payment result...",
"subDist.paymentPending": "Returned to this page. If you have completed payment, activation will finish after the callback is confirmed. Please refresh shortly.",
"subDist.openedSuccess": "Site activated successfully",
"subDist.alreadyOpenTitle": "Your site is already activated",
"subDist.alreadyOpenDesc": "Site {{name}} has been activated. Use the same account in the main console to continue setup.",
"tokens.title": "API Keys",
"tokens.subtitle": "Manage your API access tokens",
+9
View File
@@ -135,6 +135,15 @@
"subDist.fillRequired": "请填写站点名称、标识和支付方式",
"subDist.selectPayment": "请选择支付方式",
"subDist.createFailed": "创建订单失败",
"subDist.paymentPageOpened": "订单已创建,请在打开的支付页面完成付款",
"subDist.paymentPageFailed": "支付页面打开失败,请稍后重试或联系站点管理员",
"subDist.popupBlocked": "浏览器拦截了支付窗口,请允许弹窗后重试",
"subDist.cryptoOrderCreated": "加密货币订单已创建,请按页面信息完成转账",
"subDist.confirmingPayment": "正在确认支付结果...",
"subDist.paymentPending": "已返回当前页面。若您已完成付款,系统会在回调确认后自动开通,请稍后刷新查看。",
"subDist.openedSuccess": "站点已开通成功",
"subDist.alreadyOpenTitle": "您已开通站点",
"subDist.alreadyOpenDesc": "站点 {{name}} 已完成开通,请使用同一账号进入主站控制台继续配置。",
"tokens.title": "API 密钥",
"tokens.subtitle": "管理您的 API 访问令牌",
+65 -6
View File
@@ -1,5 +1,5 @@
import React, { useEffect, useMemo, useState } from 'react';
import { Link } from 'react-router-dom';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import toast from 'react-hot-toast';
import { createSubDistributorOrder, getSubDistributorInfo } from '../api';
@@ -9,7 +9,7 @@ import { useSite, useCurrency } from '../context/SiteContext';
function submitEpayForm(resData) {
const params = resData.data;
const url = resData.url;
if (!params || !url) return;
if (!params || !url) return false;
const form = document.createElement('form');
form.action = url;
form.method = 'POST';
@@ -27,13 +27,16 @@ function submitEpayForm(resData) {
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
return true;
}
export default function SubDistributor() {
const { t } = useTranslation();
const { user } = useAuth();
const { user, refreshUser, loading: authLoading } = useAuth();
const { site } = useSite();
const { symbol, fmtCNY } = useCurrency();
const location = useLocation();
const navigate = useNavigate();
const [loading, setLoading] = useState(true);
const [subInfo, setSubInfo] = useState(null);
const [submitting, setSubmitting] = useState(false);
@@ -66,6 +69,41 @@ export default function SubDistributor() {
() => paymentMethods.find((item) => item.type === form.payment_method),
[paymentMethods, form.payment_method]
);
const paymentReturned = useMemo(
() => new URLSearchParams(location.search).get('payment') === 'return',
[location.search]
);
useEffect(() => {
if (!paymentReturned || authLoading) return;
let cancelled = false;
const toastId = 'sub-dist-payment-return';
const checkPaymentResult = async () => {
if (!user) {
toast(t('subDist.paymentPending'), { id: toastId });
navigate('/sub-site', { replace: true });
return;
}
toast.loading(t('subDist.confirmingPayment'), { id: toastId });
const refreshed = await refreshUser({ skipErrorHandler: true });
if (cancelled) return;
if (refreshed?.has_distributor) {
toast.success(t('subDist.openedSuccess'), { id: toastId });
} else {
toast(t('subDist.paymentPending'), { id: toastId });
}
navigate('/sub-site', { replace: true });
};
checkPaymentResult();
return () => {
cancelled = true;
};
}, [authLoading, navigate, paymentReturned, refreshUser, t, user]);
const handleSubmit = async (e) => {
e.preventDefault();
@@ -89,7 +127,7 @@ export default function SubDistributor() {
name: form.name.trim(),
slug: form.slug.trim().toLowerCase(),
payment_method: form.payment_method,
return_url: `${window.location.origin}/sub-distributor`,
return_url: `${window.location.origin}/sub-site?payment=return`,
};
if (form.payment_method === 'crypto') {
payload.chain = form.chain;
@@ -98,14 +136,26 @@ export default function SubDistributor() {
const res = await createSubDistributorOrder(payload);
if (res.data.message === 'success') {
if (res.data.payment_type === 'stripe' && res.data.data?.pay_link) {
window.open(res.data.data.pay_link, '_blank');
const opened = window.open(res.data.data.pay_link, '_blank');
if (opened) {
toast.success(t('subDist.paymentPageOpened'));
} else {
toast.error(t('subDist.popupBlocked'));
}
} else if (res.data.payment_type === 'crypto') {
setCryptoOrder(res.data.data);
toast.success(t('subDist.cryptoOrderCreated'));
} else {
submitEpayForm(res.data);
if (submitEpayForm(res.data)) {
toast.success(t('subDist.paymentPageOpened'));
} else {
toast.error(t('subDist.paymentPageFailed'));
}
}
} else if (res.data.data) {
toast.error(typeof res.data.data === 'string' ? res.data.data : t('subDist.createFailed'));
} else {
toast.error(t('subDist.createFailed'));
}
} catch (e) {
// handled by interceptor
@@ -146,6 +196,15 @@ export default function SubDistributor() {
<Link to="/register" className="btn-secondary">{t('subDist.goRegister')}</Link>
</div>
</div>
) : user?.has_distributor ? (
<div className="rounded-2xl border border-emerald-500/20 bg-emerald-500/5 p-5 space-y-3">
<p className="text-sm font-medium text-page">{t('subDist.alreadyOpenTitle')}</p>
<p className="text-sm text-page-secondary">
{t('subDist.alreadyOpenDesc', {
name: user.distributor_name || user.distributor_slug || t('subDist.defaultSiteName'),
})}
</p>
</div>
) : (
<form onSubmit={handleSubmit} className="space-y-5">
<div>