From b440df97d537012067ae7b2c592eb43f3698ffc6 Mon Sep 17 00:00:00 2001 From: Stephan D Date: Thu, 12 Mar 2026 00:42:49 +0100 Subject: [PATCH] propagated payment commentto bff --- api/billing/documents/go.mod | 2 +- api/billing/documents/go.sum | 4 +- api/billing/fees/go.mod | 2 +- api/billing/fees/go.sum | 4 +- api/discovery/go.mod | 2 +- api/discovery/go.sum | 4 +- api/edge/bff/go.mod | 2 +- api/edge/bff/go.sum | 12 +-- api/edge/callbacks/go.mod | 2 +- api/edge/callbacks/go.sum | 4 +- api/fx/ingestor/go.mod | 2 +- api/fx/ingestor/go.sum | 4 +- api/fx/oracle/go.mod | 2 +- api/fx/oracle/go.sum | 4 +- api/fx/storage/go.mod | 2 +- api/fx/storage/go.sum | 4 +- api/gateway/aurora/client/client.go | 10 +++ api/gateway/aurora/go.mod | 2 +- api/gateway/aurora/go.sum | 4 +- .../service/gateway/card_payout_handlers.go | 2 + .../service/gateway/card_processor.go | 6 ++ .../service/gateway/card_processor_test.go | 7 ++ .../internal/service/gateway/connector.go | 19 ++++- .../internal/service/gateway/helpers.go | 2 + api/gateway/aurora/storage/model/state.go | 1 + .../aurora/storage/mongo/store/payouts.go | 1 + api/gateway/chain/go.mod | 4 +- api/gateway/chain/go.sum | 8 +- api/gateway/chsettle/go.mod | 2 +- api/gateway/chsettle/go.sum | 4 +- api/gateway/common/go.mod | 2 +- api/gateway/common/go.sum | 4 +- api/gateway/mntx/client/client.go | 10 +++ api/gateway/mntx/client/client_test.go | 46 +++++++++++ api/gateway/mntx/go.mod | 2 +- api/gateway/mntx/go.sum | 4 +- .../service/gateway/card_payout_handlers.go | 2 + .../service/gateway/card_processor.go | 6 ++ .../service/gateway/card_processor_test.go | 7 ++ .../internal/service/gateway/connector.go | 19 ++++- .../mntx/internal/service/gateway/helpers.go | 2 + api/gateway/mntx/storage/model/state.go | 1 + .../mntx/storage/mongo/store/payouts.go | 1 + api/gateway/tgsettle/go.mod | 2 +- api/gateway/tgsettle/go.sum | 4 +- api/gateway/tron/go.mod | 4 +- api/gateway/tron/go.sum | 8 +- api/ledger/go.mod | 4 +- api/ledger/go.sum | 4 +- api/notification/go.mod | 2 +- api/notification/go.sum | 4 +- api/payments/methods/go.mod | 2 +- api/payments/methods/go.sum | 4 +- api/payments/orchestrator/go.mod | 2 +- api/payments/orchestrator/go.sum | 4 +- .../service/orchestrationv2/agg/module.go | 2 + .../service/orchestrationv2/agg/service.go | 1 + .../orchestrationv2/batchmeta/module.go | 2 + .../service/orchestrationv2/prepo/document.go | 1 + .../service/orchestrationv2/prepo/service.go | 1 + .../orchestrationv2/prmap/intent_mapping.go | 2 +- .../orchestrationv2/prmap/service_test.go | 4 +- .../service/orchestrationv2/psvc/execute.go | 1 + .../orchestrationv2/psvc/execute_batch.go | 2 + .../psvc/execute_batch_test.go | 23 ++++-- .../service/orchestrationv2/psvc/runtime.go | 4 + .../service/orchestrationv2/sexec/service.go | 2 + .../service/orchestrationv2/ssched/input.go | 6 ++ .../xplan/compile_batch_targets_test.go | 15 +++- .../orchestrationv2/xplan/expansion.go | 1 + .../orchestrationv2/xplan/fee_planning.go | 4 +- .../service/orchestrationv2/xplan/module.go | 1 + .../xplan/service_boundaries.go | 3 + .../orchestrator/card_payout_executor.go | 4 + .../orchestrator/card_payout_executor_test.go | 39 ++++++++- .../service/orchestrator/crypto_executor.go | 1 + .../orchestrator/crypto_executor_test.go | 82 +++++++++++++++++++ .../orchestrator/destination_comment.go | 29 +++++++ .../orchestrator/destination_comment_test.go | 80 ++++++++++++++++++ .../orchestrator/settlement_executor.go | 1 + .../orchestrator/settlement_executor_test.go | 81 ++++++++++++++++++ api/payments/quotation/go.mod | 2 +- api/payments/quotation/go.sum | 4 +- .../intent_adapters.go | 1 + .../transfer_intent_hydrator/hydrator.go | 3 - .../transfer_intent_hydrator_test.go | 6 ++ api/payments/storage/go.mod | 2 +- api/payments/storage/go.sum | 4 +- api/payments/storage/model/payment.go | 2 + api/pkg/go.mod | 4 +- api/pkg/go.sum | 12 +-- api/proto/gateway/mntx/v1/mntx.proto | 3 + docker-compose.dev.yml | 32 ++++---- t.json | 0 94 files changed, 626 insertions(+), 119 deletions(-) create mode 100644 api/payments/orchestrator/internal/service/orchestrator/destination_comment.go create mode 100644 api/payments/orchestrator/internal/service/orchestrator/destination_comment_test.go create mode 100644 t.json diff --git a/api/billing/documents/go.mod b/api/billing/documents/go.mod index 6027dc3a..8f3a3457 100644 --- a/api/billing/documents/go.mod +++ b/api/billing/documents/go.mod @@ -60,7 +60,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/billing/documents/go.sum b/api/billing/documents/go.sum index 69b4be16..bb0999c7 100644 --- a/api/billing/documents/go.sum +++ b/api/billing/documents/go.sum @@ -221,8 +221,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= diff --git a/api/billing/fees/go.mod b/api/billing/fees/go.mod index f7b13ef7..acf93e2c 100644 --- a/api/billing/fees/go.mod +++ b/api/billing/fees/go.mod @@ -45,7 +45,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/billing/fees/go.sum b/api/billing/fees/go.sum index a55b4d54..bc3c2396 100644 --- a/api/billing/fees/go.sum +++ b/api/billing/fees/go.sum @@ -172,8 +172,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/discovery/go.mod b/api/discovery/go.mod index 0a5803ea..2c23914b 100644 --- a/api/discovery/go.mod +++ b/api/discovery/go.mod @@ -38,7 +38,7 @@ require ( go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/discovery/go.sum b/api/discovery/go.sum index a55b4d54..bc3c2396 100644 --- a/api/discovery/go.sum +++ b/api/discovery/go.sum @@ -172,8 +172,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/edge/bff/go.mod b/api/edge/bff/go.mod index 0f6ee05f..4d81b54b 100644 --- a/api/edge/bff/go.mod +++ b/api/edge/bff/go.mod @@ -154,7 +154,7 @@ require ( go.opentelemetry.io/otel/trace v1.42.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect golang.org/x/text v0.35.0 // indirect diff --git a/api/edge/bff/go.sum b/api/edge/bff/go.sum index 55627e56..b7f8c921 100644 --- a/api/edge/bff/go.sum +++ b/api/edge/bff/go.sum @@ -330,8 +330,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -374,8 +374,8 @@ golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= -golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= +golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= +golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -399,8 +399,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 h1:tu/dtnW1o3wfaxCOjSLn5IRX4YDcJrtlpzYkhHhGaC4= -google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171/go.mod h1:M5krXqk4GhBKvB596udGL3UyjL4I1+cTbK0orROM9ng= +google.golang.org/genproto/googleapis/api v0.0.0-20260311181403-84a4fc48630c h1:OyQPd6I3pN/9gDxz6L13kYGJgqkpdrAohJRBeXyxlgI= +google.golang.org/genproto/googleapis/api v0.0.0-20260311181403-84a4fc48630c/go.mod h1:X2gu9Qwng7Nn009s/r3RUxqkzQNqOrAy79bluY7ojIg= google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c h1:xgCzyF2LFIO/0X2UAoVRiXKU5Xg6VjToG4i2/ecSswk= google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU= diff --git a/api/edge/callbacks/go.mod b/api/edge/callbacks/go.mod index 4f367a21..30883229 100644 --- a/api/edge/callbacks/go.mod +++ b/api/edge/callbacks/go.mod @@ -52,7 +52,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/edge/callbacks/go.sum b/api/edge/callbacks/go.sum index bb3bc27d..b34db71b 100644 --- a/api/edge/callbacks/go.sum +++ b/api/edge/callbacks/go.sum @@ -205,8 +205,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/fx/ingestor/go.mod b/api/fx/ingestor/go.mod index af5fada1..e5cb2808 100644 --- a/api/fx/ingestor/go.mod +++ b/api/fx/ingestor/go.mod @@ -43,7 +43,7 @@ require ( go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect golang.org/x/text v0.35.0 // indirect diff --git a/api/fx/ingestor/go.sum b/api/fx/ingestor/go.sum index a55b4d54..bc3c2396 100644 --- a/api/fx/ingestor/go.sum +++ b/api/fx/ingestor/go.sum @@ -172,8 +172,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/fx/oracle/go.mod b/api/fx/oracle/go.mod index 5563fcfd..6996fd7d 100644 --- a/api/fx/oracle/go.mod +++ b/api/fx/oracle/go.mod @@ -43,7 +43,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/fx/oracle/go.sum b/api/fx/oracle/go.sum index a55b4d54..bc3c2396 100644 --- a/api/fx/oracle/go.sum +++ b/api/fx/oracle/go.sum @@ -172,8 +172,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/fx/storage/go.mod b/api/fx/storage/go.mod index 1cdb4657..d6366aa9 100644 --- a/api/fx/storage/go.mod +++ b/api/fx/storage/go.mod @@ -23,7 +23,7 @@ require ( github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/text v0.35.0 // indirect google.golang.org/protobuf v1.36.11 // indirect diff --git a/api/fx/storage/go.sum b/api/fx/storage/go.sum index e709ef1a..d1d261e3 100644 --- a/api/fx/storage/go.sum +++ b/api/fx/storage/go.sum @@ -136,8 +136,8 @@ go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/gateway/aurora/client/client.go b/api/gateway/aurora/client/client.go index 75f91c90..65326c48 100644 --- a/api/gateway/aurora/client/client.go +++ b/api/gateway/aurora/client/client.go @@ -202,6 +202,7 @@ func payoutParamsFromCard(req *mntxv1.CardPayoutRequest) map[string]interface{} params := map[string]interface{}{ "project_id": req.GetProjectId(), "parent_payment_ref": strings.TrimSpace(req.GetParentPaymentRef()), + "comment": strings.TrimSpace(req.GetComment()), "customer_id": strings.TrimSpace(req.GetCustomerId()), "customer_first_name": strings.TrimSpace(req.GetCustomerFirstName()), "customer_middle_name": strings.TrimSpace(req.GetCustomerMiddleName()), @@ -230,6 +231,7 @@ func payoutParamsFromToken(req *mntxv1.CardTokenPayoutRequest) map[string]interf params := map[string]interface{}{ "project_id": req.GetProjectId(), "parent_payment_ref": strings.TrimSpace(req.GetParentPaymentRef()), + "comment": strings.TrimSpace(req.GetComment()), "customer_id": strings.TrimSpace(req.GetCustomerId()), "customer_first_name": strings.TrimSpace(req.GetCustomerFirstName()), "customer_middle_name": strings.TrimSpace(req.GetCustomerMiddleName()), @@ -299,6 +301,9 @@ func sanitizeMetadata(source map[string]string) map[string]string { if k == "" { continue } + if strings.EqualFold(k, "comment") { + continue + } out[k] = strings.TrimSpace(value) } if len(out) == 0 { @@ -320,6 +325,11 @@ func payoutFromOperation(op *connectorv1.Operation) *mntxv1.CardPayoutState { state.Currency = strings.TrimSpace(money.GetCurrency()) state.AmountMinor = minorFromMoney(money) } + if params := op.GetParams(); params != nil { + if field, ok := params.GetFields()["comment"]; ok { + state.Comment = strings.TrimSpace(field.GetStringValue()) + } + } return state } diff --git a/api/gateway/aurora/go.mod b/api/gateway/aurora/go.mod index 29d24777..ddd956df 100644 --- a/api/gateway/aurora/go.mod +++ b/api/gateway/aurora/go.mod @@ -46,7 +46,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/gateway/aurora/go.sum b/api/gateway/aurora/go.sum index cbdf5d65..f5502ceb 100644 --- a/api/gateway/aurora/go.sum +++ b/api/gateway/aurora/go.sum @@ -174,8 +174,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/gateway/aurora/internal/service/gateway/card_payout_handlers.go b/api/gateway/aurora/internal/service/gateway/card_payout_handlers.go index e986765f..b7def7a1 100644 --- a/api/gateway/aurora/internal/service/gateway/card_payout_handlers.go +++ b/api/gateway/aurora/internal/service/gateway/card_payout_handlers.go @@ -140,6 +140,7 @@ func sanitizeCardPayoutRequest(req *mntxv1.CardPayoutRequest) *mntxv1.CardPayout r.OperationRef = strings.TrimSpace(r.GetOperationRef()) r.IdempotencyKey = strings.TrimSpace(r.GetIdempotencyKey()) r.IntentRef = strings.TrimSpace(r.GetIntentRef()) + r.Comment = strings.TrimSpace(r.GetComment()) return r } @@ -171,6 +172,7 @@ func sanitizeCardTokenPayoutRequest(req *mntxv1.CardTokenPayoutRequest) *mntxv1. r.OperationRef = strings.TrimSpace(r.GetOperationRef()) r.IdempotencyKey = strings.TrimSpace(r.GetIdempotencyKey()) r.IntentRef = strings.TrimSpace(r.GetIntentRef()) + r.Comment = strings.TrimSpace(r.GetComment()) return r } diff --git a/api/gateway/aurora/internal/service/gateway/card_processor.go b/api/gateway/aurora/internal/service/gateway/card_processor.go index faa40b43..823a9b4d 100644 --- a/api/gateway/aurora/internal/service/gateway/card_processor.go +++ b/api/gateway/aurora/internal/service/gateway/card_processor.go @@ -92,6 +92,9 @@ func mergePayoutStateWithExisting(state, existing *model.CardPayout) { if state.IntentRef == "" { state.IntentRef = existing.IntentRef } + if state.Comment == "" { + state.Comment = existing.Comment + } if existing.PaymentRef != "" { state.PaymentRef = existing.PaymentRef } @@ -182,6 +185,7 @@ func payoutStateLogFields(state *model.CardPayout) []zap.Field { zap.String("operation_ref", state.OperationRef), zap.String("idempotency_key", state.IdempotencyKey), zap.String("intent_ref", state.IntentRef), + zap.String("comment", state.Comment), } } @@ -1099,6 +1103,7 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout OperationRef: operationRef, IdempotencyKey: strings.TrimSpace(req.GetIdempotencyKey()), IntentRef: strings.TrimSpace(req.GetIntentRef()), + Comment: strings.TrimSpace(req.GetComment()), ProjectID: projectID, CustomerID: strings.TrimSpace(req.GetCustomerId()), AmountMinor: req.GetAmountMinor(), @@ -1259,6 +1264,7 @@ func (p *cardPayoutProcessor) SubmitToken(ctx context.Context, req *mntxv1.CardT OperationRef: operationRef, IdempotencyKey: strings.TrimSpace(req.GetIdempotencyKey()), IntentRef: strings.TrimSpace(req.GetIntentRef()), + Comment: strings.TrimSpace(req.GetComment()), ProjectID: projectID, CustomerID: strings.TrimSpace(req.GetCustomerId()), AmountMinor: req.GetAmountMinor(), diff --git a/api/gateway/aurora/internal/service/gateway/card_processor_test.go b/api/gateway/aurora/internal/service/gateway/card_processor_test.go index 1c8f1486..6766e455 100644 --- a/api/gateway/aurora/internal/service/gateway/card_processor_test.go +++ b/api/gateway/aurora/internal/service/gateway/card_processor_test.go @@ -93,6 +93,7 @@ func TestCardPayoutProcessor_Submit_Success(t *testing.T) { req := validCardPayoutRequest() req.ProjectId = 0 + req.Comment = "invoice-2002" resp, err := processor.Submit(context.Background(), req) if err != nil { @@ -118,6 +119,12 @@ func TestCardPayoutProcessor_Submit_Success(t *testing.T) { if stored.ProviderPaymentID == "" { t.Fatalf("expected provider payment id") } + if got, want := stored.Comment, "invoice-2002"; got != want { + t.Fatalf("expected stored comment %q, got %q", want, got) + } + if got, want := resp.GetPayout().GetComment(), "invoice-2002"; got != want { + t.Fatalf("expected response comment %q, got %q", want, got) + } if !stored.CreatedAt.Equal(existingCreated) { t.Fatalf("expected created_at preserved in model, got %v", stored.CreatedAt) } diff --git a/api/gateway/aurora/internal/service/gateway/connector.go b/api/gateway/aurora/internal/service/gateway/connector.go index 8983ad0c..ff299627 100644 --- a/api/gateway/aurora/internal/service/gateway/connector.go +++ b/api/gateway/aurora/internal/service/gateway/connector.go @@ -129,6 +129,7 @@ func connectorOperationParams() []*connectorv1.OperationParamSpec { {Key: "amount_minor", Type: connectorv1.ParamType_INT, Required: false}, {Key: "project_id", Type: connectorv1.ParamType_INT, Required: false}, {Key: "parent_payment_ref", Type: connectorv1.ParamType_STRING, Required: true}, + {Key: "comment", Type: connectorv1.ParamType_STRING, Required: false}, {Key: "customer_middle_name", Type: connectorv1.ParamType_STRING, Required: false}, {Key: "customer_country", Type: connectorv1.ParamType_STRING, Required: false}, {Key: "customer_state", Type: connectorv1.ParamType_STRING, Required: false}, @@ -188,7 +189,18 @@ func metadataFromReader(reader params.Reader) map[string]string { if len(metadata) == 0 { return nil } - return metadata + out := make(map[string]string, len(metadata)) + for key, value := range metadata { + k := strings.TrimSpace(key) + if k == "" || strings.EqualFold(k, "comment") { + continue + } + out[k] = strings.TrimSpace(value) + } + if len(out) == 0 { + return nil + } + return out } func buildCardTokenPayoutRequestFromParams(reader params.Reader, @@ -218,6 +230,7 @@ func buildCardTokenPayoutRequestFromParams(reader params.Reader, CardToken: strings.TrimSpace(reader.String("card_token")), CardHolder: strings.TrimSpace(reader.String("card_holder")), MaskedPan: strings.TrimSpace(reader.String("masked_pan")), + Comment: strings.TrimSpace(reader.String("comment")), Metadata: metadataFromReader(reader), OperationRef: operationRef, IdempotencyKey: strings.TrimSpace(idempotencyKey), @@ -254,6 +267,7 @@ func buildCardPayoutRequestFromParams(reader params.Reader, CardExpYear: uint32(readerInt64(reader, "card_exp_year")), //nolint:gosec // values are validated by request validators CardExpMonth: uint32(readerInt64(reader, "card_exp_month")), //nolint:gosec // values are validated by request validators CardHolder: strings.TrimSpace(reader.String("card_holder")), + Comment: strings.TrimSpace(reader.String("comment")), Metadata: metadataFromReader(reader), OperationRef: operationRef, IdempotencyKey: strings.TrimSpace(idempotencyKey), @@ -305,6 +319,9 @@ func payoutToOperation(state *mntxv1.CardPayoutState) *connectorv1.Operation { params["payment_ref"] = paymentRef params["parent_payment_ref"] = paymentRef } + if comment := strings.TrimSpace(state.GetComment()); comment != "" { + params["comment"] = comment + } if providerCode := strings.TrimSpace(state.GetProviderCode()); providerCode != "" { params["provider_code"] = providerCode } diff --git a/api/gateway/aurora/internal/service/gateway/helpers.go b/api/gateway/aurora/internal/service/gateway/helpers.go index 0d7986f3..e3bb3445 100644 --- a/api/gateway/aurora/internal/service/gateway/helpers.go +++ b/api/gateway/aurora/internal/service/gateway/helpers.go @@ -26,6 +26,7 @@ func CardPayoutStateFromProto(clock clockpkg.Clock, p *mntxv1.CardPayoutState) * PaymentRef: strings.TrimSpace(p.GetParentPaymentRef()), OperationRef: p.GetOperationRef(), IntentRef: p.GetIntentRef(), + Comment: strings.TrimSpace(p.GetComment()), IdempotencyKey: p.GetIdempotencyKey(), ProjectID: p.ProjectId, CustomerID: p.CustomerId, @@ -52,6 +53,7 @@ func StateToProto(m *model.CardPayout) *mntxv1.CardPayoutState { ProviderCode: m.ProviderCode, ProviderMessage: m.ProviderMessage, ProviderPaymentId: m.ProviderPaymentID, + Comment: strings.TrimSpace(m.Comment), CreatedAt: timestamppb.New(m.CreatedAt), UpdatedAt: timestamppb.New(m.UpdatedAt), } diff --git a/api/gateway/aurora/storage/model/state.go b/api/gateway/aurora/storage/model/state.go index be91e760..0fdf6ff5 100644 --- a/api/gateway/aurora/storage/model/state.go +++ b/api/gateway/aurora/storage/model/state.go @@ -13,6 +13,7 @@ type CardPayout struct { OperationRef string `bson:"operationRef" json:"operation_ref"` IdempotencyKey string `bson:"idempotencyKey" json:"idempotency_key"` IntentRef string `bson:"intentRef" json:"intentRef"` + Comment string `bson:"comment,omitempty" json:"comment,omitempty"` ProjectID int64 `bson:"projectId" json:"project_id"` CustomerID string `bson:"customerId" json:"customer_id"` AmountMinor int64 `bson:"amountMinor" json:"amount_minor"` diff --git a/api/gateway/aurora/storage/mongo/store/payouts.go b/api/gateway/aurora/storage/mongo/store/payouts.go index c1a4de3f..86be442c 100644 --- a/api/gateway/aurora/storage/mongo/store/payouts.go +++ b/api/gateway/aurora/storage/mongo/store/payouts.go @@ -89,6 +89,7 @@ func (p *Payouts) Upsert(ctx context.Context, record *model.CardPayout) error { record.OperationRef = strings.TrimSpace(record.OperationRef) record.PaymentRef = strings.TrimSpace(record.PaymentRef) record.CustomerID = strings.TrimSpace(record.CustomerID) + record.Comment = strings.TrimSpace(record.Comment) record.ProviderCode = strings.TrimSpace(record.ProviderCode) record.ProviderPaymentID = strings.TrimSpace(record.ProviderPaymentID) diff --git a/api/gateway/chain/go.mod b/api/gateway/chain/go.mod index f38aa945..a56d9d91 100644 --- a/api/gateway/chain/go.mod +++ b/api/gateway/chain/go.mod @@ -23,7 +23,7 @@ require ( require ( github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260309015608-bb9dacb41b4e // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260311194731-d5b7577c683d // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.24.4 // indirect github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect @@ -84,7 +84,7 @@ require ( go.opentelemetry.io/otel/trace v1.42.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect diff --git a/api/gateway/chain/go.sum b/api/gateway/chain/go.sum index 2b65605c..80c47a9e 100644 --- a/api/gateway/chain/go.sum +++ b/api/gateway/chain/go.sum @@ -6,8 +6,8 @@ github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260309015608-bb9dacb41b4e h1:sYPOzrcpCOv6rolFVWyEmjCSuZNg0yn2mVjlJYq8+2g= -github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260309015608-bb9dacb41b4e/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260311194731-d5b7577c683d h1:EA+kZ8mxGb1W/ewiIBMzb/1gg5BiW1Fvr3r4qCUBJEg= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260311194731-d5b7577c683d/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0= github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -313,8 +313,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= diff --git a/api/gateway/chsettle/go.mod b/api/gateway/chsettle/go.mod index 8df5d4c4..a0ddd00e 100644 --- a/api/gateway/chsettle/go.mod +++ b/api/gateway/chsettle/go.mod @@ -43,7 +43,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/gateway/chsettle/go.sum b/api/gateway/chsettle/go.sum index a55b4d54..bc3c2396 100644 --- a/api/gateway/chsettle/go.sum +++ b/api/gateway/chsettle/go.sum @@ -172,8 +172,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/gateway/common/go.mod b/api/gateway/common/go.mod index 7407a441..48f78a81 100644 --- a/api/gateway/common/go.mod +++ b/api/gateway/common/go.mod @@ -22,7 +22,7 @@ require ( github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect golang.org/x/text v0.35.0 // indirect diff --git a/api/gateway/common/go.sum b/api/gateway/common/go.sum index 4605c955..3b3b49dc 100644 --- a/api/gateway/common/go.sum +++ b/api/gateway/common/go.sum @@ -123,8 +123,8 @@ go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= diff --git a/api/gateway/mntx/client/client.go b/api/gateway/mntx/client/client.go index 5327d0d4..4d792078 100644 --- a/api/gateway/mntx/client/client.go +++ b/api/gateway/mntx/client/client.go @@ -202,6 +202,7 @@ func payoutParamsFromCard(req *mntxv1.CardPayoutRequest) map[string]interface{} params := map[string]interface{}{ "project_id": req.GetProjectId(), "parent_payment_ref": strings.TrimSpace(req.GetParentPaymentRef()), + "comment": strings.TrimSpace(req.GetComment()), "customer_id": strings.TrimSpace(req.GetCustomerId()), "customer_first_name": strings.TrimSpace(req.GetCustomerFirstName()), "customer_middle_name": strings.TrimSpace(req.GetCustomerMiddleName()), @@ -230,6 +231,7 @@ func payoutParamsFromToken(req *mntxv1.CardTokenPayoutRequest) map[string]interf params := map[string]interface{}{ "project_id": req.GetProjectId(), "parent_payment_ref": strings.TrimSpace(req.GetParentPaymentRef()), + "comment": strings.TrimSpace(req.GetComment()), "customer_id": strings.TrimSpace(req.GetCustomerId()), "customer_first_name": strings.TrimSpace(req.GetCustomerFirstName()), "customer_middle_name": strings.TrimSpace(req.GetCustomerMiddleName()), @@ -299,6 +301,9 @@ func sanitizeMetadata(source map[string]string) map[string]string { if k == "" { continue } + if strings.EqualFold(k, "comment") { + continue + } out[k] = strings.TrimSpace(value) } if len(out) == 0 { @@ -320,6 +325,11 @@ func payoutFromOperation(op *connectorv1.Operation) *mntxv1.CardPayoutState { state.Currency = strings.TrimSpace(money.GetCurrency()) state.AmountMinor = minorFromMoney(money) } + if params := op.GetParams(); params != nil { + if field, ok := params.GetFields()["comment"]; ok { + state.Comment = strings.TrimSpace(field.GetStringValue()) + } + } return state } diff --git a/api/gateway/mntx/client/client_test.go b/api/gateway/mntx/client/client_test.go index 33c50c52..9e792ac6 100644 --- a/api/gateway/mntx/client/client_test.go +++ b/api/gateway/mntx/client/client_test.go @@ -142,3 +142,49 @@ func TestCreateCardTokenPayout_UsesOperationRefWhenReceiptOperationIDMissing(t * t.Fatalf("payout_id mismatch: got=%q want=%q", got, want) } } + +func TestCreateCardPayout_SendsCommentAsSeparateParam(t *testing.T) { + stub := &stubConnectorClient{ + submitResp: &connectorv1.SubmitOperationResponse{ + Receipt: &connectorv1.OperationReceipt{ + OperationId: "payment-4:hop_4_card_payout_send", + Status: connectorv1.OperationStatus_OPERATION_WAITING, + }, + }, + } + client := &gatewayClient{client: stub, cfg: Config{}} + + _, err := client.CreateCardPayout(context.Background(), &mntxv1.CardPayoutRequest{ + OperationRef: "payment-4:hop_4_card_payout_send", + IdempotencyKey: "idem-4", + AmountMinor: 1000, + Currency: "RUB", + Comment: "invoice-44", + Metadata: map[string]string{ + "comment": "legacy-comment", + "trace_id": "trace-44", + }, + }) + if err != nil { + t.Fatalf("CreateCardPayout returned error: %v", err) + } + if stub.submitReq == nil || stub.submitReq.GetOperation() == nil { + t.Fatal("expected submitted operation") + } + + fields := stub.submitReq.GetOperation().GetParams().GetFields() + if got, want := fields["comment"].GetStringValue(), "invoice-44"; got != want { + t.Fatalf("comment param mismatch: got=%q want=%q", got, want) + } + metadataField, ok := fields["metadata"] + if !ok || metadataField == nil || metadataField.GetStructValue() == nil { + t.Fatal("expected metadata param") + } + metadata := metadataField.GetStructValue().GetFields() + if _, hasComment := metadata["comment"]; hasComment { + t.Fatalf("metadata must not include comment key") + } + if got, want := metadata["trace_id"].GetStringValue(), "trace-44"; got != want { + t.Fatalf("trace_id metadata mismatch: got=%q want=%q", got, want) + } +} diff --git a/api/gateway/mntx/go.mod b/api/gateway/mntx/go.mod index 6eaf780b..f57b0c7c 100644 --- a/api/gateway/mntx/go.mod +++ b/api/gateway/mntx/go.mod @@ -46,7 +46,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/gateway/mntx/go.sum b/api/gateway/mntx/go.sum index cbdf5d65..f5502ceb 100644 --- a/api/gateway/mntx/go.sum +++ b/api/gateway/mntx/go.sum @@ -174,8 +174,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/gateway/mntx/internal/service/gateway/card_payout_handlers.go b/api/gateway/mntx/internal/service/gateway/card_payout_handlers.go index 3b1ded96..5fbf0b64 100644 --- a/api/gateway/mntx/internal/service/gateway/card_payout_handlers.go +++ b/api/gateway/mntx/internal/service/gateway/card_payout_handlers.go @@ -141,6 +141,7 @@ func sanitizeCardPayoutRequest(req *mntxv1.CardPayoutRequest) *mntxv1.CardPayout r.OperationRef = strings.TrimSpace(r.GetOperationRef()) r.IdempotencyKey = strings.TrimSpace(r.GetIdempotencyKey()) r.IntentRef = strings.TrimSpace(r.GetIntentRef()) + r.Comment = strings.TrimSpace(r.GetComment()) return r } @@ -172,6 +173,7 @@ func sanitizeCardTokenPayoutRequest(req *mntxv1.CardTokenPayoutRequest) *mntxv1. r.OperationRef = strings.TrimSpace(r.GetOperationRef()) r.IdempotencyKey = strings.TrimSpace(r.GetIdempotencyKey()) r.IntentRef = strings.TrimSpace(r.GetIntentRef()) + r.Comment = strings.TrimSpace(r.GetComment()) return r } diff --git a/api/gateway/mntx/internal/service/gateway/card_processor.go b/api/gateway/mntx/internal/service/gateway/card_processor.go index 49ef63c4..588f79dd 100644 --- a/api/gateway/mntx/internal/service/gateway/card_processor.go +++ b/api/gateway/mntx/internal/service/gateway/card_processor.go @@ -87,6 +87,9 @@ func mergePayoutStateWithExisting(state, existing *model.CardPayout) { if state.IntentRef == "" { state.IntentRef = existing.IntentRef } + if state.Comment == "" { + state.Comment = existing.Comment + } if existing.PaymentRef != "" { state.PaymentRef = existing.PaymentRef } @@ -168,6 +171,7 @@ func payoutStateLogFields(state *model.CardPayout) []zap.Field { zap.String("operation_ref", state.OperationRef), zap.String("idempotency_key", state.IdempotencyKey), zap.String("intent_ref", state.IntentRef), + zap.String("comment", state.Comment), } } @@ -1070,6 +1074,7 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout OperationRef: operationRef, IdempotencyKey: strings.TrimSpace(req.GetIdempotencyKey()), IntentRef: strings.TrimSpace(req.GetIntentRef()), + Comment: strings.TrimSpace(req.GetComment()), ProjectID: projectID, CustomerID: strings.TrimSpace(req.GetCustomerId()), AmountMinor: req.GetAmountMinor(), @@ -1237,6 +1242,7 @@ func (p *cardPayoutProcessor) SubmitToken(ctx context.Context, req *mntxv1.CardT OperationRef: operationRef, IdempotencyKey: strings.TrimSpace(req.GetIdempotencyKey()), IntentRef: strings.TrimSpace(req.GetIntentRef()), + Comment: strings.TrimSpace(req.GetComment()), ProjectID: projectID, CustomerID: strings.TrimSpace(req.GetCustomerId()), AmountMinor: req.GetAmountMinor(), diff --git a/api/gateway/mntx/internal/service/gateway/card_processor_test.go b/api/gateway/mntx/internal/service/gateway/card_processor_test.go index 52c340a8..5f76922b 100644 --- a/api/gateway/mntx/internal/service/gateway/card_processor_test.go +++ b/api/gateway/mntx/internal/service/gateway/card_processor_test.go @@ -80,6 +80,7 @@ func TestCardPayoutProcessor_Submit_Success(t *testing.T) { req := validCardPayoutRequest() req.ProjectId = 0 + req.Comment = "invoice-1001" resp, err := processor.Submit(context.Background(), req) if err != nil { @@ -105,6 +106,12 @@ func TestCardPayoutProcessor_Submit_Success(t *testing.T) { if stored.ProviderPaymentID == "" { t.Fatalf("expected provider payment id") } + if got, want := stored.Comment, "invoice-1001"; got != want { + t.Fatalf("expected stored comment %q, got %q", want, got) + } + if got, want := resp.GetPayout().GetComment(), "invoice-1001"; got != want { + t.Fatalf("expected response comment %q, got %q", want, got) + } if !stored.CreatedAt.Equal(existingCreated) { t.Fatalf("expected created_at preserved in model, got %v", stored.CreatedAt) } diff --git a/api/gateway/mntx/internal/service/gateway/connector.go b/api/gateway/mntx/internal/service/gateway/connector.go index 2c371a4c..a123163e 100644 --- a/api/gateway/mntx/internal/service/gateway/connector.go +++ b/api/gateway/mntx/internal/service/gateway/connector.go @@ -129,6 +129,7 @@ func mntxOperationParams() []*connectorv1.OperationParamSpec { {Key: "amount_minor", Type: connectorv1.ParamType_INT, Required: false}, {Key: "project_id", Type: connectorv1.ParamType_INT, Required: false}, {Key: "parent_payment_ref", Type: connectorv1.ParamType_STRING, Required: true}, + {Key: "comment", Type: connectorv1.ParamType_STRING, Required: false}, {Key: "customer_middle_name", Type: connectorv1.ParamType_STRING, Required: false}, {Key: "customer_country", Type: connectorv1.ParamType_STRING, Required: false}, {Key: "customer_state", Type: connectorv1.ParamType_STRING, Required: false}, @@ -188,7 +189,18 @@ func metadataFromReader(reader params.Reader) map[string]string { if len(metadata) == 0 { return nil } - return metadata + out := make(map[string]string, len(metadata)) + for key, value := range metadata { + k := strings.TrimSpace(key) + if k == "" || strings.EqualFold(k, "comment") { + continue + } + out[k] = strings.TrimSpace(value) + } + if len(out) == 0 { + return nil + } + return out } func buildCardTokenPayoutRequestFromParams(reader params.Reader, @@ -218,6 +230,7 @@ func buildCardTokenPayoutRequestFromParams(reader params.Reader, CardToken: strings.TrimSpace(reader.String("card_token")), CardHolder: strings.TrimSpace(reader.String("card_holder")), MaskedPan: strings.TrimSpace(reader.String("masked_pan")), + Comment: strings.TrimSpace(reader.String("comment")), Metadata: metadataFromReader(reader), OperationRef: operationRef, IdempotencyKey: strings.TrimSpace(idempotencyKey), @@ -254,6 +267,7 @@ func buildCardPayoutRequestFromParams(reader params.Reader, CardExpYear: uint32(readerInt64(reader, "card_exp_year")), //nolint:gosec // values are validated by request validators CardExpMonth: uint32(readerInt64(reader, "card_exp_month")), //nolint:gosec // values are validated by request validators CardHolder: strings.TrimSpace(reader.String("card_holder")), + Comment: strings.TrimSpace(reader.String("comment")), Metadata: metadataFromReader(reader), OperationRef: operationRef, IdempotencyKey: strings.TrimSpace(idempotencyKey), @@ -305,6 +319,9 @@ func payoutToOperation(state *mntxv1.CardPayoutState) *connectorv1.Operation { params["payment_ref"] = paymentRef params["parent_payment_ref"] = paymentRef } + if comment := strings.TrimSpace(state.GetComment()); comment != "" { + params["comment"] = comment + } if providerCode := strings.TrimSpace(state.GetProviderCode()); providerCode != "" { params["provider_code"] = providerCode } diff --git a/api/gateway/mntx/internal/service/gateway/helpers.go b/api/gateway/mntx/internal/service/gateway/helpers.go index 981ad450..f0f0269e 100644 --- a/api/gateway/mntx/internal/service/gateway/helpers.go +++ b/api/gateway/mntx/internal/service/gateway/helpers.go @@ -26,6 +26,7 @@ func CardPayoutStateFromProto(clock clockpkg.Clock, p *mntxv1.CardPayoutState) * PaymentRef: strings.TrimSpace(p.GetParentPaymentRef()), OperationRef: p.GetOperationRef(), IntentRef: p.GetIntentRef(), + Comment: strings.TrimSpace(p.GetComment()), IdempotencyKey: p.GetIdempotencyKey(), ProjectID: p.ProjectId, CustomerID: p.CustomerId, @@ -52,6 +53,7 @@ func StateToProto(m *model.CardPayout) *mntxv1.CardPayoutState { ProviderCode: m.ProviderCode, ProviderMessage: m.ProviderMessage, ProviderPaymentId: m.ProviderPaymentID, + Comment: strings.TrimSpace(m.Comment), CreatedAt: timestamppb.New(m.CreatedAt), UpdatedAt: timestamppb.New(m.UpdatedAt), } diff --git a/api/gateway/mntx/storage/model/state.go b/api/gateway/mntx/storage/model/state.go index be91e760..0fdf6ff5 100644 --- a/api/gateway/mntx/storage/model/state.go +++ b/api/gateway/mntx/storage/model/state.go @@ -13,6 +13,7 @@ type CardPayout struct { OperationRef string `bson:"operationRef" json:"operation_ref"` IdempotencyKey string `bson:"idempotencyKey" json:"idempotency_key"` IntentRef string `bson:"intentRef" json:"intentRef"` + Comment string `bson:"comment,omitempty" json:"comment,omitempty"` ProjectID int64 `bson:"projectId" json:"project_id"` CustomerID string `bson:"customerId" json:"customer_id"` AmountMinor int64 `bson:"amountMinor" json:"amount_minor"` diff --git a/api/gateway/mntx/storage/mongo/store/payouts.go b/api/gateway/mntx/storage/mongo/store/payouts.go index 156ed0a1..00d83a04 100644 --- a/api/gateway/mntx/storage/mongo/store/payouts.go +++ b/api/gateway/mntx/storage/mongo/store/payouts.go @@ -89,6 +89,7 @@ func (p *Payouts) Upsert(ctx context.Context, record *model.CardPayout) error { record.OperationRef = strings.TrimSpace(record.OperationRef) record.PaymentRef = strings.TrimSpace(record.PaymentRef) record.CustomerID = strings.TrimSpace(record.CustomerID) + record.Comment = strings.TrimSpace(record.Comment) record.ProviderCode = strings.TrimSpace(record.ProviderCode) record.ProviderPaymentID = strings.TrimSpace(record.ProviderPaymentID) diff --git a/api/gateway/tgsettle/go.mod b/api/gateway/tgsettle/go.mod index 27146df5..102869d8 100644 --- a/api/gateway/tgsettle/go.mod +++ b/api/gateway/tgsettle/go.mod @@ -43,7 +43,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/gateway/tgsettle/go.sum b/api/gateway/tgsettle/go.sum index a55b4d54..bc3c2396 100644 --- a/api/gateway/tgsettle/go.sum +++ b/api/gateway/tgsettle/go.sum @@ -172,8 +172,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/gateway/tron/go.mod b/api/gateway/tron/go.mod index 3638c2c3..72e31004 100644 --- a/api/gateway/tron/go.mod +++ b/api/gateway/tron/go.mod @@ -26,7 +26,7 @@ require ( require ( github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260309015608-bb9dacb41b4e // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260311194731-d5b7577c683d // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.24.4 // indirect github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect @@ -92,7 +92,7 @@ require ( go.opentelemetry.io/otel/trace v1.42.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect diff --git a/api/gateway/tron/go.sum b/api/gateway/tron/go.sum index 100b70b8..b97322b4 100644 --- a/api/gateway/tron/go.sum +++ b/api/gateway/tron/go.sum @@ -6,8 +6,8 @@ github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260309015608-bb9dacb41b4e h1:sYPOzrcpCOv6rolFVWyEmjCSuZNg0yn2mVjlJYq8+2g= -github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260309015608-bb9dacb41b4e/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260311194731-d5b7577c683d h1:EA+kZ8mxGb1W/ewiIBMzb/1gg5BiW1Fvr3r4qCUBJEg= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260311194731-d5b7577c683d/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0= github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -328,8 +328,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= diff --git a/api/ledger/go.mod b/api/ledger/go.mod index d034111e..0f03acbe 100644 --- a/api/ledger/go.mod +++ b/api/ledger/go.mod @@ -1,6 +1,6 @@ module github.com/tech/sendico/ledger -go 1.25.0 +go 1.25.7 replace github.com/tech/sendico/pkg => ../pkg @@ -44,7 +44,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/ledger/go.sum b/api/ledger/go.sum index 57c08698..d63bca46 100644 --- a/api/ledger/go.sum +++ b/api/ledger/go.sum @@ -174,8 +174,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/notification/go.mod b/api/notification/go.mod index 94b344c1..82fca8b6 100644 --- a/api/notification/go.mod +++ b/api/notification/go.mod @@ -46,7 +46,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/notification/go.sum b/api/notification/go.sum index 8a40c794..91fb1c36 100644 --- a/api/notification/go.sum +++ b/api/notification/go.sum @@ -189,8 +189,8 @@ go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/payments/methods/go.mod b/api/payments/methods/go.mod index e8f45922..0b0d67f8 100644 --- a/api/payments/methods/go.mod +++ b/api/payments/methods/go.mod @@ -44,7 +44,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/payments/methods/go.sum b/api/payments/methods/go.sum index 57c08698..d63bca46 100644 --- a/api/payments/methods/go.sum +++ b/api/payments/methods/go.sum @@ -174,8 +174,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/payments/orchestrator/go.mod b/api/payments/orchestrator/go.mod index 065092d0..eae1ad51 100644 --- a/api/payments/orchestrator/go.mod +++ b/api/payments/orchestrator/go.mod @@ -59,7 +59,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/payments/orchestrator/go.sum b/api/payments/orchestrator/go.sum index bc53f93f..1e64e8c4 100644 --- a/api/payments/orchestrator/go.sum +++ b/api/payments/orchestrator/go.sum @@ -175,8 +175,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/agg/module.go b/api/payments/orchestrator/internal/service/orchestrationv2/agg/module.go index c2688be4..3228bf5b 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/agg/module.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/agg/module.go @@ -51,6 +51,7 @@ type StepShell struct { InstanceID string `bson:"instanceId,omitempty" json:"instanceId,omitempty"` ReportVisibility model.ReportVisibility `bson:"reportVisibility,omitempty" json:"reportVisibility,omitempty"` UserLabel string `bson:"userLabel,omitempty" json:"userLabel,omitempty"` + Comment string `bson:"comment,omitempty" json:"comment,omitempty"` PlannedMoney *paymenttypes.Money `bson:"plannedMoney,omitempty" json:"plannedMoney,omitempty"` PlannedConvertedMoney *paymenttypes.Money `bson:"plannedConvertedMoney,omitempty" json:"plannedConvertedMoney,omitempty"` } @@ -64,6 +65,7 @@ type StepExecution struct { InstanceID string `bson:"instanceId,omitempty" json:"instanceId,omitempty"` ReportVisibility model.ReportVisibility `bson:"reportVisibility,omitempty" json:"reportVisibility,omitempty"` UserLabel string `bson:"userLabel,omitempty" json:"userLabel,omitempty"` + Comment string `bson:"comment,omitempty" json:"comment,omitempty"` State StepState `bson:"state" json:"state"` Attempt uint32 `bson:"attempt" json:"attempt"` StartedAt *time.Time `bson:"startedAt,omitempty" json:"startedAt,omitempty"` diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/agg/service.go b/api/payments/orchestrator/internal/service/orchestrationv2/agg/service.go index 97e51d1c..2da2b2dd 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/agg/service.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/agg/service.go @@ -156,6 +156,7 @@ func buildInitialStepTelemetry(shell []StepShell) ([]StepExecution, error) { InstanceID: instanceID, ReportVisibility: visibility, UserLabel: userLabel, + Comment: strings.TrimSpace(shell[i].Comment), State: StepStatePending, Attempt: 1, PlannedMoney: svcshared.CloneMoneyTrimNonEmpty(shell[i].PlannedMoney), diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/batchmeta/module.go b/api/payments/orchestrator/internal/service/orchestrationv2/batchmeta/module.go index 3ed7be3d..1a5ffc66 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/batchmeta/module.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/batchmeta/module.go @@ -42,6 +42,7 @@ const ( type PayoutTarget struct { TargetRef string `json:"target_ref,omitempty"` IntentRef []string `json:"intent_refs,omitempty"` + Comment string `json:"comment,omitempty"` Amount *paymenttypes.Money `json:"amount,omitempty"` Card *model.CardEndpoint `json:"card,omitempty"` Customer *model.Customer `json:"customer,omitempty"` @@ -208,6 +209,7 @@ func normalizeTarget(target PayoutTarget, index int) PayoutTarget { target.TargetRef = "target-" + strconv.Itoa(index+1) } target.IntentRef = normalizeStringSlice(target.IntentRef) + target.Comment = strings.TrimSpace(target.Comment) if target.Amount != nil { amount := strings.TrimSpace(target.Amount.Amount) currency := strings.ToUpper(strings.TrimSpace(target.Amount.Currency)) diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/prepo/document.go b/api/payments/orchestrator/internal/service/orchestrationv2/prepo/document.go index 02c5a6fc..3ad6a367 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/prepo/document.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/prepo/document.go @@ -103,6 +103,7 @@ func cloneStepExecutions(src []agg.StepExecution) []agg.StepExecution { step.ReportVisibility = model.ReportVisibilityUnspecified } step.UserLabel = strings.TrimSpace(step.UserLabel) + step.Comment = strings.TrimSpace(step.Comment) step.FailureCode = strings.TrimSpace(step.FailureCode) step.FailureMsg = strings.TrimSpace(step.FailureMsg) if step.Attempt == 0 { diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/prepo/service.go b/api/payments/orchestrator/internal/service/orchestrationv2/prepo/service.go index 44a6961c..8bf01755 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/prepo/service.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/prepo/service.go @@ -529,6 +529,7 @@ func normalizePayment(payment *agg.Payment, requirePaymentRef bool) (*paymentDoc step := &doc.StepExecutions[i] step.StepRef = strings.TrimSpace(step.StepRef) step.StepCode = strings.TrimSpace(step.StepCode) + step.Comment = strings.TrimSpace(step.Comment) step.FailureCode = strings.TrimSpace(step.FailureCode) step.FailureMsg = strings.TrimSpace(step.FailureMsg) if step.StepRef == "" { diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/prmap/intent_mapping.go b/api/payments/orchestrator/internal/service/orchestrationv2/prmap/intent_mapping.go index a40ec8aa..d194e015 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/prmap/intent_mapping.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/prmap/intent_mapping.go @@ -36,7 +36,7 @@ func mapIntentSnapshot(src model.PaymentIntent) (*quotationv2.QuoteIntent, error SettlementMode: settlementMode, FeeTreatment: feeTreatment, SettlementCurrency: strings.ToUpper(strings.TrimSpace(src.SettlementCurrency)), - Comment: strings.TrimSpace(src.Attributes["comment"]), + Comment: strings.TrimSpace(src.Comment), }, nil } diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/prmap/service_test.go b/api/payments/orchestrator/internal/service/orchestrationv2/prmap/service_test.go index 165f201e..2942f155 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/prmap/service_test.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/prmap/service_test.go @@ -271,9 +271,7 @@ func newPaymentFixture() *agg.Payment { SettlementMode: model.SettlementModeFixSource, FeeTreatment: model.FeeTreatmentDeductFromDestination, SettlementCurrency: "USD", - Attributes: map[string]string{ - "comment": "invoice-7", - }, + Comment: "invoice-7", }, QuoteSnapshot: &model.PaymentQuoteSnapshot{ DebitAmount: &paymenttypes.Money{ diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/psvc/execute.go b/api/payments/orchestrator/internal/service/orchestrationv2/psvc/execute.go index e32fda86..79d7370f 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/psvc/execute.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/psvc/execute.go @@ -228,6 +228,7 @@ func toStepShells(graph *xplan.Graph, intent model.PaymentIntent, quote *model.P InstanceID: graph.Steps[i].InstanceID, ReportVisibility: graph.Steps[i].Visibility, UserLabel: graph.Steps[i].UserLabel, + Comment: graph.Steps[i].Comment, PlannedMoney: plannedMoney, PlannedConvertedMoney: plannedConverted, }) diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/psvc/execute_batch.go b/api/payments/orchestrator/internal/service/orchestrationv2/psvc/execute_batch.go index e93ae308..ecae880e 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/psvc/execute_batch.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/psvc/execute_batch.go @@ -320,6 +320,7 @@ func buildBatchPayoutTargets(group opagg.Group) []batchmeta.PayoutTarget { target := batchmeta.PayoutTarget{ TargetRef: firstNonEmpty(strings.TrimSpace(member.IntentRef), "recipient-"+strconv.Itoa(i+1)), IntentRef: normalizeIntentRefs([]string{member.IntentRef}), + Comment: strings.TrimSpace(member.IntentSnapshot.Comment), Amount: batchPayoutAmountFromMember(member), } if member.IntentSnapshot.Destination.Type == model.EndpointTypeCard && member.IntentSnapshot.Destination.Card != nil { @@ -344,6 +345,7 @@ func buildBatchPayoutTargets(group opagg.Group) []batchmeta.PayoutTarget { target := batchmeta.PayoutTarget{ TargetRef: firstNonEmpty(strings.TrimSpace(group.RecipientKey), "recipient-1"), IntentRef: normalizeIntentRefs(group.IntentRefs), + Comment: strings.TrimSpace(group.IntentSnapshot.Comment), Amount: batchPayoutAmount(group), } if group.IntentSnapshot.Destination.Type == model.EndpointTypeCard && group.IntentSnapshot.Destination.Card != nil { diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/psvc/execute_batch_test.go b/api/payments/orchestrator/internal/service/orchestrationv2/psvc/execute_batch_test.go index d2798b07..c4e32c75 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/psvc/execute_batch_test.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/psvc/execute_batch_test.go @@ -80,11 +80,13 @@ func TestExecuteBatchPayment_CardBatchCreatesPerTargetPayoutStepsWithoutMerging( var ( targetRefs []string amounts []string + comments []string ) env := newTestEnv(t, func(kind string, req sexec.StepRequest) (*sexec.ExecuteOutput, error) { if kind == "card_payout" { targetRefs = append(targetRefs, req.Step.Metadata[batchmeta.MetaPayoutTargetRef]) amounts = append(amounts, req.Step.Metadata[batchmeta.MetaAmount]) + comments = append(comments, req.Step.Comment) } step := req.StepExecution step.State = agg.StepStateCompleted @@ -116,15 +118,22 @@ func TestExecuteBatchPayment_CardBatchCreatesPerTargetPayoutStepsWithoutMerging( if got, want := len(amounts), 2; got != want { t.Fatalf("expected %d card payout amounts, got=%d", want, got) } + if got, want := len(comments), 2; got != want { + t.Fatalf("expected %d card payout comments, got=%d", want, got) + } sort.Strings(targetRefs) sort.Strings(amounts) + sort.Strings(comments) if targetRefs[0] == targetRefs[1] { t.Fatalf("expected distinct target refs, got=%v", targetRefs) } if got, want := amounts, []string{"100", "150"}; got[0] != want[0] || got[1] != want[1] { t.Fatalf("amount overrides mismatch: got=%v want=%v", got, want) } + if got, want := comments, []string{"batch-comment-a", "batch-comment-b"}; got[0] != want[0] || got[1] != want[1] { + t.Fatalf("comment overrides mismatch: got=%v want=%v", got, want) + } } func TestExecuteBatchPayment_CryptoPolicyMergesByDestination(t *testing.T) { @@ -343,9 +352,10 @@ func newExecutableBatchCardQuoteDiffDest(orgRef bson.ObjectID, quoteRef string) Items: []*model.PaymentQuoteItemV2{ { Intent: &model.PaymentIntent{ - Ref: "intent-a", - Kind: model.PaymentKindPayout, - Source: testLedgerEndpoint("ledger-src"), + Ref: "intent-a", + Kind: model.PaymentKindPayout, + Comment: "batch-comment-a", + Source: testLedgerEndpoint("ledger-src"), Destination: model.PaymentEndpoint{ Type: model.EndpointTypeCard, Card: &model.CardEndpoint{ @@ -372,9 +382,10 @@ func newExecutableBatchCardQuoteDiffDest(orgRef bson.ObjectID, quoteRef string) }, { Intent: &model.PaymentIntent{ - Ref: "intent-b", - Kind: model.PaymentKindPayout, - Source: testLedgerEndpoint("ledger-src"), + Ref: "intent-b", + Kind: model.PaymentKindPayout, + Comment: "batch-comment-b", + Source: testLedgerEndpoint("ledger-src"), Destination: model.PaymentEndpoint{ Type: model.EndpointTypeCard, Card: &model.CardEndpoint{ diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/psvc/runtime.go b/api/payments/orchestrator/internal/service/orchestrationv2/psvc/runtime.go index a8d4dbd1..50cbc507 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/psvc/runtime.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/psvc/runtime.go @@ -325,6 +325,7 @@ func normalizeExecutorOutput(current agg.StepExecution, out *sexec.ExecuteOutput if out.StepExecution.Attempt != 0 { next.Attempt = out.StepExecution.Attempt } + next.Comment = strings.TrimSpace(out.StepExecution.Comment) next.ExternalRefs = out.StepExecution.ExternalRefs next.ExecutedMoney = svcshared.CloneMoneyTrimNonEmpty(out.StepExecution.ExecutedMoney) next.ConvertedMoney = svcshared.CloneMoneyTrimNonEmpty(out.StepExecution.ConvertedMoney) @@ -431,6 +432,9 @@ func stepExecutionEqual(left, right agg.StepExecution) bool { if strings.TrimSpace(left.FailureMsg) != strings.TrimSpace(right.FailureMsg) { return false } + if strings.TrimSpace(left.Comment) != strings.TrimSpace(right.Comment) { + return false + } if !timePtrEqual(left.StartedAt, right.StartedAt) || !timePtrEqual(left.CompletedAt, right.CompletedAt) { return false } diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/sexec/service.go b/api/payments/orchestrator/internal/service/orchestrationv2/sexec/service.go index adb09675..bf849815 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/sexec/service.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/sexec/service.go @@ -114,6 +114,7 @@ func validateInput(in ExecuteInput) (StepRequest, error) { func normalizeStep(step xplan.Step) (xplan.Step, error) { step.StepRef = strings.TrimSpace(step.StepRef) step.StepCode = strings.TrimSpace(step.StepCode) + step.Comment = strings.TrimSpace(step.Comment) if step.StepRef == "" { return xplan.Step{}, merrors.InvalidArgument("step.step_ref is required") } @@ -126,6 +127,7 @@ func normalizeStep(step xplan.Step) (xplan.Step, error) { func normalizeStepExecution(exec agg.StepExecution, step xplan.Step) (agg.StepExecution, error) { exec.StepRef = strings.TrimSpace(exec.StepRef) exec.StepCode = strings.TrimSpace(exec.StepCode) + exec.Comment = strings.TrimSpace(exec.Comment) if exec.StepRef == "" { exec.StepRef = step.StepRef } diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/ssched/input.go b/api/payments/orchestrator/internal/service/orchestrationv2/ssched/input.go index c6162de6..ca5cb375 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/ssched/input.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/ssched/input.go @@ -64,6 +64,7 @@ func (s *svc) prepareInput(in Input) (*preparedInput, error) { func normalizeGraphStep(step xplan.Step, index int) (xplan.Step, error) { step.StepRef = strings.TrimSpace(step.StepRef) step.StepCode = strings.TrimSpace(step.StepCode) + step.Comment = strings.TrimSpace(step.Comment) if step.StepRef == "" { return xplan.Step{}, merrors.InvalidArgument("steps[" + itoa(index) + "].step_ref is required") } @@ -157,6 +158,9 @@ func (s *svc) normalizeStepExecutions( if strings.TrimSpace(exec.InstanceID) == "" { exec.InstanceID = strings.TrimSpace(step.InstanceID) } + if strings.TrimSpace(exec.Comment) == "" { + exec.Comment = strings.TrimSpace(step.Comment) + } exec.ReportVisibility = effectiveStepVisibility(exec.ReportVisibility, stepsByRef[stepRef].Visibility) exec.UserLabel = firstNonEmpty(exec.UserLabel, stepsByRef[stepRef].UserLabel) cloned := cloneStepExecution(exec) @@ -168,6 +172,7 @@ func (s *svc) normalizeStepExecutions( func (s *svc) normalizeStepExecution(exec agg.StepExecution, index int) (agg.StepExecution, error) { exec.StepRef = strings.TrimSpace(exec.StepRef) exec.StepCode = strings.TrimSpace(exec.StepCode) + exec.Comment = strings.TrimSpace(exec.Comment) exec.FailureCode = strings.TrimSpace(exec.FailureCode) exec.FailureMsg = strings.TrimSpace(exec.FailureMsg) exec.UserLabel = strings.TrimSpace(exec.UserLabel) @@ -220,6 +225,7 @@ func seedMissingExecutions( Rail: step.Rail, Gateway: strings.TrimSpace(step.Gateway), InstanceID: strings.TrimSpace(step.InstanceID), + Comment: strings.TrimSpace(step.Comment), ReportVisibility: effectiveStepVisibility(model.ReportVisibilityUnspecified, step.Visibility), UserLabel: strings.TrimSpace(step.UserLabel), State: agg.StepStatePending, diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/xplan/compile_batch_targets_test.go b/api/payments/orchestrator/internal/service/orchestrationv2/xplan/compile_batch_targets_test.go index f00a8daa..10e72ac7 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/xplan/compile_batch_targets_test.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/xplan/compile_batch_targets_test.go @@ -14,11 +14,13 @@ func TestCompile_InternalToCard_WithBatchTargetsExpandsPerRecipientPayoutBranche targetsRaw, err := batchmeta.EncodePayoutTargets([]batchmeta.PayoutTarget{ { TargetRef: "recipient-1", + Comment: "batch-comment-1", Amount: &paymenttypes.Money{Amount: "100", Currency: "RUB"}, Card: &model.CardEndpoint{Pan: "2200700142860161", ExpMonth: 3, ExpYear: 2030}, }, { TargetRef: "recipient-2", + Comment: "batch-comment-2", Amount: &paymenttypes.Money{Amount: "150", Currency: "RUB"}, Card: &model.CardEndpoint{Pan: "2200700142860162", ExpMonth: 4, ExpYear: 2030}, }, @@ -69,6 +71,7 @@ func TestCompile_InternalToCard_WithBatchTargetsExpandsPerRecipientPayoutBranche } seenTargets := map[string]string{} + seenComments := map[string]string{} for i := range sendSteps { step := sendSteps[i] if got, want := step.DependsOn, []string{graph.Steps[0].StepRef}; !equalStringSlice(got, want) { @@ -76,10 +79,12 @@ func TestCompile_InternalToCard_WithBatchTargetsExpandsPerRecipientPayoutBranche } targetRef := step.Metadata[batchmeta.MetaPayoutTargetRef] amount := step.Metadata[batchmeta.MetaAmount] - if targetRef == "" || amount == "" { - t.Fatalf("expected target metadata on send step, got=%v", step.Metadata) + comment := step.Comment + if targetRef == "" || amount == "" || comment == "" { + t.Fatalf("expected target fields on send step, metadata=%v comment=%q", step.Metadata, step.Comment) } seenTargets[targetRef] = amount + seenComments[targetRef] = comment } if got, want := seenTargets["recipient-1"], "100"; got != want { t.Fatalf("recipient-1 amount mismatch: got=%q want=%q", got, want) @@ -87,4 +92,10 @@ func TestCompile_InternalToCard_WithBatchTargetsExpandsPerRecipientPayoutBranche if got, want := seenTargets["recipient-2"], "150"; got != want { t.Fatalf("recipient-2 amount mismatch: got=%q want=%q", got, want) } + if got, want := seenComments["recipient-1"], "batch-comment-1"; got != want { + t.Fatalf("recipient-1 comment mismatch: got=%q want=%q", got, want) + } + if got, want := seenComments["recipient-2"], "batch-comment-2"; got != want { + t.Fatalf("recipient-2 comment mismatch: got=%q want=%q", got, want) + } } diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/xplan/expansion.go b/api/payments/orchestrator/internal/service/orchestrationv2/xplan/expansion.go index 7a50ee2c..e36c8fa2 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/xplan/expansion.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/xplan/expansion.go @@ -81,6 +81,7 @@ func normalizeStep(step Step) Step { step.Gateway = strings.TrimSpace(step.Gateway) step.InstanceID = strings.TrimSpace(step.InstanceID) step.UserLabel = strings.TrimSpace(step.UserLabel) + step.Comment = strings.TrimSpace(step.Comment) step.Visibility = model.NormalizeReportVisibility(step.Visibility) step.CommitPolicy = normalizeCommitPolicy(step.CommitPolicy) step.DependsOn = normalizeStringList(step.DependsOn) diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/xplan/fee_planning.go b/api/payments/orchestrator/internal/service/orchestrationv2/xplan/fee_planning.go index 8afefe75..ba8ff73b 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/xplan/fee_planning.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/xplan/fee_planning.go @@ -21,12 +21,12 @@ func planFeeHops( return nil, err } if !hasFee { - return nil, nil + return map[string]struct{}{}, nil } sourceHop, ok := sourceFeeHop(hops) if !ok { - return nil, nil + return map[string]struct{}{}, nil } return map[string]struct{}{ observedKey(sourceHop): {}, diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/xplan/module.go b/api/payments/orchestrator/internal/service/orchestrationv2/xplan/module.go index a00b74fc..a5b87d76 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/xplan/module.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/xplan/module.go @@ -56,6 +56,7 @@ type Step struct { HopRole paymenttypes.QuoteRouteHopRole Visibility model.ReportVisibility UserLabel string + Comment string CommitPolicy model.CommitPolicy CommitAfter []string Metadata map[string]string diff --git a/api/payments/orchestrator/internal/service/orchestrationv2/xplan/service_boundaries.go b/api/payments/orchestrator/internal/service/orchestrationv2/xplan/service_boundaries.go index 304abafe..b3953a8e 100644 --- a/api/payments/orchestrator/internal/service/orchestrationv2/xplan/service_boundaries.go +++ b/api/payments/orchestrator/internal/service/orchestrationv2/xplan/service_boundaries.go @@ -123,14 +123,17 @@ func (s *svc) applyBatchCardPayoutBoundary( return merrors.InvalidArgument("intent_snapshot.attributes[" + batchmeta.AttrPayoutTargets + "]: card is required for each target") } targetMeta := batchmeta.StepMetadataForTarget(target, i) + targetComment := strings.TrimSpace(target.Comment) sendStep := makeRailSendStep(to, intent) sendStep.DependsOn = []string{blockRef} + sendStep.Comment = targetComment sendStep.Metadata = cloneMetadata(targetMeta) sendRef := ex.appendBranch(sendStep) observeStep := makeRailObserveStep(to, intent) observeStep.DependsOn = []string{sendRef} + observeStep.Comment = targetComment observeStep.Metadata = cloneMetadata(targetMeta) observeRef := ex.appendBranch(observeStep) diff --git a/api/payments/orchestrator/internal/service/orchestrator/card_payout_executor.go b/api/payments/orchestrator/internal/service/orchestrator/card_payout_executor.go index b16e66b8..195aee07 100644 --- a/api/payments/orchestrator/internal/service/orchestrator/card_payout_executor.go +++ b/api/payments/orchestrator/internal/service/orchestrator/card_payout_executor.go @@ -79,6 +79,7 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s customer := cardPayoutCustomerFromPayment(req.Payment, card, req.Step.Metadata) cardHolder := cardPayoutCardholder(card, customer) metadata := cardPayoutMetadata(req.Payment, req.Step) + comment := destinationOperationComment(req.Payment, req.Step) intentRef := strings.TrimSpace(req.Payment.IntentSnapshot.Ref) var responsePayout *mntxv1.CardPayoutState @@ -102,6 +103,7 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s CardHolder: cardHolder, MaskedPan: strings.TrimSpace(card.MaskedPan), Metadata: metadata, + Comment: comment, OperationRef: operationRef, IdempotencyKey: idempotencyKey, IntentRef: intentRef, @@ -141,6 +143,7 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s CardExpMonth: card.ExpMonth, CardHolder: cardHolder, Metadata: metadata, + Comment: comment, OperationRef: operationRef, IdempotencyKey: idempotencyKey, IntentRef: intentRef, @@ -177,6 +180,7 @@ func (e *gatewayCardPayoutExecutor) ExecuteCardPayout(ctx context.Context, req s step.ConvertedMoney = nil step.FailureCode = "" step.FailureMsg = "" + assignDestinationStepComment(&step, req.Payment, req.Step) return &sexec.ExecuteOutput{StepExecution: step}, nil } diff --git a/api/payments/orchestrator/internal/service/orchestrator/card_payout_executor_test.go b/api/payments/orchestrator/internal/service/orchestrator/card_payout_executor_test.go index b2866c3a..0a476b66 100644 --- a/api/payments/orchestrator/internal/service/orchestrator/card_payout_executor_test.go +++ b/api/payments/orchestrator/internal/service/orchestrator/card_payout_executor_test.go @@ -58,7 +58,8 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_SubmitsCardPayout(t *testin IdempotencyKey: "idem-1", QuotationRef: "quote-1", IntentSnapshot: model.PaymentIntent{ - Ref: "intent-1", + Ref: "intent-1", + Comment: "invoice-1", Destination: model.PaymentEndpoint{ Type: model.EndpointTypeCard, Card: &model.CardEndpoint{ @@ -98,6 +99,7 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_SubmitsCardPayout(t *testin Rail: discovery.RailCardPayout, Gateway: paymenttypes.DefaultCardsGatewayID, InstanceID: paymenttypes.DefaultCardsGatewayID, + HopRole: paymenttypes.QuoteRouteHopRoleDestination, }, StepExecution: agg.StepExecution{ StepRef: "hop_4_card_payout_send", @@ -156,6 +158,15 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_SubmitsCardPayout(t *testin if got, want := payoutReq.GetMetadata()[settlementMetadataOutgoingLeg], string(discovery.RailCardPayout); got != want { t.Fatalf("outgoing_leg metadata mismatch: got=%q want=%q", got, want) } + if got, want := payoutReq.GetComment(), "invoice-1"; got != want { + t.Fatalf("comment mismatch: got=%q want=%q", got, want) + } + if _, ok := payoutReq.GetMetadata()["comment"]; ok { + t.Fatalf("comment must not be sent in metadata") + } + if got, want := out.StepExecution.Comment, "invoice-1"; got != want { + t.Fatalf("step comment mismatch: got=%q want=%q", got, want) + } if got, want := payoutReq.GetParentPaymentRef(), "payment-1"; got != want { t.Fatalf("parent_payment_ref mismatch: got=%q want=%q", got, want) } @@ -324,6 +335,7 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_UsesStepMetadataOverrides(t Rail: discovery.RailCardPayout, Gateway: paymenttypes.DefaultCardsGatewayID, InstanceID: paymenttypes.DefaultCardsGatewayID, + Comment: "batch-note-2", Metadata: map[string]string{ batchmeta.MetaPayoutTargetRef: "recipient-2", batchmeta.MetaAmount: "150", @@ -332,6 +344,7 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_UsesStepMetadataOverrides(t batchmeta.MetaCardExpMonth: "4", batchmeta.MetaCardExpYear: "2030", }, + HopRole: paymenttypes.QuoteRouteHopRoleDestination, }, StepExecution: agg.StepExecution{ StepRef: "hop_4_card_payout_send", @@ -368,6 +381,12 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_UsesStepMetadataOverrides(t if got, want := payoutReq.GetMetadata()[batchmeta.MetaPayoutTargetRef], "recipient-2"; got != want { t.Fatalf("target_ref metadata mismatch: got=%q want=%q", got, want) } + if got, want := payoutReq.GetComment(), "batch-note-2"; got != want { + t.Fatalf("comment mismatch: got=%q want=%q", got, want) + } + if _, ok := payoutReq.GetMetadata()["comment"]; ok { + t.Fatalf("comment must not be sent in metadata") + } if got, want := payoutReq.GetParentPaymentRef(), "payment-2"; got != want { t.Fatalf("parent_payment_ref mismatch: got=%q want=%q", got, want) } @@ -450,7 +469,8 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_BatchChildrenUseDistinctOpe IdempotencyKey: "idem-3", QuotationRef: "quote-3", IntentSnapshot: model.PaymentIntent{ - Ref: "intent-3", + Ref: "intent-3", + Comment: "group-default-comment", Destination: model.PaymentEndpoint{ Type: model.EndpointTypeCard, Card: &model.CardEndpoint{ @@ -488,6 +508,7 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_BatchChildrenUseDistinctOpe Rail: discovery.RailCardPayout, Gateway: paymenttypes.DefaultCardsGatewayID, InstanceID: paymenttypes.DefaultCardsGatewayID, + HopRole: paymenttypes.QuoteRouteHopRoleDestination, }, StepExecution: agg.StepExecution{ StepRef: "hop_4_card_payout_send", @@ -504,6 +525,7 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_BatchChildrenUseDistinctOpe Rail: discovery.RailCardPayout, Gateway: paymenttypes.DefaultCardsGatewayID, InstanceID: paymenttypes.DefaultCardsGatewayID, + Comment: "recipient-2-comment", Metadata: map[string]string{ batchmeta.MetaPayoutTargetRef: "recipient-2", batchmeta.MetaAmount: "150", @@ -512,6 +534,7 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_BatchChildrenUseDistinctOpe batchmeta.MetaCardExpMonth: "4", batchmeta.MetaCardExpYear: "2030", }, + HopRole: paymenttypes.QuoteRouteHopRoleDestination, }, StepExecution: agg.StepExecution{ StepRef: "hop_4_card_payout_send_2", @@ -545,6 +568,18 @@ func TestGatewayCardPayoutExecutor_ExecuteCardPayout_BatchChildrenUseDistinctOpe if got, want := payoutReqs[1].GetParentPaymentRef(), "payment-3"; got != want { t.Fatalf("second parent_payment_ref mismatch: got=%q want=%q", got, want) } + if got, want := payoutReqs[0].GetComment(), "group-default-comment"; got != want { + t.Fatalf("first comment mismatch: got=%q want=%q", got, want) + } + if got, want := payoutReqs[1].GetComment(), "recipient-2-comment"; got != want { + t.Fatalf("second comment mismatch: got=%q want=%q", got, want) + } + if _, ok := payoutReqs[0].GetMetadata()["comment"]; ok { + t.Fatalf("first comment must not be sent in metadata") + } + if _, ok := payoutReqs[1].GetMetadata()["comment"]; ok { + t.Fatalf("second comment must not be sent in metadata") + } if payoutReqs[0].GetCardPan() == payoutReqs[1].GetCardPan() { t.Fatalf("expected different destination cards across child operations") } diff --git a/api/payments/orchestrator/internal/service/orchestrator/crypto_executor.go b/api/payments/orchestrator/internal/service/orchestrator/crypto_executor.go index 099126ff..d81a3dbf 100644 --- a/api/payments/orchestrator/internal/service/orchestrator/crypto_executor.go +++ b/api/payments/orchestrator/internal/service/orchestrator/crypto_executor.go @@ -102,6 +102,7 @@ func (e *gatewayCryptoExecutor) ExecuteCrypto(ctx context.Context, req sexec.Ste step.State = agg.StepStateCompleted step.FailureCode = "" step.FailureMsg = "" + assignDestinationStepComment(&step, req.Payment, req.Step) return &sexec.ExecuteOutput{StepExecution: step}, nil } diff --git a/api/payments/orchestrator/internal/service/orchestrator/crypto_executor_test.go b/api/payments/orchestrator/internal/service/orchestrator/crypto_executor_test.go index 3b9cf16b..51a89d37 100644 --- a/api/payments/orchestrator/internal/service/orchestrator/crypto_executor_test.go +++ b/api/payments/orchestrator/internal/service/orchestrator/crypto_executor_test.go @@ -138,6 +138,88 @@ func TestGatewayCryptoExecutor_ExecuteCrypto_SubmitsTransfer(t *testing.T) { } } +func TestGatewayCryptoExecutor_ExecuteCrypto_AttachesCommentForDestinationHop(t *testing.T) { + orgID := bson.NewObjectID() + + var submitReq *chainv1.SubmitTransferRequest + client := &chainclient.Fake{ + SubmitTransferFn: func(_ context.Context, req *chainv1.SubmitTransferRequest) (*chainv1.SubmitTransferResponse, error) { + submitReq = req + return &chainv1.SubmitTransferResponse{ + Transfer: &chainv1.Transfer{ + TransferRef: "trf-comment", + OperationRef: "op-comment", + }, + }, nil + }, + } + executor := &gatewayCryptoExecutor{ + gatewayInvokeResolver: &fakeGatewayInvokeResolver{client: client}, + gatewayRegistry: &fakeGatewayRegistry{ + items: []*model.GatewayInstanceDescriptor{ + { + ID: "crypto_rail_gateway_arbitrum_sepolia", + InstanceID: "crypto_rail_gateway_arbitrum_sepolia", + Rail: discovery.RailCrypto, + InvokeURI: "grpc://crypto-gateway", + IsEnabled: true, + }, + }, + }, + } + + out, err := executor.ExecuteCrypto(context.Background(), sexec.StepRequest{ + Payment: &agg.Payment{ + OrganizationBoundBase: pm.OrganizationBoundBase{OrganizationRef: orgID}, + PaymentRef: "payment-comment", + IdempotencyKey: "idem-comment", + IntentSnapshot: model.PaymentIntent{ + Ref: "intent-comment", + Comment: "invoice-crypto-7", + Source: model.PaymentEndpoint{ + Type: model.EndpointTypeManagedWallet, + ManagedWallet: &model.ManagedWalletEndpoint{ + ManagedWalletRef: "wallet-src", + }, + }, + Destination: model.PaymentEndpoint{ + Type: model.EndpointTypeExternalChain, + ExternalChain: &model.ExternalChainEndpoint{ + Address: "TXYZdst", + }, + }, + Amount: &paymenttypes.Money{Amount: "1", Currency: "USDT"}, + }, + }, + Step: xplan.Step{ + StepRef: "hop_2_crypto_send", + StepCode: "hop.2.crypto.send", + Action: discovery.RailOperationSend, + Rail: discovery.RailCrypto, + Gateway: "crypto_rail_gateway_arbitrum_sepolia", + InstanceID: "crypto_rail_gateway_arbitrum_sepolia", + HopRole: paymenttypes.QuoteRouteHopRoleDestination, + }, + StepExecution: agg.StepExecution{ + StepRef: "hop_2_crypto_send", + StepCode: "hop.2.crypto.send", + Attempt: 1, + }, + }) + if err != nil { + t.Fatalf("ExecuteCrypto returned error: %v", err) + } + if submitReq == nil { + t.Fatal("expected transfer submission request") + } + if out == nil { + t.Fatal("expected output") + } + if got, want := out.StepExecution.Comment, "invoice-crypto-7"; got != want { + t.Fatalf("step comment mismatch: got=%q want=%q", got, want) + } +} + func TestGatewayCryptoExecutor_ExecuteCrypto_UsesPlannedMoney(t *testing.T) { orgID := bson.NewObjectID() diff --git a/api/payments/orchestrator/internal/service/orchestrator/destination_comment.go b/api/payments/orchestrator/internal/service/orchestrator/destination_comment.go new file mode 100644 index 00000000..ecac498e --- /dev/null +++ b/api/payments/orchestrator/internal/service/orchestrator/destination_comment.go @@ -0,0 +1,29 @@ +package orchestrator + +import ( + "strings" + + "github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/agg" + "github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/xplan" + paymenttypes "github.com/tech/sendico/pkg/payments/types" +) + +func destinationOperationComment(payment *agg.Payment, step xplan.Step) string { + if step.HopRole != paymenttypes.QuoteRouteHopRoleDestination { + return "" + } + if comment := strings.TrimSpace(step.Comment); comment != "" { + return comment + } + if payment == nil { + return "" + } + return strings.TrimSpace(payment.IntentSnapshot.Comment) +} + +func assignDestinationStepComment(stepExecution *agg.StepExecution, payment *agg.Payment, step xplan.Step) { + if stepExecution == nil { + return + } + stepExecution.Comment = destinationOperationComment(payment, step) +} diff --git a/api/payments/orchestrator/internal/service/orchestrator/destination_comment_test.go b/api/payments/orchestrator/internal/service/orchestrator/destination_comment_test.go new file mode 100644 index 00000000..6928c644 --- /dev/null +++ b/api/payments/orchestrator/internal/service/orchestrator/destination_comment_test.go @@ -0,0 +1,80 @@ +package orchestrator + +import ( + "testing" + + "github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/agg" + "github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/xplan" + "github.com/tech/sendico/payments/storage/model" + paymenttypes "github.com/tech/sendico/pkg/payments/types" +) + +func TestDestinationOperationComment_AssignsCommentByDestinationHopRole(t *testing.T) { + comment := destinationOperationComment( + &agg.Payment{IntentSnapshot: model.PaymentIntent{Comment: " invoice-7 "}}, + xplan.Step{HopRole: paymenttypes.QuoteRouteHopRoleDestination}, + ) + + if got, want := comment, "invoice-7"; got != want { + t.Fatalf("comment mismatch: got=%q want=%q", got, want) + } +} + +func TestDestinationOperationComment_DoesNotAssignForNonDestinationHop(t *testing.T) { + comment := destinationOperationComment( + &agg.Payment{IntentSnapshot: model.PaymentIntent{Comment: "invoice-7"}}, + xplan.Step{HopRole: paymenttypes.QuoteRouteHopRoleSource}, + ) + + if comment != "" { + t.Fatalf("comment must not be set for non-destination hop") + } +} + +func TestDestinationOperationComment_PrefersPerTargetComment(t *testing.T) { + comment := destinationOperationComment( + &agg.Payment{IntentSnapshot: model.PaymentIntent{Comment: "payment-comment"}}, + xplan.Step{ + HopRole: paymenttypes.QuoteRouteHopRoleDestination, + Comment: " recipient-comment ", + }, + ) + + if got, want := comment, "recipient-comment"; got != want { + t.Fatalf("comment mismatch: got=%q want=%q", got, want) + } +} + +func TestAssignDestinationStepComment_AssignsForDestinationHop(t *testing.T) { + stepExecution := agg.StepExecution{} + assignDestinationStepComment( + &stepExecution, + &agg.Payment{IntentSnapshot: model.PaymentIntent{Comment: " invoice-8 "}}, + xplan.Step{ + StepRef: "hop_4", + StepCode: "hop.4.card.send", + HopRole: paymenttypes.QuoteRouteHopRoleDestination, + }, + ) + + if got, want := stepExecution.Comment, "invoice-8"; got != want { + t.Fatalf("step comment mismatch: got=%q want=%q", got, want) + } +} + +func TestAssignDestinationStepComment_ClearsForNonDestinationHop(t *testing.T) { + stepExecution := agg.StepExecution{Comment: "old-value"} + assignDestinationStepComment( + &stepExecution, + &agg.Payment{IntentSnapshot: model.PaymentIntent{Comment: "invoice-8"}}, + xplan.Step{ + StepRef: "hop_1", + StepCode: "hop.1.crypto.send", + HopRole: paymenttypes.QuoteRouteHopRoleSource, + }, + ) + + if got := stepExecution.Comment; got != "" { + t.Fatalf("step comment must be empty for non-destination hop, got=%q", got) + } +} diff --git a/api/payments/orchestrator/internal/service/orchestrator/settlement_executor.go b/api/payments/orchestrator/internal/service/orchestrator/settlement_executor.go index 7ed054f7..00314408 100644 --- a/api/payments/orchestrator/internal/service/orchestrator/settlement_executor.go +++ b/api/payments/orchestrator/internal/service/orchestrator/settlement_executor.go @@ -104,6 +104,7 @@ func (e *gatewayProviderSettlementExecutor) ExecuteProviderSettlement(ctx contex step.State = agg.StepStateCompleted step.FailureCode = "" step.FailureMsg = "" + assignDestinationStepComment(&step, req.Payment, req.Step) return &sexec.ExecuteOutput{StepExecution: step}, nil } diff --git a/api/payments/orchestrator/internal/service/orchestrator/settlement_executor_test.go b/api/payments/orchestrator/internal/service/orchestrator/settlement_executor_test.go index 352718df..996ad613 100644 --- a/api/payments/orchestrator/internal/service/orchestrator/settlement_executor_test.go +++ b/api/payments/orchestrator/internal/service/orchestrator/settlement_executor_test.go @@ -241,6 +241,87 @@ func TestGatewayProviderSettlementExecutor_ExecuteProviderSettlement_UsesPlanned } } +func TestGatewayProviderSettlementExecutor_ExecuteProviderSettlement_AssignsDestinationComment(t *testing.T) { + orgID := bson.NewObjectID() + + var submitReq *chainv1.SubmitTransferRequest + executor := &gatewayProviderSettlementExecutor{ + gatewayInvokeResolver: &fakeGatewayInvokeResolver{ + client: &chainclient.Fake{ + SubmitTransferFn: func(_ context.Context, req *chainv1.SubmitTransferRequest) (*chainv1.SubmitTransferResponse, error) { + submitReq = req + return &chainv1.SubmitTransferResponse{ + Transfer: &chainv1.Transfer{ + TransferRef: "trf-comment", + OperationRef: "op-comment", + }, + }, nil + }, + }, + }, + gatewayRegistry: &fakeGatewayRegistry{ + items: []*model.GatewayInstanceDescriptor{ + { + ID: "payment_gateway_settlement", + InstanceID: "payment_gateway_settlement", + Rail: discovery.RailProviderSettlement, + InvokeURI: "grpc://tgsettle-gateway", + IsEnabled: true, + }, + }, + }, + } + + out, err := executor.ExecuteProviderSettlement(context.Background(), sexec.StepRequest{ + Payment: &agg.Payment{ + OrganizationBoundBase: pm.OrganizationBoundBase{OrganizationRef: orgID}, + PaymentRef: "payment-comment", + IdempotencyKey: "idem-comment", + IntentSnapshot: model.PaymentIntent{ + Ref: "intent-comment", + Comment: "settlement-note-1", + Source: model.PaymentEndpoint{ + Type: model.EndpointTypeManagedWallet, + ManagedWallet: &model.ManagedWalletEndpoint{ + ManagedWalletRef: "wallet-src", + }, + }, + Amount: &paymenttypes.Money{Amount: "1.000000", Currency: "USDT"}, + }, + QuoteSnapshot: &model.PaymentQuoteSnapshot{ + DebitAmount: &paymenttypes.Money{Amount: "1.000000", Currency: "USDT"}, + ExpectedSettlementAmount: &paymenttypes.Money{Amount: "76.63", Currency: "RUB"}, + }, + }, + Step: xplan.Step{ + StepRef: "hop_2_settlement_fx_convert", + StepCode: "hop.2.settlement.fx_convert", + Action: discovery.RailOperationFXConvert, + Rail: discovery.RailProviderSettlement, + Gateway: "payment_gateway_settlement", + InstanceID: "payment_gateway_settlement", + HopRole: paymenttypes.QuoteRouteHopRoleDestination, + }, + StepExecution: agg.StepExecution{ + StepRef: "hop_2_settlement_fx_convert", + StepCode: "hop.2.settlement.fx_convert", + Attempt: 1, + }, + }) + if err != nil { + t.Fatalf("ExecuteProviderSettlement returned error: %v", err) + } + if submitReq == nil { + t.Fatal("expected transfer submission request") + } + if out == nil { + t.Fatal("expected output") + } + if got, want := out.StepExecution.Comment, "settlement-note-1"; got != want { + t.Fatalf("step comment mismatch: got=%q want=%q", got, want) + } +} + func TestGatewayProviderSettlementExecutor_ExecuteProviderSettlement_MissingSettlementAmount(t *testing.T) { orgID := bson.NewObjectID() diff --git a/api/payments/quotation/go.mod b/api/payments/quotation/go.mod index a8afd5bd..6b8d7f30 100644 --- a/api/payments/quotation/go.mod +++ b/api/payments/quotation/go.mod @@ -58,7 +58,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/net v0.51.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect diff --git a/api/payments/quotation/go.sum b/api/payments/quotation/go.sum index 9527fc9a..d24bb294 100644 --- a/api/payments/quotation/go.sum +++ b/api/payments/quotation/go.sum @@ -175,8 +175,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/payments/quotation/internal/service/quotation/quote_computation_service/intent_adapters.go b/api/payments/quotation/internal/service/quotation/quote_computation_service/intent_adapters.go index 4edb5bb7..cc73b5ae 100644 --- a/api/payments/quotation/internal/service/quotation/quote_computation_service/intent_adapters.go +++ b/api/payments/quotation/internal/service/quotation/quote_computation_service/intent_adapters.go @@ -32,6 +32,7 @@ func modelIntentFromQuoteIntent(src *transfer_intent_hydrator.QuoteIntent) model Source: modelEndpointFromQuoteEndpoint(src.Source), Destination: modelEndpointFromQuoteEndpoint(src.Destination), Amount: cloneModelMoney(src.Amount), + Comment: strings.TrimSpace(src.Comment), FX: fxIntentFromHydratedIntent(src), RequiresFX: src.RequiresFX, Attributes: cloneStringMap(src.Attributes), diff --git a/api/payments/quotation/internal/service/quotation/transfer_intent_hydrator/hydrator.go b/api/payments/quotation/internal/service/quotation/transfer_intent_hydrator/hydrator.go index f4d97585..10139441 100644 --- a/api/payments/quotation/internal/service/quotation/transfer_intent_hydrator/hydrator.go +++ b/api/payments/quotation/internal/service/quotation/transfer_intent_hydrator/hydrator.go @@ -149,9 +149,6 @@ func (h *TransferIntentHydrator) HydrateOne(ctx context.Context, in HydrateOneIn "initiator_ref": strings.TrimSpace(in.InitiatorRef), }, } - if intent.Comment != "" { - intent.Attributes["comment"] = intent.Comment - } return intent, nil } diff --git a/api/payments/quotation/internal/service/quotation/transfer_intent_hydrator/transfer_intent_hydrator_test.go b/api/payments/quotation/internal/service/quotation/transfer_intent_hydrator/transfer_intent_hydrator_test.go index 97d654d0..3f2d37d8 100644 --- a/api/payments/quotation/internal/service/quotation/transfer_intent_hydrator/transfer_intent_hydrator_test.go +++ b/api/payments/quotation/internal/service/quotation/transfer_intent_hydrator/transfer_intent_hydrator_test.go @@ -99,6 +99,12 @@ func TestHydrateOne_SuccessWithInlineMethods(t *testing.T) { if got.Amount == nil || got.Amount.Amount != "10.25" { t.Fatalf("unexpected amount: %#v", got.Amount) } + if got.Comment != "transfer note" { + t.Fatalf("unexpected comment: got=%q", got.Comment) + } + if _, ok := got.Attributes["comment"]; ok { + t.Fatalf("comment must not be persisted in attributes") + } } func TestHydrateOne_PropagatesFXIntent(t *testing.T) { diff --git a/api/payments/storage/go.mod b/api/payments/storage/go.mod index 13ec7773..8330aabb 100644 --- a/api/payments/storage/go.mod +++ b/api/payments/storage/go.mod @@ -35,7 +35,7 @@ require ( github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.49.0 // indirect golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.42.0 // indirect golang.org/x/text v0.35.0 // indirect diff --git a/api/payments/storage/go.sum b/api/payments/storage/go.sum index bff89996..012b241f 100644 --- a/api/payments/storage/go.sum +++ b/api/payments/storage/go.sum @@ -158,8 +158,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/api/payments/storage/model/payment.go b/api/payments/storage/model/payment.go index eb7568bf..39e47c3c 100644 --- a/api/payments/storage/model/payment.go +++ b/api/payments/storage/model/payment.go @@ -214,6 +214,7 @@ type PaymentIntent struct { Source PaymentEndpoint `bson:"source" json:"source"` Destination PaymentEndpoint `bson:"destination" json:"destination"` Amount *paymenttypes.Money `bson:"amount" json:"amount"` + Comment string `bson:"comment,omitempty" json:"comment,omitempty"` RequiresFX bool `bson:"requiresFx,omitempty" json:"requiresFx,omitempty"` FX *FXIntent `bson:"fx,omitempty" json:"fx,omitempty"` FeePolicy *paymenttypes.FeePolicy `bson:"feePolicy,omitempty" json:"feePolicy,omitempty"` @@ -399,6 +400,7 @@ func (p *Payment) Normalize() { p.Intent.Attributes[k] = strings.TrimSpace(v) } } + p.Intent.Comment = strings.TrimSpace(p.Intent.Comment) p.Intent.FeeTreatment = FeeTreatment(strings.TrimSpace(string(p.Intent.FeeTreatment))) p.Intent.SettlementCurrency = strings.TrimSpace(p.Intent.SettlementCurrency) if p.Intent.Customer != nil { diff --git a/api/pkg/go.mod b/api/pkg/go.mod index fe80db8d..256cf930 100644 --- a/api/pkg/go.mod +++ b/api/pkg/go.mod @@ -18,7 +18,7 @@ require ( github.com/testcontainers/testcontainers-go/modules/mongodb v0.33.0 go.mongodb.org/mongo-driver/v2 v2.5.0 go.uber.org/zap v1.27.1 - golang.org/x/crypto v0.48.0 + golang.org/x/crypto v0.49.0 google.golang.org/grpc v1.79.2 google.golang.org/protobuf v1.36.11 ) @@ -28,7 +28,7 @@ require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260309015608-bb9dacb41b4e // indirect + github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260311194731-d5b7577c683d // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.24.4 // indirect github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect diff --git a/api/pkg/go.sum b/api/pkg/go.sum index 37e7c434..c998370b 100644 --- a/api/pkg/go.sum +++ b/api/pkg/go.sum @@ -6,8 +6,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25 github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260309015608-bb9dacb41b4e h1:sYPOzrcpCOv6rolFVWyEmjCSuZNg0yn2mVjlJYq8+2g= -github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260309015608-bb9dacb41b4e/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260311194731-d5b7577c683d h1:EA+kZ8mxGb1W/ewiIBMzb/1gg5BiW1Fvr3r4qCUBJEg= +github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260311194731-d5b7577c683d/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -275,8 +275,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -317,8 +317,8 @@ golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= -golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= +golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= +golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/api/proto/gateway/mntx/v1/mntx.proto b/api/proto/gateway/mntx/v1/mntx.proto index cc5e5a4c..d977fcec 100644 --- a/api/proto/gateway/mntx/v1/mntx.proto +++ b/api/proto/gateway/mntx/v1/mntx.proto @@ -44,6 +44,7 @@ message CardPayoutRequest { string idempotency_key = 32; string intent_ref = 33; string parent_payment_ref = 34; + string comment = 35; } // Persisted payout state for retrieval and status updates. @@ -63,6 +64,7 @@ message CardPayoutState { string idempotency_key = 13; string intent_ref = 14; string parent_payment_ref = 15; + string comment = 16; } // Response returned immediately after submitting a payout to Monetix. @@ -125,6 +127,7 @@ message CardTokenPayoutRequest { string idempotency_key = 32; string intent_ref = 33; string parent_payment_ref = 34; + string comment = 35; } // Response returned immediately after submitting a token payout to Monetix. diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 6a0e19c0..78ab62cf 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -253,7 +253,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # FX Oracle Service @@ -297,7 +297,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # Billing Fees Service @@ -342,7 +342,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # Billing Documents Service @@ -385,7 +385,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # Ledger Service @@ -437,7 +437,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # FX Ingestor Service @@ -479,7 +479,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # Payments Orchestrator Service @@ -526,7 +526,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # Payments Quotation Service @@ -576,7 +576,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # Payments Methods Service @@ -629,7 +629,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # Chain Gateway Vault Agent (sidecar for AppRole authentication) @@ -713,7 +713,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # TRON Gateway Vault Agent (sidecar for AppRole authentication) @@ -799,7 +799,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # Aurora Gateway Service (simulated card payouts) @@ -848,7 +848,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # ChimeraSettle Gateway Service (simulated settlements) @@ -896,7 +896,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # Notification Service @@ -937,7 +937,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # Callbacks Vault Agent (sidecar for AppRole authentication) @@ -1017,7 +1017,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # BFF Vault Agent (sidecar for AppRole authentication) @@ -1115,7 +1115,7 @@ services: interval: 10s timeout: 5s retries: 12 - start_period: 40s + start_period: 180s # -------------------------------------------------------------------------- # Frontend (Flutter Web) diff --git a/t.json b/t.json new file mode 100644 index 00000000..e69de29b