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 }