> For the complete documentation index, see [llms.txt](https://developers.munzen.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.munzen.io/payment-widget/integration-guide-for-payment-widget.md).

# Integration Guide for Payment Widget

You can read basic information about the payment widget here: [Payment Widget](/payment-widget/what-is-payment-widget.md).

### Base URLs

You can use Payment Widget both for Invoices and Channels. Use the following URLs to generate links for an invoice or channel:

<table data-full-width="false"><thead><tr><th width="128.49999999999994">Type</th><th width="784">URL</th></tr></thead><tbody><tr><td>Invoice</td><td><code>https://sandbox-payment-widget.munzen.io/invoice?[params]</code></td></tr><tr><td>Channel</td><td><code>https://sandbox-payment-widget.munzen.io/channel?[params]</code></td></tr></tbody></table>

### Params for Initialisation

You can set the following params for the Payment Widget to add custom information about customer, order, etc:

```typescript
{
  customer_external_id: string;
  external_id: string;
  external_data: Record<string, string>;
  description: string;
  name: string;
	
  // Theme is a purely presentational parameter, not used in signature generation
  // It has 2 options, "dark" or "light" -
  // Choose what better suits your application look & feel
  theme: 'dark' | 'light';
};
```

{% hint style="info" %}
Here is the only required param: `customer_external_id`. All other parameters are optional, you can ignore them if you want.
{% endhint %}

Here is an example of defined params:

```typescript
const parameters = {
    customer_external_id: 'johnny@email.com',
    external_id: 'invoice_1',
    external_data: { "game_id": "1" },
    name: "Invoice #1 from site.com",
    description: "Invoice payment from the main page",
}
```

When you build your params then you need to generate a signature.

### Generate Signature

We need a signature to validate that you can use the widget to accept customer payments. Here is an example of signature generation:

<details>

<summary>JS Example Code</summary>

```typescript
const crypto = require('crypto');

// You should never expose this key to client code (front-end).
// Make sure to generate signatures only on the back-end
const SECRET_KEY = 'PUT_YOUR_API_SECRET_HERE'

const values = {
    theme: 'light', // or 'dark'
    customer_external_id: 'johnny@email.com',
    external_id: 'invoice_1',
    external_data: { "game_id": "1" },
    name: "Invoice #1 from site.com",
    description: "Invoice payment from the main page",
}

const signature = getSignature({
  timestamp: 1684241941,
  customer_external_id: values.customer_external_id,
  external_id: values.external_id,
  external_data: JSON.stringify(values.external_data),
  description: values.description,
  name: values.name,
}).then(signature => console.log(signature));

async function getSignature(data) {
  const sortedData = ksortRecursive({ ...data });
  const string = implodeRecursive(sortedData);
  const message = `POST` + string;
  
  console.log(message);
  const signature = hmacSha256(message, SECRET_KEY);

  return signature;
}

async function hmacSha256(data, secret) {
  const hash = crypto.createHmac("sha-256", secret).update(data).digest('hex');

  return hash;
}

function ksortRecursive(obj) {
  if (!Array.isArray(obj) && typeof obj !== 'object') {
    return obj;
  }
  const sortedObj = {};

  Object.keys(obj)
    .sort()
    .forEach((key) => {
      const value = obj[key];
      sortedObj[key] = ksortRecursive(value);
    });
  return sortedObj;
}

function implodeRecursive(arr) {
  if (!Array.isArray(arr) && typeof arr !== 'object') {
    throw new Error('implodeRecursive: argument must be an array or object');
  }

  let output = '';
  Object.keys(arr).forEach((key) => {
    const item = arr[key];
    if (Array.isArray(item)) {
      output += implodeRecursive(item);
    } else {
      output += item;
    }
  });
  return output;
}

```

</details>

### Generate Widget Link

Let's generate query params for the Payment Widget URL:

```typescript
const params = {
  signature: signature,
  timestamp: timestamp,
  customer_external_id: encodeURIComponent(
    values.customer_external_id
  ),
  theme: values.theme,
  external_id: encodeURIComponent(values.external_id),
  external_data: JSON.stringify(values.external_data),
  description: encodeURIComponent(values.description),
  name: encodeURIComponent(values.name),
}

const widgetUrlParams = new URLSearchParams(params);
const queryString = widgetUrlParams.toString();

// Example usage with URL
const url = new URL('https://sandbox-payment-widget.munzen.io/invoice');
url.search = queryString;

console.log(url.toString());
```

You will receive a full URL to the Payment Widget. It will look like this:

{% code overflow="wrap" %}

```
https://sandbox-payment-widget.munzen.io/invoice?signature=8cb2dd83f06ff3dcbf61d501e5fb512e3d5343ffc6823651097739e23a0475ce&amp;timestamp=1684241941&amp;customer_external_id=johnny%2540email.com&amp;theme=light&amp;external_id=invoice_1&amp;external_data=%7B%22game_id%22%3A%221%22%7D&amp;description=Invoice%2520payment%2520from%2520the%2520main%2520page&amp;name=Invoice%2520%25231%2520from%2520site.com
```

{% endcode %}

### Show Widget to the Customer

Now you have an URL for the payment widget. You can redirect the customer to this URL or open this URL inside an iframe.&#x20;
