Merge branch 'main' of gitee.com:wg123/video-gen into main

This commit is contained in:
18610128193
2026-06-10 14:44:35 +08:00
5 changed files with 61 additions and 34 deletions
+4
View File
@@ -207,6 +207,10 @@ export async function updatePaymentConfig(id: string, value: string): Promise<vo
await api.put(`/admin/payment-configs/${id}`, { value }); await api.put(`/admin/payment-configs/${id}`, { value });
} }
export async function batchUpdatePaymentConfigs(configs: Record<string, string>): Promise<void> {
await api.put('/admin/payment-configs/batch', configs);
}
export async function getAdminNotifications(): Promise<{ total: number; items: any[] }> { export async function getAdminNotifications(): Promise<{ total: number; items: any[] }> {
return api.get('/admin/notifications'); return api.get('/admin/notifications');
} }
@@ -5,18 +5,10 @@ import {
import { import {
SaveOutlined, WechatOutlined, AlipayCircleOutlined, DollarOutlined, SaveOutlined, WechatOutlined, AlipayCircleOutlined, DollarOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { getPaymentConfigs, updatePaymentConfig } from '../api'; import { getPaymentConfigs, batchUpdatePaymentConfigs } from '../api';
interface PaymentConfig {
id: string;
key: string;
value: string;
description?: string;
}
const AdminPaymentConfig: React.FC = () => { const AdminPaymentConfig: React.FC = () => {
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
const [configs, setConfigs] = useState<PaymentConfig[]>([]);
const [wechatEnabled, setWechatEnabled] = useState(false); const [wechatEnabled, setWechatEnabled] = useState(false);
const [alipayEnabled, setAlipayEnabled] = useState(false); const [alipayEnabled, setAlipayEnabled] = useState(false);
const [form] = Form.useForm(); const [form] = Form.useForm();
@@ -24,9 +16,8 @@ const AdminPaymentConfig: React.FC = () => {
const load = async () => { const load = async () => {
try { try {
const data = await getPaymentConfigs(); const data = await getPaymentConfigs();
setConfigs(data);
const map: Record<string, string> = {}; const map: Record<string, string> = {};
data.forEach((c: PaymentConfig) => { map[c.key] = c.value; }); data.forEach((c: any) => { map[c.key] = c.value; });
form.setFieldsValue({ form.setFieldsValue({
wechat_mch_id: map['payment_wechat_mch_id'] || '', wechat_mch_id: map['payment_wechat_mch_id'] || '',
wechat_api_key: map['payment_wechat_api_key'] || '', wechat_api_key: map['payment_wechat_api_key'] || '',
@@ -36,6 +27,7 @@ const AdminPaymentConfig: React.FC = () => {
alipay_private_key: map['payment_alipay_private_key'] || '', alipay_private_key: map['payment_alipay_private_key'] || '',
alipay_public_key: map['payment_alipay_public_key'] || '', alipay_public_key: map['payment_alipay_public_key'] || '',
alipay_notify_url: map['payment_alipay_notify_url'] || '', alipay_notify_url: map['payment_alipay_notify_url'] || '',
alipay_gateway: map['payment_alipay_gateway'] || '',
}); });
setWechatEnabled(map['payment_wechat_enabled'] === 'true'); setWechatEnabled(map['payment_wechat_enabled'] === 'true');
setAlipayEnabled(map['payment_alipay_enabled'] === 'true'); setAlipayEnabled(map['payment_alipay_enabled'] === 'true');
@@ -50,24 +42,19 @@ const AdminPaymentConfig: React.FC = () => {
try { try {
const values = await form.validateFields(); const values = await form.validateFields();
setSaving(true); setSaving(true);
const updates: [string, string][] = [ await batchUpdatePaymentConfigs({
['payment_wechat_enabled', String(wechatEnabled)], payment_wechat_enabled: String(wechatEnabled),
['payment_wechat_mch_id', values.wechat_mch_id || ''], payment_wechat_mch_id: values.wechat_mch_id || '',
['payment_wechat_api_key', values.wechat_api_key || ''], payment_wechat_api_key: values.wechat_api_key || '',
['payment_wechat_cert_path', values.wechat_cert_path || ''], payment_wechat_cert_path: values.wechat_cert_path || '',
['payment_wechat_notify_url', values.wechat_notify_url || ''], payment_wechat_notify_url: values.wechat_notify_url || '',
['payment_alipay_enabled', String(alipayEnabled)], payment_alipay_enabled: String(alipayEnabled),
['payment_alipay_app_id', values.alipay_app_id || ''], payment_alipay_app_id: values.alipay_app_id || '',
['payment_alipay_private_key', values.alipay_private_key || ''], payment_alipay_private_key: values.alipay_private_key || '',
['payment_alipay_public_key', values.alipay_public_key || ''], payment_alipay_public_key: values.alipay_public_key || '',
['payment_alipay_notify_url', values.alipay_notify_url || ''], payment_alipay_notify_url: values.alipay_notify_url || '',
]; payment_alipay_gateway: values.alipay_gateway || '',
for (const [key, value] of updates) { });
const cfg = configs.find(c => c.key === key);
if (cfg) {
await updatePaymentConfig(cfg.id, value);
}
}
message.success('支付配置已保存'); message.success('支付配置已保存');
load(); load();
} catch { } catch {
@@ -141,7 +128,10 @@ const AdminPaymentConfig: React.FC = () => {
<Form.Item name="alipay_public_key" label="支付宝公钥"> <Form.Item name="alipay_public_key" label="支付宝公钥">
<Input.TextArea rows={3} placeholder="支付宝公钥" disabled={!alipayEnabled} /> <Input.TextArea rows={3} placeholder="支付宝公钥" disabled={!alipayEnabled} />
</Form.Item> </Form.Item>
<Form.Item name="alipay_notify_url" label="回调地址"> <Form.Item name="alipay_gateway" label="网关地址" extra="正式环境: https://openapi.alipay.com/gateway.do 沙箱环境: https://openapi-sandbox.dl.alipaydev.com/gateway.do">
<Input placeholder="https://openapi.alipay.com/gateway.do" size="large" disabled={!alipayEnabled} />
</Form.Item>
<Form.Item name="alipay_notify_url" label="回调地址" extra="用户支付成功后,支付宝会主动通知此地址,服务器收到通知后给用户加积分">
<Input placeholder="https://yourdomain.com/api/payments/alipay/callback" size="large" disabled={!alipayEnabled} /> <Input placeholder="https://yourdomain.com/api/payments/alipay/callback" size="large" disabled={!alipayEnabled} />
</Form.Item> </Form.Item>
</Form> </Form>
+28
View File
@@ -412,6 +412,34 @@ async def list_payment_configs(
] ]
@router.put("/payment-configs/batch")
async def batch_update_payment_configs(
req: dict[str, str],
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
"""Batch upsert payment configs. Creates missing keys, updates existing ones."""
from app.utils.id_gen import generate_id
for key, value in req.items():
if not key.startswith("payment_"):
continue
result = await db.execute(
select(SystemConfig).where(SystemConfig.key == key).limit(1)
)
config = result.scalar_one_or_none()
if config:
config.value = value
else:
db.add(SystemConfig(
id=generate_id(),
key=key,
value=value,
))
await db.flush()
return {"ok": True}
@router.put("/payment-configs/{config_id}") @router.put("/payment-configs/{config_id}")
async def update_payment_config( async def update_payment_config(
config_id: str, config_id: str,
+4 -3
View File
@@ -41,7 +41,7 @@ _alipay_client = None
_alipay_client_app_id = None _alipay_client_app_id = None
def _get_alipay_client(app_id: str, private_key: str, public_key: str): def _get_alipay_client(app_id: str, private_key: str, public_key: str, gateway: str = ""):
"""Get or create an Alipay client. Recreated if app_id changes.""" """Get or create an Alipay client. Recreated if app_id changes."""
global _alipay_client, _alipay_client_app_id global _alipay_client, _alipay_client_app_id
@@ -59,7 +59,7 @@ def _get_alipay_client(app_id: str, private_key: str, public_key: str):
return None return None
config = AlipayClientConfig() config = AlipayClientConfig()
config.server_url = "https://openapi.alipay.com/gateway.do" config.server_url = gateway or "https://openapi.alipay.com/gateway.do"
config.app_id = app_id config.app_id = app_id
config.app_private_key = private_key config.app_private_key = private_key
config.alipay_public_key = public_key config.alipay_public_key = public_key
@@ -187,12 +187,13 @@ def _create_alipay_order(order: PaymentOrder, db_configs: dict[str, str]) -> str
private_key = db_configs.get("payment_alipay_private_key", "") private_key = db_configs.get("payment_alipay_private_key", "")
public_key = db_configs.get("payment_alipay_public_key", "") public_key = db_configs.get("payment_alipay_public_key", "")
notify_url = db_configs.get("payment_alipay_notify_url", "") notify_url = db_configs.get("payment_alipay_notify_url", "")
gateway = db_configs.get("payment_alipay_gateway", "")
if not app_id or not private_key: if not app_id or not private_key:
logger.warning("Alipay config missing in database (app_id / private_key)") logger.warning("Alipay config missing in database (app_id / private_key)")
return None return None
client = _get_alipay_client(app_id, private_key, public_key) client = _get_alipay_client(app_id, private_key, public_key, gateway)
if client is None: if client is None:
return None return None
@@ -93,6 +93,7 @@ const AdminPaymentConfig: React.FC = () => {
alipay_app_id: '', alipay_app_id: '',
alipay_private_key: '', alipay_private_key: '',
alipay_public_key: '', alipay_public_key: '',
alipay_gateway: '',
alipay_notify_url: '', alipay_notify_url: '',
}}> }}>
<Form.Item name="alipay_app_id" label="AppID"> <Form.Item name="alipay_app_id" label="AppID">
@@ -104,7 +105,10 @@ const AdminPaymentConfig: React.FC = () => {
<Form.Item name="alipay_public_key" label="支付宝公钥"> <Form.Item name="alipay_public_key" label="支付宝公钥">
<Input.TextArea rows={3} placeholder="支付宝公钥" disabled={!alipayEnabled} /> <Input.TextArea rows={3} placeholder="支付宝公钥" disabled={!alipayEnabled} />
</Form.Item> </Form.Item>
<Form.Item name="alipay_notify_url" label="回调地址"> <Form.Item name="alipay_gateway" label="网关地址" extra="正式环境: https://openapi.alipay.com/gateway.do 沙箱环境: https://openapi-sandbox.dl.alipaydev.com/gateway.do">
<Input placeholder="https://openapi.alipay.com/gateway.do" size="large" disabled={!alipayEnabled} />
</Form.Item>
<Form.Item name="alipay_notify_url" label="回调地址" extra="用户支付成功后,支付宝会主动通知此地址,服务器收到通知后给用户加积分">
<Input placeholder="https://yourdomain.com/api/payments/alipay/callback" size="large" disabled={!alipayEnabled} /> <Input placeholder="https://yourdomain.com/api/payments/alipay/callback" size="large" disabled={!alipayEnabled} />
</Form.Item> </Form.Item>
</Form> </Form>