Reputation: 477
I am new to elixir and I need to create ISO 8583 client with this language and Phoenix framework. I found an Erlang library for it from stackoverflow thread here, compiled successfully and followed the example in the repository here but got error when marshaling the message. Here is my Elixir code to marshal the message:
msg1 = :erl8583_message.new()
msg2 = :erl8583_message.set_mti("0800", msg1)
msg3 = :erl8583_message.set(3, "300000", msg2)
msg4 = :erl8583_message.set(24, "045", msg3)
msg5 = :erl8583_message.set(41, "11111111", msg4)
msg6 = :erl8583_message.set(42, "222222222222222", msg5)
msg7 = :erl8583_message.set(63, "This is a Test Message", msg6)
marshalled = :erl8583_marshaller_ascii.marshal(msg7)
That's just an elixir version from the example on the repo. This is the error I've got when running the app:
[error] #PID<0.438.0> running TestlangIsoClientWeb.Endpoint (cowboy_protocol) terminated
Server: 127.0.0.1:4001 (http)
Request: POST /api/process
** (exit) an exception was raised:
** (FunctionClauseError) no function clause matching in :erl8583_marshaller_ascii.marshal_data_element/2
(erl8583) /home/muhammad/Workspace/testlang/testlang_iso_client/deps/erl8583/src/erl8583_marshaller_ascii.erl:168: :erl8583_marshaller_ascii.marshal_data_element({:n, :fixed, 4}, "0800")
(erl8583) /home/muhammad/Workspace/testlang/testlang_iso_client/deps/erl8583/src/erl8583_marshaller.erl:108: :erl8583_marshaller.marshal/2
(testlang_iso_client) lib/testlang_iso_client_web/controllers/my_controller.ex:61: TestlangIsoClientWeb.MyController.process/2
(testlang_iso_client) lib/testlang_iso_client_web/controllers/my_controller.ex:1: TestlangIsoClientWeb.MyController.action/2
(testlang_iso_client) lib/testlang_iso_client_web/controllers/my_controller.ex:1: TestlangIsoClientWeb.MyController.phoenix_controller_pipeline/2
(testlang_iso_client) lib/testlang_iso_client_web/endpoint.ex:1: TestlangIsoClientWeb.Endpoint.instrument/4
(phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1
(testlang_iso_client) lib/testlang_iso_client_web/endpoint.ex:1: TestlangIsoClientWeb.Endpoint.plug_builder_call/2
(testlang_iso_client) lib/testlang_iso_client_web/endpoint.ex:1: TestlangIsoClientWeb.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:16: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) /home/muhammad/Workspace/testlang/testlang_iso_client/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
Is there something I missed to make it work? Any help would be very appreciated.
I have tried to changed the string parameter to charlist, but still got the same error. Here is the code snippet:
def test(conn, _params) do
IO.puts("Test")
msg1 = :erl8583_message.new()
msg2 = :erl8583_message.set_mti('0800', msg1)
msg3 = :erl8583_message.set(3, '300000', msg2)
msg4 = :erl8583_message.set(24, '045', msg3)
msg5 = :erl8583_message.set(41, '11111111', msg4)
msg6 = :erl8583_message.set(42, '222222222222222', msg5)
msg7 = :erl8583_message.set(63, 'This is a Test Message', msg6)
marshalled = :erl8583_marshaller_ascii.marshal(msg7)
json(conn, %{status: "ok"})
end
Here is the function erl8583_marshaller.erl:108
mentioned in the stacktrace:
marshal(Message, MarshalHandlers) ->
OptionsRecord = parse_options(MarshalHandlers, #marshal_options{}),
{Marshalled1, Message1} = init_marshalling(OptionsRecord, Message),
MarshalledMti = encode_mti(OptionsRecord, Message1), % --- Line 108
Marshalled2 = <<Marshalled1/binary, MarshalledMti/binary>>,
{MarshalledBitmap, Message2} = encode_bitmap(OptionsRecord, Message1),
Marshalled3 = <<Marshalled2/binary, MarshalledBitmap/binary>>,
MarshalledFields = encode_fields(OptionsRecord, Message2),
Marshalled4 = <<Marshalled3/binary, MarshalledFields/binary>>,
end_marshalling(OptionsRecord, Message2, Marshalled4).
And here is the function erl8583_marshaller_ascii.erl:168
mentioned in the stacktrace:
%%
%% Local Functions
%%
marshal_data_element({n, llvar, Length}, FieldValue) when length(FieldValue) =< Length ->
erl8583_convert:integer_to_string(length(FieldValue), 2) ++ FieldValue;
I don't understand why the call to that function was failed to match with parameters {:n, :fixed, 4}, "0800"
that was sent from my function. I have tried to change the double quotes to single quotes with no success. Is there any other suggestions what am I supposed to do?
Upvotes: 1
Views: 274
Reputation: 51
there may be a bug in the code. you can reference this issue here
there is one elixir library out which is relatively new.
its called ale8583.
documentation is still coming out on this one but looks very promising.
you can check it out.
Upvotes: 3
Reputation: 41598
Try passing charlists instead of strings:
msg1 = :erl8583_message.new()
msg2 = :erl8583_message.set_mti('0800', msg1)
msg3 = :erl8583_message.set(3, '300000', msg2)
msg4 = :erl8583_message.set(24, '045', msg3)
msg5 = :erl8583_message.set(41, '11111111', msg4)
msg6 = :erl8583_message.set(42, '222222222222222', msg5)
msg7 = :erl8583_message.set(63, 'This is a Test Message', msg6)
marshalled = :erl8583_marshaller_ascii.marshal(msg7)
There is potential for confusion here:
"foo"
), Elixir calls "charlists" and puts in single quotes ('foo'
)."foo"
), Erlang calls "binaries" and puts in double quotes plus angle brackets (<<"foo">>
).It seems like the erl8583 library expects Erlang strings throughout.
Upvotes: 0