الطباعة بنظام ESC/POS من المتصفح: دليل المطورين

مشكلة الطباعة في المتصفح

إذا سبق لك أن حاولت طباعة إيصال من تطبيق ويب، فأنت تعرف المعاناة: window.print() يفتح مربع حوار الطباعة، ويعرض الصفحة كملف PDF، ولا يدعم إطلاقًا أوامر ESC/POS مثل القطع التلقائي أو عرض الورق المخصص.

بالنسبة لطابعات الإيصالات الحرارية، هذا أمر حاسم. أنت بحاجة إلى:

  • طباعة صامتة — بدون مربع حوار، بدون تفاعل المستخدم
  • أوامر ESC/POS — للقطع التلقائي، النص الغامق، المحاذاة، الرموز الشريطية (barcodes)
  • ترميز موثوق — UTF-8 إلى صفحة الرموز الصحيحة لطابعتك
  • دعم متعدد المنصات — Mac، Windows، Linux

الحل هو جسر WebSocket محلي — تطبيق صغير يعمل في الخلفية على جهاز المستخدم، يقبل مهام الطباعة من تطبيق الويب الخاص بك، ويرسل أوامر ESC/POS الأولية إلى الطابعة.


كيف يعمل جسر WebSocket

تطبيق الويب الخاص بك ← WebSocket (ws://localhost:8765) ← وكيل الطباعة ← طابعة حرارية

التدفق بسيط:

  1. يفتح تطبيق الويب الخاص بك اتصال WebSocket إلى ws://localhost:8765
  2. ترسل حمولة JSON تصف الإيصال
  3. يقوم وكيل الطباعة بتحويلها إلى ESC/POS ويرسلها إلى الطابعة
  4. تطبع الطابعة بصمت — بدون مربع حوار، بدون تفاعل مع برنامج التشغيل

MenuForma Print Agent ينفذ هذا الجسر. إنه مجاني ومفتوح المصدر ويعمل على Mac و Windows و Linux.


مرجع API

الاتصال

const ws = new WebSocket('ws://localhost:8765');

ws.onopen = () => {
  console.log('Print Agent connected');
};

ws.onerror = () => {
  console.log('Print Agent not running');
};

التحقق من حالة الوكيل

أرسل ping للتحقق من أن الوكيل يعمل:

ws.send(JSON.stringify({ type: 'ping' }));

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  if (data.type === 'pong') {
    console.log('Agent version:', data.version);
  }
};

طباعة إيصال

const receipt = {
  type: 'print',
  printer: 'auto',   // أو IP محدد مثل '192.168.1.100'
  data: {
    storeName: 'My Restaurant',
    storeAddress: '123 Main St',
    orderNumber: '#1042',
    tableNumber: 'Table 5',
    items: [
      { name: 'Margherita Pizza', qty: 1, price: 14.90 },
      { name: 'Sparkling Water', qty: 2, price: 3.50 },
    ],
    subtotal: 21.90,
    tax: 1.97,
    total: 23.87,
    paymentMethod: 'Card',
    footer: 'Thank you for dining with us!',
  }
};

ws.send(JSON.stringify(receipt));

مثال تكامل React

import { useEffect, useRef, useCallback, useState } from 'react';

function usePrintAgent() {
  const wsRef = useRef(null);
  const [connected, setConnected] = useState(false);

  useEffect(() => {
    const connect = () => {
      const ws = new WebSocket('ws://localhost:8765');
      ws.onopen = () => setConnected(true);
      ws.onclose = () => {
        setConnected(false);
        setTimeout(connect, 3000); // إعادة المحاولة
      };
      wsRef.current = ws;
    };
    connect();
    return () => wsRef.current?.close();
  }, []);

const print = useCallback((receiptData) => { if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) { throw new Error('Print Agent not connected'); } wsRef.current.send(JSON.stringify({ type: 'print', data: receiptData })); }, []);

return { connected, print }; }


---

## تكامل Shopify

لمتاجر Shopify، يمكنك تشغيل الطباعة من خطاف ويب (webhook) للطلب أو من إضافة متصفح:

```javascript
// في واجهة متجر Shopify أو إضافة المسؤول الخاصة بك
async function printShopifyOrder(order) {
  const ws = new WebSocket('ws://localhost:8765');
  
  ws.onopen = () => {
    ws.send(JSON.stringify({
      type: 'print',
      data: {
        storeName: order.shop_name,
        orderNumber: order.name,
        items: order.line_items.map(item => ({
          name: item.title,
          qty: item.quantity,
          price: parseFloat(item.price),
        })),
        total: parseFloat(order.total_price),
        paymentMethod: order.payment_gateway,
      }
    }));
  };
}

إعداد الطابعة

يقبل حقل "printer" في حمولة الطباعة ما يلي:

القيمة الوصف
"auto" استخدم الطابعة المكونة في إعدادات Print Agent
"192.168.1.100" الاتصال مباشرة بطابعة شبكة عن طريق IP
"USB" استخدم أول طابعة USB مكتشفة

معالجة الأخطاء

ws.onmessage = (event) => {
  const response = JSON.parse(event.data);
  
  if (response.type === 'print_success') {
    console.log('Printed successfully');
  } else if (response.type === 'print_error') {
    console.error('Print failed:', response.error);
    // إظهار واجهة مستخدم احتياطية أو إعادة المحاولة
  }
};

اكتشاف ما إذا كان Print Agent مثبتًا

قبل إظهار وظيفة الطباعة في واجهة المستخدم الخاصة بك، تحقق مما إذا كان الوكيل قيد التشغيل:

async function isPrintAgentAvailable() {
  return new Promise((resolve) => {
    const ws = new WebSocket('ws://localhost:8765');
    const timeout = setTimeout(() => {
      ws.close();
      resolve(false);
    }, 1000);
    ws.onopen = () => {
      clearTimeout(timeout);
      ws.close();
      resolve(true);
    };
    ws.onerror = () => {
      clearTimeout(timeout);
      resolve(false);
    };
  });
}

// الاستخدام
const agentAvailable = await isPrintAgentAvailable();
if (!agentAvailable) {
  // إظهار مطالبة التنزيل
  window.open('/print-agent', '_blank');
}

تنزيل Print Agent

MenuForma Print Agent مجاني ومتاح لأنظمة Mac و Windows و Linux. يدعم الطابعات الحرارية USB والشبكة والبلوتوث، وينفذ واجهة برمجة تطبيقات WebSocket الكاملة الموضحة في هذا الدليل.

للحصول على وثائق API الكاملة والكود مفتوح المصدر، قم بزيارة صفحة Print Agent.

Related Articles

MenuForma Products