Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
34c94220
authored
Jul 10, 2025
by
wzxjohn
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: add stripe topup page
parent
8e6660cf
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
220 additions
and
2 deletions
+220
-2
controller/topup_stripe.go
+0
-1
web/src/pages/TopUp/index.js
+220
-1
No files found.
controller/topup_stripe.go
View file @
34c94220
...
...
@@ -28,7 +28,6 @@ var stripeAdaptor = &StripeAdaptor{}
type
StripePayRequest
struct
{
Amount
int64
`json:"amount"`
PaymentMethod
string
`json:"payment_method"`
TopUpCode
string
`json:"top_up_code"`
}
type
StripeAdaptor
struct
{
...
...
web/src/pages/TopUp/index.js
View file @
34c94220
...
...
@@ -59,6 +59,13 @@ const TopUp = () => {
statusState
?.
status
?.
enable_online_topup
||
false
,
);
const
[
priceRatio
,
setPriceRatio
]
=
useState
(
statusState
?.
status
?.
price
||
1
);
const
[
stripeAmount
,
setStripeAmount
]
=
useState
(
0.0
);
const
[
stripeMinTopUp
,
setStripeMinTopUp
]
=
useState
(
statusState
?.
status
?.
stripe_min_topup
||
1
);
const
[
stripeTopUpCount
,
setStripeTopUpCount
]
=
useState
(
statusState
?.
status
?.
stripe_min_topup
||
1
);
const
[
enableStripeTopUp
,
setEnableStripeTopUp
]
=
useState
(
statusState
?.
status
?.
enable_stripe_topup
||
false
);
const
[
stripeOpen
,
setStripeOpen
]
=
useState
(
false
);
const
[
userQuota
,
setUserQuota
]
=
useState
(
0
);
const
[
isSubmitting
,
setIsSubmitting
]
=
useState
(
false
);
const
[
open
,
setOpen
]
=
useState
(
false
);
...
...
@@ -231,6 +238,65 @@ const TopUp = () => {
}
};
const
stripePreTopUp
=
async
()
=>
{
if
(
!
enableStripeTopUp
)
{
showError
(
t
(
'管理员未开启在线充值!'
));
return
;
}
setPayWay
(
'stripe'
)
setPaymentLoading
(
true
);
try
{
await
getStripeAmount
();
if
(
stripeTopUpCount
<
stripeMinTopUp
)
{
showError
(
t
(
'充值数量不能小于'
)
+
stripeMinTopUp
);
return
;
}
setStripeOpen
(
true
);
}
catch
(
error
)
{
showError
(
t
(
'获取金额失败'
));
}
finally
{
setPayWay
(
''
)
setPaymentLoading
(
false
);
}
};
const
onlineStripeTopUp
=
async
()
=>
{
if
(
stripeAmount
===
0
)
{
await
getStripeAmount
();
}
if
(
stripeTopUpCount
<
stripeMinTopUp
)
{
showError
(
t
(
'充值数量不能小于'
)
+
stripeMinTopUp
);
return
;
}
setConfirmLoading
(
true
);
try
{
const
res
=
await
API
.
post
(
'/api/user/stripe/pay'
,
{
amount
:
parseInt
(
stripeTopUpCount
),
payment_method
:
'stripe'
,
});
if
(
res
!==
undefined
)
{
const
{
message
,
data
}
=
res
.
data
;
if
(
message
===
'success'
)
{
processStripeCallback
(
data
)
}
else
{
showError
(
data
);
}
}
else
{
showError
(
res
);
}
}
catch
(
err
)
{
console
.
log
(
err
);
showError
(
t
(
'支付请求失败'
));
}
finally
{
setStripeOpen
(
false
);
setConfirmLoading
(
false
);
}
}
const
processStripeCallback
=
(
data
)
=>
{
location
.
href
=
data
.
pay_link
;
};
const
getUserQuota
=
async
()
=>
{
setUserDataLoading
(
true
);
let
res
=
await
API
.
get
(
`/api/user/self`
);
...
...
@@ -327,6 +393,10 @@ const TopUp = () => {
setTopUpLink
(
statusState
.
status
.
top_up_link
||
''
);
setEnableOnlineTopUp
(
statusState
.
status
.
enable_online_topup
||
false
);
setPriceRatio
(
statusState
.
status
.
price
||
1
);
setStripeMinTopUp
(
statusState
.
status
.
stripe_min_topup
||
1
);
setStripeTopUpCount
(
statusState
.
status
.
stripe_min_topup
||
1
);
setEnableStripeTopUp
(
statusState
.
status
.
enable_stripe_topup
||
false
);
}
},
[
statusState
?.
status
]);
...
...
@@ -334,6 +404,10 @@ const TopUp = () => {
return
amount
+
' '
+
t
(
'元'
);
};
const
renderStripeAmount
=
()
=>
{
return
stripeAmount
+
' '
+
t
(
'元'
);
};
const
getAmount
=
async
(
value
)
=>
{
if
(
value
===
undefined
)
{
value
=
topUpCount
;
...
...
@@ -361,10 +435,40 @@ const TopUp = () => {
setAmountLoading
(
false
);
};
const
getStripeAmount
=
async
(
value
)
=>
{
if
(
value
===
undefined
)
{
value
=
stripeTopUpCount
}
try
{
const
res
=
await
API
.
post
(
'/api/user/stripe/amount'
,
{
amount
:
parseFloat
(
value
),
});
if
(
res
!==
undefined
)
{
const
{
message
,
data
}
=
res
.
data
;
// showInfo(message);
if
(
message
===
'success'
)
{
setStripeAmount
(
parseFloat
(
data
))
}
else
{
setStripeAmount
(
0
)
Toast
.
error
({
content
:
'错误:'
+
data
,
id
:
'getAmount'
});
}
}
else
{
showError
(
res
);
}
}
catch
(
err
)
{
console
.
log
(
err
);
}
finally
{
}
}
const
handleCancel
=
()
=>
{
setOpen
(
false
);
};
const
handleStripeCancel
=
()
=>
{
setStripeOpen
(
false
);
};
const
handleTransferCancel
=
()
=>
{
setOpenTransfer
(
false
);
};
...
...
@@ -374,6 +478,9 @@ const TopUp = () => {
setTopUpCount
(
preset
.
value
);
setSelectedPreset
(
preset
.
value
);
setAmount
(
preset
.
value
*
priceRatio
);
setStripeTopUpCount
(
preset
.
value
);
setStripeAmount
(
preset
.
value
);
};
// 格式化大数字显示
...
...
@@ -496,6 +603,25 @@ const TopUp = () => {
<
/div
>
<
/Modal
>
<
Modal
title
=
{
t
(
'确定要充值吗'
)}
visible
=
{
stripeOpen
}
onOk
=
{
onlineStripeTopUp
}
onCancel
=
{
handleStripeCancel
}
maskClosable
=
{
false
}
size
=
'small'
centered
confirmLoading
=
{
confirmLoading
}
>
<
p
>
{
t
(
'充值数量'
)}
:
{
stripeTopUpCount
}
<
/p
>
<
p
>
{
t
(
'实付金额'
)}
:
{
renderStripeAmount
()}
<
/p
>
<
p
>
{
t
(
'是否确认充值?'
)}
<
/p
>
<
/Modal
>
<
div
className
=
'grid grid-cols-1 lg:grid-cols-12 gap-6'
>
{
/* 左侧充值区域 */
}
<
div
className
=
'lg:col-span-7 space-y-6 w-full'
>
...
...
@@ -798,7 +924,7 @@ const TopUp = () => {
<
/
>
)}
{
!
enableOnlineTopUp
&&
(
{
!
enableOnlineTopUp
&&
!
enableStripeTopUp
&&
(
<
Banner
type
=
'warning'
description
=
{
t
(
...
...
@@ -809,6 +935,99 @@ const TopUp = () => {
/>
)}
{
enableStripeTopUp
&&
(
<>
{
/* 桌面端显示的自定义金额和支付按钮 */
}
<
div
className
=
'hidden md:block space-y-4'
>
{
!
enableOnlineTopUp
?(
<
Divider
style
=
{{
margin
:
'24px 0'
}}
>
<
Text
className
=
'text-sm font-medium'
>
{
t
(
'或输入自定义金额'
)}
<
/Text
>
<
/Divider
>
)
:
(
<
Divider
style
=
{{
margin
:
'24px 0'
}}
>
<
Text
className
=
'text-sm font-medium'
>
{
t
(
'Stripe'
)}
<
/Text
>
<
/Divider
>
)
}
<
div
>
<
div
className
=
'flex justify-between mb-2'
>
<
Text
strong
>
{
t
(
'充值数量'
)}
<
/Text
>
{
amountLoading
?
(
<
Skeleton
.
Title
style
=
{{
width
:
'80px'
,
height
:
'16px'
}}
/
>
)
:
(
<
Text
type
=
'tertiary'
>
{
t
(
'实付金额:'
)
+
renderStripeAmount
()}
<
/Text
>
)}
<
/div
>
<
InputNumber
disabled
=
{
!
enableOnlineTopUp
}
placeholder
=
{
t
(
'充值数量,最低 '
)
+
renderQuotaWithAmount
(
stripeMinTopUp
)
}
value
=
{
stripeTopUpCount
}
min
=
{
stripeMinTopUp
}
max
=
{
999999999
}
step
=
{
1
}
precision
=
{
0
}
onChange
=
{
async
(
value
)
=>
{
if
(
value
&&
value
>=
1
)
{
setStripeTopUpCount
(
value
);
setSelectedPreset
(
null
);
await
getStripeAmount
(
value
);
}
}}
onBlur
=
{(
e
)
=>
{
const
value
=
parseInt
(
e
.
target
.
value
);
if
(
!
value
||
value
<
1
)
{
setStripeTopUpCount
(
1
);
getStripeAmount
(
1
);
}
}}
size
=
'large'
className
=
'w-full'
formatter
=
{(
value
)
=>
(
value
?
`
${
value
}
`
:
''
)}
parser
=
{(
value
)
=>
value
?
parseInt
(
value
.
replace
(
/
[^\d]
/g
,
''
))
:
0
}
/
>
<
/div
>
<
div
>
<
Text
strong
className
=
'block mb-3'
>
{
t
(
'选择支付方式'
)}
<
/Text
>
<
div
className
=
'grid grid-cols-1 gap-3'
>
<
Button
key
=
'stripe'
type
=
'primary'
onClick
=
{()
=>
stripePreTopUp
()}
size
=
'large'
disabled
=
{
!
enableStripeTopUp
}
loading
=
{
paymentLoading
&&
payWay
===
'stripe'
}
icon
=
{
<
CreditCard
size
=
{
16
}
/>
}
style
=
{{
height
:
'40px'
,
color
:
'#b161fe'
,
}}
className
=
'transition-all hover:shadow-md w-full'
>
<
span
className
=
'ml-1'
>
Stripe
<
/span
>
<
/Button
>
<
/div
>
<
/div
>
<
/div
>
<
/
>
)}
<
Divider
style
=
{{
margin
:
'24px 0'
}}
>
<
Text
className
=
'text-sm font-medium'
>
{
t
(
'兑换码充值'
)}
<
/Text
>
<
/Divider
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment