In this blog, we will discuss the implementation of pos printing in react js app and communicate with flutter app to print the receipt. Here there are two parts.

  • Sending buffer data from reactjs
  • Receiving buffer data from flutter app and sending it to pos printer.

Before diving into details, first of all we have to know what is pos printing, how it works. A short explanation is given below. If you want to know more, please google it.

POS printing/receipt printing

In restaurant/super shop we might see that the seller gives us a receipt after the successful bill payment using a pos printer. Some well known pos printer manufacturer companies are Sunmi, rongta, xprinter, star printer etc. There are 3 types of pos printers. They are thermal, inkjet and dot matrix. In our case, we have used a thermal printer. Receipts are printed by direct contact between the thermal head and thermal paper with the use of heat. Therefore, no ink is required.

Sending buffer data from react js

While we started thinking about the integration of pos printing in our system, we faced some challenges.

  • Order api response
  • Receipt Template
  • Communication between flutter app and react js web app
  • Printing setup (USB/Bluetooth)

Order api response

We know that flutter has complete pos printing libraries but why need to implement this from react js app. The answer is our system deals with multiple providers, different providers provide different responses while sending api responses. So, we need to process it from frontend to view those api responses. Another thing is displaying the whole website into  webview. For this, flutter app has limited access to get the order response from the backend. Thus, we overcame the first problem.

Receipt Template

The main challenge was making the template. Initially, we thought of making a template using html and css. Because it is developer friendly and easy to maintain. But, pos printer doesn’t support html. It only understands the esc/pos command. So, we had to change our decision. There are a lot of libraries for generating templates using the esc/pos command. But, coping up with our api response was a little bit tough as there were nested level addons list. Then, we found xml-escpose-helper library which provided a xml layout, converted the xml into esc/pos command using xml parser and generated our desired buffer data. It supports all the basic things you need like raw text, qr code, bar code, image, new line, paper cut etc. Here, we have also used another npm library called table which generates a string table like github readme table. It is very helpful to display the tabular format data easily.

escpos 156 ESC/POS printing by bridging (React Js + Flutter)

Procedure

STEPS 1: Template Data as object 

First, we need to make an object for populating the xml template. Keep in mind that the object key must be the same as the key used in the xml template.

const templateData = {
      orderDate: 'Oct 27, 2022, 12:00',
      userName: 'Tahsin Ahmed Khan',
      providerName: 'Test',
      shortId: `#TS-1234`,
      qrCode,
      qrCodeLabel,
      brandTemplateTable,
      cartTemplateTable,
      pricesTemplateTable,
      totalTemplateTable,
      logo: `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAQAAAC0NkA6AAA223pUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHjapZ1pkiY3zqT`
}

STEPS 2: Xml template

The key which is used in object must be the key of the template. Here, the key must be surrounded by two curly braces like {{key}}. Keep in mind that extra space causes problems while generating buffer. Please make sure to avoid it.

export const cartXmlTemplate = (qrCodeContent, qrCodeLabel) => `
  <?xml version="1.0" encoding="UTF-8"?>
  <document> 
    <text-line>Order Date: {{orderDate}}</text-line>
    <line-feed />
    <text-line size="1:1">{{userName}}</text-line>
    <line-feed />
    <text-line size="1:1">{{providerName}} {{shortId}}</text-line>
    <line-feed />
    <text-line>{{brandTemplateTable}}</text-line>
    <line-feed />
    <bold>
      <text-line>{{cartTemplateTable}}</text-line>
    </bold>
    <text-line>{{pricesTemplateTable}}</text-line>
    <bold>
      <text-line>{{totalTemplateTable}}</text-line>
    </bold>
    <line-feed />
    ${qrCodeLabel ? `<align mode="center"> <text-line> {{qrCodeLabel}} </text-line></align> <line-feed />` : ``}
    ${
      qrCodeContent
        ? `<align mode="center">
        <image density="d24">
        {{qrCode}}
      </image>
      </align> 
    <line-feed />`
        : `<line-feed />`
    }
    <align mode="center">
      <small>
        <text-line>Powered by</text-line>
      </small>
      <image density="d24">
        {{logo}}
      </image>
      <small>
        <text-line>Company name</text-line>
      </small>
    </align>
    <line-feed />
    <paper-cut/>
  </document>`;

STEPS 3: Generating buffer from template data and xml

A method called getBufferFromTemplate takes 2 parameters. First parameter is xml, the second is template data as an object.

const buffer = EscPos.getBufferFromTemplate(
      cartXmlTemplate(qrCodeContent, qrCodeLabel),
      templateData,
    );

We faced some problems while trying to make a template. They were–

  • Some characters aren’t supported by pos printers like Peso (Philippines currency). Because, it depends on its code page. In computing, a code page is a character encoding and as such it is a specific association of a set of printable characters and control characters with unique numbers. Some renowned code pages are PC437(Standard Europe), Katakana, PC850(Multilingual, PC860(Portuguese), PC863 (Canadian), PC865(Nordic) etc. It varies from printer to printer.
  • Most of the printers support bar code but some of them don’t support qr code. We also faced this problem. We overcame this problem using @cheprasov/qrcode. It converts the qrcode as image and image is supported by pos printer.

Summarising the whole process is like this –

Template Data as object -> Syncing with xml template -> Generate buffer using data and xml template -> Send it to flutter app -> Ready to Print

Communication between flutter app and react js web app

The problem is quite simple. We took the help of postMessage which solved our second problem. After making the buffer data from order api response, we sent it to the flutter end using postMessage.

Receiving buffer and Printing Receipt

Currently we are providing support for USB. The set up and printing process was done from the flutter end. So, please go to this link to see the details.

Final Output

IMG 20220725 172224 ESC/POS printing by bridging (React Js + Flutter)