feat(nsd-adapter): REST-клиент ИШ НРД + маршрутизация типов пакетов
- internal/nsdadapter/igw/client.go: REST-клиент ИШ (SendPackage, GetStatus, ListIncoming) с base64-JSON, ретраями на 5xx, 4xx без ретраев - internal/nsdadapter/router.go: маршрутизация MessageKind -> PackageType ЭДО (#M2MTR, #M2MTD, #M2MER, SUBBR/SUBER/SUB16, Assets_investment) - internal/nsdadapter/sender.go: реализация m2mcore.NSDSender (Send/SendDecision) через REST ИШ, сериализация Request/Decision в windows-1251 - internal/nsdadapter/config.go: профили guest/test3/prod × gost/rsa (URL ИШ, канал, контейнер ключа, retry) - internal/nsdadapter/onyx/onyx.go: скелет резервного канала WS ONYX (ждёт PR-6 crypto-service для подписи) - cmd/nsd-adapter/main.go: HTTP /healthz + фоновый поллер входящих по типам ЭДО; idle-режим без BJ_NSD_PROFILE make ci зелёный. Без внешних Go-зависимостей. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
package nsdadapter_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/m2m"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/nsdadapter"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/nsdadapter/igw"
|
||||
)
|
||||
|
||||
type mockIGW struct {
|
||||
gotChannel string
|
||||
gotType string
|
||||
gotBody []byte
|
||||
returnID string
|
||||
returnErr error
|
||||
}
|
||||
|
||||
func (m *mockIGW) SendPackage(_ context.Context, channel, packageType string, body []byte) (string, error) {
|
||||
m.gotChannel = channel
|
||||
m.gotType = packageType
|
||||
m.gotBody = append([]byte(nil), body...)
|
||||
return m.returnID, m.returnErr
|
||||
}
|
||||
|
||||
func (m *mockIGW) ListIncoming(_ context.Context, _ string, _ time.Time, _ string) ([]igw.Package, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// validRequest строит минимально валидный M2MTransferRequest для теста Sender.
|
||||
func validRequest() *m2m.M2MTransferRequest {
|
||||
whole := uint64(100)
|
||||
isin := m2m.ISIN("RU0007661625")
|
||||
return &m2m.M2MTransferRequest{
|
||||
Header: m2m.RequestHeader{
|
||||
GUID: m2m.UUID("c02a1d5e-c2af-4799-bab4-953f133c5133"),
|
||||
SenderCode: "MC0079200000",
|
||||
ReceiverCode: "MC0010300000",
|
||||
CostInfo: m2m.CostInfo{No: &m2m.CostInfoNo{}},
|
||||
},
|
||||
Data: m2m.RequestData{
|
||||
InvestorInformation: m2m.InvestorInformation{
|
||||
LastName: "Иванов",
|
||||
FirstName: "Иван",
|
||||
IdentityDocument: m2m.IdentityDocument{
|
||||
DocumentType: m2m.DocCode21,
|
||||
DocumentNumber: m2m.IdentityDocSerial("654321"),
|
||||
},
|
||||
},
|
||||
TransferringDepository: m2m.SettlementRequisites{INN: "7702070139"},
|
||||
ReceivingDepository: m2m.SettlementRequisites{INN: "7802031669"},
|
||||
TransferredSecurities: m2m.RequestTransferredSecurities{
|
||||
Securities: []m2m.RequestSecurity{
|
||||
{
|
||||
ReferenceID: "M2M2026030200001",
|
||||
SecurityCode: "MM0766162534",
|
||||
SecurityDetails: m2m.SecurityDetails{ISIN: &isin},
|
||||
Quantity: m2m.Quantity{Whole: &whole},
|
||||
SettlementAccount: []m2m.RequestSettlementAccount{
|
||||
{
|
||||
SettlementRequisites: m2m.SettlementRequisites{INN: "7702070139"},
|
||||
SettlementLocation: m2m.SettlementDepositoryLocation{
|
||||
DeponentCode: "DP789456",
|
||||
AccountID: "31MC0021900000F01",
|
||||
SectionID: "P001",
|
||||
},
|
||||
},
|
||||
},
|
||||
IsolationStatus: m2m.IsolationSGDN,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestSenderSend(t *testing.T) {
|
||||
profile, err := nsdadapter.LookupProfile("test3-gost")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mock := &mockIGW{returnID: "pkg-1"}
|
||||
s := nsdadapter.NewSender(profile, mock)
|
||||
|
||||
_, err = s.Send(context.Background(), validRequest())
|
||||
if err != nil {
|
||||
t.Fatalf("Send: %v", err)
|
||||
}
|
||||
if mock.gotChannel != "TEST3" {
|
||||
t.Errorf("channel = %q, ожидалось TEST3", mock.gotChannel)
|
||||
}
|
||||
if mock.gotType != string(nsdadapter.PackageM2MTransferRequest) {
|
||||
t.Errorf("type = %q, ожидалось %s", mock.gotType, nsdadapter.PackageM2MTransferRequest)
|
||||
}
|
||||
if len(mock.gotBody) == 0 {
|
||||
t.Error("body пустой")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSenderSendNilRequest(t *testing.T) {
|
||||
profile, _ := nsdadapter.LookupProfile("guest-gost")
|
||||
s := nsdadapter.NewSender(profile, &mockIGW{})
|
||||
if _, err := s.Send(context.Background(), nil); err == nil {
|
||||
t.Error("ожидалась ошибка на nil request")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user