104 lines
2.3 KiB
Go
104 lines
2.3 KiB
Go
package payCenter
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"videoweb/pub/common/log"
|
|
)
|
|
|
|
// FenToYuan 用整数拆分分/元,避免浮点运算改变下单金额及签名原文。
|
|
func FenToYuan(price int64) string {
|
|
amount := big.NewInt(price)
|
|
negative := amount.Sign() < 0
|
|
amount.Abs(amount)
|
|
yuan := new(big.Int)
|
|
fen := new(big.Int)
|
|
yuan.QuoRem(amount, big.NewInt(100), fen)
|
|
result := yuan.String()
|
|
if fen.Sign() != 0 {
|
|
result += fmt.Sprintf(".%02d", fen.Int64())
|
|
}
|
|
if negative {
|
|
return "-" + result
|
|
}
|
|
return result
|
|
}
|
|
|
|
func YuanToFen(ctx context.Context, money string) int64 {
|
|
result, err := ParseYuanToFen(money)
|
|
if err != nil {
|
|
log.Error("【新支付中心金额转换】元转分失败", log.E(err))
|
|
}
|
|
return result
|
|
}
|
|
|
|
// ParseYuanToFen 只接受十进制金额和最多两位小数,拒绝指数、内嵌符号和溢出。
|
|
func ParseYuanToFen(money string) (int64, error) {
|
|
money = strings.TrimSpace(money)
|
|
if money == "" {
|
|
return 0, errors.New("money is empty")
|
|
}
|
|
|
|
negative := strings.HasPrefix(money, "-")
|
|
if negative {
|
|
money = money[1:]
|
|
if money == "" {
|
|
return 0, errors.New("money is empty")
|
|
}
|
|
}
|
|
parts := strings.Split(money, ".")
|
|
if len(parts) > 2 {
|
|
return 0, fmt.Errorf("invalid money format %q", money)
|
|
}
|
|
if strings.ReplaceAll(money, ".", "") == "" {
|
|
return 0, errors.New("money has no digits")
|
|
}
|
|
for _, part := range parts {
|
|
for _, digit := range part {
|
|
if digit < '0' || digit > '9' {
|
|
return 0, errors.New("money must contain only decimal digits")
|
|
}
|
|
}
|
|
}
|
|
if parts[0] == "" {
|
|
parts[0] = "0"
|
|
}
|
|
|
|
yuan, ok := new(big.Int).SetString(parts[0], 10)
|
|
if !ok {
|
|
return 0, fmt.Errorf("invalid yuan amount %q", money)
|
|
}
|
|
|
|
decimalPart := "00"
|
|
if len(parts) == 2 {
|
|
decimalPart = parts[1]
|
|
if len(decimalPart) > 2 {
|
|
return 0, fmt.Errorf("money has more than two decimal places: %q", money)
|
|
}
|
|
if len(decimalPart) == 0 {
|
|
decimalPart = "00"
|
|
} else if len(decimalPart) == 1 {
|
|
decimalPart += "0"
|
|
}
|
|
}
|
|
cents, err := strconv.ParseInt(decimalPart, 10, 64)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("invalid fen amount %q: %w", money, err)
|
|
}
|
|
|
|
total := new(big.Int).Mul(yuan, big.NewInt(100))
|
|
total.Add(total, big.NewInt(cents))
|
|
if negative {
|
|
total.Neg(total)
|
|
}
|
|
if !total.IsInt64() {
|
|
return 0, fmt.Errorf("money overflows int64 fen: %q", money)
|
|
}
|
|
return total.Int64(), nil
|
|
}
|