node-sispnode-sisp
Beta

@akira-io/sisp beta documentation. APIs may change before the stable release.

Security

Fingerprints

Every exchange with SISP is signed with SHA-512 over an exact field concatenation. The token is base64(sha512(posAutCode)), computed once and prefixed to every fingerprint. Amounts always enter fingerprints as integer thousandths parsed decimally from strings, never through float multiplication.

  • Payment request: token, timestamp, amount, merchantRef, merchantSession, posID, currency, transactionCode.
  • Callback: sixteen fields in gateway order, validated with crypto.timingSafeEqual. A mismatch fails the transaction with invalid_callback_fingerprint and stops the pipeline.
  • Refund (version 2): trimmed fields with clearingPeriod zero-padded to 4 and transactionID to 8.

All three algorithms are verified byte for byte against golden vectors generated by the PHP package (tests/fixtures/golden-vectors.json).

Payload encryption

With an appKey configured, the transaction payload column is encrypted at rest with AES-256-GCM (random IV, authenticated). Reads are transparent: models return the decrypted object, tampered or foreign ciphertexts fall back to the raw value, and plaintext rows written before the key existed keep working.

Signed URLs

Retry and cancel routes only respond to URLs signed with HMAC-SHA256 derived from appKey. Retry URLs expire after 30 minutes. Tampering with any parameter, the path, or the expiry invalidates the signature.

Idempotency and callback safety

The package stores checkout idempotency keys in sisp_payment_intents. A duplicate payment POST with the same key returns the already linked transaction instead of creating a new one. Failed intents without a transaction can be reclaimed on the next request.

Every gateway submission is stored in sisp_transaction_attempts. Callback validation uses the attempt’s merchantRef and merchantSession, then updates the attempt and parent transaction atomically. This prevents a late failed callback from an old retry attempt from overwriting the active pending retry.

Idempotency does not replace SISP fingerprints. Fingerprints still prove callback integrity. Idempotency prevents duplicate local transactions and gives each retry a distinct audit trail.

Blacklist and rate limits

await sisp.models.blacklist.add({ type: 'ip', value: '10.0.0.1', reason: 'fraud', expiresInMinutes: 60 });
await sisp.models.blacklist.remove('ip', '10.0.0.1');

Blacklisted IPs are rejected before any work happens. Rate limits are DB-backed sliding windows per identifier; exceeding a window blocks the identifier for the window duration. Both tables are shared with the Laravel package schema.

Metadata redaction

Captured request metadata stores a copy of the query, body, and headers with sensitive keys redacted (authorization, cookie, password, token, card, cvv, pin, and friends), plus a SHA-256 device fingerprint.

Next: Sandbox and Testing