【问题标题】:Communicate with Cash Drawer from Website从网站与钱箱沟通
【发布时间】:2018-08-01 21:48:53
【问题描述】:

我目前正在为我的公司构建 POS 解决方案。最困难的部分是购买现金抽屉,因为我对它们没有太多经验,并且更喜欢 USB 现金抽屉。我找到了一个我感兴趣的模型

CR-4005

http://www.thebarcodewarehouse.co.uk/epos-systems/cash-drawers/cr-4005-b/

供应商包括一个驱动程序,可以在这里找到

http://www.posiflexusa.com/driver.php

这允许您使用 dll 文件打开抽屉等。给出的代码示例如下:

Public Declare Function OpenUSB Lib "usbcr.dll" () As Long

我对 C 语言有少量经验,但在使用 google 时,我确信我可以解决这部分问题。

我遇到的问题是,该解决方案实际上只是一个托管在异地的网站,我需要做的是从站点发出命令到使用它的客户端计算机。这样当他们完成销售时,我就可以打开该特定机器的抽屉。

我需要澄清的是我是如何做到这一点的。例如,我假设我在客户端机器上安装了驱动程序并插入现金抽屉。然后当他们访问该站点时,我需要执行上面显示的 C 命令来打开抽屉。我遇到的问题是我想知道这将如何工作。当然,如果我在服务器上执行命令,它将有效地查看服务器的 USB 端口并尝试打开抽屉。而不是向客户端机器发出命令。因此,为了解决这个问题,可能有可能在客户端机器上拥有 c 文件,然后我只需使用类似的东西调用站点上的文件

C:\Windows\execute.bat

依次调用客户端机器上的 c 文件。

我知道我没有太多信息可以提供,因为我试图在继续购买之前弄清楚这一点,我可能过于复杂了,但任何指针或信息将不胜感激。此外,我还没有完全确定这个模型,所以如果你知道有一些好的文档或现有解决方案的替代方案,我也对此持开放态度。

备注

我了解 chrome api 调用可能有解决方案

我可能会安装 xampp 并创建一个简单的 php 文件,该文件调用执行必要工作的 exe。因此,访问客户端机器上的本地地址可能是另一个潜在的想法(即 127.0.0.1/open.php)。

更新

我的网站(包括 POS 方面)已建成并准备就绪。这是使用 PHP 构建的,并托管在外部服务器上。我们通过域访问该站点。

当用户在外部站点上执行特定操作时,它需要通过打开本地文件(即可以打开抽屉的 exe)或访问本地网络服务器来打开工作人员本地抽屉。机器即本地主机/打开。

直到抽屉是上面列出的,它通过 USB 连接到客户端机器。没有使用收据打印机。

【问题讨论】:

    标签: php c


    【解决方案1】:

    让我说清楚:

    1. 你做了一个网络应用,它是一个 POS(大概是 PHP)
    2. 您的用户通过本地服务器上的网络浏览器访问 POS
    3. 您需要能够在客户端打开现金抽屉...(例如,将零钱还给客户)

    选项 1:

    考虑到:

    • 您可以控制客户 POS 客户端(因为您可以安装软件和设置策略)
    • 您可以安装 google chrome 并将其设置为您的应用程序的要求

    然后你可以尝试使用原生 chrome USB 库:

    http://developer.chrome.com/apps/app_usb

    has it's caveats,是的,但是你可能很幸运并且可以用它打开设备。我在一家 POS 软件公司工作了几年,串行和 USB 现金抽屉都有一个非常简单的协议,即使使用 FoxPro 也可以打开它们。

    您必须创建一个小型 chrome 应用程序来发送打开抽屉的命令。此应用程序应该公开一个函数,一旦您编写操作或将事务提交到服务器(例如,当您保存销售记录时)就可以调用该函数,因此您可以在 jQuery o javascript 中附加一个回调,在您发布后执行此操作数据并收到成功的响应。

    选项 2:

    Java 小程序:

    我没有这方面的经验。但是您也许可以使用 JNI(Java 本机接口)来调用本机代码。我不确定小程序容器是否以不允许您这样做的方式被沙盒化,但是这两个链接可能会派上用场:

    How To Call Native (DLL) Code From Java Using JNI Calling C library routines from java

    选项 3:

    在操作系统方面进行:

    另一个选项,对我来说似乎是最简单的,是在操作系统级别映射击键,以便组合执行特定命令。您可以看到here 对如何在 Windows 中执行此操作的说明。在 linux(gnome 和 kde 等)中,这很容易。

    一旦你这样做了,你可以使用this jQuery library,它“模拟”击键,所以,再次,当你收到交易完成并且你需要打开现金抽屉的回复时,你会想要回调一个执行模拟击键的函数,你之前根据我给你的文章配置了它。

    当然,这个命令会运行一个本地的本地应用程序,它实际上会打开抽屉,可以是 C/C++/C# 或任何受支持的设备 API。但我确信这是一个标准界面,因此您可以轻松地用任何语言编写该应用程序。 Here's C# 的良好开端。

    选项 4:

    本地网络服务器。

    既然您提到拥有本地网络服务器,这实际上可能是一种选择。但是,为什么要在客户端机器上安装 XAMPP?有更好的方法来做到这一点。答案是用 C#/.NET 编写一个非常小而简单的 HTTP Web 服务器。所以按照这种方法你会想要:

    1. 用 C#/.Net 编写一个 HTTP 服务器,监听一个特定的端口(@98​​7654328@,它只有 50 行代码)
    2. 在您的 C# 代码中,您需要使用硬件随附的任何集成 API,P/Invoke to the C library(我不推荐),或者只是使用发送到USB port commands 的方法。因此,在集成了操作系统的 C# 中打开抽屉、打印或做任何您需要的事情会更简单。 (即使对于带有单声道的 linux/mac)
    3. 在 C# 中设置您的代码,以便服务器只侦听本地地址,因此除非是同一个网络,否则没有人可以打开直到,哎呀,我只允许 127.0.0.1 只是为了确保只有本地地址机器可以打开它。
    4. 将此编译后的 exe 放在 Windows 自动启动上,这样每当计算机启动时,打开收银台的迷你 Web 服务器也会启动。
    5. 只要交易成功到 POS 服务器,就捕获您的回调,最后执行以下操作:

      $.ajax({
          type: 'POST',
          dataType: 'json',
          data: 1,
          url: '127.0.0.1:8088/open',
          error: function() {
              alert('Could not open cash drawer');
          },
          success: function() {
              //do something else
          }
      });
      

    因此,您将向本地计算机发送一个 POST 请求,该计算机在 8088 端口(或您在代码中设置的任何内容)侦听 HTTP 协议,然后它会在打开抽屉时在内部处理该请求,如果您在该代码中抛出异常,则可以从此 C# 迷你网络服务器返回 HTTP 500 响应,以便您在 jquery(或您使用的任何库)的错误处理程序上捕获它

    我强烈建议,就像我告诉你的那样,这个应用程序出于安全原因只听本地请求,即使你只是做一个简单的操作。它会起作用,因为客户端 jquery 代码正在被本地机器调用。

    您还可以优化网络服务器应用程序,使其读取 .ini 文件或某些设置文件(.Net 具有 .config 默认值,这是可行的方法),以便您可以根据每个客户对其进行调整不要硬编码选项。

    祝你好运!让我们知道你是怎么做到的

    【讨论】:

    • 我已经取得了一些进展,我已经设法让 C 文件工作以打开收款机,并且我已经安装了 autohotkley,现在只需按几个键即可执行 exe。所以肯定会向前移动。因此,当事务完成时,它执行按键的最后阶段,即 CTRL+ALT+INSERT。我一直在研究模拟按键,但答案似乎都是在听按键而不是执行按键。你能给我指明文档的方向吗?
    • @TheHumbleRat 我的错,忘了放 jQuery 模拟库的链接,我编辑了我的回复。无论如何,你可以在这里看到这个库:github.com/j-ulrich/jquery-simulate-ext 虽然我不确定是否可以在沙盒浏览器之外“发送”击键。
    • @TheHumbleRat 刚刚添加了第四个选项,如果您没有 .NET 方面的经验,我可以为您提供一点帮助。
    • 我肯定会试一试,我目前正在探索一些途径。在此之前,我从未接触过 C、Chrome 应用程序/Chrome 扩展等,并且在短短一周内就学到了很多东西,这绝对是我所面临的最大挑战。如果没有您的建议,我敢肯定,我离现在的位置还很远。非常感谢您到目前为止所花费的所有时间,努力是显而易见的。当我到达那里时,我一定会告诉你结果和解决方案(手指交叉)。
    • 刚刚在我自己的一些服务器上做了一个快速测试,这个方法似乎可以解决问题,当然我正在使用 xampp,但它是概念证明。我肯定会使用您提到的 C#/.NET HTTP 方法,并且一定会在安全性方面听取您的建议。我这周下班了,现在我想知道是否制作自己的 exe 文件来安装 C# HTTP 服务器,编译我拥有的打开 till 的 c 代码,并安装并激活自动热键映射以打开 till经理。我认为选项 3 和 4 适合我的环境(即完全控制)。非常感谢你是个天才!
    【解决方案2】:

    不是一个真正的答案,虽然评论太长了..

    听起来你想从浏览器调用本机代码。这不会取悦很多人,尽管我知道实现这一目标的方法正是一种。它涉及 Internet Explorer 和一个 COM 服务器 (activeX)。 IE 可以创建您需要编写的 activeX 程序的实例。

    然后这个 activeX 可以向供应商提供的 DLL 发出命令。但是,问题在于,如果我坐在其中一个终端机上并且有键盘,我也可以打开抽屉。您还需要一种将打开抽屉的意图从服务器传递到客户端的方法。我想您可以使用 WebSockets 来维护客户端和服务器之间的通信通道,您可以通过该通道发出打开抽屉的意图。

    这在锁定的情况下可能没问题,尽管我在这里没有考虑也没有提到各种安全问题。

    回顾一下,这是一个可能的解决方案:

    1. 在客户端和服务器之间建立 WebSocket 连接。
    2. 通过此通道从服务器向客户端浏览器发出命令。
    3. 在浏览器中捕捉这个命令,然后创建一个 ActiveX 对象。
    4. 使用 javascript,告诉这个 activeX 对象打开抽屉。
    5. 在 ActiveX 对象中,通过调用供应商提供的 DLL 中的适当函数来响应打开抽屉的请求。

    我对亲自实施这一点感到有点不安(并希望得到丰厚的补偿)。

    顺便说一句,您可以通过这种方式控制 MS Office 等其他示例 - 允许您从浏览器中创建电子表格/word 文档/等,使用用户输入的信息填充新文档。

    这是我 18 个月前为一个项目编写的一个 JS 文件,用于控制 Excel。

    //
    // jsExcelObj.js
    // 28/08/2012 
    
    // the (only Excel) app instance - we only want to have 1
    // **** don't access this variable directly ****
    var jsExcelApp = null;
    
    /*****************************************************************************
        Excel class
    *****************************************************************************/
    function startExcel()
    {
        jsExcelApp = new ActiveXObject("Excel.Application");
    }
    
    function stopExcel()
    {
        jsExcelApp.Quit();
        delete(jsExcelApp);
        jsExcelApp = null;
    }
    
    function jsExcelWorkbook(filename)
    {
        if (jsExcelApp == null)
            startExcel(); //jsExcelApp = new ActiveXObject("Excel.Application");
    
        this.mFilename = filename;
        this.mExcelSheet = null;
        this.mWorkbook = jsExcelApp.Workbooks.Open(filename);
    
        this.close = function()
        {
            this.mWorkbook.Close(false);
            this.mFilename = null;
            this.mExcelSheet = null;
            this.mWorkbook = null;
        }
    
        this.open = function(filename)
        {
            if (jsExcelApp == null)
                startExcel();
    
            if (this.mFilename != null)
                this.close();
    
            this.mFilename = filename;
            this.mExcelSheet = null;
            this.mWorkbook = jsExcelApp.Workbooks.Open(filename);
        }
    
        this.setSheet = function(sheetName)
        {
            this.mExcelSheet = this.mWorkbook.Worksheets(sheetName);
        }
    
        this.getCellValue = function(column, row)
        {
            return this.mExcelSheet.Cells(row, column).value;
        }
    
        // returns the cells background colour as a html hex color value - e.g "7a554a"
        this.getCellColor = function(column, row)
        {
            var hexStrVel, r, g, b, decNum;
    
            decNum =  this.mExcelSheet.Cells(row, column).Interior.Color;
            // get a hexidecimal string representation of the number
            hexStrVal = decNum.toString(16);
    
            // pad to 6 bytes long
            while (hexStrVal.length < 6)
            {
                hexStrVal = "0" + hexStrVal;
            }
    
            // extract the 3 components
            r = hexStrVal.substr(4,2);
            g = hexStrVal.substr(2,2);
            b = hexStrVal.substr(0,2);
    
            return r+g+b; // return them in reverse order
        }
    }
    

    使用它很简单:

    <script src='script/jsExcelObj.js'></script>
    <script>
    var fullyQualifiedPathToExcelWorkbook = "C:/someFile.xls";
    var mExcel = new jsExcelWorkbook(fullyQualifiedPathToExcelWorkbook);
    mExcel.setSheet("Sheet1");
    var col1Row1 = mExcel.getCellValue(1, 1);
    alert(col1Row1);
    mExcel.close();
    stopExcel();
    </script>
    

    对于这个问题你还会得到什么其他答案,我非常好奇。从我能想到的各个角度来看,这听起来像是穿越雷区的长征..

    我会非常认真地考虑使用 C++ 实现我自己的服务器/客户端架构,而忘记使用 HTML/PHP。这可能是因为我知道的太少,也可能是因为我知道的足够多,看到了危险——我不知道!

    【讨论】:

    • 看起来我每走一步都会出现另一个问题。我几乎毫不费力地构建了一个 pos 系统。现在看来,打开抽屉可能需要与整个项目到目前为止相同的时间!非常感谢您的输入,这让我的想法更加清晰,肯定有几个字符太长了,无法发表评论。我会看看我得到什么答案,但我觉得这最终会成为公认的答案。我一直在使用 chrome 进行开发,理想情况下希望坚持使用它,但我可能别无选择。再次感谢,问候
    • :笑:有时,编程让我想起了我们在大学做的一些数学。一个看似无辜的 1/2 行问题需要逐页回答!另一种可能的替代方法是将 IWebBroswer2 对象托管在本机应用程序中。这将消除一些障碍并引入其他障碍——尽管你仍然会被 IE 困住。 :( - 除非 Qt 或 WxWidgets 实现了自己的 HTML 控件风格(具有脚本功能) - Mozilla 过去曾在其浏览器中实现 ActiveX 服务器 - 也许 Chrome 也这样做。无论如何,不​​客气。一个有趣的问题!
    • 非常感谢您的意见,您所说的一切肯定让我走上了理解我的问题的道路。我已经接受了一个针对我的环境的答案,但是您的帮助对于这次成功绝对是至关重要的。
    • 不客气。感谢您的问题,我现在已经接触到原生 Chrome usb 库。双赢!那谢谢啦。 :) 希望项目进展顺利。
    【解决方案3】:

    鉴于客户端机器可能在某种程度上受您的控制,我的理解是您所需要的只是一个简单的远程过程调用系统,我认为坚持代码必须通过浏览器运行是不必要的困难。相反,我的建议是在客户端机器上运行一个守护程序(或服务,因为我们在 Windows 领域),它将响应远程请求以控制现金提取。该程序可以是完全独立于浏览器的程序。然后让服务器在客户端打开网页时向客户端的 IP 地址发送一个数据包,这将触发客户端上的此服务以控制现金提取。

    不幸的是,我对 windows C 编程太生疏了,无法举个例子,但会尝试尽可能简单地分解:

    在客户端机器上,运行一个守护进程,它将接受特定端口上的连接(当然只来自服务器的 IP 地址,以避免任何人连接和控制它。您也可以使用安全证书,但这超出了范围这个答案。)在这个端口上接受连接后,它将响应一组可以发送的数据包,这些数据包将对应于现金提取的操作。这实际上可以是一个简单的 C 程序,它会侦听套接字,然后在接收数据时运行该 DLL 中的函数。

    在服务器上,您需要一个程序来响应客户端访问特定网页的尝试,您可以将其连接到 PHP 中,以便 PHP 在访问页面时在服务器上运行程序,我假设您已经知道从问题中所说的如何做到这一点。然后,该程序将打开与 HTTP 请求中给出的客户端 IP 的连接,并向客户端服务正在侦听的套接字发送现金提取命令。这应该会导致客户端对平局做一些事情。 (但是,您必须希望客户端没有伪装 IP 地址。)

    最后,您需要网页允许客户端向服务器请求这些命令,存在许多安全问题,特别是与客户端服务的安全性有关,但这些都相对容易克服。对于一个简单的实现,这也应该只需要大约 150 行代码。它还避免了任何奇怪的特定于平台或特定于浏览器的代码,并完全避免了 websockets。

    希望对你有所帮助,如果有任何不清楚的地方,请发表评论。

    【讨论】:

      【解决方案4】:

      您使用的是与 epson 兼容的收据打印机(ESC/POS 语言)吗?如果是这样,您可以使用以太网打印机并使用 PHP 访问打印机以弹出与打印机连接的现金抽屉。

      这是我之前做过的代码sn-p:

      <?php
      
      $texttoprint = $_POST['printthis']; 
      $texttoprint = stripslashes($texttoprint); 
      
      $fp = fsockopen("192.168.10.30", 9100, $errno, $errstr, 10); 
      if (!$fp) { 
          echo "$errstr ($errno)<br />\n"; 
      } else { 
          fwrite($fp, "\033\100"); 
          $out = $texttoprint . "\r\n"; 
          fwrite($fp, $out); 
          fwrite($fp, "\012\012\012\012\012\012\012\012\012\033\151\010\004\001"); 
          fclose($fp); 
      } 
      
      ?>
      

      有关打印代码的详细信息,请参阅http://files.support.epson.com/pdf/general/escp2ref.pdf

      作为拥有多年 POS 经验的人,关于从头开始创建 POS 的最佳建议是:不要这样做!

      有一些免费或开源的解决方案可以满足您的需求,但即使您最终支付了费用,也不会比构建 POS 更令人头疼。抱歉,如果这不是您想听到的,但我看到很多人尝试过,尤其是基于网络的(由于许多其他原因,这也是一个坏主意)。

      【讨论】:

        猜你喜欢
        • 2013-10-16
        • 1970-01-01
        • 2016-12-13
        • 1970-01-01
        • 2021-09-18
        • 2018-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多