Getting Started
This document provides instructions for embedding PC WEB SDK in web application. In order to understand better how to work with PC we recommend you to read the following documents as well:
- Architecture and functionality presentation
- Architecture and functionality
The PC WEB SDK allow to implement all functionality of PC right in your web application.
Project integration
The PC WEB SDK library can be imported into your project from the SafeTech npm repository.
npm i @safetech/pcsdk
After installing the library, PCSDK can be imported into the project.
import PCSDK from ‘@safetech/pcsdk’
Your web application must use one instance of PCSDK class during operating.
SDK Initialization
To initialize PC SDK library you need to call async method PCSDK.init(callback) passing the callback function. The function is called when a token is connected or disconnected. An object with properties {connected, disconnected} is passed as arguments, which contains arrays with identifiers of connected and disconnected tokens. Your are expected to initialize PCSDK before calling any other methods from PCSDK.
import PCSDK from ‘@safetech/pcsdk’
try {
await PCSDK.init(callback);
} catch (error) {
// handle the error
}
Registering users
Process of user registration includes followings steps:
- Getting the personalization data from the PC Server (via deeplink, deeplink + activation code) see Architecture and functionality document for more details on this.
- Registering a PC User on PC Server. During this process PCSDK generates needed key sets
- Storing user's keys in token storage for further usage
Step 1. Import PCUser from an appropriate source
First of all, you need to get a list of connected tokens and information about them using the method PCSDK.getTokensInfo()
Second, you should construct a PCUser object (also referenced as key) from String value which contains either JSON extracted from deeplink or JSON delivered to your app with usage of PC Server API and the deviceId where the user will be stored.
import PCSDK, {PCUsersManager} from ‘@safetech/pcsdk’;
try {
const devices = await PCSDK.getTokensInfo();
//returns array of objects with properties { label, serial, leftSpace, deviceId}
const user = await PCUsersManager.importUser(source, deviceId);
} catch(error) {
// handle the error
}
// If no errors, PCUser imported successfully - continue registration
Step 2. Check if PCUser requires activation
When delivering personalization data to your clients your infrastructure may use different methods (via deeplink, deeplink + activation code, JSON-value) to deliver the key data to the web app. The following snippet demonstrates how to import key data to a valid PCUser object:
import PCSDK, {PCUsersManager} from ‘@safetech/pcsdk’;
try {
const devices = await PCSDK.getTokensInfo()
if (devices.length) {
const {deviceId} = devices[0];
const user = await PCUsersManager.importUser(source, deviceId);
if (!user.isActivated()) {
// PCUser requires activation, get activation code according to your rules
const activationCode = getActivationCode();
await PCUsersManager.activate(user, activationCode);
} else {
// No activation is required
}
} else {
console.log(‘No connected tokens’)
}
} catch(error) {
// handle the error
}
// If no errors, PCUser imported successfully - continue registration
Step 3. Registering the key on the PC Server
Now, you can register the PCUser on the PC Server. The key pair is generated and the public key is sent to the server while the private key is encrypted with password and encryption layer. You use PCUsersManager.register() to registered the key on the server side.
import {PCUsersManager} from ‘@safetech/pcsdk’;
try {
// Prompt the tokens password
const password = promptPassword();
await PCUsersManager.register(user, password)
} catch(error) {
// handle the error
}
// If no errors, PCUser register successfully - continue registration
Step 4: Save the PCUser object to the token store.
The final step is, you must save the PCUser into storage. Each PCUser object is stored in token and referenced by a unique name which is supposed to be entered by a client of your app.
Besides, the keys which are used to confirm transactions (HMAC key which is used to calculate a confirmation code and private key used to generate ECDSA-signature) are always additionally protected with a tokens password and encryption layer.
So, the process of saving a key will look in this way:
// Prompt a unique name for the key from your client or generate it in your web app
const keyName = promptKeyName();
// Prompt the tokens password
const password = promptPassword();
// Save the key to storage
try {
await PCUsersManager.store(user, keyName, password);
} catch(error) {
// handle the error
}
// If no errors, PCUser save successfully
Overall key registration flow
The overall process of registration may have the following structure:
import PCSDK, {PCUsersManager} from ‘@safetech/pcsdk’;
// 1. Import PCUser
let user = null;
try {
const devices = await PCSDK.getTokensInfo()
if (devices.length) {
const {deviceId} = devices[0];
user = await PCUsersManager.importUser(source, deviceId);
} else {
console.log(‘No connected tokens’)
}
} catch(error) {
// Import failed - handle a error
}
// 2. Check if PCUser requires to be activated
try {
if (!user.isActivated()) {
const activationCode = getActivationCode();
await PCUsersManager.activate(user, activationCode);
} else {
// No activation is required
}
} catch(error) {
// Activation failed - handle a error
}
// 3. Register PCUser
try {
const password = promptPassword();
await PCUsersManager.register(user, password)
} catch(error) {
// Registration failed - handle a error
}
// 4. Store the key
const keyName = promptKeyName();
const password = promptPassword();
try {
await PCUsersManager.store(user, keyName, password);
} catch(error) {
// Store failed - handle a error
}
Process transactions
The overall scenario of processing a transaction includes the following stages:
- Call PCUsersManager.listStorage() to obtain a list of users from the storage.
- Filter the list of users for which transactions will be loaded.
- Call PCTransactionsManager.getTransactionList() for each desired PCUser to find out if there are any transactions to be processed.
- Call PCTransactionsManager.getTransaction() to get transaction by its identifier. Consider also calling PCTransactionsManager.getTransactionBinaryData() for transactions which contain attachments.
- Display loaded transactions to your client in a desired way with buttons for confirmation and declination.
- Handle events from clicking the confirmation/declination buttons:
- Prompt the password
- Call either PCTransactionsManager.sign() or PCTransactionsManager.decline() to sign or decline the transaction.
Getting transaction data
This code snippet demonstrates how to download available transactions and get ready to display them.
import {PCUsersManager, PCTransactionsManager} from ‘@safetech/pcsdk’;
try {
const users = await PCUsersManager.listStorage();
// Filter list of PUsers in a desired way
for (let user of users) {
if (user.userId === TARGET_USER_ID || user.keyName === TARGET_KEY_NAME) {
// Load list of transactions for the user
const transactionsIdArr = await PCTransactionsManager.getTransactionList(user)
if (transactionsId.length) {
for (let transactionId of transactionsIdArr) {
const transaction = await PCTransactionsManager.getTransaction(user,transactionId);
if (transaction.hasBinaryData()) {
await PCTransactionsManager.getTransactionBinaryData(user, transaction);
} else {
// No attachment for this transaction - display it immediately
}
}
}
}
}
} catch (error) {
// handle the error
}
Displaying transaction data
Before transaction can be confirmed or declined it should be shown to a client. To show the transaction in more user-friendly way consider the following methods that you can use when working with a particular PCTransaction:
- PCTransaction.getTransactionText() - returns the text of transaction. Might be null if the transaction contains an attachment only;
- PCTransaction.getSnippet() - returns short description of the transaction which comes in handy when displaying a transaction in the list. Might be null.
- PCTransaction.getStoredBinaryData() - returns Uint8Array pointing to binary attachment (which is PDF document for example). Might be null if the transaction does not contain any attachment.
- PCTransaction.getTextRenderType() - returns type of transaction text. It makes sense to call this method if PCTransaction.text non-null and non-empty value to render the text in a proper way. This method returns either null or 'raw' for plain-text transactions and 'markdown' if the text of the transaction follows markdown syntax.
- PCTransaction.getSnippetRenderType() - the similar for the PCTransaction.textRenderType.
Confirm or decline the transaction
As soon as you have downloaded and displayed transaction data, it can be confirmed through sign method or declined with decline method of PCTransactionsManager class. The sample confirmation flow looks like the following:
import {PCTransactionsManager} from ‘@safetech/pcsdk’;
const password = promptPassword();
if (confirmationButtonPressed) {
PCTransactionsManager.sign(user, transaction, password)
.then(/* Notify the client that the transaction has been signed successfully*/)
.catch((error) => {/* Handle the error if the transaction was not signed*/})
} else {
PCTransactionsManager.decline(user, transaction, password)
.then(/* Notify the client that the transaction has been declined successfully*/)
.catch((error) => {/* Handle the error if the transaction was not declined*/})
}