Hej, piszę funkcję do generowania tokena w javascript pod url {{ksef_url}}/online/Session/InitToken.
Niestety nie wiem jakie są wymagania od ksefu, jest tylko formułka tokenu, ale co konkretnie to nie ma:
Base64(encrypt(public_key, bytes(token + ‘|’ + challengeTime)))
Niestety error cody Ksefu nie sa zbyt pomocne i dostaję odpowiedź:
"exceptionCode": 31000,
"exceptionDescription": "Nieprawidłowe wywołanie."
Czy ktoś robi integrację z KSeFem przez javascript / Typescript i ma gotowca żeby się podzielić? Byłbym niezmiernie wdzięczny, albo o zerknięcie na kod niżej i zobaczenie czy coś jest w moim myśleniu nie tak.
Struktura projektu:
files/publicKey.pem
initToken.js
publicKey.pem
Kopiuj
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuWosgHSpiRLadA0fQbzshi5TluliZfDsJujPlyYqp6A3qnzS3WmHxtwgO58uTbemQ1HCC2qwrMwuJqR6l8tgA4ilBMDbEEtkzgbjkJ6xoEqBptgxivP/ovOFYYoAnY6brZhXytCamSvjY9KI0g0McRk24pOueXT0cbb0tlwEEjVZ8NveQNKT2c1EEE2cjmW0XB3UlIBqNqiY2rWF86DcuFDTUy+KzSmTJTFvU/ENNyLTh5kkDOmB1SY1Zaw9/Q6+a4VJ0urKZPw+61jtzWmucp4CO2cfXg9qtF6cxFIrgfbtvLofGQg09Bh7Y6ZA5VfMRDVDYLjvHwDYUHg2dPIk0wIDAQAB
-----END PUBLIC KEY-----
Kopiuj
import fs from 'fs';
import path from 'path';
import crypto from 'crypto';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const USER_AUTH_TOKEN = '9B25A44A7FC94B00C3BB17C2E1468380522609DD96B667DDC8741EEB555E2ED4'; // Token autoryzacyjny
const AUTHORIZATION_CHALLENGE = {
timestamp: "2025-02-06T08:51:51.318Z",
challenge: "20250205-CR-3C98C1F822-4588DBAD54-47"
};
function fetchKsefPublicKey() {
const publicKeyPath = path.join(__dirname, "files", "publicKey.pem");
const publicKeyPem = fs.readFileSync(publicKeyPath, "utf8");
return publicKeyPem;
}
function parseChallengeTimestamp(challengeTimestamp) {
return new Date(challengeTimestamp);
}
// formula: Base64(encrypt(public_key, bytes(token + ‘|’ + challengeTime)))
function generateSessionToken(userAuthToken, challengeTimestamp) {
const publicKeyPem = fetchKsefPublicKey();
const publicKey = crypto.createPublicKey({
key: publicKeyPem,
format: 'pem',
type: 'spki'
});
const message = `${userAuthToken}|${challengeTimestamp.getTime()}`;
console.log('token|timestamp: \n', message);
const buffer = Buffer.from(message, 'utf8');
const encryptedToken = crypto.publicEncrypt({
key: publicKey,
padding: crypto.constants.RSA_PKCS1_PADDING
}, buffer);
return encryptedToken.toString('base64');
}
// Example usage
const challengeTimestamp = parseChallengeTimestamp(AUTHORIZATION_CHALLENGE.timestamp);
const encodedToken = generateSessionToken(USER_AUTH_TOKEN, challengeTimestamp);
console.log('Encoded Token: \n', encodedToken);
logi:
token|timestamp:
9B25A44A7FC94B00C3BB17C2E1468380522609DD96B667DDC8741EEB555E2ED4|1738832031318
tokenForInitSessionTokenRequest.js:36
Encoded Token:
StVogqPJW2m/4vj6bfAfXexioMAdLDMYEbwvouamP82naGNy2bRBgbT+ZZy5o6XaC09tPi1ycW2zy4h6Yqd1ESbOnsIHBbzkO3G+GtdwfANSzdbKHjJuoMIzjgeFpFsiGexXfgsrkAUhRXcK9dhywFEZHOtNYMEgfQO+t09I2o2Z/TT8B7Z1Dg+EmUG0TqgSW5u7iP6TJPNSlKpR/P4uG10isEwibe8wfrXePy6bY5xx2SN0o/4WEATMGQsxoYW+xte4nAIBktsdhk1IyjWMRhxOhXfWVB5YiFlMRrPscQJq4EyxcxwK70TrCg0fbN1D2dR7m3SG8v7QKpt8KOXaww==
POST {{ksef_url}}/online/Session/InitToken
POST https://ksef-test.mf.gov.pl/api/online/Session/InitToken
W headerach Content-Type: application/octet-stream
Kopiuj
<ns3:InitSessionTokenRequest xmlns="http://ksef.mf.gov.pl/schema/gtw/svc/online/types/2021/10/01/0001"
xmlns:ns2="http://ksef.mf.gov.pl/schema/gtw/svc/types/2021/10/01/0001"
xmlns:ns3="http://ksef.mf.gov.pl/schema/gtw/svc/online/auth/request/2021/10/01/0001">
<ns3:Context>
<Challenge>{{-challenge-}}</Challenge>
<Identifier xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:SubjectIdentifierByCompanyType">
<ns2:Identifier>{{-nipIdentifier-}}</ns2:Identifier>
</Identifier>
<DocumentType>
<ns2:Service>KSeF</ns2:Service>
<ns2:FormCode>
<ns2:SystemCode>FA (2)</ns2:SystemCode>
<ns2:SchemaVersion>1-0E</ns2:SchemaVersion>
<ns2:TargetNamespace>http://crd.gov.pl/wzor/2021/11/29/11089/</ns2:TargetNamespace>
<ns2:Value>FA</ns2:Value>
</ns2:FormCode>
</DocumentType>
<Token>{{-initSessionToken-}}</Token>
</ns3:Context>
</ns3:InitSessionTokenRequest>