佳博/芯桦打票机对接(含USB和网口)

本文记录了使用PHP远程连接佳博/芯桦打票机的过程,包括网口和USB口的对接,内网穿透问题,以及异常处理。遇到的主要挑战包括网络稳定性、指令接收的准确性、内网穿透工具的选择(如NAT123和frp)以及不同设备兼容性问题。解决方案涉及超时机制、指令重发和错误处理。此外,代码示例展示了PHP如何编写打印指令。
摘要由CSDN通过智能技术生成

佳博/芯桦打票机对接(含USB和网口)

记录一下最近实现的一个需求,用PHP远程连接芯桦、佳博打票机,代码还未进行优化,基本功能已经实现打印,具体打印指令需要查看佳博/芯桦的打票机指令,USB口打印质量需要其他语言配合,我这边用到了.net编写USB口的接收指令程序,有兴趣了解的可以联系一起学习探讨。

遇到一些雷点:

  1. 比如如何保证极端环境下,不漏单,可以使用佳博/芯桦打票机的一个回应的指令判断,但是值得注意的是,需要有一些判断网络连接的措施,比如可以有超时的机制,出现超时、指令异常的情况,放入队列等待重新发送指令。

  2. 内网穿透的问题,因为商家打票机处于一个IP内的局域网环境,所以需要使用到内网穿透,一开始我们采用的是NAT123,后面发现这个是个大坑啊!!! 我了个槽,不仅转发极其缓慢,偶尔还有时候会转发出错。
    然后后面果断改变策略,使用了一个frp的工具,把转发交给了自家的服务器,果然快了很多!
    基本上都是秒出单的(也有可能是暂时单少),frp搭建和使用可能后面有时间会写,暂时太忙了,没什么时间写,不过网上也一堆教程,有需要可以去看看。

  3. 网口和USB口的区别,网口的话芯桦和佳博默认端口都是9100,设备都会有网卡,只需要在frp做内网穿透的时候,绑定转发到这个端口就行了。USB口的话,需要编写接收程序去驱动这个USB串口,至于方法的话,有很多种,有其他语言基础的小伙伴可以看看佳博官方的demo,不过值得注意的就是demo仅供参考。。。最终的实现方案,还有容错机制还是要自己去实现的。。

  4. 商家设备问题,遇到一个客如云的商家,安卓系统,原本想要做成APP去做驱动USB串口,没想到客如云直接不让你安装第三方未授权APP(简直流氓!),然后此类的商家的话,只能是找客如云合作,或者购买其他的打票设备了。windows收银机的话,.net是可以编写接收指令和驱动串口的,开机直接后台启动,当然容错机制和LOG也是要有的,自己注意就好!不跑题了,官方的其他方法没试过,有条件的小伙伴可以自行尝试。

  5. 接收指令的问题,刚开始做打票机指令接收的时候,发现指令断断续续的,有时候还会有丢数据的情况出现,这个问题我不知道是不是网络的粘包问题,有时候接收的指令都是不全的,出现此问题可以尝试分段读取流,或者尝试流传输时带长度,然后接受时校验,然后容错那里也可以加上佳博/芯桦打票机的一个打印后返回指令,如果不正常,就通知服务器发送端,后面尝试重新发送指令。

最后说说:

  • 这次需求比较着急,实现的也比较仓促,从0到1,代码还没时间去做深层的优化,写的不好不要喷我,哈哈哈。代码仅供参考!!!

  • 有类似需求,但是不懂的,也可以私信联系,大家可以一起探讨,虽然不是最好的,但是也有一些自己的经验、见解。希望可以帮到大家。

  • 还有就是希望看到这里的码友,在平常实现需求的过程中,不要轻言放弃,虽然问题会一个接着一个,但总会有方法破浪前行的,以此共勉!

<?php

class Printer
{
    protected $ESC="\x1b";//设置
    protected $GS="\x1d";//页面设置    字体大小17倍数
    protected $HT="\x09";//跳格设置    9,17,25,33,41
    protected $CUT="\x1d";//切纸
    protected $DEL="\x10";//切纸
    protected $EOT="\x04";//切纸
    protected $LF="\x0a";//打印缓冲区并换行
    public $fp = '';
    public $errno = '';
    public $ip = '';
    public $port = '';

    public function __construct($print_ip,$print_port)
    {
        $this->fp = @fsockopen($print_ip,$print_port,$errno,$errstr,30);
        $this->errno = $errno;
        $this->ip = $print_ip;
        $this->port = $print_port;
    }

    /**
     * 网口类型打票机60mm
     * @param $order
     */
    public function printOrder($order) {
        fwrite($this->fp,$this->ESC."@");//初始化
        fwrite($this->fp,$this->GS."!".chr(17));
        fwrite($this->fp,$this->ESC."a".chr(1));//居中
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE",'取餐号:'.$order['meal_code']));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE",$order['shop']['shop_title']));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,$this->GS."!".chr(0));
        fwrite($this->fp,"------------------------------------------------");
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,$this->GS."!".chr(17));
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","桌号:".$order['table'] ? $order['table']['number'] : ''));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,$this->GS."!".chr(0));
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","结账时间:".date('Y-m-d H:i:s',$order['pay_time'])));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","收银员:顾客/系统"));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","单号:".$order['oid']));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,"------------------------------------------------");
        fwrite($this->fp,$this->ESC."a".chr(0));
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","品项"));
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","数量"));
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","原价"));
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","优惠价"));
        fwrite($this->fp,$this->LF);

        foreach ($order['product'] as $val) {
            $mc=$val['title'].'('.$val['sku_cn'].')';
            $str_length = mb_strlen($mc);
            $str_count = ceil($str_length / 7);
            if ($str_count > 0) {
                for ($i = 1;$i <= $str_count;$i ++) {
                    fwrite($this->fp,iconv("UTF-8","GBK//IGNORE",mb_substr($mc,($i - 1) * 7,7)));
                    if ($i == 1) {
                        fwrite($this->fp,$this->HT);
                        fwrite($this->fp,$this->HT);
                        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE",$val['number']));//数量
                        fwrite($this->fp,$this->HT);
                        fwrite($this->fp,iconv("UTF-8", "GBK//IGNORE",$val['money']));//价格
                        fwrite($this->fp,$this->HT);
                        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE",$val['money']));//优惠价
                        fwrite($this->fp,$this->HT);
                    } else {
                        fwrite($this->fp,$this->HT);
                        fwrite($this->fp,$this->HT);
                        fwrite($this->fp,$this->HT);
                        fwrite($this->fp,$this->HT);
                        fwrite($this->fp,$this->LF);
                    }
                }
            }
        }


        fwrite($this->fp,"------------------------------------------------");
        fwrite($this->fp,$this->ESC."a".chr(0));
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","菜品原价"));
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE",$order['sum_price']));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","订单原价"));
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE",$order['sum_price']));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,$this->GS."!".chr(0));
        fwrite($this->fp,"------------------------------------------------");
        $mc = "支付方式";
        $this->setHt($mc);
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,$this->HT);
        $pay = $order['pay'];
        if (mb_strlen($pay) < 4) {
            fwrite($this->fp,$this->HT);
        }
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE",$pay));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","应付金额"));
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,$this->HT);
        fwrite($this->fp,$this->HT);
        $price = $order['money'];
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE",$price));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,$this->GS."!".chr(0));
        fwrite($this->fp,"------------------------------------------------");
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","下单人:顾客/系统"));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","下单时间:".date('Y-m-d H:i:s',$order['created_time'])));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","打印人:管理员"));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","打印时间:".date('Y-m-d H:i:s',time())));
        fwrite($this->fp,$this->LF);
        fwrite($this->fp,iconv("UTF-8","GBK//IGNORE","备注:".$order['remark']));
        fwrite($this->fp,$this->ESC."d".chr(5));//走行
        fwrite($this->fp,$this->CUT."V".chr(0).chr(2));//切纸
        fwrite($this->fp,$this->ESC."C".chr(3).chr(2).chr(3));
        fwrite($this->fp,$this->DEL.$this->EOT.chr(1));

    }

    /**
     * 网口标签机
     * @param $item
     * @param $usb_port
     */
    public function printOrder2Label($item) {
        $list = [
            'SIZE 40 mm,30 mm', //设置纸张
            'GAP 3 mm,0 mm', //设置间距
            'CLS', //刷新缓冲区
            'DENSITY 7',
            'REFERENCE 0,0',
            'SHIFT 0',
            'TEXT 20,20,"TSS24.BF2",0,1,1,"'.iconv("UTF-8","GBK//IGNORE",'美团外卖 #'.$item['table'].' '.$item['meal_code']).'"', //文字
            'TEXT 20,50,"TSS24.BF2",0,1,1,"'.iconv("UTF-8","GBK//IGNORE",$item['title']).'"', //文字
            'TEXT 20,80,"TSS24.BF2",0,1,1,"'.iconv("UTF-8","GBK//IGNORE",mb_substr($item['sku_cn'],0,13)).'"', //文字
            'TEXT 20,110,"TSS24.BF2",0,1,1,"'.iconv("UTF-8","GBK//IGNORE",mb_substr($item['sku_cn'],13,13)).'"', //文字
            'TEXT 20,140,"TSS24.BF2",0,1,1,"'.iconv("UTF-8","GBK//IGNORE",'价格:'.$item['price']).'"', //文字
            'TEXT 20,170,"TSS24.BF2",0,1,1,"'.iconv("UTF-8","GBK//IGNORE",$item['shop_title']).'"', //文字
            'TEXT 20,200,"TSS24.BF2",0,1,1,"'.date('Y-m-d H:i:s').'"', //文字
            'PRINT 1'
        ];
        foreach ($list as &$val) {
            $val = $val.'\r\n';
            $val = str_replace("\\r\\n", "\r\n",$val);
            $val = str_replace("\\", "",$val);
            fwrite($this->fp,$val);
        }
    }

    /**
     * USB标签机
     * @param $item
     * @param $usb_port
     */
    public function printOrder2($item) {
        $list = [
            'SIZE 40 mm,30 mm', //设置纸张
            'GAP 3 mm,0 mm', //设置间距
            'CLS', //刷新缓冲区
            'DENSITY 7',
            'REFERENCE 0,0',
            'SHIFT 0',
            'TEXT 20,20,"TSS24.BF2",0,1,1,"美团外卖 #'.$item['meal_code'].'"', //文字
            'TEXT 20,50,"TSS24.BF2",0,1,1,"'.$item['title'].'"', //文字
            'TEXT 20,80,"TSS24.BF2",0,1,1,"'.mb_substr($item['sku_cn'],0,13).'"', //文字
            'TEXT 20,110,"TSS24.BF2",0,1,1,"'.mb_substr($item['sku_cn'],13,13).'"', //文字
            'TEXT 20,140,"TSS24.BF2",0,1,1,"价格:'.$item['price'].'"', //文字
            'TEXT 20,170,"TSS24.BF2",0,1,1,"'.$item['shop_title'].'"', //文字
            'TEXT 20,200,"TSS24.BF2",0,1,1,"'.date('Y-m-d H:i:s').'"', //文字
            'PRINT 1'
        ];

        foreach ($list as &$val) {
            $val = $val.'\r\n';
            fwrite($this->fp,$val);
        }
    }

    /**
     * USB40mm打票机
     * @param $order
     * @param $usb_port
     */
    public function printOrder3($order) {
        $add = [
            $this->ESC."@",
            $this->GS."!".chr(17),
            $this->ESC."a".chr(1),
            '取餐号:'.$order['meal_code'],
            $this->LF,
            $order['shop']['shop_title'],
            $this->LF,
            $this->GS."!".chr(0),
            "--------------------------------",
            $this->LF,
            $this->GS."!".chr(17),
            "桌号:".$order['table']['number'],
            $this->LF,
            $this->GS."!".chr(0),
            "结账时间:".date('Y-m-d H:i:s',$order['pay_time']),
            $this->LF,
            "收银员:顾客/系统",
            $this->LF,
            "单号:".$order['oid'],
            $this->LF,
            $this->GS."!".chr(0),
            "--------------------------------",
            "品项",
            $this->HT,
            $this->HT,
            "数量",
            "原价",
            "优惠价",
            $this->LF
        ];


        if ($order['product']) {
            foreach ($order['product'] as $val) {
                $mc=$val['title'].'('.$val['sku_cn'].')';
                $add[] = $mc;
                $add[] = $this->HT;
                $add[] = $val['number'];
                $add[] = $this->HT;
                $add[] = $val['money'];
                $add[] = $this->HT;
            }
        }


        $add[] = "--------------------------------";
        $add[] = "菜品原价";
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $order['sum_price'];
        $add[] = $this->LF;
        $add[] = "订单原价";
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $order['sum_price'];
        $add[] = $this->LF;
        $add[] = $this->GS."!".chr(0);
        $add[] = "--------------------------------";
        $add[] = $this->LF;
        $mc = "支付方式";
        $this->setHt1($mc,$add);
        $add[] = $this->HT;
        $pay = $order['pay'];
        if (mb_strlen($pay) < 4) {
            $add[] = $this->HT;
        }
        $add[] = $pay;
        $add[] = $this->LF;
        $add[] = "应付金额";
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $this->HT;

        $price = $order['money'];
        if (mb_strlen($price) < 4) {
            $add[] = $this->HT;
        }
        $add[] = $price;
        $add[] = $this->LF;
        $add[] = $this->GS."!".chr(0);
        $add[] = "--------------------------------";
        $add[] = $this->LF;
        $add[] = "下单人:顾客/系统";
        $add[] = $this->LF;
        $add[] = "下单时间:".date('Y-m-d H:i:s',$order['created_time']);
        $add[] = $this->LF;
        $add[] = "打印人:管理员";
        $add[] = $this->LF;
        $add[] = "打印时间:".date('Y-m-d H:i:s',time());
        $add[] = $this->LF;
        $add[] = "备注:".$order['remark'];
        $add[] = $this->ESC."d".chr(5);
        $add[] = $this->CUT."V".chr(0).chr(8);
        $add[] = $this->ESC."C".chr(3).chr(2).chr(3);

        foreach ($add as &$val) {
            fwrite($this->fp,$val);
        }
    }

    /**
     * USB打印60mm格式
     * @param $order
     * @param $usb_port
     */
    public function printOrder4($order,$usb_port = 0) {
        $add = [
            $this->ESC."@",
            $this->GS."!".chr(17),
            $this->ESC."a".chr(1),
            $this->LF,
            '取餐号:'.$order['meal_code'],
            $this->LF,
            $order['shop']['shop_title'],
            $this->LF,
            $this->GS."!".chr(0),
            $this->GS."!".chr(0),
            "------------------------------------------------",
            $this->LF,
            $this->GS."!".chr(17),
            "桌号:".$order['table']['number'],
            $this->LF,
            $this->GS."!".chr(0),
            "结账时间:".date('Y-m-d H:i:s',$order['pay_time']),
            $this->LF,
            "收银员:顾客/系统",
            $this->LF,
            "单号:".$order['oid'],
            $this->LF,
            $this->GS."!".chr(0),
            "------------------------------------------------",
            $this->LF,
            $this->ESC."a".chr(0),
            "品项",
            $this->HT,
            $this->HT,
            $this->HT,
            "数量",
            $this->HT,
            "原价",
            $this->HT,
            "优惠价",
            $this->LF
        ];


        if ($order['product']) {
            foreach ($order['product'] as $val) {
                $mc=$val['title'].'('.$val['sku_cn'].')';
                $str_length = mb_strlen($mc);
                $str_count = ceil($str_length / 7);
                if ($str_count > 0) {
                    for ($i = 1;$i <= $str_count;$i ++) {
                        $add[] = mb_substr($mc,($i - 1) * 7,7);
                        if ($i == 1) {
                            $add[] = $this->HT;
                            $add[] = $this->HT;
                            if ($str_length < 7 && $str_count == 1) {
                                $add[] = $this->HT;
                            }
                            $add[] = $val['number'];
                            $add[] = $this->HT;
                            $add[] = $val['money'];
                            $add[] = $this->HT;
                            $add[] = $val['money'];
                            $add[] = $this->LF;
                        } else {
                            $add[] = $this->HT;
                            $add[] = $this->HT;
                            $add[] = $this->HT;
                            $add[] = $this->HT;
                            $add[] = $this->LF;
                        }
                    }
                }
            }
        }

        $add[] = "------------------------------------------------";
        $add[] = $this->LF;
        $add[] = $this->ESC."a".chr(0);
        $add[] = "菜品原价";
        // $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $order['sum_price'];
        $add[] = $this->LF;
        $add[] = "订单原价";
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $this->HT;
        // $add[] = $this->HT;
        $add[] = $order['sum_price'];
        $add[] = $this->LF;
        $add[] = $this->GS."!".chr(0);
        $add[] = "------------------------------------------------";
        $add[] = $this->LF;
        $mc = "支付方式";
        $add[] = $mc;
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $this->HT;
        $pay = $order['pay'];
        if (mb_strlen($pay) <= 4) {
            $add[] = $this->HT;
        }
        $add[] = $pay;
        $add[] = $this->LF;
        $add[] = "应付金额";
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $this->HT;
        $add[] = $this->HT;

        $price = $order['money'];
        $add[] = $price;
        $add[] = $this->LF;
        $add[] = $this->GS."!".chr(0);
        $add[] = "------------------------------------------------";
        $add[] = $this->LF;
        $add[] = "下单人:顾客/系统";
        $add[] = $this->LF;
        $add[] = "下单时间:".date('Y-m-d H:i:s',$order['created_time']);
        $add[] = $this->LF;
        $add[] = "打印人:管理员";
        $add[] = $this->LF;
        $add[] = "打印时间:".date('Y-m-d H:i:s',time());
        $add[] = $this->LF;
        $add[] = "备注:".$order['remark'];
        $add[] = $this->ESC."d".chr(5);
        $add[] = $this->CUT."V".chr(0).chr(2);
        $add[] = $this->ESC."C".chr(3).chr(2).chr(3);

        foreach ($add as $val) {
            fwrite($this->fp,$val);
        }

    }
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值