社区/文章分享/商家自动打印订单小票,原来可以这样做

商家自动打印订单小票,原来可以这样做

**云开发(CloudBase)**是一款云端一体化的产品方案 ,采用 serverless 架构,免环境搭建等运维事务 ,支持一云多端,助力快速构建小程序、Web 应用、移动应用。

很多商家,尤其是餐饮/超市行业的商家,他们的小程序在收到新订单的时候,无法像美团那样自动打印订单小票,这给他们配货、送货带来很大的不便。所以他们非常希望小程序能够对接小票打印机自动打印小票,我们今天就介绍一下如何通过云开发实现这个功能。

作者介绍

唐全,小程序云开发的布道师,持续分享云开发代开发、云开发对接外部系统的课程和知识。

2013 年大学毕业后从事银行设备软件的开发、售前技术支持工作,在东南亚、中东各国开发过项目。2018 年 9 月,开始从事小程序开发创业工作,尤其专注于云开发技术的研究,对于云开发第三方平台代开发、云开发与外部系统对接等有着丰富的经验。2019 年 1 月,正式创立广州采云信息科技有限公司,公司致力于为广大中小商家提供优质的云开发小程序。希望将云开发普及到各行各业,让云开发帮助商家(开发者)降低成本、提升效率。

1、 准备一台网络小票打印机

我们以飞鹅这个牌子为例。首先购买一台飞鹅打印机,然后在飞鹅网站上注册成为开发者,添加这台打印机,USER 和 UKEY 会用在云开发后台来调用打印机。

2、云开发后台调用打印机

在打印机所有接口中,最重要是“小票机打印订单”这个接口。在这个接口中,我们看到只需要将打印参数组装好,然后通过 POST 请求发送给 URL 即可。

代码非常简单,如下:

request("http://api.feieyun.cn/Api/Open/", qs.stringify(postData));

postData是要发送的数据,因为打印机要求请求头是:application/x-www-form-urlencoded,所以请注意请求头而且请求数据需要进行 qs.stringify()拼接操作。至于postData的具体内容将在第 3 步中介绍。

3、postData 组成

根据文档,数据由用户名、时间戳、签名、接口名、打印机编号、打印内容、打印次数等组合而成。我们按照要求将数据进行组合就行了。

代码非常简单,如下:

const postData = {
  user: USER, //用户名
  stime: timeStamp, //时间戳
  sig: crypto
    .createHash("sha1")
    .update(USER + UKEY + timeStamp)
    .digest("hex"), //签名
  apiname: "Open_printMsg",
  sn: printer, //打印机编号
  content: util.formatOrderInfo(orderInfo), //打印内容
  times: times, //打印份数
};

4、打印效果如下

5、打印格式参考代码

打印内容处理:

const formatOrderInfo = function (cloudOrder, name = "") {
  var orderInfo = "<CB>" + name + " 新订单</CB><BR>";
  orderInfo = "<B>" + cloudOrder.startDate + "</B><BR><BR>";
  orderInfo += "名称 数量 单价 总价<BR>";
  orderInfo += "--------------------------------<BR>";
  for (var i = 0; i < cloudOrder.products.length; i++) {
    let price = cloudOrder.products[i].price;
    orderInfo +=
      cloudOrder.products[i].name +
      " " +
      cloudOrder.products[i].label +
      hanleSpace(
        cloudOrder.products[i].name + " " + cloudOrder.products[i].label,
        16
      ) +
      cloudOrder.products[i].number +
      hanleSpace(cloudOrder.products[i].number.toString(), 4) +
      price +
      hanleSpace(price.toString(), 6) +
      parseFloat(parseFloat(cloudOrder.products[i].number * price).toFixed(2)) +
      "<BR><BR>";
  }
  if (cloudOrder.coupon)
    orderInfo += "优惠券抵扣:-" + cloudOrder.coupon.disCount + "<BR>";
  if (cloudOrder.remark)
    orderInfo += "<B>备注:" + cloudOrder.remark + "</B><BR>";
  orderInfo += "--------------------------------<BR>";
  orderInfo += "<B>总计:" + cloudOrder.amount + "元</B><BR>";
  orderInfo +=
    "<B>" + cloudOrder.linkMan + " " + cloudOrder.mobile + "</B><BR>";
  if (cloudOrder.city || cloudOrder.address)
    orderInfo += "<B>" + cloudOrder.city + cloudOrder.address + "</B><BR>";

  orderInfo += "支付方式:" + cloudOrder.payWay + "<BR>";
  orderInfo += "下单时间:" + cloudOrder.dateTime + "<BR>";
  orderInfo += "订单编号:" + cloudOrder.orderId + "<BR>";
  orderInfo += "下单手机:" + cloudOrder.phoneNumber + "<BR>";
  orderInfo += "会员卡号:" + cloudOrder.cardNumber + "<BR>";

  //orderInfo += '<QR>http://www.pcloud.ac.cn</QR>';
  return orderInfo;
};

空格处理:

const hanleSpace = function (item, widht) {
  var len = 0;
  for (var j = 0; j < item.length; j++) {
    var c = item.charCodeAt(j);
    //单字节加1
    if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
      len++;
    } else {
      len += 2;
    }
  }
  let tmp = widht - (len % 32);
  len = tmp > 0 ? tmp : 32 + tmp;
  var kong = "";
  for (var a = 0; a < len; a++) {
    kong += " ";
  }
  return kong;
};