Skip to content

HubfiscalStoreShopify

Receives a raw Shopify order payload (from a webhook or previous node) and stores it in the Hub Fiscal centralized MySQL/MariaDB database as pending. Designed to be placed at the beginning of a fiscal workflow, before invoicing, to queue the order and ensure no order is ever lost even if the fiscal provider step fails later.

Key features:

  • Upsert: If the order already has a record (same entity_id + entity_source + type), it updates only safe fields (status stays completed/failed once set). Prevents duplicates on Shopify webhook retries.
  • Auto-detection: Extracts country from billing_address.country_code and auto-selects the fiscal provider (PT/AO/MZ → billpt, ES/DE → fiskaly).
  • NIF resolution: Reads the customer NIF/VAT from Shopify note_attributes (configurable key).
  • Atomic transaction: Inserts into documents, fiscal_status and logs in one transaction.
FieldTypeRequiredDescription
credentials_idcredentialsYesHub Fiscal MySQL/MariaDB credential (sqlQuery type)
country_isotextNoCountry ISO code. Defaults to billing_address.country_code
document_typeselectNoFT, FR, ORC, NC. Default: FT
fiscal_providerselectNobillpt, fiskaly, sage. Auto-detected by country if empty
initial_statusselectNopending (default) or completed
nif_attributetextNoShopify note_attributes key where the customer NIF/VAT is stored. Default: nif
entity_sourcetextNoOrder source: shopify, manual, api. Default: shopify
assign_numberingselectNoNo (default): only stores portal and zone. Yes: also assigns the series number and sets completed (portals without a fiscal third party)
save_payloadselectNoSave full Shopify JSON in payload_json (up to 50KB). Default: Yes

Requires a sqlQuery credential (MySQL/MariaDB) with:

  • host: Database host (e.g. 127.0.0.1)
  • user: Database user (e.g. user_hubfiscal)
  • password: User password
  • database: Hub Fiscal database name (e.g. hubfiscal)
  • port: Port (default: 3306)

The node maps Shopify order fields to Hub Fiscal automatically:

Hub Fiscal fieldShopify source
entity_iddata.id
order_numberdata.order_number → data.name
country_isoconfig → billing_address.country_code → PT
typeconfig document_type → FT
fiscal_providerconfig → auto by country
contact_namebilling_address.name
contact_emaildata.email
contact_nifnote_attributes[nif_attribute].value
total_netdata.subtotal_price
total_taxdata.current_total_tax → data.total_tax
total_grossdata.total_price
currencydata.currency
issued_atdata.created_at (date only)

When fiscal_provider is left empty, the node selects the provider based on country_iso:

CountryProvider
PT, AO, MZ, CVbillpt
ES, DE, ATfiskaly
Othernull (stored empty, fill manually later)

Shopify does not have a native NIF/VAT field. Configure your Shopify checkout to collect it as a note attribute and set nif_attribute to match the key name:

"note_attributes": [
{ "name": "nif", "value": "PT999999990" }
]

Common key names: nif, vat, tax_id, nif_vat, numero_fiscal.

The documents table has a unique constraint on (entity_id, entity_source, type). On Shopify webhook retries:

  • If the document is still pending: all fields are refreshed.
  • If the document is already completed or failed: status is preserved, only totals and payload update.

This ensures a re-delivered webhook never overwrites an already-fiscalized document.

Expected input: a Shopify Order object from a webhook or previous node:

{
"id": 6684429451477,
"order_number": 14522,
"name": "#14522",
"email": "customer@example.com",
"financial_status": "paid",
"currency": "EUR",
"subtotal_price": "63.56",
"current_total_tax": "14.62",
"total_price": "78.18",
"created_at": "2026-04-20T10:00:00Z",
"billing_address": {
"name": "John Doe",
"country_code": "PT"
},
"note_attributes": [
{ "name": "nif", "value": "PT999999990" }
]
}
{
"success": true,
"hub_document_id": 22,
"entity_id": "6684429451477",
"order_number": "14522",
"country_iso": "PT",
"type": "FT",
"status": "pending",
"fiscal_provider": "billpt",
"contact_name": "John Doe",
"contact_email": "customer@example.com",
"contact_nif": "PT999999990",
"total_net": 63.56,
"total_tax": 14.62,
"total_gross": 78.18,
"currency": "EUR",
"message": "Pedido Shopify #14522 registrado en Hub Fiscal (ID: 22)"
}

Pattern 1 — Register then fiscalize:

Shopify Webhook → HubfiscalStoreShopify (pending)
→ BillptCreateInvoiceFromShopify
→ HubfiscalStoreBillpt (updates to completed)

Pattern 2 — Register only (deferred fiscalization):

Shopify Webhook → HubfiscalStoreShopify (pending)

Fiscalization is handled by a separate scheduled workflow that queries status = 'pending' from Hub Fiscal.

  • The fiscal_status table records the initial register action with status: pending for traceability.
  • contact_nif is only populated if the Shopify order contains a note_attribute matching nif_attribute. If the NIF is stored elsewhere (metafields, tags), a preceding Transform node can move it into note_attributes or use the contact_nif field override.
  • The issued_at date is extracted from created_at (date only, time is dropped).

Portal and numbering (daily aggregation to Sage X3)

Section titled “Portal and numbering (daily aggregation to Sage X3)”

Besides storing the document, the node determines the sales portal (equivalenza.com, .it, .fr or .pt) from the order and the zone (Canary Islands, if the shipping postal code starts with 35 or 38), and stores them on the document. HubfiscalAggregateSales uses this to group the day’s sales.

With the Number and complete option set to Yes, on portals without a fiscal third party (equivalenza.com, .it and .fr) the node also:

  • assigns the next sequential number of the series, with no leading zeros and no yearly reset (FESH1, FESH2…), and
  • sets the document to completed.
PortalInvoiceCredit note
equivalenza.comFESHAESH
equivalenza.com (Canary Islands)FCAHACAH
equivalenza.itFITHAITH
equivalenza.frFFRHAFRH
  • No gaps or duplicates, even when orders arrive at the same time: each series counter is locked while assigning, and an error does not consume the number.
  • Idempotent: resending the same order does not renumber it.
  • equivalenza.pt is not numbered here: Bill.pt does it (FHPT / AHPT).
  • A type other than invoice or credit note (for example ORC) or a portal with no rule is not numbered.
  • It is off by default (No): only portal and zone are stored. Turn it on when you decide from which day numbering starts, because numbering consumes real series numbers.

It requires applying to the Hub Fiscal database the portal and zone columns and the document_sequences and portal_providers tables. If they are not applied, the node keeps working as before and does not number.

Extra node output with this data: portal, zone, fiscal_doc_number and numbering (the result: numerado, ya_numerado, numeracion_desactivada, delegado_en_billpt, esquema_no_aplicado…).