diff --git a/common/topup-ratio.go b/common/topup-ratio.go new file mode 100644 index 00000000..e045d9b7 --- /dev/null +++ b/common/topup-ratio.go @@ -0,0 +1,31 @@ +package common + +import "encoding/json" + +var TopupGroupRatio = map[string]float64{ + "default": 1, + "vip": 1, + "svip": 1, +} + +func TopupGroupRatio2JSONString() string { + jsonBytes, err := json.Marshal(TopupGroupRatio) + if err != nil { + SysError("error marshalling model ratio: " + err.Error()) + } + return string(jsonBytes) +} + +func UpdateTopupGroupRatioByJSONString(jsonStr string) error { + TopupGroupRatio = make(map[string]float64) + return json.Unmarshal([]byte(jsonStr), &TopupGroupRatio) +} + +func GetTopupGroupRatio(name string) float64 { + ratio, ok := TopupGroupRatio[name] + if !ok { + SysError("topup group ratio not found: " + name) + return 1 + } + return ratio +} diff --git a/controller/topup.go b/controller/topup.go index 6fd0a223..5d945878 100644 --- a/controller/topup.go +++ b/controller/topup.go @@ -38,9 +38,13 @@ func GetEpayClient() *epay.Client { return withUrl } -func GetAmount(count float64) float64 { +func GetAmount(count float64, user model.User) float64 { // 别问为什么用float64,问就是这么点钱没必要 - amount := count * common.Price + topupGroupRatio := common.GetTopupGroupRatio(user.Group) + if topupGroupRatio == 0 { + topupGroupRatio = 1 + } + amount := count * common.Price * topupGroupRatio return amount } @@ -57,7 +61,8 @@ func RequestEpay(c *gin.Context) { } id := c.GetInt("id") - amount := GetAmount(float64(req.Amount)) + user, _ := model.GetUserById(id, false) + amount := GetAmount(float64(req.Amount), *user) if req.PaymentMethod == "zfb" { req.PaymentMethod = "alipay" @@ -148,7 +153,7 @@ func EpayNotify(c *gin.Context) { return } log.Printf("易支付回调更新用户成功 %v", topUp) - model.RecordLog(topUp.UserId, model.LogTypeTopup, fmt.Sprintf("使用在线充值成功,充值金额: %v", common.LogQuota(topUp.Amount*500000))) + model.RecordLog(topUp.UserId, model.LogTypeTopup, fmt.Sprintf("使用在线充值成功,充值金额: %v,支付金额:%d", common.LogQuota(topUp.Amount*500000), topUp.Money)) } } else { log.Printf("易支付异常回调: %v", verifyInfo) @@ -166,6 +171,7 @@ func RequestAmount(c *gin.Context) { c.JSON(200, gin.H{"message": "error", "data": "充值金额不能小于1"}) return } - - c.JSON(200, gin.H{"message": "success", "data": GetAmount(float64(req.Amount))}) + id := c.GetInt("id") + user, _ := model.GetUserById(id, false) + c.JSON(200, gin.H{"message": "success", "data": GetAmount(float64(req.Amount), *user)}) } diff --git a/model/option.go b/model/option.go index 84841e08..a56ab4a5 100644 --- a/model/option.go +++ b/model/option.go @@ -57,6 +57,7 @@ func InitOptionMap() { common.OptionMap["EpayId"] = "" common.OptionMap["EpayKey"] = "" common.OptionMap["Price"] = strconv.FormatFloat(common.Price, 'f', -1, 64) + common.OptionMap["TopupGroupRatio"] = common.TopupGroupRatio2JSONString() common.OptionMap["GitHubClientId"] = "" common.OptionMap["GitHubClientSecret"] = "" common.OptionMap["WeChatServerAddress"] = "" @@ -184,6 +185,8 @@ func updateOptionMap(key string, value string) (err error) { common.EpayKey = value case "Price": common.Price, _ = strconv.ParseFloat(value, 64) + case "TopupGroupRatio": + err = common.UpdateTopupGroupRatioByJSONString(value) case "GitHubClientId": common.GitHubClientId = value case "GitHubClientSecret": diff --git a/web/src/components/SystemSetting.js b/web/src/components/SystemSetting.js index efb437ab..2197f3fb 100644 --- a/web/src/components/SystemSetting.js +++ b/web/src/components/SystemSetting.js @@ -1,6 +1,6 @@ import React, {useEffect, useState} from 'react'; import {Button, Divider, Form, Grid, Header, Modal, Message} from 'semantic-ui-react'; -import {API, removeTrailingSlash, showError} from '../helpers'; +import {API, removeTrailingSlash, showError, verifyJSON} from '../helpers'; const SystemSetting = () => { let [inputs, setInputs] = useState({ @@ -20,6 +20,7 @@ const SystemSetting = () => { EpayId: '', EpayKey: '', Price: 7.3, + TopupGroupRatio: '', PayAddress: '', Footer: '', WeChatAuthEnabled: '', @@ -45,6 +46,9 @@ const SystemSetting = () => { if (success) { let newInputs = {}; data.forEach((item) => { + if (item.key === 'TopupGroupRatio') { + item.value = JSON.stringify(JSON.parse(item.value), null, 2); + } newInputs[item.key] = item.value; }); setInputs({ @@ -123,7 +127,8 @@ const SystemSetting = () => { name === 'WeChatAccountQRCodeImageURL' || name === 'TurnstileSiteKey' || name === 'TurnstileSecretKey' || - name === 'EmailDomainWhitelist' + name === 'EmailDomainWhitelist' || + name === 'TopupGroupRatio' ) { setInputs((inputs) => ({...inputs, [name]: value})); } else { @@ -141,6 +146,13 @@ const SystemSetting = () => { showError('请先填写服务器地址'); return } + if (originInputs['TopupGroupRatio'] !== inputs.TopupGroupRatio) { + if (!verifyJSON(inputs.TopupGroupRatio)) { + showError('充值分组倍率不是合法的 JSON 字符串'); + return; + } + await updateOption('TopupGroupRatio', inputs.TopupGroupRatio); + } let PayAddress = removeTrailingSlash(inputs.PayAddress); await updateOption('PayAddress', PayAddress); await updateOption('EpayId', inputs.EpayId); @@ -297,8 +309,19 @@ const SystemSetting = () => { onChange={handleInputChange} /> +