Cerrtify

BankID — QR-kod

Visa BankID:s animerade QR-kod. Cerrtify ger dig QR-datan för varje sekund; du ritar bara upp den.

När användaren öppnar BankID på en annan enhet (oftast mobilen) visar du en QR-kod. BankID kräver en animerad QR-kod: innehållet ändras varje sekund, och en skärmdump av en gammal kod slutar fungera. Du behöver inte räkna ut något själv — Cerrtify ger dig den aktuella QR-datan.

Kort sagt

Starta ordern och anropa sedan GET /service/bankid/qr-code?orderRef=… ungefär en gång per sekund. Rita upp qrData som en QR-kod. Sluta när /collect svarar complete eller failed. QR-anropet är gratis — bara själva BankID-ordern debiteras.

Så hänger det ihop

Webbläsare  ──var 1 s──▶  din backend  ──▶  GET /service/bankid/qr-code   (Cerrtify)
Webbläsare  ◀── qrData ─  din backend
Webbläsare  ──var 2 s──▶  din backend  ──▶  POST /service/bankid/collect  (Cerrtify)

API-nyckeln skickas aldrig till webbläsaren. Webbläsaren frågar din backend, och din backend anropar Cerrtify med nyckeln.

1. Starta ordern

POST /service/bankid/auth (inloggning), POST /service/bankid/sign (underskrift) eller POST /service/bankid/payment (betalning). Svaret innehåller orderRef:

{
  "orderRef": "131daac9-16c6-4618-beb0-365768f37288",
  "autoStartToken": "7c40b5c9-fa74-49cf-b98c-bfe651f9a7c6",
  "qrStartToken": "67df3917-fa0d-44e5-b327-edcc928297f8",
  "qrStartSecret": "d28db9a7-4cde-429e-a983-359be676944c"
}

2. Hämta QR-datan varje sekund

curl "https://sandbox-api.cerrtify.com/service/bankid/qr-code?orderRef=131daac9-16c6-4618-beb0-365768f37288" \
  -H "X-API-Key: cert_..."
{ "qrData": "bankid.67df3917-fa0d-44e5-b327-edcc928297f8.4.dee5cd3f9b..." }

Skicka qrData som vanlig text till valfritt QR-bibliotek — till exempel qrcode (npm), qrcode.react eller segno / qrcode (Python). Byt bilden varje sekund.

// Backend (Node/Express): webbläsaren anropar GET /bankid/qr?orderRef=… varje sekund
app.get("/bankid/qr", async (req, res) => {
  const r = await fetch(
    `https://sandbox-api.cerrtify.com/service/bankid/qr-code?orderRef=${encodeURIComponent(req.query.orderRef)}`,
    { headers: { "X-API-Key": process.env.CERRTIFY_API_KEY } },
  );
  res.status(r.status).json(await r.json()); // { qrData: "bankid.…" }
});

3. Sluta

Polla POST /service/bankid/collect varannan sekund (inloggningsflödet). Stoppa QR-loopen när statusen är complete eller failed, när användaren har skannat (hintCode userSign), eller efter ungefär 5 minuter — BankID-ordrar och QR-sessioner går ut.

Fel

SvarBetydelse
400 missing_orderRefIngen orderRef i frågesträngen.
400 no_active_qr_sessionOrdern är okänd, äldre än 5 minuter, tillhör en annan organisation eller startades med ?async=true (se nedan). Starta en ny order.
429Hastighetsgräns. Ett QR-anrop per sekund och öppen order är normalt; räkna med det när du sätter nyckelns gränser.

Räkna ut QR-koden själv (valfritt)

För ordrar som startats med ?async=true, eller om du inte vill göra ett anrop per sekund, räknar du ut datan från startsvaret. Behåll qrStartSecret på din server.

qrData = "bankid." + qrStartToken + "." + sekunder + "." + HMAC-SHA256(qrStartSecret, sekunder) i hex med gemener, där sekunder är antalet hela sekunder sedan ordern startade (0, 1, 2 …).

import { createHmac } from "node:crypto";
const seconds = Math.floor((Date.now() - startedAt) / 1000);
const qrData = `bankid.${qrStartToken}.${seconds}.${createHmac("sha256", qrStartSecret).update(String(seconds)).digest("hex")}`;
import hmac, hashlib, time
seconds = int(time.time() - started_at)
qr_data = f"bankid.{qr_start_token}.{seconds}." + hmac.new(qr_start_secret.encode(), str(seconds).encode(), hashlib.sha256).hexdigest()

Samma enhet i stället för QR

Om användaren redan sitter på mobilen med BankID hoppar du över QR-koden och öppnar appen med autoStartToken:

bankid:///?autostarttoken=<autoStartToken>&redirect=<din retur-URL, URL-kodad>

Fortsätt polla /collect när användaren kommer tillbaka.

On this page