113 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package financeorder
import (
"errors"
"fmt"
"sort"
"strings"
"hyapp-admin-server/internal/appctx"
"hyapp-admin-server/internal/model"
"hyapp-admin-server/internal/modules/shared"
)
const financeUSDTAddressGroup = "finance-usdt-address"
var financeUSDTChainOrder = map[string]int{
"TRON": 0,
"BSC": 1,
}
type financeUSDTAddressDTO struct {
Chain string `json:"chain"`
Address string `json:"address"`
UpdatedAtMS int64 `json:"updatedAtMs"`
}
type financeUSDTAddressesDTO struct {
AppCode string `json:"appCode"`
Items []financeUSDTAddressDTO `json:"items"`
}
// GetUSDTAddresses 只读取当前 App 自己持有的配置行,不继承空 app_code 的历史基线。
// 收款地址一旦跨 App 回退,运营会拿到另一账套的地址并让链上订单校验必然失败。
func (s *Service) GetUSDTAddresses(actor shared.Actor, appCode string) (*financeUSDTAddressesDTO, error) {
if s == nil || s.store == nil {
return nil, errors.New("admin store is not configured")
}
if actor.UserID == 0 || !hasPermission(actor.Permissions, permissionCoinSellerRechargeView) {
return nil, errCoinSellerRechargeForbidden
}
if strings.TrimSpace(appCode) == "" {
return nil, errInvalidCoinSellerRechargeOrderInput
}
appCode = appctx.Normalize(appCode)
// App 范围是后台用户的数据边界;即使调用方绕过页面手写 app_code也不能读取未授权账套地址。
access, err := s.store.AppAccessForUser(actor.UserID)
if err != nil {
return nil, err
}
if !access.Allows(appCode) {
return nil, errCoinSellerRechargeForbidden
}
configs, err := s.store.ListOwnedAppConfigs(appCode, financeUSDTAddressGroup)
if err != nil {
return nil, err
}
items, err := financeUSDTAddressesFromConfigs(configs)
if err != nil {
return nil, err
}
return &financeUSDTAddressesDTO{AppCode: appCode, Items: items}, nil
}
func financeUSDTAddressesFromConfigs(configs []model.AppConfig) ([]financeUSDTAddressDTO, error) {
items := make([]financeUSDTAddressDTO, 0, len(configs))
for _, config := range configs {
chain := strings.ToUpper(strings.TrimSpace(config.Key))
if _, supported := financeUSDTChainOrder[chain]; !supported {
// 同组未来若新增其他链,旧版本必须安全忽略,不能把未知地址误标成 TRON/BSC。
continue
}
address := strings.TrimSpace(config.Value)
if address == "" {
continue
}
if !validFinanceUSDTAddress(chain, address) {
return nil, fmt.Errorf("%s USDT 收款地址配置不正确", chain)
}
items = append(items, financeUSDTAddressDTO{Chain: chain, Address: address, UpdatedAtMS: config.UpdatedAtMS})
}
sort.Slice(items, func(i, j int) bool {
return financeUSDTChainOrder[items[i].Chain] < financeUSDTChainOrder[items[j].Chain]
})
return items, nil
}
func validFinanceUSDTAddress(chain string, address string) bool {
switch chain {
case "TRON":
if len(address) != 34 || address[0] != 'T' {
return false
}
for _, char := range address {
if !strings.ContainsRune("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz", char) {
return false
}
}
return true
case "BSC":
if len(address) != 42 || !strings.HasPrefix(address, "0x") {
return false
}
for _, char := range address[2:] {
if !strings.ContainsRune("0123456789abcdefABCDEF", char) {
return false
}
}
return true
default:
return false
}
}