feat: require compliance confirmation for paid features

Gate payment, redemption, subscription, and invitation reward flows behind an audited compliance acknowledgement.
This commit is contained in:
CaIon
2026-05-13 22:18:46 +08:00
parent aa56667b8f
commit 0526a22643
57 changed files with 1806 additions and 216 deletions
+12
View File
@@ -38,6 +38,7 @@ const InvitationCard = ({
setOpenTransfer,
affLink,
handleAffLinkClick,
complianceConfirmed = true,
}) => {
return (
<Card className='!rounded-2xl shadow-sm border-0'>
@@ -81,6 +82,7 @@ const InvitationCard = ({
theme='solid'
size='small'
disabled={
!complianceConfirmed ||
!userState?.user?.aff_quota ||
userState?.user?.aff_quota <= 0
}
@@ -91,6 +93,16 @@ const InvitationCard = ({
{t('划转到余额')}
</Button>
</div>
{!complianceConfirmed && (
<Text
style={{
color: 'rgba(255,255,255,0.8)',
fontSize: 12,
}}
>
{t('邀请奖励划转已禁用,管理员需先确认合规声明。')}
</Text>
)}
{/* 统计数据 */}
<div className='grid grid-cols-3 gap-6 mt-4'>
+58 -48
View File
@@ -96,6 +96,7 @@ const RechargeCard = ({
activeSubscriptions = [],
allSubscriptions = [],
reloadSubscriptionSelf,
enableRedemption = true,
}) => {
const onlineFormApiRef = useRef(null);
const redeemFormApiRef = useRef(null);
@@ -566,57 +567,66 @@ const RechargeCard = ({
</Card>
{/* 兑换码充值 */}
<Card
className='!rounded-xl w-full'
title={
<Text type='tertiary' strong>
{t('兑换码充值')}
</Text>
}
>
<Form
getFormApi={(api) => (redeemFormApiRef.current = api)}
initValues={{ redemptionCode: redemptionCode }}
{enableRedemption ? (
<Card
className='!rounded-xl w-full'
title={
<Text type='tertiary' strong>
{t('兑换码充值')}
</Text>
}
>
<Form.Input
field='redemptionCode'
noLabel={true}
placeholder={t('请输入兑换码')}
value={redemptionCode}
onChange={(value) => setRedemptionCode(value)}
prefix={<IconGift />}
suffix={
<div className='flex items-center gap-2'>
<Button
type='primary'
theme='solid'
onClick={topUp}
loading={isSubmitting}
>
{t('兑换额度')}
</Button>
</div>
}
showClear
style={{ width: '100%' }}
extraText={
topUpLink && (
<Text type='tertiary'>
{t('在找兑换码?')}
<Text
type='secondary'
underline
className='cursor-pointer'
onClick={openTopUpLink}
<Form
getFormApi={(api) => (redeemFormApiRef.current = api)}
initValues={{ redemptionCode: redemptionCode }}
>
<Form.Input
field='redemptionCode'
noLabel={true}
placeholder={t('请输入兑换码')}
value={redemptionCode}
onChange={(value) => setRedemptionCode(value)}
prefix={<IconGift />}
suffix={
<div className='flex items-center gap-2'>
<Button
type='primary'
theme='solid'
onClick={topUp}
loading={isSubmitting}
>
{t('购买兑换码')}
{t('兑换额度')}
</Button>
</div>
}
showClear
style={{ width: '100%' }}
extraText={
topUpLink && (
<Text type='tertiary'>
{t('在找兑换码?')}
<Text
type='secondary'
underline
className='cursor-pointer'
onClick={openTopUpLink}
>
{t('购买兑换码')}
</Text>
</Text>
</Text>
)
}
/>
</Form>
</Card>
)
}
/>
</Form>
</Card>
) : (
<Banner
type='warning'
description={t('兑换码功能已禁用,管理员需先确认合规声明。')}
closeIcon={null}
className='!rounded-xl'
/>
)}
</Space>
);
+13 -1
View File
@@ -110,6 +110,8 @@ const TopUp = () => {
const [topupInfo, setTopupInfo] = useState({
amount_options: [],
discount: {},
enable_redemption: true,
payment_compliance_confirmed: true,
});
const confirmPayMethods = [
@@ -645,7 +647,7 @@ const TopUp = () => {
? data.waffo_min_topup
: enableWaffoPancakeTopUp
? data.waffo_pancake_min_topup
: 1;
: 1;
setEnableOnlineTopUp(enableOnlineTopUp);
setEnableStripeTopUp(enableStripeTopUp);
setEnableCreemTopUp(enableCreemTopUp);
@@ -657,6 +659,14 @@ const TopUp = () => {
setMinTopUp(minTopUpValue);
setTopUpCount(minTopUpValue);
setTopUpLink(data.topup_link || '');
setTopupInfo((prev) => ({
...prev,
enable_redemption: data.enable_redemption !== false,
payment_compliance_confirmed:
data.payment_compliance_confirmed !== false,
payment_compliance_terms_version:
data.payment_compliance_terms_version || '',
}));
// 设置 Creem 产品
try {
@@ -984,6 +994,7 @@ const TopUp = () => {
activeSubscriptions={activeSubscriptions}
allSubscriptions={allSubscriptions}
reloadSubscriptionSelf={getSubscriptionSelf}
enableRedemption={topupInfo.enable_redemption !== false}
/>
<InvitationCard
t={t}
@@ -992,6 +1003,7 @@ const TopUp = () => {
setOpenTransfer={setOpenTransfer}
affLink={affLink}
handleAffLinkClick={handleAffLinkClick}
complianceConfirmed={topupInfo.payment_compliance_confirmed !== false}
/>
</div>
</div>