Closed svz-ya closed 1 year ago
@svz-ya thank you for your contribution to the package!
Do you want to remove fields from the request message in order to use it as a response message?
Setting zero value to remove the field works as unexpected behavior. For example, if a field has a padder and the field is set with an empty string, it will be padded (or filled) during packing (it will not be empty string as a result, but something like 0000000
). So, we can't use empty values to remove fields.
We also have a PR with a pretty long discussion here: https://github.com/moov-io/iso8583/pull/113
Removing the field from the message has one concern - we may not remove/reset all we need, and it may result in undesired side effects. For example, this PR does not unset bit in the bitmap, and it also doesn't remove the field from m.fields
. What should happen if you remove field 1
(bitmap)?
If you want to proceed with the PR, let's focus on RemoveFields
(any better name? Unset
?) method then. We cleaned up some internal things in the package since https://github.com/moov-io/iso8583/pull/113 and I feel more confident with implementing field removal now. Let's just address things that I mentioned above.
Also, do you use data structs to (un)marshal messages? If so, then here is what you can do in order to create a copy of the request. I'm providing two variants:
package demo
import (
"github.com/moov-io/iso8583"
"github.com/moov-io/iso8583/field"
)
// 0100
type AuthorizationRequest struct {
MTI *field.String `index:"0"`
PrimaryAccountNumber *field.String `index:"2"`
ProcessingCode *field.String `index:"3"`
AmountTransaction *field.Numeric `index:"4"`
TransmissionDateTime *field.String `index:"7"`
STAN *field.String `index:"11"`
LocalTransactionTime *field.String `index:"12"`
LocalTransactionDate *field.String `index:"13"`
RetrievalReferenceNumber *field.String `index:"37"`
}
// 0110
type AuthorizationResponse struct {
MTI *field.String `index:"0"`
PrimaryAccountNumber *field.String `index:"2"`
ProcessingCode *field.String `index:"3"`
AmountTransaction *field.Numeric `index:"4"`
TransmissionDateTime *field.String `index:"7"`
STAN *field.String `index:"11"`
LocalTransactionTime *field.String `index:"12"`
LocalTransactionDate *field.String `index:"13"`
RetrievalReferenceNumber *field.String `index:"37"`
// reponse has additional fields
AuthorizationCode *field.String `index:"38"`
ResponseCode *field.String `index:"39"`
}
// handler for incoming messages
func handler(requestMessage *iso8583.Message) (*iso8583.Message, error) {
// *******************************************************************
// variant 1
// copy all fields from the request message into a new response message
responseMessage, err := copyRequestFieldsIntoNewMessage(requestMessage)
if err != nil {
// handle error
}
// set or overwrite fields in the response message
// set the MTI to 0110
responseMessage.MTI("0110")
// set the authorization code to 123456
responseMessage.Field(38, "123456")
// set the response code to 00
responseMessage.Field(39, "00")
// send the response message to the network connection
// ...
// *******************************************************************
// variant 2
responseData, err := copyRequestFieldsIntoResponse(requestMessage)
if err != nil {
// handle error
}
responseData.AuthorizationCode.Value = "123456"
responseData.ResponseCode.Value = "00"
// create response
responseMessage := iso8583.NewMessage(spec)
err = responseMessage.Marshal(responseData)
if err != nil {
// handle error
}
// send the response message to the network connection
// ...
}
func copyRequestFieldsIntoNewMessage(requestMessage *iso8583.Message) (*iso8583.Message, error) {
// by unmarshalling the request message into response data, we get
// values for all fields defined in the response struct
responseData := &AuthorizationResponse{}
err := requestMessage.Unmarshal(responseData)
if err != nil {
// handle error
}
responseMessage := iso8583.NewMessage(spec)
err = responseMessage.Marshal(responseData)
if err != nil {
// handle error
}
return responseMessage, nil
}
func copyRequestFieldsIntoResponse(requestMessage *iso8583.Message) (*AuthorizationResponse, error) {
// by unmarshalling the request message into response data, we get
// values for all fields defined in the response struct
responseData := &AuthorizationResponse{}
err := requestMessage.Unmarshal(responseData)
if err != nil {
// handle error
}
return responseData, nil
}
@alovak Thank you for such a detailed comment! Your point is clear and I will proceed with Variant 2.
So I think the proposed change is not needed anymore :)
I would like to have the ability to reset a field in message. So calling
or
clears Field 14 from message and it will not appear in raw message after packing.