Moneris Semi Integrated Solution Not Working

若如初见. 提交于 2020-01-15 15:33:44

问题


I am quite frustrated at this point, and I thought I would post this as a last resort.

I am in the process of developing a C# .NET 4.5 app that will communicate via USB to a Moneris payment device. Its a Moneris ICT-250 and Moneris refers to this as a "semi-integrated" application. I have been trying to send over a test payment to get the device to work using the Serial Port class but nothing seems to be working.

For starters, Moneris does provide a simulator to get up and running. I can confirm that I can go ahead, set up a test payment - say $100.00 - send it off....and the device lights up. It also outputs a detailed log of both the request and response.

Each request has to be a specifically formatted string that identifies the payment type, amount, etc....I have taken the string that is found in the log and sent that off, but nothing appears to be working. The device doesn't register a fail or a success.

I know that the device is connected properly. If I change the port number or unplug the device, my catch will handle it (below).

Below is a simple Console app. Is something wrong in my code? Has anyone else had any experience in connecting to a semi-integrated Moneris solution? I am open to any ideas. Moneris is unable to provide any support or code snippets. Very frustrating to say the least...

Thanks everyone! Code is below :)

using System;
using System.IO.Ports;

class Moneris_Integration
{
    public static void Main()
    {
        SerialPort port = new SerialPort("COM8");

        // These properties are required by the device         
        port.BaudRate = 19200;
        port.Parity = Parity.Even;
        port.StopBits = StopBits.One;
        port.DataBits = 8;

        port.Open();

        // This is the request that is sent by the simulator to the device
        port.Write("<STX>02<FS>0011000<FS>0020<ETX><LRC>");

        port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

        Console.WriteLine("===| Moneris Test |===");
        Console.ReadKey();
    }

    private static void DataReceivedHandler(
                        object sender,
                        SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        string incomingData = sp.ReadExisting();
        Console.WriteLine("Response:");
        Console.Write(incomingData);
    }
}

回答1:


As suggested by somebody else on your question's comments, it certainly looks like what you're writing to the port:

port.Write("<STX>02<FS>0011000<FS>0020<ETX><LRC>");

needs to be fully translated to ASCII.

First, define the ASCII control characters:

private byte[] STX = new byte[] { 0x02 };
private byte[] EXT = new byte[] { 0x03 };
private byte[] FS = new byte[] { 0x1C };

You also need a function to calculate the LRC, which is based on the rest of the message. I took this one:

public static byte calculateLRC(byte[] bytes)
{
    byte LRC = 0;
    for (int i = 0; i < bytes.Length; i++)
    {
        LRC ^= bytes[i];
    }
    return LRC;
}

Then convert the numeric strings on the message to bytes using ASCII encoding:

byte[] bytes1 = System.Text.Encoding.ASCII.GetBytes("02");
byte[] bytes2 = System.Text.Encoding.ASCII.GetBytes("0011000");
byte[] bytes3 = System.Text.Encoding.ASCII.GetBytes("0011000");

We create a new memory block to store the message:

var message = new MemoryStream();

Append the bytes we want to send to our message, in chunks:

message.Write(STX, 0 , 1);
message.Write(bytes1, 0, bytes1.Length);
message.Write(FS, 0 , 1);
message.Write(bytes2, 0, bytes2.Length);
message.Write(FS, 0 , 1);
message.Write(bytes3, 0, bytes3.Length);
message.Write(EXT, 0 , 1);

Calculate the LRC:

var LRC_msg = calculateLRC(message)

Append it to the message:

message.Write(LRC_msg, 0, LRC_msg.Length);

And finally, write it to the port:

port.Write(message, 0, message.Length);

You should also consider that the log you see might be misleading you with the numeric part of the message. If you still don't get an answer it might be time to take a look at the real data on the port. To do that you can open a terminal like Termite or RealTerm. I'm not sure how the simulator you mention works, but I assume it's software and it needs a serial port where it connects to send data. If that's the case, you can try to forward two real or virtual serial ports on your computer as I explained here.

It was also suggested that you might need to terminate your command with a CR or LF.




回答2:


OK - I got this working. I want to post my solution here in case someone else get's stuck with trying to communicate to a Moneris payment device through what they call a "semi-integrated" solution.

Everyone's suggestions got me thinking...so after some more research and testing, I was able to get the device to work.

NOTE: In this example, the hex being sent over is hard coded (for now) and I have hard coded the LRC. Moving forward, the hex requests + LRC will need to be calculated on the fly. Also, set the DataBits to 7 and NOT 8!!

using System;
using System.IO.Ports;

class Moneris_Integration
{
    public static void Main()
    {
        SerialPort port = new SerialPort("COM4");

        port.BaudRate = 19200;
        port.Parity = Parity.Even;
        port.StopBits = StopBits.One;
        port.DataBits = 7;      // Changed to 7. Was incorrectly told it was 8.

        port.Open();

        // You'll need to change this to be whatever your app is trying to send at the time
        // Last array item is the LRC. In my case, it was 0x31
        var bytesToSend = new byte[] { 0x02, 0x30, 0x30, 0x1c, 0x30, 0x30, 0x31, 0x31, 0x30, 0x30, 0x30, 0x1c, 0x30, 0x30, 0x32, 0x30, 0x03, 0x31 };

        port.Write(bytesToSend, 0, bytesToSend.Length);

        port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

        Console.ReadKey();
    }

    public static byte calculateLRC(byte[] bytes)
    {
        byte LRC = 0;
        for (int i = 0; i < bytes.Length; i++)
        {
            if (i == 0)
            {
                LRC = bytes[i];
            }
            else
            {
                LRC ^= bytes[i];
            }

        }
        return LRC;
    }

    private static void DataReceivedHandler(
    object sender,
    SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        string incomingData = sp.ReadExisting();
        Console.WriteLine("Response:");
        Console.Write(incomingData);
    }
}


来源:https://stackoverflow.com/questions/56876799/moneris-semi-integrated-solution-not-working

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!