Native App Bridge

This SDK registers a global bridge between your web app and the First Iraqi Bank's native mobile app, allowing you to communicate with the native app for a seamless experience to authenticate users, pay for products and services when we include your web app in our native app.

npm
yarn
pnpm
bun
deno
npm install @first-iraqi-bank/sdk

Usage

This SDK is designed to be used in the browser, it accesses the global window object to register the bridge and communicate with the native app.

To use this functionality, you need to import the registerFIBNativeBridge function and call it in your JavaScript code, as soon as your web app loads.

For example if you're using React Router, you need to import it and call it in entry.client.tsx file, or in Vite you need to import it in the main JS/TS module inside index.html which is called an entry file.

For other frameworks, please consult their documentation on how to run code when the app loads.

// other imports
import { registerFIBNativeBridge } from "@first-iraqi-bank/sdk/fib-native-bridge";

registerFIBNativeBridge();

This will ensure that the bridge is registered and ready to use when your code needs to communicate with the native app or the native bridge needs to send an event to your app.

If your web application could be deployed to be embedded as FIB App in App and also run independently in the browser, you might need to check whether the current environment supports FIB Native Bridge or not. For this purpose, you can use the window.FIBNativeBridge.isFIBBridgeAvailable, it'll return true if your app is embedded as FIB App in App, otherwise it'll return false.

if (window.FIBNativeBridge.isFIBBridgeAvailable()) {
  // Your app is running inside FIB Native App, you can use the bridge
} else {
  // Your app is running in the browser, the bridge is not available
}

When you want to send an event to the native app, you can use the window.FIBNativeBridge.sendMessage object:

window.FIBNativeBridge.sendMessage({
  type: "AUTHENTICATE",
  body: { readableId },
});

The Native app can send events to your app as well, when you're expecting such events and want to handle them, you can use the window.FIBNativeBridge.addEventListener method:

const { readableId } = loaderData;

window.FIBNativeBridge.addEventListener("AUTHENTICATED", async (event) => {
  // do something when this event is received
});
Tip

Checkout Single Sign on to authenticate your users and use Payment API to create FIB transactions.

Error Handling

There are two types of errors you might want to watch out for:

  1. When the SDK is used in an app the isn't integrated with the First Iraqi Bank's native app, in this case the SDK will throw an UnsupportedPlatformError error when you try to send a message to the native app. You can catch this error and handle it gracefully, for example by showing an error message to the user.

    try {
      window.FIBNativeBridge.sendMessage({
        type: "AUTHENTICATE",
        body: { readableId },
      });
    } catch (error) {
      if (error instanceof UnsupportedPlatformError) {
        console.error(
          "FIB Native App Bridge is not available, call the SDK only when its loaded inside FIB Native apps!",
          error,
        );
      }
    }
  2. When you try to send a message to the native app, but the message type is not one of the supported sendable message types, or the body of the message doesn't contain necessary information, the SDK will throw an InvalidMessageError error.

    try {
      window.FIBNativeBridge.sendMessage({
        type: "UNKNOWN_MESSAGE_TYPE", // this is not a valid message type
      });
    } catch (error) {
      if (error instanceof InvalidMessageError) {
        console.error("Invalid message type or body", error);
      }
    }

    or

    try {
      window.FIBNativeBridge.sendMessage({
        type: "AUTHENTICATE",
        // No `readableId` provided, this is not a valid message type
      });
    } catch (error) {
      if (error instanceof InvalidMessageError) {
        console.error("Invalid message type or body", error);
      }
    }

Typical App Flow

Here is how a typical flow of your web app would look like when using the native app bridge:

Web → Native App Communication

When you want to send a message from your web app to the native app, you can use the sendMessage method on the FIBNativeBridge object. This method takes an object with two properties:

  • type: a string indicating the type of the message, for example "AUTHENTICATE" or "PAYMENT".
  • body: an object containing the data you want to send to the native app, for example, it can contain a readableId or other relevant information.

AUTHENTICATE event

You can send this message to the native bridge after you obtained the readableId from your backend, this will trigger the native app to authenticate the readableId with user logged in on the Native FIB App.

const normalizedReadableId = readableId.replaceAll("-", "");

window.FIBNativeBridge.sendMessage({
  type: "AUTHENTICATE",
  body: { readableId: normalizedReadableId },
});
Warning

Make sure you remove all - characters from the readableId before sending it to the native app, as the native app expects a clean ID without any dashes.

When FIB Native app successfully authenticates the readableId, it will send an AUTHENTICATED event back to your web app. You should add an event listener for this event to handle the authentication result.

PAYMENT event

You can use FIB's payment API to create a payment when a user tries to purchase a product or service in your web app. Then, you can send a PAYMENT message to the native app bridge, which will display the payment screen in the FIB app.

const { paymentId: transactionId, readableId } = paymentDetails;

const normalizedReadableId = readableId.replaceAll("-", "");

window.FIBNativeBridge.sendMessage({
  type: "PAYMENT",
  body: { transactionId, readableId: normalizedReadableId },
});
Warning

Make sure you remove all - characters from the readableId before sending it to the native app, as the native app expects a clean ID without any dashes.

When the payment is authorized and successfully completed, the native app will send a PAYMENT_SUCCESSFULLY_PAID event back to your web app, which you can handle by adding an event listener for this event.

Otherwise if the payment is canceled or failed, the native app will send a PAYMENT_FAILED event back to your web app, which you can also handle by adding an event listener for this event.

EXIT event

If you want to close your web app and return to the native app, you can send an EXIT message to the native app bridge.

window.FIBNativeBridge.sendMessage({ type: "EXIT" });

This will close the web view and return to First Iraqi Bank's native mobile Home Screen, allowing the user to continue using the native app.

If your web app is running on an Android POS device with print functionality, you can send a PRINT_INVOICE message to print a receipt or invoice. The body contains an items array of label-value pairs that will be printed in order, a total string that represents the total amount, appLabel which will be shown on the receipt, and appIdentifier field to identify the calling application.

window.FIBNativeBridge.sendMessage({
  type: "PRINT_INVOICE",
  body: {
    items: [
      { label: "Terminal ID", value: "12345678" },
      { label: "Merchant ID", value: "87654321" },
      { label: "Date", value: "12.12.2023 14:30" },
      { label: "Reference", value: "525110010001" },
      { label: "Auth Code", value: "495367" },
    ],
    total: "40,000 IQD",
    appLabel: "Store",
    appIdentifier: "STORE",
  },
});

Each item in the items array is an object with:

  • label: A string describing what the value represents (e.g. "Total", "Tax", "Product Name").
  • value: A string containing the corresponding value (e.g. "40,000 IQD", "2").

The total field is a string representing the total amount of the invoice (e.g. "40,000 IQD").

The appLabel field is a string representing a human-readable name for your application (e.g. "Store").

The appIdentifier an optional field that identifies the mini app. It should be a string that uniquely identifies your application (e.g. "STORE").

The items are printed in the order they appear in the array, so you can control the layout of the invoice.

When the native app successfully prints the invoice, it will send a INVOICE_SUCCESSFULLY_PRINTED event back to your web app. If the printing fails (e.g. printer not connected, out of paper), it will send a PRINT_INVOICE_FAILED event with a reason.

Native App → Web Communication

FIBNativeBridge extends the EventTarget interface, which means you can listen to events sent from the native app to your web app.

Use the window.FIBNativeBridge.addEventListener to register events and window.FIBNativeBridge.removeEventListener to remove them.

AUTHENTICATED event

When the native app successfully authenticates the readableId, it will send an AUTHENTICATED event back to your web app.

window.FIBNativeBridge.addEventListener("AUTHENTICATED", async (event) => {
  checkSSOStatus();
});

AUTHENTICATION_FAILED event

When the native app fails to authenticate the readableId, it will send an AUTHENTICATION_FAILED event back to your web app.

Authenticating can fail for various reasons, and you should handle this event to provide a better user experience, for example, by showing a retry screen or an error message.

window.FIBNativeBridge.addEventListener(
  "AUTHENTICATION_FAILED",
  async (event) => {
    // handle authentication failure
    setShowRetryScreen(true);
  },
);

PAYMENT_SUCCESSFULLY_PAID event

When the native app successfully completes the payment, it will send a PAYMENT_SUCCESSFULLY_PAID event back to your web app.

window.FIBNativeBridge.addEventListener(
  "PAYMENT_SUCCESSFULLY_PAID",
  async (event) => {
    const { transactionId } = event.detail.body;
    // handle the payment success, for example, show a success message or redirect to a success page
  },
);

PAYMENT_FAILED event

When the native app fails to complete the payment, it will send a PAYMENT_FAILED event back to your web app.

window.FIBNativeBridge.addEventListener("PAYMENT_FAILED", async (event) => {
  const { transactionId, reason } = event.detail.body;
  // handle the payment failure, for example, show an error message or redirect to an error page
});

PAYMENT_CANCELED event

When the user cancels the payment in the native app, it will send a PAYMENT_CANCELED event back to your web app.

window.FIBNativeBridge.addEventListener("PAYMENT_CANCELED", async (event) => {
  const { transactionId } = event.detail.body;
  // handle the payment cancellation, for example, show a toast message or go back to the previous page
});

INVOICE_SUCCESSFULLY_PRINTED event

When the native app successfully prints the invoice on the POS device, it will send a INVOICE_SUCCESSFULLY_PRINTED event back to your web app.

window.FIBNativeBridge.addEventListener(
  "INVOICE_SUCCESSFULLY_PRINTED",
  async (event) => {
    // handle the print success, for example, show a success message
    showToast("Invoice printed successfully!");
  },
);

When the native app fails to print the invoice (e.g. printer not connected, out of paper, hardware error), it will send a PRINT_INVOICE_FAILED event back to your web app.

window.FIBNativeBridge.addEventListener(
  "PRINT_INVOICE_FAILED",
  async (event) => {
    const { reason } = event.detail.body;
    // handle the print failure, for example, show an error message or offer a retry
    showError(`Failed to print invoice: ${reason}`);
  },
);