修复拉卡拉支付时间偏差
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"hfb_sys/backend/internal/modules/chat"
|
||||
"hfb_sys/backend/internal/modules/notification"
|
||||
"hfb_sys/backend/internal/modules/wallet"
|
||||
"hfb_sys/backend/internal/timeutil"
|
||||
"hfb_sys/backend/pkg/money"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
@@ -1627,7 +1628,7 @@ func makeAccountSnapshot(account model.GameAccount) (datatypes.JSON, error) {
|
||||
func newOrderNo() (string, error) {
|
||||
// 生成格式:RO + YYYYMMDDHHMMSS + 3位随机数
|
||||
// 例如:RO20260603123456789
|
||||
now := time.Now()
|
||||
now := timeutil.ShanghaiNow()
|
||||
|
||||
// 时间部分:年月日时分秒 (14位)
|
||||
timeStr := now.Format("20060102150405")
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
"hfb_sys/backend/internal/timeutil"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
@@ -131,3 +132,29 @@ func TestArchiveListingAfterCheckoutMovesListingOffline(t *testing.T) {
|
||||
// - Order should enter completed or closed state
|
||||
_ = time.Now()
|
||||
}
|
||||
|
||||
func TestNewOrderNoUsesShanghaiTimeWhenLocalIsUTC(t *testing.T) {
|
||||
oldLocal := time.Local
|
||||
time.Local = time.UTC
|
||||
defer func() {
|
||||
time.Local = oldLocal
|
||||
}()
|
||||
|
||||
loc := timeutil.ShanghaiLocation()
|
||||
before := time.Now().In(loc)
|
||||
orderNo, err := newOrderNo()
|
||||
after := time.Now().In(loc)
|
||||
if err != nil {
|
||||
t.Fatalf("newOrderNo() error = %v", err)
|
||||
}
|
||||
if len(orderNo) != len("RO20260603123456789") {
|
||||
t.Fatalf("orderNo length = %d, want %d: %s", len(orderNo), len("RO20260603123456789"), orderNo)
|
||||
}
|
||||
parsed, err := time.ParseInLocation("20060102150405", orderNo[2:16], loc)
|
||||
if err != nil {
|
||||
t.Fatalf("parse order no time: %v", err)
|
||||
}
|
||||
if parsed.Before(before.Add(-2*time.Second)) || parsed.After(after.Add(2*time.Second)) {
|
||||
t.Fatalf("order no time = %s, want between %s and %s", parsed, before, after)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"hfb_sys/backend/internal/modules/order"
|
||||
"hfb_sys/backend/internal/modules/paymentconfig"
|
||||
"hfb_sys/backend/internal/modules/wallet"
|
||||
"hfb_sys/backend/internal/timeutil"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
@@ -756,9 +757,27 @@ func canReuseOrderPayment(payment model.PaymentOrder, runtimeConfig runtimePayme
|
||||
if payment.MerchantID != "" && runtimeConfig.MerchantID != "" && payment.MerchantID != runtimeConfig.MerchantID {
|
||||
return false
|
||||
}
|
||||
if payment.Status == "paying" && paymentCashierExpired(payment) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func paymentCashierExpired(payment model.PaymentOrder) bool {
|
||||
if len(payment.RawRequest) == 0 {
|
||||
return false
|
||||
}
|
||||
var raw map[string]string
|
||||
if err := json.Unmarshal(payment.RawRequest, &raw); err != nil {
|
||||
return false
|
||||
}
|
||||
deadline := parseChannelTime(raw["order_efficient_time"])
|
||||
if deadline == nil {
|
||||
return false
|
||||
}
|
||||
return !timeutil.ShanghaiNow().Before(*deadline)
|
||||
}
|
||||
|
||||
func newOrderPayment(row model.RentalOrder, amountCent int64, req StartPaymentRequest, runtimeConfig runtimePaymentConfig) (model.PaymentOrder, error) {
|
||||
paymentNo, err := newPaymentNo()
|
||||
if err != nil {
|
||||
@@ -999,7 +1018,7 @@ func parseChannelTime(value string) *time.Time {
|
||||
return nil
|
||||
}
|
||||
for _, layout := range []string{"2006-01-02 15:04:05", "20060102150405", time.RFC3339} {
|
||||
parsed, err := time.ParseInLocation(layout, value, time.Local)
|
||||
parsed, err := time.ParseInLocation(layout, value, timeutil.ShanghaiLocation())
|
||||
if err == nil {
|
||||
return &parsed
|
||||
}
|
||||
|
||||
@@ -2,8 +2,12 @@ package payment
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
"hfb_sys/backend/internal/timeutil"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
func TestCanReuseOrderPaymentRejectsTerminalAndOldChannel(t *testing.T) {
|
||||
@@ -85,3 +89,42 @@ func TestNewOrderPaymentUsesPaymentNoAsThirdOrderID(t *testing.T) {
|
||||
t.Fatalf("payment order fields mismatch: %+v", payment)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanReuseOrderPaymentRejectsExpiredCashier(t *testing.T) {
|
||||
runtimeConfig := runtimePaymentConfig{
|
||||
Provider: "lakala",
|
||||
MerchantID: "M2",
|
||||
}
|
||||
expiredPayment := model.PaymentOrder{
|
||||
Status: "paying",
|
||||
Provider: "lakala",
|
||||
MerchantID: "M2",
|
||||
RawRequest: datatypes.JSON([]byte(`{"order_efficient_time":"20000101000000"}`)),
|
||||
}
|
||||
if canReuseOrderPayment(expiredPayment, runtimeConfig) {
|
||||
t.Fatal("canReuseOrderPayment() = true, want false for expired cashier")
|
||||
}
|
||||
|
||||
activePayment := expiredPayment
|
||||
activePayment.RawRequest = datatypes.JSON([]byte(`{"order_efficient_time":"20990101000000"}`))
|
||||
if !canReuseOrderPayment(activePayment, runtimeConfig) {
|
||||
t.Fatal("canReuseOrderPayment() = false, want true for active cashier")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseChannelTimeUsesShanghaiWhenLocalIsUTC(t *testing.T) {
|
||||
oldLocal := time.Local
|
||||
time.Local = time.UTC
|
||||
defer func() {
|
||||
time.Local = oldLocal
|
||||
}()
|
||||
|
||||
parsed := parseChannelTime("20260607202700")
|
||||
if parsed == nil {
|
||||
t.Fatal("parseChannelTime() = nil")
|
||||
}
|
||||
got := parsed.In(timeutil.ShanghaiLocation()).Format("20060102150405")
|
||||
if got != "20260607202700" {
|
||||
t.Fatalf("parseChannelTime() = %s, want 20260607202700 in Asia/Shanghai", got)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
"hfb_sys/backend/internal/timeutil"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
@@ -291,7 +292,7 @@ func toLedgerDTO(row model.WalletLedger) LedgerDTO {
|
||||
func newLedgerNo() (string, error) {
|
||||
// 生成格式:WL + YYYYMMDDHHMMSS + 毫秒 + 4位随机数
|
||||
// 例如:WL202606051234561230456,便于用户和客服识别。
|
||||
now := time.Now()
|
||||
now := timeutil.ShanghaiNow()
|
||||
buf := make([]byte, 2)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
return "", err
|
||||
|
||||
Reference in New Issue
Block a user