> 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;


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers.munzen.io/payment-widget/integration-guide-for-payment-widget.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
