142 lines
3.5 KiB
Go
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))
|
|
}
|
|
}
|