npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

swish-mock

v0.1.0

Published

Drop-in mock server for the Swedish Swish Merchant API. Runs locally with no certificates, supports configurable scenarios via phone-number suffix (matching MSS), and is suitable for CI and local development.

Readme

swish-mock

CI License: MIT TypeScript

A drop-in mock server for the Swedish Swish Merchant API. Runs locally with no certificates, drives outcomes from the payer phone number (matching the MSS convention), fires real callbacks, and is suitable for CI and local development.

Tested against swish-merchant (the published Swish Merchant client on npm) — the integration tests in this repo run a real Swish instance against the mock and assert a full create → poll → terminal-state → callback flow.

Why

Swish has an official simulator (MSS), but it requires:

  • A publicly reachable HTTPS callback URL — ngrok or similar for local dev.
  • Network round-trips that introduce latency and flakiness in CI.
  • Sharing a globally rate-limited test endpoint with everyone else.

This package runs entirely in-process, resolves payments deterministically, and lets you assert callback contents without an HTTP listener.

Install

npm install --save-dev swish-mock

Quickstart — CLI

npx swish-mock

Starts a server on http://127.0.0.1:8586 with the three Merchant endpoints:

PUT   /api/v2/paymentrequests/{instructionUUID}
GET   /api/v1/paymentrequests/{id}
PATCH /api/v1/paymentrequests/{id}

Environment variables

| Var | Default | Description | |---|---|---| | PORT / SWISH_MOCK_PORT | 8586 | Listen port | | HOST / SWISH_MOCK_HOST | 127.0.0.1 | Listen host | | SWISH_MOCK_SCENARIO | paid | Default scenario when no header / phone match | | SWISH_MOCK_RESOLVE_DELAY_MS | 1500 | ms before a payment resolves to terminal | | SWISH_MOCK_ORDER_TTL_MS | unset | Evict payments older than this many ms | | SWISH_MOCK_BODY_LIMIT | 100kb | Maximum JSON request body size |

Invalid values exit with a clear error rather than crashing on NaN.

Quickstart — programmatic

import { createMockServer } from "swish-mock";

const captured: unknown[] = [];

const { app, flush } = createMockServer({
  defaultScenario: "paid",
  resolveDelayMs: 0,
  // Capture callbacks in tests without spinning up an HTTP listener
  onCallback: (url, payload) => captured.push({ url, payload }),
});

app.listen(8586);

Scenarios

Five scenarios drive the terminal state:

| Scenario | Final status | errorCode | |---|---|---| | paid | PAID | — | | declined | DECLINED | — | | cancelled | CANCELLED | — | | error | ERROR | BANKIDCL | | timeout | ERROR | TM01 |

Routing precedence (highest first)

  1. Phone-suffix on payerAlias — last digit drives outcome (matches MSS):

    | Suffix | Scenario | |---|---| | 0 | paid | | 1 | declined | | 2 | error | | 3 | timeout | | 4 | cancelled |

  2. x-mock-scenario HTTP header — fallback when no payerAlias or suffix is unmapped.

  3. Server defaultScenario — used when neither phone nor header matches.

# Resolves to DECLINED (suffix wins)
curl -X PUT http://127.0.0.1:8586/api/v2/paymentrequests/11A86BE70EA346E4B1C39C874173F088 \
  -H "Content-Type: application/json" \
  -d '{
    "payeeAlias": "1231181189",
    "payerAlias": "46701112231",
    "amount": "100",
    "currency": "SEK",
    "message": "Test"
  }'

State machine

A payment starts in CREATED and transitions exactly once to one of PAID, DECLINED, CANCELLED, ERROR after resolveDelayMs. Merchant cancellation via PATCH is only valid from CREATED — terminal states return 422 RP09.

When the payment reaches its terminal state, the mock POSTs the serialized payment to callbackUrl (if provided). Tests that don't want real HTTP can supply onCallback to capture deliveries in-process.

Endpoints

Create payment

PUT /api/v2/paymentrequests/{instructionUUID}

instructionUUID is 32 uppercase hex chars (no hyphens), client-generated. Returns 201 Created with Location and PaymentRequestToken headers and an empty body — the same as real Swish.

Get payment

GET /api/v1/paymentrequests/{id}

Returns the full payment object, including current status, errorCode, paymentReference, and datePaid when applicable.

Cancel payment

PATCH /api/v1/paymentrequests/{id}
Content-Type: application/json

[{ "op": "replace", "path": "/status", "value": "cancelled" }]

Only valid while the payment is CREATED.

Use with swish-merchant

Point the published Swish Merchant client at the mock by overriding url and dropping its httpsAgent:

const Swish = require("swish-merchant");

// `cert`/`key` strings ≥ 1264 chars are passed through inline (the client
// otherwise treats them as filesystem paths).
const DUMMY = "x".repeat(1300);

const client = new Swish({
  alias: "1231181189",
  paymentRequestCallback: "https://merchant.example/cb",
  cert: DUMMY,
  key: DUMMY,
});
client.url = "http://127.0.0.1:8586";
client.httpsAgent = undefined; // node-fetch otherwise honors the dummy agent

const created = await client.createPaymentRequest({
  phoneNumber: "46701112230", // ends in 0 → paid
  amount: 100,
  message: "Order 42",
});

See tests/integration.test.ts for the full flow including callback assertions.

Use in tests

import { createMockServer } from "swish-mock";
import request from "supertest";

const { app, flush, store } = createMockServer({ resolveDelayMs: 60_000 });

await request(app)
  .put("/api/v2/paymentrequests/11A86BE70EA346E4B1C39C874173F088")
  .send({ payeeAlias: "1231181189", amount: "100", currency: "SEK" });

await flush(); // resolve everything synchronously, bypass timers

const payment = store.get("11A86BE70EA346E4B1C39C874173F088");
expect(payment?.status).toBe("PAID");

CI example

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: npm ci
      - run: npx swish-mock &
      - run: sleep 1 && npm test
        env:
          SWISH_BASE_URL: http://127.0.0.1:8586

What the mock does not do

  • No mTLS — the mock accepts plain HTTP. Bypass httpsAgent / cert/key in your client when pointing at the mock.
  • No QR image rendering — the PaymentRequestToken header is returned; bring your own QR library if you need to render it.
  • No refunds endpoint — only the three core paymentrequest endpoints are mocked.
  • No persistence — payments live in memory and are wiped on process exit.
  • No real callback retries — same as real Swish.

Maintained by

Built and maintained by Fiive.

License

MIT — see LICENSE.