fix(payment): resolve payment settings save logic and enable persistence
- Fix Bug 1: Always save all provider-specific fields regardless of currently selected provider in dropdown, preventing data loss when switching between Alipay/WeChat/ePay/Yipay configurations - Fix Bug 2: Add EpayEnabled/YipayEnabled backend Go variables and OptionMap entries so enable/disable checkboxes persist across page reloads - Fix white screen crash by wrapping orphan Col elements in proper Row - Add EpayEnabled/YipayEnabled to PaymentSetting.jsx initial state - Remove duplicate payment card imports for Stripe/Creem/Waffo/Alipay/Wechat
This commit is contained in:
parent
6fc114ec32
commit
82016579db
|
|
@ -102,6 +102,8 @@ func InitOptionMap() {
|
||||||
common.OptionMap["YipayReturnUrl"] = operation_setting.YipayReturnUrl
|
common.OptionMap["YipayReturnUrl"] = operation_setting.YipayReturnUrl
|
||||||
common.OptionMap["YipayRequestURL"] = operation_setting.YipayRequestURL
|
common.OptionMap["YipayRequestURL"] = operation_setting.YipayRequestURL
|
||||||
common.OptionMap["YipayChannelExtra"] = operation_setting.YipayChannelExtra
|
common.OptionMap["YipayChannelExtra"] = operation_setting.YipayChannelExtra
|
||||||
|
common.OptionMap["EpayEnabled"] = strconv.FormatBool(operation_setting.EpayEnabled)
|
||||||
|
common.OptionMap["YipayEnabled"] = strconv.FormatBool(operation_setting.YipayEnabled)
|
||||||
common.OptionMap["Price"] = strconv.FormatFloat(operation_setting.Price, 'f', -1, 64)
|
common.OptionMap["Price"] = strconv.FormatFloat(operation_setting.Price, 'f', -1, 64)
|
||||||
common.OptionMap["USDExchangeRate"] = strconv.FormatFloat(operation_setting.USDExchangeRate, 'f', -1, 64)
|
common.OptionMap["USDExchangeRate"] = strconv.FormatFloat(operation_setting.USDExchangeRate, 'f', -1, 64)
|
||||||
common.OptionMap["MinTopUp"] = strconv.Itoa(operation_setting.MinTopUp)
|
common.OptionMap["MinTopUp"] = strconv.Itoa(operation_setting.MinTopUp)
|
||||||
|
|
@ -495,6 +497,10 @@ func updateOptionMap(key string, value string) (err error) {
|
||||||
case "YipayChannelExtra":
|
case "YipayChannelExtra":
|
||||||
operation_setting.YipayChannelExtra = strings.TrimSpace(value)
|
operation_setting.YipayChannelExtra = strings.TrimSpace(value)
|
||||||
common.OptionMap[key] = operation_setting.YipayChannelExtra
|
common.OptionMap[key] = operation_setting.YipayChannelExtra
|
||||||
|
case "EpayEnabled":
|
||||||
|
operation_setting.EpayEnabled = value == "true"
|
||||||
|
case "YipayEnabled":
|
||||||
|
operation_setting.YipayEnabled = value == "true"
|
||||||
case "Price":
|
case "Price":
|
||||||
operation_setting.Price, _ = strconv.ParseFloat(value, 64)
|
operation_setting.Price, _ = strconv.ParseFloat(value, 64)
|
||||||
case "USDExchangeRate":
|
case "USDExchangeRate":
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ var CustomCallbackAddress = ""
|
||||||
var EpayId = ""
|
var EpayId = ""
|
||||||
var EpayKey = ""
|
var EpayKey = ""
|
||||||
var YipayAppSecret = ""
|
var YipayAppSecret = ""
|
||||||
|
var EpayEnabled = false
|
||||||
|
var YipayEnabled = false
|
||||||
var OnlinePayProvider = "yipay"
|
var OnlinePayProvider = "yipay"
|
||||||
var Price = 7.3
|
var Price = 7.3
|
||||||
var MinTopUp = 1
|
var MinTopUp = 1
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,7 @@ import React, { useEffect, useState } from "react";
|
||||||
import { Card, Spin } from "@douyinfe/semi-ui";
|
import { Card, Spin } from "@douyinfe/semi-ui";
|
||||||
import SettingsGeneralPayment from "../../pages/Setting/Payment/SettingsGeneralPayment";
|
import SettingsGeneralPayment from "../../pages/Setting/Payment/SettingsGeneralPayment";
|
||||||
import SettingsPaymentGateway from "../../pages/Setting/Payment/SettingsPaymentGateway";
|
import SettingsPaymentGateway from "../../pages/Setting/Payment/SettingsPaymentGateway";
|
||||||
import SettingsPaymentGatewayStripe from "../../pages/Setting/Payment/SettingsPaymentGatewayStripe";
|
|
||||||
import SettingsPaymentGatewayCreem from "../../pages/Setting/Payment/SettingsPaymentGatewayCreem";
|
|
||||||
import SettingsPaymentGatewayWaffo from "../../pages/Setting/Payment/SettingsPaymentGatewayWaffo";
|
|
||||||
import SettingsPaymentGatewayAlipay from "../../pages/Setting/Payment/SettingsPaymentGatewayAlipay";
|
|
||||||
import SettingsPaymentGatewayWechat from "../../pages/Setting/Payment/SettingsPaymentGatewayWechat";
|
|
||||||
import { API, showError, toBoolean } from "../../helpers";
|
import { API, showError, toBoolean } from "../../helpers";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
|
@ -45,6 +41,8 @@ const PaymentSetting = () => {
|
||||||
YipayReturnUrl: "",
|
YipayReturnUrl: "",
|
||||||
YipayChannelExtra: "",
|
YipayChannelExtra: "",
|
||||||
YipayRequestURL: "",
|
YipayRequestURL: "",
|
||||||
|
EpayEnabled: false,
|
||||||
|
YipayEnabled: false,
|
||||||
Price: 7.3,
|
Price: 7.3,
|
||||||
MinTopUp: 1,
|
MinTopUp: 1,
|
||||||
TopupGroupRatio: "",
|
TopupGroupRatio: "",
|
||||||
|
|
@ -53,13 +51,6 @@ const PaymentSetting = () => {
|
||||||
AmountOptions: "",
|
AmountOptions: "",
|
||||||
AmountDiscount: "",
|
AmountDiscount: "",
|
||||||
|
|
||||||
StripeApiSecret: "",
|
|
||||||
StripeWebhookSecret: "",
|
|
||||||
StripePriceId: "",
|
|
||||||
StripeUnitPrice: 8.0,
|
|
||||||
StripeMinTopUp: 1,
|
|
||||||
StripePromotionCodesEnabled: false,
|
|
||||||
|
|
||||||
AlipayEnabled: false,
|
AlipayEnabled: false,
|
||||||
AlipayAppId: "",
|
AlipayAppId: "",
|
||||||
AlipayPrivateKey: "",
|
AlipayPrivateKey: "",
|
||||||
|
|
@ -131,10 +122,6 @@ const PaymentSetting = () => {
|
||||||
break;
|
break;
|
||||||
case "Price":
|
case "Price":
|
||||||
case "MinTopUp":
|
case "MinTopUp":
|
||||||
case "StripeUnitPrice":
|
|
||||||
case "StripeMinTopUp":
|
|
||||||
newInputs[item.key] = parseFloat(item.value);
|
|
||||||
break;
|
|
||||||
case "YipayAppSecret":
|
case "YipayAppSecret":
|
||||||
newInputs[item.key] =
|
newInputs[item.key] =
|
||||||
item.value != null && item.value !== undefined
|
item.value != null && item.value !== undefined
|
||||||
|
|
@ -181,21 +168,6 @@ const PaymentSetting = () => {
|
||||||
<Card style={{ marginTop: "10px" }}>
|
<Card style={{ marginTop: "10px" }}>
|
||||||
<SettingsPaymentGateway options={inputs} refresh={onRefresh} />
|
<SettingsPaymentGateway options={inputs} refresh={onRefresh} />
|
||||||
</Card>
|
</Card>
|
||||||
<Card style={{ marginTop: "10px" }}>
|
|
||||||
<SettingsPaymentGatewayStripe options={inputs} refresh={onRefresh} />
|
|
||||||
</Card>
|
|
||||||
<Card style={{ marginTop: "10px" }}>
|
|
||||||
<SettingsPaymentGatewayCreem options={inputs} refresh={onRefresh} />
|
|
||||||
</Card>
|
|
||||||
<Card style={{ marginTop: "10px" }}>
|
|
||||||
<SettingsPaymentGatewayWaffo options={inputs} refresh={onRefresh} />
|
|
||||||
</Card>
|
|
||||||
<Card style={{ marginTop: "10px" }}>
|
|
||||||
<SettingsPaymentGatewayAlipay options={inputs} refresh={onRefresh} />
|
|
||||||
</Card>
|
|
||||||
<Card style={{ marginTop: "10px" }}>
|
|
||||||
<SettingsPaymentGatewayWechat options={inputs} refresh={onRefresh} />
|
|
||||||
</Card>
|
|
||||||
</Spin>
|
</Spin>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,8 @@ const RechargeCard = ({
|
||||||
statusLoading,
|
statusLoading,
|
||||||
topupInfo,
|
topupInfo,
|
||||||
onOpenHistory,
|
onOpenHistory,
|
||||||
|
enableAlipayTopUp,
|
||||||
|
enableWechatPayTopUp,
|
||||||
enableWaffoTopUp,
|
enableWaffoTopUp,
|
||||||
waffoTopUp,
|
waffoTopUp,
|
||||||
waffoPayMethods,
|
waffoPayMethods,
|
||||||
|
|
@ -213,13 +215,15 @@ const RechargeCard = ({
|
||||||
) : enableOnlineTopUp ||
|
) : enableOnlineTopUp ||
|
||||||
enableStripeTopUp ||
|
enableStripeTopUp ||
|
||||||
enableCreemTopUp ||
|
enableCreemTopUp ||
|
||||||
|
enableAlipayTopUp ||
|
||||||
|
enableWechatPayTopUp ||
|
||||||
enableWaffoTopUp ? (
|
enableWaffoTopUp ? (
|
||||||
<Form
|
<Form
|
||||||
getFormApi={(api) => (onlineFormApiRef.current = api)}
|
getFormApi={(api) => (onlineFormApiRef.current = api)}
|
||||||
initValues={{ topUpCount: topUpCount }}
|
initValues={{ topUpCount: topUpCount }}
|
||||||
>
|
>
|
||||||
<div className='space-y-6'>
|
<div className='space-y-6'>
|
||||||
{(enableOnlineTopUp || enableStripeTopUp || enableWaffoTopUp) && (
|
{(enableOnlineTopUp || enableStripeTopUp || enableWaffoTopUp || enableAlipayTopUp || enableWechatPayTopUp) && (
|
||||||
<Row gutter={12}>
|
<Row gutter={12}>
|
||||||
<Col xs={24} sm={24} md={24} lg={10} xl={10}>
|
<Col xs={24} sm={24} md={24} lg={10} xl={10}>
|
||||||
<Form.InputNumber
|
<Form.InputNumber
|
||||||
|
|
@ -228,7 +232,9 @@ const RechargeCard = ({
|
||||||
disabled={
|
disabled={
|
||||||
!enableOnlineTopUp &&
|
!enableOnlineTopUp &&
|
||||||
!enableStripeTopUp &&
|
!enableStripeTopUp &&
|
||||||
!enableWaffoTopUp
|
!enableWaffoTopUp &&
|
||||||
|
!enableAlipayTopUp &&
|
||||||
|
!enableWechatPayTopUp
|
||||||
}
|
}
|
||||||
placeholder={
|
placeholder={
|
||||||
t('充值数量,最低 ') + renderTopUpCount(minTopUp)
|
t('充值数量,最低 ') + renderTopUpCount(minTopUp)
|
||||||
|
|
@ -282,26 +288,30 @@ const RechargeCard = ({
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
{payMethods &&
|
{payMethods &&
|
||||||
payMethods.filter((m) => m.type !== 'waffo').length > 0 && (
|
payMethods.filter((m) => m.type !== 'waffo' && m.type !== 'custom1').length > 0 && (
|
||||||
<Col xs={24} sm={24} md={24} lg={14} xl={14}>
|
<Col xs={24} sm={24} md={24} lg={14} xl={14}>
|
||||||
<Form.Slot label={t('选择支付方式')}>
|
<Form.Slot label={t('选择支付方式')}>
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
{payMethods
|
{payMethods
|
||||||
.filter((m) => m.type !== 'waffo')
|
.filter((m) => m.type !== 'waffo' && m.type !== 'custom1')
|
||||||
.map((payMethod) => {
|
.map((payMethod) => {
|
||||||
const minTopupVal =
|
const minTopupVal =
|
||||||
Number(payMethod.min_topup) || 0;
|
Number(payMethod.min_topup) || 0;
|
||||||
const isStripe = payMethod.type === 'stripe';
|
const isStripe = payMethod.type === 'stripe';
|
||||||
|
const isAlipay = payMethod.type === 'alipay';
|
||||||
|
const isWechat = payMethod.type === 'wxpay';
|
||||||
const disabled =
|
const disabled =
|
||||||
(!enableOnlineTopUp && !isStripe) ||
|
(!enableOnlineTopUp && !isStripe && !isAlipay && !isWechat) ||
|
||||||
(!enableStripeTopUp && isStripe) ||
|
(!enableStripeTopUp && isStripe) ||
|
||||||
|
(!enableAlipayTopUp && isAlipay) ||
|
||||||
|
(!enableWechatPayTopUp && isWechat) ||
|
||||||
minTopupVal > Number(topUpCount || 0);
|
minTopupVal > Number(topUpCount || 0);
|
||||||
|
|
||||||
const buttonEl = (
|
const buttonEl = (
|
||||||
<Button
|
<Button
|
||||||
key={payMethod.type}
|
key={payMethod.type}
|
||||||
theme='outline'
|
theme={payWay === payMethod.type ? 'solid' : 'outline'}
|
||||||
type='tertiary'
|
type={payWay === payMethod.type ? 'primary' : 'tertiary'}
|
||||||
onClick={() => preTopUp(payMethod.type)}
|
onClick={() => preTopUp(payMethod.type)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
loading={
|
loading={
|
||||||
|
|
@ -310,11 +320,11 @@ const RechargeCard = ({
|
||||||
}
|
}
|
||||||
icon={
|
icon={
|
||||||
payMethod.type === 'alipay' ? (
|
payMethod.type === 'alipay' ? (
|
||||||
<SiAlipay size={18} color='#1677FF' />
|
<SiAlipay size={18} color={payWay === payMethod.type ? 'white' : '#1677FF'} />
|
||||||
) : payMethod.type === 'wxpay' ? (
|
) : payMethod.type === 'wxpay' ? (
|
||||||
<SiWechat size={18} color='#07C160' />
|
<SiWechat size={18} color={payWay === payMethod.type ? 'white' : '#07C160'} />
|
||||||
) : payMethod.type === 'stripe' ? (
|
) : payMethod.type === 'stripe' ? (
|
||||||
<SiStripe size={18} color='#635BFF' />
|
<SiStripe size={18} color={payWay === payMethod.type ? 'white' : '#635BFF'} />
|
||||||
) : (
|
) : (
|
||||||
<CreditCard
|
<CreditCard
|
||||||
size={18}
|
size={18}
|
||||||
|
|
@ -356,7 +366,7 @@ const RechargeCard = ({
|
||||||
</Row>
|
</Row>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(enableOnlineTopUp || enableStripeTopUp || enableWaffoTopUp) && (
|
{(enableOnlineTopUp || enableStripeTopUp || enableWaffoTopUp || enableAlipayTopUp || enableWechatPayTopUp) && (
|
||||||
<Form.Slot
|
<Form.Slot
|
||||||
label={
|
label={
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
|
|
|
||||||
|
|
@ -527,22 +527,26 @@ const TopUp = () => {
|
||||||
const enableStripeTopUp = data.enable_stripe_topup || false;
|
const enableStripeTopUp = data.enable_stripe_topup || false;
|
||||||
const enableOnlineTopUp = data.enable_online_topup || false;
|
const enableOnlineTopUp = data.enable_online_topup || false;
|
||||||
const enableCreemTopUp = data.enable_creem_topup || false;
|
const enableCreemTopUp = data.enable_creem_topup || false;
|
||||||
|
const enableWaffoTopUp = data.enable_waffo_topup || false;
|
||||||
|
const enableAlipayTopUp = data.enable_alipay_topup || false;
|
||||||
|
const enableWechatPayTopUp = data.enable_wechatpay_topup || false;
|
||||||
const minTopUpValue = enableOnlineTopUp
|
const minTopUpValue = enableOnlineTopUp
|
||||||
? data.min_topup
|
? data.min_topup
|
||||||
: enableStripeTopUp
|
: enableStripeTopUp
|
||||||
? data.stripe_min_topup
|
? data.stripe_min_topup
|
||||||
: data.enable_waffo_topup
|
: enableWaffoTopUp
|
||||||
? data.waffo_min_topup
|
? data.waffo_min_topup
|
||||||
: 1;
|
: enableAlipayTopUp
|
||||||
|
? data.alipay_min_topup
|
||||||
|
: enableWechatPayTopUp
|
||||||
|
? data.wechatpay_min_topup
|
||||||
|
: 1;
|
||||||
setEnableOnlineTopUp(enableOnlineTopUp);
|
setEnableOnlineTopUp(enableOnlineTopUp);
|
||||||
setEnableStripeTopUp(enableStripeTopUp);
|
setEnableStripeTopUp(enableStripeTopUp);
|
||||||
setEnableCreemTopUp(enableCreemTopUp);
|
setEnableCreemTopUp(enableCreemTopUp);
|
||||||
const enableWaffoTopUp = data.enable_waffo_topup || false;
|
|
||||||
const enableAlipayTopUp = data.enable_alipay_topup || false;
|
|
||||||
setEnableAlipayTopUp(enableAlipayTopUp);
|
|
||||||
const enableWechatPayTopUp = data.enable_wechatpay_topup || false;
|
|
||||||
setEnableWechatPayTopUp(enableWechatPayTopUp);
|
|
||||||
setEnableWaffoTopUp(enableWaffoTopUp);
|
setEnableWaffoTopUp(enableWaffoTopUp);
|
||||||
|
setEnableAlipayTopUp(enableAlipayTopUp);
|
||||||
|
setEnableWechatPayTopUp(enableWechatPayTopUp);
|
||||||
setWaffoPayMethods(data.waffo_pay_methods || []);
|
setWaffoPayMethods(data.waffo_pay_methods || []);
|
||||||
setWaffoMinTopUp(data.waffo_min_topup || 1);
|
setWaffoMinTopUp(data.waffo_min_topup || 1);
|
||||||
setMinTopUp(minTopUpValue);
|
setMinTopUp(minTopUpValue);
|
||||||
|
|
@ -810,9 +814,13 @@ const TopUp = () => {
|
||||||
}
|
}
|
||||||
const minTopupVal = Number(method.min_topup) || 0;
|
const minTopupVal = Number(method.min_topup) || 0;
|
||||||
const isStripe = method.type === 'stripe';
|
const isStripe = method.type === 'stripe';
|
||||||
|
const isAlipay = method.type === 'alipay';
|
||||||
|
const isWechat = method.type === 'wxpay';
|
||||||
const disabled =
|
const disabled =
|
||||||
(!enableOnlineTopUp && !isStripe) ||
|
(!enableOnlineTopUp && !isStripe && !isAlipay && !isWechat) ||
|
||||||
(!enableStripeTopUp && isStripe) ||
|
(!enableStripeTopUp && isStripe) ||
|
||||||
|
(!enableAlipayTopUp && isAlipay) ||
|
||||||
|
(!enableWechatPayTopUp && isWechat) ||
|
||||||
minTopupVal > Number(count || 0);
|
minTopupVal > Number(count || 0);
|
||||||
return !disabled;
|
return !disabled;
|
||||||
});
|
});
|
||||||
|
|
@ -823,7 +831,7 @@ const TopUp = () => {
|
||||||
selectPresetAmount(preset);
|
selectPresetAmount(preset);
|
||||||
const enabledMethods = getEnabledEpayMethods(preset.value);
|
const enabledMethods = getEnabledEpayMethods(preset.value);
|
||||||
if (enabledMethods.length === 0) {
|
if (enabledMethods.length === 0) {
|
||||||
showError(t('当前额度暂无可用支付方式'));
|
showError(t('暂无可用的支付方式,请联系管理员配置'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (enabledMethods.length === 1) {
|
if (enabledMethods.length === 1) {
|
||||||
|
|
@ -880,6 +888,8 @@ const TopUp = () => {
|
||||||
payMethods={payMethods}
|
payMethods={payMethods}
|
||||||
enableOnlineTopUp={enableOnlineTopUp}
|
enableOnlineTopUp={enableOnlineTopUp}
|
||||||
enableStripeTopUp={enableStripeTopUp}
|
enableStripeTopUp={enableStripeTopUp}
|
||||||
|
enableAlipayTopUp={enableAlipayTopUp}
|
||||||
|
enableWechatPayTopUp={enableWechatPayTopUp}
|
||||||
onSelect={handlePaymentMethodSelect}
|
onSelect={handlePaymentMethodSelect}
|
||||||
paymentLoading={paymentLoading}
|
paymentLoading={paymentLoading}
|
||||||
payWay={payWay}
|
payWay={payWay}
|
||||||
|
|
@ -994,6 +1004,8 @@ const TopUp = () => {
|
||||||
enableWaffoTopUp={enableWaffoTopUp}
|
enableWaffoTopUp={enableWaffoTopUp}
|
||||||
waffoTopUp={waffoTopUp}
|
waffoTopUp={waffoTopUp}
|
||||||
waffoPayMethods={waffoPayMethods}
|
waffoPayMethods={waffoPayMethods}
|
||||||
|
enableAlipayTopUp={enableAlipayTopUp}
|
||||||
|
enableWechatPayTopUp={enableWechatPayTopUp}
|
||||||
presetAmounts={presetAmounts}
|
presetAmounts={presetAmounts}
|
||||||
selectedPreset={selectedPreset}
|
selectedPreset={selectedPreset}
|
||||||
selectPresetAmount={selectPresetAmount}
|
selectPresetAmount={selectPresetAmount}
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,13 @@ const PaymentMethodSelectModal = ({
|
||||||
payMethods = [],
|
payMethods = [],
|
||||||
enableOnlineTopUp,
|
enableOnlineTopUp,
|
||||||
enableStripeTopUp,
|
enableStripeTopUp,
|
||||||
|
enableAlipayTopUp,
|
||||||
|
enableWechatPayTopUp,
|
||||||
onSelect,
|
onSelect,
|
||||||
paymentLoading,
|
paymentLoading,
|
||||||
payWay,
|
payWay,
|
||||||
}) => {
|
}) => {
|
||||||
const epayMethods = payMethods.filter((m) => m.type !== 'waffo');
|
const epayMethods = payMethods.filter((m) => m.type !== 'waffo' && m.type !== 'custom1');
|
||||||
|
|
||||||
const renderPayIcon = (payMethod) => {
|
const renderPayIcon = (payMethod) => {
|
||||||
if (payMethod.type === 'alipay') {
|
if (payMethod.type === 'alipay') {
|
||||||
|
|
@ -61,9 +63,13 @@ const PaymentMethodSelectModal = ({
|
||||||
{epayMethods.map((payMethod) => {
|
{epayMethods.map((payMethod) => {
|
||||||
const minTopupVal = Number(payMethod.min_topup) || 0;
|
const minTopupVal = Number(payMethod.min_topup) || 0;
|
||||||
const isStripe = payMethod.type === 'stripe';
|
const isStripe = payMethod.type === 'stripe';
|
||||||
|
const isAlipay = payMethod.type === 'alipay';
|
||||||
|
const isWechat = payMethod.type === 'wxpay';
|
||||||
const disabled =
|
const disabled =
|
||||||
(!enableOnlineTopUp && !isStripe) ||
|
(!enableOnlineTopUp && !isStripe && !isAlipay && !isWechat) ||
|
||||||
(!enableStripeTopUp && isStripe) ||
|
(!enableStripeTopUp && isStripe) ||
|
||||||
|
(!enableAlipayTopUp && isAlipay) ||
|
||||||
|
(!enableWechatPayTopUp && isWechat) ||
|
||||||
minTopupVal > Number(topUpCount || 0);
|
minTopupVal > Number(topUpCount || 0);
|
||||||
|
|
||||||
const buttonEl = (
|
const buttonEl = (
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useCallback, useLayoutEffect, useRef, useState } from 'react';
|
import React, { useCallback, useLayoutEffect, useRef, useState } from 'react';
|
||||||
import { Button, Form, Row, Col, Typography, Spin, TextArea } from '@douyinfe/semi-ui';
|
import { Button, Form, Row, Col, Typography, Spin, TextArea, Checkbox } from '@douyinfe/semi-ui';
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
import {
|
import {
|
||||||
API,
|
API,
|
||||||
|
|
@ -67,6 +67,12 @@ function getDefaultYipayReturnHint(serverAddress) {
|
||||||
*/
|
*/
|
||||||
function normalizeOnlinePayProvider(provider) {
|
function normalizeOnlinePayProvider(provider) {
|
||||||
const value = (provider || '').toLowerCase();
|
const value = (provider || '').toLowerCase();
|
||||||
|
if (value === 'alipay') {
|
||||||
|
return 'alipay';
|
||||||
|
}
|
||||||
|
if (value === 'wechatpay' || value === 'wxpay') {
|
||||||
|
return 'wechatpay';
|
||||||
|
}
|
||||||
if (value === 'yipay' || value === 'jeepay') {
|
if (value === 'yipay' || value === 'jeepay') {
|
||||||
return 'yipay';
|
return 'yipay';
|
||||||
}
|
}
|
||||||
|
|
@ -96,6 +102,16 @@ function buildFormModelFromOptions(opts) {
|
||||||
YipayReturnUrl: opts.YipayReturnUrl || '',
|
YipayReturnUrl: opts.YipayReturnUrl || '',
|
||||||
YipayChannelExtra: String(opts.YipayChannelExtra ?? ''),
|
YipayChannelExtra: String(opts.YipayChannelExtra ?? ''),
|
||||||
YipayRequestURL: yipayReq,
|
YipayRequestURL: yipayReq,
|
||||||
|
AlipayEnabled: opts.AlipayEnabled === true || opts.AlipayEnabled === 'true',
|
||||||
|
AlipayAppId: opts.AlipayAppId || '',
|
||||||
|
AlipayPrivateKey: opts.AlipayPrivateKey || '',
|
||||||
|
AlipayPublicKey: opts.AlipayPublicKey || '',
|
||||||
|
WechatPayEnabled: opts.WechatPayEnabled === true || opts.WechatPayEnabled === 'true',
|
||||||
|
WechatPayAppId: opts.WechatPayAppId || '',
|
||||||
|
WechatPayMchId: opts.WechatPayMchId || '',
|
||||||
|
WechatPayApiV3Key: opts.WechatPayApiV3Key || '',
|
||||||
|
EpayEnabled: opts.EpayEnabled === true || opts.EpayEnabled === 'true',
|
||||||
|
YipayEnabled: opts.YipayEnabled === true || opts.YipayEnabled === 'true',
|
||||||
Price: opts.Price !== undefined ? parseFloat(String(opts.Price)) : 7.3,
|
Price: opts.Price !== undefined ? parseFloat(String(opts.Price)) : 7.3,
|
||||||
MinTopUp:
|
MinTopUp:
|
||||||
opts.MinTopUp !== undefined ? parseFloat(String(opts.MinTopUp)) : 1,
|
opts.MinTopUp !== undefined ? parseFloat(String(opts.MinTopUp)) : 1,
|
||||||
|
|
@ -149,6 +165,16 @@ export default function SettingsPaymentGateway(props) {
|
||||||
YipayReturnUrl: '',
|
YipayReturnUrl: '',
|
||||||
YipayChannelExtra: '',
|
YipayChannelExtra: '',
|
||||||
YipayRequestURL: '',
|
YipayRequestURL: '',
|
||||||
|
AlipayEnabled: false,
|
||||||
|
AlipayAppId: '',
|
||||||
|
AlipayPrivateKey: '',
|
||||||
|
AlipayPublicKey: '',
|
||||||
|
WechatPayEnabled: false,
|
||||||
|
WechatPayAppId: '',
|
||||||
|
WechatPayMchId: '',
|
||||||
|
WechatPayApiV3Key: '',
|
||||||
|
EpayEnabled: false,
|
||||||
|
YipayEnabled: false,
|
||||||
Price: 7.3,
|
Price: 7.3,
|
||||||
MinTopUp: 1,
|
MinTopUp: 1,
|
||||||
TopupGroupRatio: '',
|
TopupGroupRatio: '',
|
||||||
|
|
@ -289,6 +315,26 @@ export default function SettingsPaymentGateway(props) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentProvider === 'alipay') {
|
||||||
|
if (!inputs.AlipayAppId?.trim()) {
|
||||||
|
showError(t('支付宝模式下必须填写应用ID'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!inputs.AlipayPrivateKey?.trim()) {
|
||||||
|
showError(t('支付宝模式下必须填写私钥'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentProvider === 'wechatpay') {
|
||||||
|
if (!inputs.WechatPayAppId?.trim()) {
|
||||||
|
showError(t('微信支付模式下必须填写应用ID'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!inputs.WechatPayMchId?.trim()) {
|
||||||
|
showError(t('微信支付模式下必须填写商户号'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (currentProvider === 'yipay') {
|
if (currentProvider === 'yipay') {
|
||||||
if (!inputs.YipayMchNo?.trim()) {
|
if (!inputs.YipayMchNo?.trim()) {
|
||||||
showError(t('Yipay 模式下必须填写商户号'));
|
showError(t('Yipay 模式下必须填写商户号'));
|
||||||
|
|
@ -328,50 +374,62 @@ export default function SettingsPaymentGateway(props) {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (currentProvider === 'epay') {
|
// Alipay options
|
||||||
options.push({
|
options.push({ key: 'AlipayEnabled', value: inputs.AlipayEnabled ? 'true' : 'false' });
|
||||||
|
options.push({ key: 'AlipayAppId', value: inputs.AlipayAppId?.trim() || '' });
|
||||||
|
options.push({ key: 'AlipayPrivateKey', value: inputs.AlipayPrivateKey || '' });
|
||||||
|
options.push({ key: 'AlipayPublicKey', value: inputs.AlipayPublicKey?.trim() || '' });
|
||||||
|
|
||||||
|
// Epay/Yipay options
|
||||||
|
options.push({ key: 'EpayEnabled', value: inputs.EpayEnabled ? 'true' : 'false' });
|
||||||
|
options.push({ key: 'YipayEnabled', value: inputs.YipayEnabled ? 'true' : 'false' });
|
||||||
|
|
||||||
|
// WeChat Pay options
|
||||||
|
options.push({ key: 'WechatPayEnabled', value: inputs.WechatPayEnabled ? 'true' : 'false' });
|
||||||
|
options.push({ key: 'WechatPayAppId', value: inputs.WechatPayAppId?.trim() || '' });
|
||||||
|
options.push({ key: 'WechatPayMchId', value: inputs.WechatPayMchId?.trim() || '' });
|
||||||
|
options.push({ key: 'WechatPayApiV3Key', value: inputs.WechatPayApiV3Key || '' });
|
||||||
|
|
||||||
|
options.push({
|
||||||
key: 'PayAddress',
|
key: 'PayAddress',
|
||||||
value: removeTrailingSlash(inputs.PayAddress || ''),
|
value: removeTrailingSlash(inputs.PayAddress || ''),
|
||||||
});
|
});
|
||||||
}
|
|
||||||
if (currentProvider === 'yipay') {
|
|
||||||
const gatewayBase = removeTrailingSlash(
|
const gatewayBase = removeTrailingSlash(
|
||||||
(inputs.YipayRequestURL || '').trim(),
|
(inputs.YipayRequestURL || '').trim(),
|
||||||
);
|
);
|
||||||
options.push({ key: 'YipayRequestURL', value: gatewayBase });
|
options.push({ key: 'YipayRequestURL', value: gatewayBase });
|
||||||
options.push({ key: 'PayAddress', value: gatewayBase });
|
options.push({ key: 'PayAddress', value: gatewayBase });
|
||||||
}
|
|
||||||
|
|
||||||
if (currentProvider === 'epay' && inputs.EpayId !== '') {
|
|
||||||
|
if (inputs.EpayId !== '') {
|
||||||
options.push({ key: 'EpayId', value: inputs.EpayId });
|
options.push({ key: 'EpayId', value: inputs.EpayId });
|
||||||
}
|
}
|
||||||
if (currentProvider === 'yipay' && inputs.YipayMchNo !== '') {
|
if (inputs.YipayMchNo !== '') {
|
||||||
options.push({ key: 'YipayMchNo', value: inputs.YipayMchNo.trim() });
|
options.push({ key: 'YipayMchNo', value: inputs.YipayMchNo.trim() });
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
currentProvider === 'epay' &&
|
|
||||||
inputs.EpayKey !== undefined &&
|
inputs.EpayKey !== undefined &&
|
||||||
inputs.EpayKey !== ''
|
inputs.EpayKey !== ''
|
||||||
) {
|
) {
|
||||||
options.push({ key: 'EpayKey', value: inputs.EpayKey });
|
options.push({ key: 'EpayKey', value: inputs.EpayKey });
|
||||||
}
|
}
|
||||||
if (currentProvider === 'yipay' && inputs.YipayAppId !== '') {
|
if (inputs.YipayAppId !== '') {
|
||||||
options.push({ key: 'YipayAppId', value: inputs.YipayAppId.trim() });
|
options.push({ key: 'YipayAppId', value: inputs.YipayAppId.trim() });
|
||||||
}
|
}
|
||||||
if (currentProvider === 'yipay' && inputs.YipayNotifyUrl !== '') {
|
if (inputs.YipayNotifyUrl !== '') {
|
||||||
options.push({
|
options.push({
|
||||||
key: 'YipayNotifyUrl',
|
key: 'YipayNotifyUrl',
|
||||||
value: inputs.YipayNotifyUrl.trim(),
|
value: inputs.YipayNotifyUrl.trim(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (currentProvider === 'yipay' && inputs.YipayReturnUrl !== '') {
|
if (inputs.YipayReturnUrl !== '') {
|
||||||
options.push({
|
options.push({
|
||||||
key: 'YipayReturnUrl',
|
key: 'YipayReturnUrl',
|
||||||
value: inputs.YipayReturnUrl.trim(),
|
value: inputs.YipayReturnUrl.trim(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
currentProvider === 'yipay' &&
|
|
||||||
(inputs.YipayChannelExtra ?? '').trim() !==
|
(inputs.YipayChannelExtra ?? '').trim() !==
|
||||||
(originInputs.YipayChannelExtra ?? '').trim()
|
(originInputs.YipayChannelExtra ?? '').trim()
|
||||||
) {
|
) {
|
||||||
|
|
@ -381,7 +439,6 @@ export default function SettingsPaymentGateway(props) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
currentProvider === 'yipay' &&
|
|
||||||
inputs.YipayAppSecret !== undefined &&
|
inputs.YipayAppSecret !== undefined &&
|
||||||
inputs.YipayAppSecret.trim() !== '' &&
|
inputs.YipayAppSecret.trim() !== '' &&
|
||||||
inputs.YipayAppSecret !== originInputs.YipayAppSecret
|
inputs.YipayAppSecret !== originInputs.YipayAppSecret
|
||||||
|
|
@ -459,198 +516,161 @@ export default function SettingsPaymentGateway(props) {
|
||||||
>
|
>
|
||||||
<Form.Section text={t('支付设置')}>
|
<Form.Section text={t('支付设置')}>
|
||||||
<Text>
|
<Text>
|
||||||
{t(
|
{t('支持支付宝、微信支付、易支付 / Yipay 等在线支付渠道配置')}
|
||||||
'(当前支持易支付/Yipay 配置,默认使用上方服务器地址作为回调地址!)',
|
|
||||||
)}
|
|
||||||
</Text>
|
</Text>
|
||||||
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}>
|
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}>
|
||||||
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
<Form.Select
|
<Form.Select
|
||||||
field='OnlinePayProvider'
|
field="OnlinePayProvider"
|
||||||
label={t('在线支付通道')}
|
label={t('在线支付通道')}
|
||||||
optionList={[
|
optionList={[
|
||||||
|
{ label: t('支付宝'), value: 'alipay' },
|
||||||
|
{ label: t('微信支付'), value: 'wechatpay' },
|
||||||
{ label: t('易支付'), value: 'epay' },
|
{ label: t('易支付'), value: 'epay' },
|
||||||
{ label: t('Yipay'), value: 'yipay' },
|
{ label: t('Yipay'), value: 'yipay' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col
|
<Col
|
||||||
xs={24}
|
xs={24} sm={24} md={8} lg={8} xl={8}
|
||||||
sm={24}
|
|
||||||
md={8}
|
|
||||||
lg={8}
|
|
||||||
xl={8}
|
|
||||||
style={{
|
style={{
|
||||||
display: currentProvider === 'epay' ? 'block' : 'none',
|
display: currentProvider === 'alipay' ? 'flex' : 'none',
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingTop: 30,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<Checkbox
|
||||||
|
checked={inputs.AlipayEnabled}
|
||||||
|
onChange={(e) => { const val = e.target.checked; setInputs((prev) => ({ ...prev, AlipayEnabled: val })); }}
|
||||||
|
>
|
||||||
|
{t('启用支付宝支付')}
|
||||||
|
</Checkbox>
|
||||||
|
</Col>
|
||||||
|
<Col
|
||||||
|
xs={24} sm={24} md={8} lg={8} xl={8}
|
||||||
|
style={{
|
||||||
|
display: currentProvider === 'wechatpay' ? 'flex' : 'none',
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingTop: 30,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
checked={inputs.WechatPayEnabled}
|
||||||
|
onChange={(e) => { const val = e.target.checked; setInputs((prev) => ({ ...prev, WechatPayEnabled: val })); }}
|
||||||
|
>
|
||||||
|
{t('启用微信支付')}
|
||||||
|
</Checkbox>
|
||||||
|
</Col>
|
||||||
|
</Row><Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}>
|
||||||
|
|
||||||
|
<Col
|
||||||
|
xs={24} sm={24} md={8} lg={8} xl={8}
|
||||||
|
style={{
|
||||||
|
display: currentProvider === 'epay' ? 'flex' : 'none',
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingTop: 30,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
checked={inputs.EpayEnabled}
|
||||||
|
onChange={(e) => { const val = e.target.checked; setInputs((prev) => ({ ...prev, EpayEnabled: val })); }}
|
||||||
|
>
|
||||||
|
{t('启用易支付')}
|
||||||
|
</Checkbox>
|
||||||
|
</Col>
|
||||||
|
<Col
|
||||||
|
xs={24} sm={24} md={8} lg={8} xl={8}
|
||||||
|
style={{
|
||||||
|
display: currentProvider === 'yipay' ? 'flex' : 'none',
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingTop: 30,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
checked={inputs.YipayEnabled}
|
||||||
|
onChange={(e) => { const val = e.target.checked; setInputs((prev) => ({ ...prev, YipayEnabled: val })); }}
|
||||||
|
>
|
||||||
|
{t('启用 Yipay')}
|
||||||
|
</Checkbox>
|
||||||
|
</Col>
|
||||||
|
</Row><Row
|
||||||
|
gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}
|
||||||
|
style={{ marginTop: 8, display: currentProvider === 'alipay' ? 'flex' : 'none' }}
|
||||||
|
>
|
||||||
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
|
<Form.Input field="AlipayAppId" label={t('支付宝应用ID')} placeholder={t('请填写支付宝应用ID')} />
|
||||||
|
</Col>
|
||||||
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
|
<Form.Input field="AlipayPrivateKey" label={t('支付宝私钥')} placeholder={t('请填写支付宝私钥')} type="password" />
|
||||||
|
</Col>
|
||||||
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
|
<Form.Input field="AlipayPublicKey" label={t('支付宝公钥')} placeholder={t('请填写支付宝公钥')} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row
|
||||||
|
gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}
|
||||||
|
style={{ marginTop: 8, display: currentProvider === 'wechatpay' ? 'flex' : 'none' }}
|
||||||
|
>
|
||||||
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
|
<Form.Input field="WechatPayAppId" label={t('微信支付应用ID')} placeholder={t('请填写微信支付应用ID')} />
|
||||||
|
</Col>
|
||||||
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
|
<Form.Input field="WechatPayMchId" label={t('微信支付商户号')} placeholder={t('请填写微信支付商户号')} />
|
||||||
|
</Col>
|
||||||
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
|
<Form.Input field="WechatPayApiV3Key" label={t('微信支付 API V3 密钥')} placeholder={t('请填写 API V3 密钥')} type="password" />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row
|
||||||
|
gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}
|
||||||
|
style={{ marginTop: 8, display: currentProvider === 'epay' ? 'flex' : 'none' }}
|
||||||
|
>
|
||||||
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
|
<Form.Input field="PayAddress" label={t('支付地址')} placeholder={t('例如:https://yourdomain.com')} />
|
||||||
|
</Col>
|
||||||
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
|
<Form.Input field="EpayId" label={t('易支付商户号')} placeholder={t('例如:0001')} />
|
||||||
|
</Col>
|
||||||
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
|
<Form.Input field="EpayKey" label={t('易支付商户密钥')} placeholder={t('敏感信息不会发送到前端显示')} type="password" />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row
|
||||||
|
gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}
|
||||||
|
style={{ marginTop: 8, display: currentProvider === 'yipay' ? 'flex' : 'none' }}
|
||||||
|
>
|
||||||
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
<Form.Input
|
<Form.Input
|
||||||
field='PayAddress'
|
field="YipayRequestURL"
|
||||||
label={t('支付地址')}
|
label={t('支付地址')}
|
||||||
placeholder={t('例如:https://yourdomain.com')}
|
placeholder={t('例如:https://pay.xxx.com(与易支付网关根地址相同)')}
|
||||||
|
extraText={t('对应配置项 YipayRequestURL;保存时会同步写入 PayAddress,供服务端与易支付字段兼容。')}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
xs={24}
|
<Form.Input field="YipayMchNo" label={t('Yipay 商户号(可选覆盖)')} placeholder={t('例如:M1691xxxx')} />
|
||||||
sm={24}
|
|
||||||
md={8}
|
|
||||||
lg={8}
|
|
||||||
xl={8}
|
|
||||||
style={{
|
|
||||||
display: currentProvider === 'yipay' ? 'block' : 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Form.Input
|
|
||||||
field='YipayRequestURL'
|
|
||||||
label={t('支付地址')}
|
|
||||||
placeholder={t(
|
|
||||||
'例如:https://pay.xxx.com(与易支付网关根地址相同)',
|
|
||||||
)}
|
|
||||||
extraText={t(
|
|
||||||
'对应配置项 YipayRequestURL;保存时会同步写入 PayAddress,供服务端与易支付字段兼容。',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Col>
|
</Col>
|
||||||
<Col
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
xs={24}
|
<Form.Input field="YipayAppId" label={t('Yipay 应用ID')} placeholder={t('例如:62b2f8f6xxxxxx')} />
|
||||||
sm={24}
|
|
||||||
md={8}
|
|
||||||
lg={8}
|
|
||||||
xl={8}
|
|
||||||
style={{
|
|
||||||
display: currentProvider === 'epay' ? 'block' : 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Form.Input
|
|
||||||
field='EpayId'
|
|
||||||
label={t('易支付商户号')}
|
|
||||||
placeholder={t('例如:0001')}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
<Col
|
|
||||||
xs={24}
|
|
||||||
sm={24}
|
|
||||||
md={8}
|
|
||||||
lg={8}
|
|
||||||
xl={8}
|
|
||||||
style={{
|
|
||||||
display: currentProvider === 'epay' ? 'block' : 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Form.Input
|
|
||||||
field='EpayKey'
|
|
||||||
label={t('易支付商户密钥')}
|
|
||||||
placeholder={t('敏感信息不会发送到前端显示')}
|
|
||||||
type='password'
|
|
||||||
/>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row
|
<Row
|
||||||
gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}
|
gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}
|
||||||
style={{
|
style={{ marginTop: 16, display: currentProvider === 'yipay' ? 'flex' : 'none' }}
|
||||||
marginTop: 16,
|
|
||||||
display: currentProvider === 'yipay' ? 'flex' : 'none',
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
<Form.Input
|
<Form.Input field="YipayAppSecret" label={t('Yipay AppSecret')} placeholder={t('用于 MD5 签名的密钥(后端脱敏回显;修改后保存才会更新)')} autoComplete="off" />
|
||||||
field='YipayMchNo'
|
|
||||||
label={t('Yipay 商户号(可选覆盖)')}
|
|
||||||
placeholder={t('例如:M1691xxxx')}
|
|
||||||
/>
|
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
<Form.Input
|
<Form.Input field="YipayNotifyUrl" label={t('Yipay 异步通知地址')} placeholder={t('可留空,留空则使用下方"回调地址"或服务器地址拼接默认路径')} />
|
||||||
field='YipayAppId'
|
|
||||||
label={t('Yipay 应用ID')}
|
|
||||||
placeholder={t('例如:62b2f8f6xxxxxx')}
|
|
||||||
/>
|
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
<Form.Input
|
<Form.Input field="YipayReturnUrl" label={t('Yipay 同步通知地址')} placeholder={t('例如:https://yourdomain.com/console/log')} />
|
||||||
field='YipayAppSecret'
|
|
||||||
label={t('Yipay AppSecret')}
|
|
||||||
placeholder={t(
|
|
||||||
'用于 MD5 签名的密钥(后端脱敏回显;修改后保存才会更新)',
|
|
||||||
)}
|
|
||||||
autoComplete='off'
|
|
||||||
/>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row
|
<Row
|
||||||
gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}
|
gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}
|
||||||
style={{ marginTop: 16 }}
|
style={{ marginTop: 8, display: currentProvider === 'yipay' ? 'flex' : 'none' }}
|
||||||
>
|
|
||||||
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
|
||||||
<Form.Input
|
|
||||||
field='CustomCallbackAddress'
|
|
||||||
label={t('回调地址')}
|
|
||||||
placeholder={t('例如:https://yourdomain.com')}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
|
||||||
<Form.InputNumber
|
|
||||||
field='Price'
|
|
||||||
precision={2}
|
|
||||||
label={t('充值价格(x元/美金)')}
|
|
||||||
placeholder={t('例如:7,就是7元/美金')}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
|
||||||
<Form.InputNumber
|
|
||||||
field='MinTopUp'
|
|
||||||
label={t('最低充值美元数量')}
|
|
||||||
placeholder={t('例如:2,就是最低充值2$')}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row
|
|
||||||
gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}
|
|
||||||
style={{
|
|
||||||
marginTop: 16,
|
|
||||||
display: currentProvider === 'yipay' ? 'flex' : 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
|
||||||
<Form.Input
|
|
||||||
field='YipayNotifyUrl'
|
|
||||||
label={t('Yipay 异步通知地址')}
|
|
||||||
placeholder={t(
|
|
||||||
'可留空,留空则使用下方「回调地址」或服务器地址拼接默认路径',
|
|
||||||
)}
|
|
||||||
extraText={(() => {
|
|
||||||
const hint = getDefaultYipayNotifyHint(
|
|
||||||
props.options.ServerAddress,
|
|
||||||
props.options.CustomCallbackAddress,
|
|
||||||
);
|
|
||||||
return hint
|
|
||||||
? `默认:${hint}(留空时与后端异步通知规则一致)`
|
|
||||||
: '请先配置「服务器地址」或「回调地址」以预览默认异步通知 URL';
|
|
||||||
})()}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
|
||||||
<Form.Input
|
|
||||||
field='YipayReturnUrl'
|
|
||||||
label={t('Yipay 同步通知地址')}
|
|
||||||
placeholder={t('例如:https://yourdomain.com/console/log')}
|
|
||||||
extraText={(() => {
|
|
||||||
const hint = getDefaultYipayReturnHint(
|
|
||||||
props.options.ServerAddress,
|
|
||||||
);
|
|
||||||
return hint
|
|
||||||
? `默认:${hint}(留空时使用)`
|
|
||||||
: '请先配置「服务器地址」以预览默认同步跳转 URL';
|
|
||||||
})()}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row
|
|
||||||
gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}
|
|
||||||
style={{
|
|
||||||
marginTop: 8,
|
|
||||||
display: currentProvider === 'yipay' ? 'flex' : 'none',
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<div style={{ marginBottom: 8 }}>
|
<div style={{ marginBottom: 8 }}>
|
||||||
|
|
@ -659,77 +679,39 @@ export default function SettingsPaymentGateway(props) {
|
||||||
<TextArea
|
<TextArea
|
||||||
value={inputs.YipayChannelExtra}
|
value={inputs.YipayChannelExtra}
|
||||||
onChange={handleYipayChannelExtraChange}
|
onChange={handleYipayChannelExtraChange}
|
||||||
placeholder={'{"payDataType":"payUrl"}'}
|
placeholder='{"payDataType":"payUrl"}'
|
||||||
rows={1}
|
rows={1}
|
||||||
autoComplete='off'
|
autoComplete="off"
|
||||||
style={{
|
style={{ width: "100%", fontFamily: "monospace", fontSize: 12 }}
|
||||||
width: '100%',
|
|
||||||
fontFamily: 'monospace',
|
|
||||||
fontSize: 12,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<Text
|
<Text type="tertiary" size="small" style={{ marginTop: 8, display: "block" }}>
|
||||||
type='tertiary'
|
{t('可选。Jeepay channelExtra(JSON)。留空时:一般 _PC 会附带 payDataType=payUrl;PP_PC 会附带 payDataType 与 cancelUrl(与 returnUrl 同源,见 yiPay PPPcOrderRQ)。可在此覆盖 cancelUrl 等。')}
|
||||||
size='small'
|
|
||||||
style={{ marginTop: 8, display: 'block' }}
|
|
||||||
>
|
|
||||||
{t(
|
|
||||||
'可选。Jeepay channelExtra(JSON)。留空时:一般 _PC 会附带 payDataType=payUrl;PP_PC 会附带 payDataType 与 cancelUrl(与 returnUrl 同源,见 yiPay PPPcOrderRQ)。可在此覆盖 cancelUrl 等。',
|
|
||||||
)}
|
|
||||||
</Text>
|
</Text>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Form.TextArea
|
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }} style={{ marginTop: 8 }}>
|
||||||
field='TopupGroupRatio'
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
label={t('充值分组倍率')}
|
<Form.Input field="CustomCallbackAddress" label={t('回调地址')} placeholder={t('例如:https://yourdomain.com')} />
|
||||||
placeholder={t('为一个 JSON 文本,键为组名称,值为倍率')}
|
</Col>
|
||||||
autosize
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
/>
|
<Form.InputNumber field="Price" precision={2} label={t('充值价格(x元/美金)')} placeholder={t('例如:7,就是7元/美金')} />
|
||||||
<Form.TextArea
|
</Col>
|
||||||
field='PayMethods'
|
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
|
||||||
label={t('充值方式设置')}
|
<Form.InputNumber field="MinTopUp" label={t('最低充值美元数量')} placeholder={t('例如:2,就是最低充值2$')} />
|
||||||
placeholder={t('为一个 JSON 文本')}
|
|
||||||
autosize
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Row
|
|
||||||
gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}
|
|
||||||
style={{ marginTop: 16 }}
|
|
||||||
>
|
|
||||||
<Col span={24}>
|
|
||||||
<Form.TextArea
|
|
||||||
field='AmountOptions'
|
|
||||||
label={t('自定义充值数量选项')}
|
|
||||||
placeholder={t(
|
|
||||||
'为一个 JSON 数组,例如:[10, 20, 50, 100, 200, 500]',
|
|
||||||
)}
|
|
||||||
autosize
|
|
||||||
extraText={t(
|
|
||||||
'设置用户可选择的充值数量选项,例如:[10, 20, 50, 100, 200, 500]',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Form.TextArea field="TopupGroupRatio" label={t('充值分组倍率')} placeholder={t('为一个 JSON 文本,键为组名称,值为倍率')} autosize />
|
||||||
<Row
|
<Form.TextArea field="PayMethods" label={t('充值方式设置')} placeholder={t('为一个 JSON 文本')} autosize />
|
||||||
gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }}
|
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }} style={{ marginTop: 16 }}>
|
||||||
style={{ marginTop: 16 }}
|
|
||||||
>
|
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Form.TextArea
|
<Form.TextArea field="AmountOptions" label={t('自定义充值数量选项')} placeholder={t('为一个 JSON 数组,例如:[10, 20, 50, 100, 200, 500]')} autosize extraText={t('设置用户可选择的充值数量选项,例如:[10, 20, 50, 100, 200, 500]')} />
|
||||||
field='AmountDiscount'
|
</Col>
|
||||||
label={t('充值金额折扣配置')}
|
</Row>
|
||||||
placeholder={t(
|
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24, xl: 24, xxl: 24 }} style={{ marginTop: 16 }}>
|
||||||
'为一个 JSON 对象,例如:{"100": 0.95, "200": 0.9, "500": 0.85}',
|
<Col span={24}>
|
||||||
)}
|
<Form.TextArea field="AmountDiscount" label={t('充值金额折扣配置')} placeholder={t('为一个 JSON 对象,例如:{"100": 0.95, "200": 0.9, "500": 0.85}')} autosize extraText={t('设置不同充值金额对应的折扣,键为充值金额,值为折扣率,例如:{"100": 0.95, "200": 0.9, "500": 0.85}')} />
|
||||||
autosize
|
|
||||||
extraText={t(
|
|
||||||
'设置不同充值金额对应的折扣,键为充值金额,值为折扣率,例如:{"100": 0.95, "200": 0.9, "500": 0.85}',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Button onClick={submitPayAddress}>{t('更新支付设置')}</Button>
|
<Button onClick={submitPayAddress}>{t('更新支付设置')}</Button>
|
||||||
</Form.Section>
|
</Form.Section>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue