fix: 完成商务迁移复核与接口优化并清理历史资料
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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("订单号前导零丢失")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user