Plugins

To facilitate a smoother integration OpenCard provides JS plugins that an EMS can use in their environment to further improve the OpenCard integration and make it part of the EMS own product suit.

PDPC plugin

When a card holder is created OpenCard automatically sends an email to card holder with a PDPC (personal data processing consent). It is mandatory for the card holder to sign the PDPC in order for OpenCard to deliver any data to the EMS on behalf of the card holder.

With the PDPC plugin the EMS can integrate the PDPC into their own product, which gives the EMS more control of the onboarding flow.

The below steps is recommended to in order to use the PDPC plugin:

  1. When a card holder is created via the API the EMS can set the skip_pdpc_email flag to true, this will prevent an email beeing sent.
  2. When a card holder has been created the URL to the PDPC is returned in the response. The URL should be stored in the EMS product.
  3. Using the JS plugin the EMS can now display a message to the card holder in their product informing the card holder that they need to sign the PDPC and where this can be done.
  4. It is recommended that you subscribe on the webhook card_holder.identified which will let you know when the PDPC has been signed.

Plugin usage

Using the plugin is very simple. Below is an example.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
    <title>ocPdpc</title>
    <link rel="stylesheet" href="https://sandbox-api.opencard.io/plugin/pdpc/css/pdpc.min.css">
    <script src="https://sandbox-api.opencard.io/plugin/pdpc/js/pdpc.min.js" defer></script>
    <script>
      var ocPdpc;
      document.addEventListener('DOMContentLoaded', function() {
        ocPdpc = new ocPdpc({
          modalMessage: 'You have not approved your PDPC, Personal Data Processing Consent. Your employer has decided to automate the processing of your expenses during the course of your employment, which means that Nordea Bank in its capacity as card issuer will need to process your personal data in the OpenCard platform.<br><br>By following the button "View Consent" you will be presented with the Personal Data Processing Consent (PDPC) and have the option to give your consent electronically.',
          buttonMessage: 'View Consent',
          pdpcUrl: 'http://application.opencard.local:9527/#/accounts/1/pdpcs/4/sign/dJERLqp56hPypMF4amkBOQTDyGx9Fu2ntecLYtYO',
          style: {
            modal: {
              backgroundColor: 'rgba(0,0,0,0.2)' //Overlay of the modal
            },
            modalContent: {
              backgroundColor: '#fefefe', //Background color of modal
              color: '#000', //Text color of modal
              font: '15px Arial, sans-serif', //Font of modal
              shadow: '5px 5px 4px #888888', //Box shadow of modal
              borderRadius: '4px' //Border radius of modal
            },
            modalContentButton: {
              backgroundColor: '#1e90ff', //Background color of PDPC button
              color: '#000' //Text color of PDPC button
            }
          }
        });
      });
    </script>
  </head>
  <body style="background: white">
    <button onclick="ocPdpc.openPdpcMessage()">Show PDPC message</button>
  </body>
</html>

TPA plugin

This plugin enables easier collection of TPA and billing information to be sent to EMS own servers.

Plugin usage

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Plugin demo</title>
    <script type="module">
      import ocTPA from "https://api.opencard.io/plugin/tpa/js/tpa.min.js";

      // Initialize the plugin with custom options
      const pluginInstance = new ocTPA({
        childTo: document.getElementById("divToBindTo"),
        orgNumber: "<user-organization-number>",
        country: "<your-country>",
        accountId: <your-accountId>,
        oAuthToken:
          "<your-token>",
      });
    </script>
    <link
      rel="stylesheet"
      href="https://api.opencard.io/plugin/tpa/css/tpa.min.css"
    />
  </head>
  <body>
    <div id="divToBindTo"></div>
  </body>
</html>

Default options

These parameters can be overriden to customize your deployment.

NOTE: (transactionInformationProductsMapping) and (enrichedInformationProductsMapping) must be fully supplied if overriden and cannot be overriden gradually

{
      childTo: null, // This is the element the UI should bind to, if none are specified the UI will bind to body
      oAuthToken: null, // Your oAuthToken generated from application.opencard.io => account => oAuth Clients. Make sure to only use scopes [public-records-read, card-issuers-read]
      accountId: null, // Your account ID
      orgNumber: null, // The users organization number
      country: null, // Country of the user. Choose one of ["SE", "NO", "DK", "FI"].
      language: "en", // The UI language, only "en" supported right now.
      showIntro: true, // Should show intro
      showProducts: true, // Should show products
      showInvoicingInformation: true, // Should show invoiceing information. If false, make sure to specify invoiceEmail and invoiceReference manually.
      invoiceEmail: null, // Value to prefill invoice email with.
      invoiceReference: null, // Value to prefill invoice reference with.
      showPoweredByOpencard: true, // Show the Powered by OpenCard logo in the top right corner.
      startAtSuccess: false, // If the first screen should be the success screen. Useful if user has already completed the process previously for example.
      showUseAgain: true, // Show the "Use again" button on the success screen.
      productsDescription: "This is a description for products page",
      invoicingDescription: "This is a description for invoicing page",
      companySignatoryCombinationDescription:
        "This is a description for signatory combination page",
      companySignatoryEmailDescription:
        "This is a description of signatory email page",
      overrideOAuthTokenCheck: false, // If the OAuthToken check should be disabled. WARNING: This should never have to be set to <true> if the OAuthToken is properly configured and safe!
      environment: "sandbox", // ["sandbox", "production"]
      priceList: "https://opencard.io/pricelist", // Link to price list as an alternative to display price in the plugin. If set to <null>, the text disappears.
      transactionInformationProductsMapping: { // Products to be displayed under "transaction information". This does not support adding or removing products right now, but description and price works as expected!
        transactions: {
          name: "Transactions", // The name shown in the UI
          products: ["product_transaction"], // The OpenCard products associated with this selection. Cannot be changed yet.
          description: "This is a description of transactions",
          price: "€1 / user / month", // Price to be shown in UI. If set to <null> it does not show at all.
          onlyAvailableIf: [], // Not working yet.
          notAvailableIf: [], // Not working yet.
          initialState: "checked", // Has to be "checked" right now.
          userChangeable: false, // Has to be <false> right now
        },
      },
      enrichedInformationProductsMapping: { // Products to be displayed under "enriched information"
        digitalReceipts: { // This is the ID of your product
          name: "Digital receipts", // Name to show in the UI
          products: ["product_digital_receipt"], // OpenCard products assoicated with this product.
          description: "Get your receipts delivered digitally", // Description to show in UI. If set to <null> description is not shown.
          price: "€5", // Price to show in UI. If set to <null> the price is not shown.
          onlyAvailableIf: [], // Only allow this to be selected if any in array is already selected e.g. ["environmentalImpact"].
          notAvailableIf: [], // Only allow this to be selected if all in array are not selected e.g. ["environmentalImpact"].
          initialState: "checked", // Initial state of the checkbox. Choose on of ["checked", "enabled", "disabled"]
          userChangeable: true, // If the checkmark should react on user click.
        },
        environmentalImpact: {
          name: "Environmental impact",
          products: ["product_aland_index"],
          description: null,
          price: null,
          onlyAvailableIf: [],
          notAvailableIf: [],
          initialState: "enabled",
          userChangeable: true,
        },
      },
      styles: { // Overridable style. You can override one at a time if needed.
        fontFamily: `'Montserrat', Arial, Helvetica, sans-serif`,
        boxShadow:
          "0 8px 16px rgba(0, 0, 0, 0.1), 0 12px 24px rgba(0, 0, 0, 0.1)",
        border: "1px solid #ccc",
        baseBorderRadius: "8px",
        buttonBorderRadius: "4px",
        inputBorderRadius: "4px",
        cardBorderRadius: "4px",
        backgroundColor: "#f7f7f8",
        titleColor: "#4a4f57",
        bodyColor: "#4a4f57",
        activateButtonBackgroundColor: "#89a98b",
        activateButtonTextColor: "white",
        navigationButtonBackgroundColor: "#4a4f57",
        navigationButtonTextColor: "white",
        successColor: "green",
        errorColor: "#c80909",
        descriptionFontSize: "16px",
      },
      onDataSend: async (data) => { // Function to send the data to your own backend. Return <true> for success or a string to display as error.
        console.log(data);
        await new Promise((resolve) => setTimeout(resolve, 3000));
        return true;
      },
    }