与网站的现金抽屉沟通

时间:2014-02-19 10:43:06

标签: php c

我目前正在为我的公司构建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有一点经验但是对谷歌我确信我可以解决这个问题。

我遇到的问题是,该解决方案实际上是一个非现场托管的网站,我需要做的是从网站发布命令到使用它的客户端机器。因此,当他们完成销售时,我可以打开该特定机器的抽屉。

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

之类的东西调用网站上的文件
C:\Windows\execute.bat

反过来调用客户端计算机上的c文件。

我知道我没有提供很多信息,因为我在购买之前想要解决这个问题,而且我可能过于复杂,但任何指针或信息都会非常受欢迎。此外,我还没有完全按照这个模型设置,所以如果您知道一些具有良好文档或现有解决方案的替代方案,我也对此持开放态度。

备注

据我所知,Chrome api调用可能有解决方案

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

更新

我的网站包括POS方面的东西已经建成并准备好了。这是使用PHP构建的,并托管在外部服务器上。我们通过域名访问该网站。

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

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

4 个答案:

答案 0 :(得分:25)

让我直截了当地说:

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

    考虑到:

    • 您可以控制客户POS客户端(就像您可以安装软件和设置策略一样)
    • 您可以安装Google Chrome并将其设置为应用的要求

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

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

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

    您必须创建一个小型Chrome应用程序,它发送命令以打开抽屉。这个应用程序应该公开一个函数,一旦你编写操作或将事务提交到服务器就可以调用(例如,当你保存销售记录时),这样你就可以在jQuery或javascript中附加回调数据并获得成功的回应。

    选项2:

    Java applet:

    我对此没有经验。但是您可以使用JNI(java本机接口)来调用本机代码。我不确定applet容器是否以不允许你这样做的方式进行沙盒化,但是这两个链接可能会派上用场:

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

    选项3:

    以操作方式执行:

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

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

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

    选项4:

    本地网络服务器。

    现在您提到拥有本地Web服务器,实际上这可能是一个选项。但是,为什么要在客户端计算机上安装XAMPP?有一种更好的方法。答案是在C#/ .NET中编写一个非常小而简单的HTTP Web服务器。因此,按照这种方法,您需要:

    1. 在C#/ .Net中写一个HTTP服务器,听一个特定的端口(here's a guide,它只有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
          }
      });
      
    6. 因此,您将向本地计算机发送POST请求,该计算机将侦听8088端口中的HTTP协议(或您在代码中设置的任何内容),然后它将在内部处理打开抽屉的请求,如果你在该代码中抛出一个异常,你可以从这个C#迷你网络服务器返回一个HTTP 500响应,这样你就可以在jquery(或你使用的任何库)的错误处理程序上捕获它

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

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

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

答案 1 :(得分:2)

不是一个真正的答案,但评论的时间太长了。

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

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

在锁定的情况下这可能没问题,但是我已经没有考虑过这种安全问题了。

总结一下,这是一个可能的解决方案:

  1. 在客户端和服务器之间建立WebSocket连接。
  2. 通过此渠道向服务器的客户端浏览器发出命令。
  3. 在浏览器中捕获此命令,然后创建一个ActiveX对象。
  4. 使用javascript,告诉此activeX对象打开抽屉。
  5. 在ActiveX对象内部,通过调用供应商提供的DLL中的相应函数来响应打开抽屉的请求。
  6. 对于亲自实施这一点感到有些不安(希望得到很好的补偿)。

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

    这是我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。这可能是因为我知道的太少,或者可能是因为我知道足够的危险 - 我不知道!

答案 2 :(得分:1)

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

遗憾的是,我对Windows C编程过于生疏,只是为了给出一个例子,但会尝试尽可能简单地解决这个问题:

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

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

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

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

答案 3 :(得分:1)

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

以下是我之前所做过的代码片段:

<?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更令人头痛。对不起,如果这不是你想听的,但我看到很多人尝试,特别是基于网络(由于许多其他原因这也是一个坏主意)。