Files

142 lines
3.5 KiB
Go

package payment
import (
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"gorm.io/datatypes"
"hfb_sys/backend/internal/model"
"hfb_sys/backend/internal/timeutil"
"math"
"strings"
"time"
)
func toDTO(payment model.PaymentOrder) PaymentDTO {
return PaymentDTO{
ID: payment.ID,
PaymentNo: payment.PaymentNo,
OrderID: payment.OrderID,
OrderNo: payment.OrderNo,
PaymentConfigID: payment.PaymentConfigID,
Provider: payment.Provider,
ThirdOrderID: payment.ThirdOrderID,
ProviderOrderID: payment.ProviderOrderID,
PayWay: payment.PayWay,
JSPayFlag: payment.JSPayFlag,
AmountCent: payment.AmountCent,
Status: payment.Status,
TDCode: payment.TDCode,
JSPayURL: payment.JSPayURL,
JSPayInfo: payment.JSPayInfo,
Paid: payment.Status == "paid",
PaidAt: payment.PaidAt,
CreatedAt: payment.CreatedAt,
UpdatedAt: payment.UpdatedAt,
}
}
func paymentErrorSummary(status string, raw datatypes.JSON) (string, string) {
if status != "failed" {
return "", ""
}
if len(raw) == 0 {
return "", ""
}
var payload map[string]any
if err := json.Unmarshal(raw, &payload); err != nil {
return "", ""
}
code := firstStringValue(payload, "code", "resp_code", "result_code", "error_code", "status")
message := firstStringValue(payload, "msg", "message", "error", "error_message", "result_msg", "result_desc")
return code, message
}
func moneyCent(value float64) int64 {
return int64(math.Round(value * 100))
}
func parseCent(value string) int64 {
var amount int64
_, _ = fmt.Sscanf(value, "%d", &amount)
return amount
}
func parseChannelTime(value string) *time.Time {
if value == "" {
return nil
}
for _, layout := range []string{"2006-01-02 15:04:05", "20060102150405", time.RFC3339} {
parsed, err := time.ParseInLocation(layout, value, timeutil.ShanghaiLocation())
if err == nil {
return &parsed
}
}
return nil
}
func jsonMap(value map[string]string) datatypes.JSON {
if value == nil {
return nil
}
raw, err := json.Marshal(value)
if err != nil {
return nil
}
return datatypes.JSON(raw)
}
func withRawSource(raw map[string]string, source string) map[string]string {
out := map[string]string{}
for key, value := range raw {
out[key] = value
}
if source != "" {
out["_source"] = source
}
out["_recorded_at"] = time.Now().Format(time.RFC3339)
return out
}
func jsonString(value map[string]string) string {
if len(value) == 0 {
return "{}"
}
raw, err := json.Marshal(value)
if err != nil {
return "{}"
}
return string(raw)
}
func newPaymentNo() (string, error) {
buf := make([]byte, 4)
if _, err := rand.Read(buf); err != nil {
return "", err
}
return fmt.Sprintf("PAY%d%s", time.Now().UnixNano(), hex.EncodeToString(buf)), nil
}
func firstNonEmpty(values ...string) string {
for _, value := range values {
if value != "" {
return value
}
}
return ""
}
// firstNonZero 返回第一个非零 uint64,用于保留历史支付单已有配置 ID。
func firstNonZero(values ...uint64) uint64 {
for _, value := range values {
if value != 0 {
return value
}
}
return 0
}
// normalizePayWay 将前端或渠道别名统一为系统内部支付方式编码。
func normalizePayWay(value string) string {
switch strings.ToUpper(strings.TrimSpace(value)) {
case "", "ZFBZF", "ALIPAY", "ALIPAYPAY":
return "ZFBZF"
case "WXZF", "WECHAT", "WECHATPAY":
return "WXZF"
default:
return strings.ToUpper(strings.TrimSpace(value))
}
}