【问题标题】:Moneris Semi Integrated Solution Not WorkingMoneris 半集成解决方案不起作用
【发布时间】:2019-11-14 12:54:43
【问题描述】:

在这一点上我很沮丧,我想我会作为最后的手段发布这个。

我正在开发一个 C# .NET 4.5 应用程序,该应用程序将通过 USB 与 Moneris 支付设备进行通信。它是 Moneris ICT-250,Moneris 将其称为“半集成”应用程序。我一直在尝试发送测试付款以使设备使用串行端口类工作,但似乎没有任何工作。

对于初学者,Moneris 确实提供了一个模拟器来启动和运行。我可以确认我可以继续,设置测试付款 - 比如 100.00 美元 - 发送它......然后设备亮起。它还输出请求和响应的详细日志。

每个请求都必须是一个特定格式的字符串,用于标识付款类型、金额等......我已将在日志中找到的字符串发送出去,但似乎没有任何效果。设备不会记录失败或成功。

我知道设备已正确连接。如果我更改端口号或拔下设备,我的 catch 将处理它(如下)。

下面是一个简单的控制台应用程序。我的代码有问题吗?有没有其他人在连接半集成 Moneris 解决方案方面有任何经验?我对任何想法持开放态度。 Moneris 无法提供任何支持或代码 sn-ps。至少可以说非常令人沮丧...

谢谢大家!代码如下:)

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);
    }
}

【问题讨论】:

  • 我不认为port.Write("&lt;STX&gt; 做你认为它做的事。 是 ASCII 代码 2,如果我没记错的话,你必须自己编码。您可能还需要设置端口使用的(不相关的)代码页编码。 SO上有这样的例子。如果找不到,请大声喊叫。
  • 设备是否期望在每个命令的末尾有一个“\n”?您正在使用 Write,也许您应该使用 WriteLine。
  • 好的 - 首先感谢大家的 cmets。您对 ASCII 的看法是正确的……我刚刚从 Moneris 那里得到了一些文档,解释了所需的 LRC 计算、所需的编码等……令人沮丧,我希望他们早点给我这个。我会在一两天内尝试一下,并就进展提出建议。再次感谢!

标签: c# serial-port


【解决方案1】:

好的 - 我得到了这个工作。我想在这里发布我的解决方案,以防其他人无法通过他们所谓的“半集成”解决方案与 Moneris 支付设备进行通信。

大家的建议让我开始思考......所以经过更多的研究和测试,我能够让设备工作。

注意:在此示例中,发送过来的十六进制是硬编码的(目前),我已经硬编码了 LRC。展望未来,十六进制请求 + LRC 将需要即时计算。另外,将 DataBits 设置为 7 而不是 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);
    }
}

【讨论】:

    【解决方案2】:

    正如somebody else 在您问题的 cmets 中所建议的,它看起来确实像您正在向端口写入的内容:

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

    需要完全转换为 ASCII。

    首先,定义ASCII control characters

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

    您还需要一个函数来计算 LRC,它基于消息的其余部分。我拿了this one

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

    然后使用 ASCII 编码将消息上的数字字符串转换为字节:

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

    我们创建一个新的内存块来存储消息:

    var message = new MemoryStream();
    

    将我们要发送的字节以块的形式附加到我们的消息中:

    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);
    

    计算 LRC:

    var LRC_msg = calculateLRC(message)
    

    将其附加到消息中:

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

    最后,将其写入端口:

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

    您还应该考虑到您看到的日志可能会误导您使用消息的数字部分。如果您仍然没有得到答案,可能是时候查看端口上的真实数据了。为此,您可以打开像 TermiteRealTerm 这样的终端。我不确定你提到的模拟器是如何工作的,但我认为它是软件,它需要一个串行端口来连接以发送数据。如果是这种情况,您可以尝试在您的计算机上转发两个真实或虚拟的串行端口,正如我在here 中解释的那样。

    还有suggested,您可能需要使用 CR 或 LF 终止命令。

    【讨论】:

      猜你喜欢
      • 2015-06-19
      • 1970-01-01
      • 1970-01-01
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多