المدونة

التحقق من ZUGFeRD باستخدام Mustang: ما الذي ينجح وما الذي يفشل ولماذا

Mustang هو مدقق Factur-X / ZUGFeRD المرجعي عمليًا. جولة في أخطاء تضمين CII XML داخل PDF/A-3، وكيف تتحقق قبل الإرسال.

إذا كنت ترسل فواتير إلكترونية إلى عميل B2B ألماني في 2026، فالملف إما متوافق مع ZUGFeRD أو سيُرفض عند الاستلام. والأمر نفسه في فرنسا مع Factur-X. التنسيق هو غلاف PDF/A-3 مع EN 16931 CII XML مرفق؛ توليده من الصفر ليس بسيطًا، والتحقق منه يحتاج إلى محرك مرجعي.

ذلك المحرك، عمليًا، هو Mustang (mustangproject.org). إنه مشروع Java مفتوح المصدر يستخرج XML المضمّن من PDF/A-3 ويتحقق منه وفق EN 16931 Schematron. لدى Mustang أعمق دعم مفتوح المصدر لـ ZUGFeRD وFactur-X، وهو ما تشغله معظم أدوات التحقق المستقلة.

هذا المقال يمر على أنماط الفشل التي يكشفها Mustang، وطريقة أسرع لتشغيله.

ما الذي يفحصه Mustang فعلًا

عندما تعطي Mustang ملف PDF من Factur-X أو ZUGFeRD، فهو يفعل تقريبًا ما يلي:

  1. استخراج الملف المضمّن. يحتفظ PDF/A-3 بالمرفقات داخل /EmbeddedFiles name tree. يبحث Mustang عن الاسم القياسي (factur-x.xml في Factur-X، وzugferd-invoice.xml في ZUGFeRD 2.x) ثم يقرأ البايتات.
  2. فحص AFRelationship. يجب أن يعلن الملف المرفق AFRelationship="Alternative" وفق baseline الخاصة بـ Factur-X / ZUGFeRD. أي قيمة أخرى (Source أو Data أو Supplement) تفشل.
  3. فحص namespace XMP والإصدار. يستخدم Factur-X 1.0 القيمة urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#. ويستخدم ZUGFeRD 2.x القيمة urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#. أي namespace أو version string خاطئ يفشل.
  4. تحليل XML كـ Cross-Industry Invoice (CII). يجب أن يكون XML well-formed وأن يبدأ بالعنصر الجذري الصحيح (rsm:CrossIndustryInvoice).
  5. تشغيل EN 16931 Schematron. هذا هو الجزء الأكبر: نحو 200 قاعدة أعمال تغطي دلالات الحقول، والأكواد الإلزامية، وحسابات الإجماليات، ومنطق VAT، ومعرفات الأطراف.

Pass يعني أن الفاتورة مقبولة لأي نظام AP متوافق مع EN 16931 في الاتحاد الأوروبي. Fail يعني أن أتمتة AP لدى العميل سترفض الفاتورة عند الاستلام وسيتحول الأمر إلى استثناء يدوي لفريق AR.

أكثر خمسة أخطاء نراها

تتكرر هذه الأخطاء على جانب Mustang في validator عندما تختبر الفرق أول فواتيرها الإلكترونية.

1. AFRelationship خاطئ

ERROR: Embedded file factur-x.xml uses AFRelationship="Source",
expected "Alternative".

تسمح مواصفة PDF بعدة relationship types للملفات المرفقة. لكن Factur-X / ZUGFeRD يتطلبان تحديدًا Alternative، أي أن XML المرفق تمثيل بديل للمحتوى المرئي في PDF. إذا كان مولد PDF مضبوطًا على Data، وهو default في كثير من المكتبات، يفشل Mustang فورًا. سيظل PDF المرئي يعرض بشكل صحيح، لكن payload المنظم غير صالح لنظام AP.

2. XMP namespace خاطئ أو مفقود

ERROR: XMP metadata missing fx:DocumentType or fx:DocumentFileName under
namespace urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#.

يجب أن يعلن XMP packet في PDF أي profile من Factur-X هذا، مثل MINIMUM أو BASIC أو EN 16931 أو EXTENDED، وما اسم الملف الذي يجب البحث عنه. يسهل نسيان ذلك عند كتابة wrapper PDF/A-3 يدويًا؛ endpoint الخاص بـ gPdf وهو /api/v1/e-invoice/render يصدر هذه القيم تلقائيًا.

3. CII XML صحيح نحويًا لكن EN 16931 Schematron يفشل

ERROR: BR-CO-25 — In an invoice (BR-01) the
  ram:SpecifiedTradePaymentTerms/ram:DueDateDateTime is required when
  ram:DocumentTypeCode is 380.

هذا هو معظم الفشل في الواقع. XML صحيح من ناحية الصياغة، لكن قواعد الأعمال تفشل. قواعد EN 16931 Schematron لها IDs مستقرة مثل BR-01 وBR-CO-25 ويمكن الرجوع إليها في المواصفة. الأشهر:

  • BR-01: يجب أن يكون للفاتورة رقم فريد.
  • BR-04: يجب أن يكون لها تاريخ إصدار.
  • BR-05: يجب أن يكون لها invoice type code.
  • BR-CO-25: payment terms مطلوبة عندما يكون document type هو “Commercial invoice”.
  • BR-Z-01: يجب أن تكون VAT category codes واحدة من S أو Z أو E أو AE أو K أو G أو O أو L أو M.

أصلح بيانات المصدر، أعد البناء، ثم أعد التحقق.

4. غلاف PDF/A نفسه لا ينجح

INFO: CII XML extracted and validates against EN 16931.
ERROR: PDF/A-3b conformance check failed: missing Output Intent.

هنا ينجح فحص XML في Mustang لكن يفشل wrapper الأساسي لـ PDF/A-3. السبب الشائع: تمت كتابة XML بشكل صحيح، لكن الناتج PDF عادي وليس PDF/A-3. الملف المرفق موجود، لكن قواعد الأرشفة غير مكتملة. يلتقط validator في gpdf.com/validator/ ذلك بتشغيل veraPDF بالتوازي: يظهر فشل PDF/A-3 في عمود veraPDF بينما يعرض Mustang نجاح XML.

5. عدم تطابق encoding / declaration

ERROR: XML declares <?xml version="1.0" encoding="UTF-8"?> but the
embedded byte stream is UTF-8 with BOM. Mustang strict mode rejects BOM.

هذا شائع عندما تولد أداة XML ملفًا مع UTF-8 BOM ثم يتم تضمينه raw. الحل: إزالة BOM قبل التضمين. endpoint الفاتورة الإلكترونية في gPdf يطبّع ذلك تلقائيًا.

تشغيل Mustang من دون تثبيت Java

تثبيت Java + Mustang CLI مناسب لفحص واحد. أما التحقق المستمر، كل فاتورة تولدها وكل CI run يؤكد e-invoice compliance، فهو احتكاك غير ضروري.

gpdf.com/validator/ يشغّل Mustang في المتصفح:

  1. اسحب PDF من Factur-X / ZUGFeRD إلى منطقة الرفع.
  2. يستخرج validator XML المضمّن ويشغّل Schematron engine الخاص بـ Mustang، المترجم إلى JavaScript / WebAssembly ويعمل داخل Cloudflare Worker.
  3. يعود تقرير Mustang جنبًا إلى جنب مع تقرير PDF/A-3 من veraPDF، لأن الطبقتين يجب أن تنجحا.
  4. نزّل تقرير JSON كدليل QA.

بلا تسجيل دخول وبلا quota. إنه نفس نمط Mustang الذي تثبته عبر Maven، لكنه متاح كخدمة عامة مجانية.

TL;DR

يكشف Mustang خمسة أنماط فشل شائعة؛ معظمها يعني أن الملف وُلد بأداة لا تصدر PDF/A-3 كامل التوافق مع Factur-X / ZUGFeRD. تصدر E-invoice API من gPdf الملف في استدعاء واحد. ويتحقق validator من النتيجة باستخدام Mustang + veraPDF بالتوازي.

معظم الأخطاء التي يمسكها Mustang تخص wrapper أو AFRelationship، لا دلالات XML فقط. توليد الملف بشكل صحيح هو معظم المعركة؛ validator هو الإيصال الذي يثبت ذلك.