KSeF Pro WCDocumentacionKSeF Connection & Authentication

KSeF Connection & Authentication

KSeF Pro for WooCommerce uses the same KSeF API authentication model as the PrestaShop and Magento 2 variants. This page covers the authentication flow with WooCommerce-specific details on credential storage, WordPress transient caching, and HPOS order meta.

Authentication Flow

KSeF authentication is session-based. Your KSeF token initiates sessions — it is not sent with every API call. Here is the complete flow KSeF Pro executes automatically:

Step 1: Request challenge
POST /api/online/Session/AuthorisationChallenge
→ Body: { "contextIdentifier": { "type": "onip", "identifier": "YOUR_NIP" } }
← Response: { "challenge": "abc123...", "timestamp": "2025-03-01T10:00:00Z" }

Step 2: Compute HMAC-SHA256 signature
Signature = HMAC_SHA256(key=TOKEN, data=CHALLENGE + TIMESTAMP)

Step 3: Exchange for session token
POST /api/online/Session/AuthorisationToken
→ Body: {
    "challenge": "abc123...",
    "authorisation": "HMAC_SIGNATURE",
    "identifier": { "type": "onip", "identifier": "YOUR_NIP" }
  }
← Response: { "sessionToken": { "token": "SESSION_TOKEN", "context": {...} } }

Step 4: Use SESSION_TOKEN as Bearer for all subsequent calls
Authorization: Bearer SESSION_TOKEN

KSeF Pro handles all four steps automatically. Session tokens are stored as WordPress transients (_ksefpl_session_token, 25-minute TTL) — shorter than the 30-minute MF-side expiry to ensure proactive refresh before timeout.

KSeF Pro WooCommerce connection status panel

WordPress-Specific Token Storage

KSeF Pro stores the KSeF API token in the wp_options table, encrypted with AES-256. The encryption key is derived in priority order:

| Priority | Source | How to set | |---|---|---| | 1 | KSEFPL_ENCRYPTION_KEY constant in wp-config.php | define('KSEFPL_ENCRYPTION_KEY', '...') | | 2 | AUTH_KEY from wp-config.php | Already present in all WordPress installations |

Why this matters: The AUTH_KEY can change during site migrations (especially when using WordPress Salts Regenerator or moving to a new server). If AUTH_KEY changes, the stored token becomes unreadable and must be re-entered.

For production installations, define a static KSEFPL_ENCRYPTION_KEY in wp-config.php that survives migrations:

// wp-config.php — add before "That's all, stop editing!"
define('KSEFPL_ENCRYPTION_KEY', 'your-64-character-random-hex-string-here');

Generate a secure key:

openssl rand -hex 32

Token Storage Diagnostic

If the plugin reports an invalid token after a site migration:

# Check if the stored token is readable
wp eval "echo get_option('ksefpl_api_token') ? 'Token present (encrypted)' : 'Token missing';"

If present but unreadable (decryption fails after key change), the plugin shows a red warning in the connection tab. Re-enter the token and save.

Test vs. Production Environments

Test Environment (ksef-test.mf.gov.pl)

| Characteristic | Value | |---|---| | URL | https://ksef-test.mf.gov.pl/api | | FA(2) schema | Same as production (2.0 from April 2026) | | Token type | Test tokens only — generate at ksef-test.mf.gov.pl | | UPOs issued | Yes — functionally complete, no legal standing | | KSeF-IDs | Assigned with test prefix — not in official ledger | | Availability | 24/7, same performance as production |

Use the test environment to validate:

  1. Token verification succeeds (NIP/token pair recognized)
  2. FA(2) XML generates without schema errors (use XML preview)
  3. Full session cycle completes: open → submit → close → UPO received
  4. KSeF-ID is written to WooCommerce order meta and visible in the order detail
  5. WordPress cron processes the queue reliably

Production Environment (ksef.mf.gov.pl)

Switch to production only after successful test validation. The environment dropdown is in WooCommerce → KSeF Pro → KSeF Connection. When switching:

  1. Change environment to Production
  2. Replace the test token with your production token (different tokens — not interchangeable)
  3. Click "Verify connection" — confirm green indicator
  4. Process one real order and confirm ACCEPTED status in the audit log

NIP registration check before going live:

curl -s -X POST https://ksef.mf.gov.pl/api/online/Session/AuthorisationChallenge \
  -H "Content-Type: application/json" \
  -d "{\"contextIdentifier\":{\"type\":\"onip\",\"identifier\":\"YOUR_NIP\"}}" \
  | python3 -m json.tool

A response containing a challenge field confirms the NIP is active in production KSeF. An error 10000 means the NIP is not registered — contact your tax authority.

NIP Validation

KSeF Pro validates NIP at three checkpoints:

1. On Seller Data Save

The plugin applies the weighted checksum algorithm:

Weights: 6, 5, 7, 2, 3, 4, 5, 6, 7
Digit 10 must equal (sum of weighted digits 1-9) mod 11

Invalid checksums show an inline red warning. This catches transcription errors (digit transposition) before they cause live submission failures.

2. On "Verify Connection" Click

KSeF Pro sends a session challenge to the selected environment with your NIP. A successful challenge response (HTTP 200 with challenge field) confirms:

  • The NIP is registered in KSeF
  • The NIP is active (not deactivated)
  • The selected environment (test/production) matches the NIP's status in that environment

3. Pre-Submission Check

Immediately before opening a new KSeF session, KSeF Pro performs a lightweight ping. This catches tokens revoked between configuration save and submission time. If the check fails:

  • The submission is blocked
  • An error entry is written to the audit log with the KSeF error code
  • No order status changes occur
  • The WordPress cron retries according to the retry policy

Session Token Lifecycle

| State | WordPress Store | Description | |---|---|---| | No session | No transient | Module is idle | | Authorising | _ksefpl_auth_pending | Challenge/response in progress | | Active | _ksefpl_session_token (25-min TTL) | Session open; invoices can be submitted | | Sending | Session meta in {prefix}_ksefpl_sessions | Batch submission in progress | | Closing | Session record status=closing | Waiting for MF UPO processing | | Closed | Session record status=closed | UPO downloaded; KSeF-IDs written to orders | | Expired | Transient TTL elapsed or deleted | Must open new session | | Terminated | Session record status=terminated | Invoices NOT accepted — must re-submit |

The Terminated state is the critical one. Any invoices in a terminated session were not accepted by KSeF and have no KSeF-IDs. They must be resubmitted in a new session from the audit log.

HPOS and Order Meta

Under HPOS (WooCommerce High-Performance Order Storage), order meta is stored in wc_orders_meta instead of wp_postmeta. KSeF Pro handles this transparently. The order meta keys are identical regardless of storage backend:

| Meta key | Content | Example | |---|---|---| | _ksefpl_ksef_id | Permanent KSeF-ID | 1234567890-20250301-000001 | | _ksefpl_session_ref | KSeF session reference number | 20250301ABCD1234 | | _ksefpl_submission_status | Current status | ACCEPTED | | _ksefpl_submission_ts | Submission Unix timestamp | 1740826800 | | _ksefpl_upo_path | Absolute path to UPO file | /var/www/.../ksefpl-upo/2025/03/1001.xml | | _ksefpl_buyer_nip | Buyer NIP from checkout | 9876543210 |

To query KSeF status for an order programmatically:

$order = wc_get_order($order_id);
$ksef_id   = $order->get_meta('_ksefpl_ksef_id');
$status    = $order->get_meta('_ksefpl_submission_status');
$upo_path  = $order->get_meta('_ksefpl_upo_path');

This works identically under both HPOS and legacy storage — get_meta() abstracts the underlying table.

Connectivity and Firewall

Required Outbound Connections

| Host | Port | Protocol | |---|---|---| | ksef-test.mf.gov.pl | 443 | HTTPS | | ksef.mf.gov.pl | 443 | HTTPS | | api.nbp.pl | 443 | HTTPS (for PLN exchange rates) |

The NBP (National Bank of Poland) API is used for currency conversion when orders are placed in non-PLN currencies. If blocked, KSeF Pro falls back to the manual exchange rate configured in Advanced settings.

Test Connectivity

# Test KSeF access
curl -sI https://ksef-test.mf.gov.pl/api/online/Session/AuthorisationChallenge \
  -H "Content-Type: application/json" | head -1
# Expected: HTTP/2 405
 
# Test NBP access
curl -s "https://api.nbp.pl/api/exchangerates/rates/A/EUR?format=json" | python3 -m json.tool | head -5
# Expected: JSON with "mid" rate

Shared Hosting Restrictions

Many shared hosting providers block outbound connections to arbitrary hosts. If your host uses an IP whitelist approach, request that ksef-test.mf.gov.pl and ksef.mf.gov.pl be added. Use hostname-based rules — the MF IP addresses change periodically.

Token Rotation

When rotating your KSeF token (recommended annually or after a security incident):

  1. Generate the new token on the KSeF portal — both old and new tokens are valid simultaneously
  2. In WooCommerce → KSeF Pro → KSeF Connection, replace the old token
  3. Click "Verify connection" to confirm the new token works
  4. Delete the old token on the KSeF portal after confirming
  5. If you have in-flight KSeF sessions using the old token, let them complete first before deleting

Token rotation does not affect existing KSeF-IDs or audit records.

Next Steps

Edit this page on GitHub
Was this page helpful?

Documentación relacionada

Este tema también está disponible para otras plataformas: