fix: 完成商务迁移复核与接口优化并清理历史资料

This commit is contained in:
Yvan
2026-11-04 14:45:02 +08:00
parent 5a96be6a79
commit 297e80827d
176 changed files with 6803 additions and 6002 deletions
+3
View File
@@ -59,6 +59,9 @@ func (s *AccountService) List(ctx context.Context, req *dto.BusinessAccountQuery
}
*field.target = &n
}
if (req.BeginTime == "") != (req.EndTime == "") {
return nil, business.ErrAccountInput
}
if req.BeginTime != "" && req.EndTime != "" {
begin, err := time.ParseInLocation("2006-01-02 15:04:05", req.BeginTime, time.Local)
if err != nil {
+4 -1
View File
@@ -26,6 +26,9 @@ func analyticsRequest(req *dto.AnalyticsQuery) (business.AnalyticsFilter, error)
}
f := business.AnalyticsFilter{Sources: sources, GameNames: splitQueryValues(req.GameNames), PromoteName: strings.TrimSpace(req.PromoteName), PromoteType: req.PromoteType, SortField: strings.TrimSpace(req.SortField), Ascending: strings.EqualFold(strings.TrimSpace(req.SortOrder), "asc")}
begin, end := strings.TrimSpace(req.BeginTime), strings.TrimSpace(req.EndTime)
if (begin == "") != (end == "") {
return f, business.ErrAnalyticsDate
}
if begin != "" && end != "" {
location := time.FixedZone("Asia/Shanghai", 8*3600)
b, err := time.ParseInLocation("2006-01-02", begin, location)
@@ -33,7 +36,7 @@ func analyticsRequest(req *dto.AnalyticsQuery) (business.AnalyticsFilter, error)
return f, business.ErrAnalyticsDate
}
e, err := time.ParseInLocation("2006-01-02", end, location)
if err != nil {
if err != nil || e.Before(b) {
return f, business.ErrAnalyticsDate
}
f.StartDate = &b
@@ -0,0 +1,33 @@
package business
import (
"context"
"kra/internal/service/dto"
"testing"
)
func TestRejectIncompleteAndReversedDateRanges(t *testing.T) {
for _, dates := range [][2]string{{"2026-11-01", ""}, {"", "2026-11-01"}, {"2026-11-03", "2026-11-01"}, {"bad", "2026-11-01"}} {
if _, err := analyticsRequest(&dto.AnalyticsQuery{BeginTime: dates[0], EndTime: dates[1]}); err == nil {
t.Errorf("analytics accepted %v", dates)
}
for _, spend := range []bool{false, true} {
_, _, err := ledgerRequest(&dto.LedgerQuery{BeginRegisterTime: dates[0], EndRegisterTime: dates[1], BeginPayTime: dates[0], EndPayTime: dates[1]}, spend)
if err == nil {
t.Errorf("ledger accepted %v (spend=%v)", dates, spend)
}
}
}
for _, dates := range [][2]string{{"", ""}, {"2026-11-01", "2026-11-01"}} {
if _, err := analyticsRequest(&dto.AnalyticsQuery{BeginTime: dates[0], EndTime: dates[1]}); err != nil {
t.Fatal(err)
}
if _, _, err := ledgerRequest(&dto.LedgerQuery{BeginPayTime: dates[0], EndPayTime: dates[1]}, true); err != nil {
t.Fatal(err)
}
}
s := &AccountService{}
if _, err := s.List(context.Background(), &dto.BusinessAccountQuery{BeginTime: "2026-11-01 00:00:00"}); err == nil {
t.Fatal("account query silently ignored incomplete date range")
}
}
+4 -1
View File
@@ -31,6 +31,9 @@ func ledgerRequest(req *dto.LedgerQuery, spend bool) (business.LedgerFilter, bus
if spend {
begin, end = req.BeginPayTime, req.EndPayTime
}
if (strings.TrimSpace(begin) == "") != (strings.TrimSpace(end) == "") {
return f, business.LedgerListOptions{}, business.ErrLedgerInput
}
if strings.TrimSpace(begin) != "" && strings.TrimSpace(end) != "" {
location := time.FixedZone("Asia/Shanghai", 8*3600)
b, err := time.ParseInLocation("2006-01-02", strings.TrimSpace(begin), location)
@@ -38,7 +41,7 @@ func ledgerRequest(req *dto.LedgerQuery, spend bool) (business.LedgerFilter, bus
return f, business.LedgerListOptions{}, business.ErrLedgerInput
}
e, err := time.ParseInLocation("2006-01-02", strings.TrimSpace(end), location)
if err != nil {
if err != nil || e.Before(b) {
return f, business.LedgerListOptions{}, business.ErrLedgerInput
}
f.StartDate = &b
@@ -55,6 +55,10 @@ func ledgerWorkbook(sheet string, headers []string, rows [][]ledgerCell) ([]byte
}
}
last, _ := excelize.ColumnNumberToName(len(headers))
// 流式读取器依赖 dimension;Excelize 的初始 A1 范围不会随写入单元格自动扩展。
if err := file.SetSheetDimension(sheet, "A1:"+last+strconv.Itoa(len(rows)+1)); err != nil {
return nil, err
}
if err := file.SetColWidth(sheet, "A", last, 20); err != nil {
return nil, err
}
@@ -32,6 +32,9 @@ func TestLedgerWorkbookPreservesNumbersAndText(t *testing.T) {
t.Fatal(err)
}
defer f.Close()
if dimension, err := f.GetSheetDimension("注册明细"); err != nil || dimension != "A1:M2" {
t.Fatalf("注册导出范围不完整: %s %v", dimension, err)
}
amount, _ := f.GetCellValue("注册明细", "H2", excelize.Options{RawCellValue: true})
formula, _ := f.GetCellFormula("注册明细", "K2")
text, _ := f.GetCellValue("注册明细", "K2")
@@ -51,6 +54,9 @@ func TestLedgerWorkbookPreservesNumbersAndText(t *testing.T) {
t.Fatal(err)
}
defer pay.Close()
if dimension, err := pay.GetSheetDimension("充值明细"); err != nil || dimension != "A1:R2" {
t.Fatalf("充值导出范围不完整: %s %v", dimension, err)
}
order, _ := pay.GetCellValue("充值明细", "E2")
if order != "000000000000000001" {
t.Fatal("订单号前导零丢失")
+10 -1
View File
@@ -222,12 +222,21 @@ func (s *PaymentService) Refund(ctx context.Context, req *dto.PaymentRefundReque
func (s *PaymentService) TestProvider(ctx context.Context, provider string) (*dto.PaymentTestResult, error) {
result, err := s.uc.TestProvider(ctx, provider)
// The usecase records provider diagnostics in server logs. Arbitrary adapter
// errors can contain URLs, credentials or SQL; never forward them over HTTP.
if err != nil {
err = paymentbiz.ErrPaymentTestFailed
}
if result == nil {
return nil, err
}
response := &dto.PaymentTestResult{Provider: result.Provider, TradeNo: result.TradeNo, Passed: result.Passed, FullFlow: result.FullFlow, Mode: result.Mode, Stages: make([]*dto.PaymentTestStage, 0, len(result.Stages))}
for _, stage := range result.Stages {
response.Stages = append(response.Stages, &dto.PaymentTestStage{Name: stage.Name, Status: stage.Status, Message: stage.Message, TradeNo: stage.TradeNo, Duration: stage.Duration})
message := stage.Message
if stage.Status == "failed" {
message = "该步骤失败,请检查配置和服务端日志"
}
response.Stages = append(response.Stages, &dto.PaymentTestStage{Name: stage.Name, Status: stage.Status, Message: message, TradeNo: stage.TradeNo, Duration: stage.Duration})
}
response.Result = paymentResultResponse(result.Result)
return response, err
+28
View File
@@ -0,0 +1,28 @@
package payment
import (
"context"
"errors"
paymentbiz "kra/internal/biz/payment"
"testing"
)
type diagnosticRepo struct{ paymentbiz.PaymentRepo }
func (diagnosticRepo) TestProvider(context.Context, string) (*paymentbiz.PaymentTestResult, error) {
return &paymentbiz.PaymentTestResult{Provider: "alipay", Stages: []paymentbiz.PaymentTestStage{
{Name: "config", Status: "passed", Message: "配置已检查"},
{Name: "create", Status: "failed", Message: "https://merchant:secret@example.test/private?token=secret"},
}}, errors.New("provider response contains a secret")
}
func TestProviderDiagnosticsDoNotExposeRawErrors(t *testing.T) {
s := NewPaymentService(paymentbiz.NewPaymentUsecase(diagnosticRepo{}, nil, nil, nil, nil, nil))
result, err := s.TestProvider(context.Background(), "alipay")
if err != paymentbiz.ErrPaymentTestFailed {
t.Fatalf("unsafe diagnostic error: %v", err)
}
if result == nil || len(result.Stages) != 2 || result.Stages[0].Message != "配置已检查" || result.Stages[1].Message != "该步骤失败,请检查配置和服务端日志" {
t.Fatalf("unexpected diagnostic response: %+v", result)
}
}