Vanilla widget
Overview
<openhive-pay> is a framework-agnostic custom element. It works with any framework (Vue, Angular, Svelte, …) or plain HTML.
It handles:
- Payment form rendering
- Payment request creation
- Success callbacks
For the React wrapper with typed props, see React widget.
Installation
- npm / bundler
- CDN
- npm
- yarn
- pnpm
npm install @openhive-eu/payment
yarn add @openhive-eu/payment
pnpm add @openhive-eu/payment
<script src="https://cdn.openhive.eu/payment/index.min.js" defer></script>
Styling
- npm / bundler
- CDN
Import the stylesheet once in your application entry point (e.g. main.ts, App.tsx):
import "@openhive-eu/payment/styles.css";
The IIFE bundle is self-contained — the CSS is automatically injected into <head> when the script loads. No stylesheet import required.
<script src="https://cdn.openhive.eu/payment/index.min.js" defer></script>
<!-- No <link> needed — CSS is injected automatically -->
Theming
The widget exposes CSS custom properties on the openhive-pay element. Override them to match your brand:
openhive-pay {
--pay-primary: #7c3aed;
--pay-primary-foreground: #ffffff;
--pay-radius: 0.5rem;
}
| Variable | Default (light) | Description |
|---|---|---|
--pay-primary | oklch(54.1% .281 293.009) | Primary action color |
--pay-primary-foreground | oklch(96.9% .016 293.756) | Text on primary background |
--pay-background | oklch(100% 0 0) | Widget background |
--pay-foreground | oklch(14.1% .005 285.823) | Default text color |
--pay-muted | oklch(96.7% .001 286.375) | Muted surface (skeleton, disabled) |
--pay-muted-foreground | oklch(55.2% .016 285.938) | Muted text |
--pay-accent | oklch(96.7% .001 286.375) | Hover / accent surface |
--pay-accent-foreground | oklch(21% .006 285.885) | Text on accent surface |
--pay-border | oklch(92% .004 286.32) | Border color |
--pay-input | oklch(92% .004 286.32) | Input border color |
--pay-ring | oklch(70.2% .183 293.541) | Focus ring color |
--pay-destructive | oklch(57.7% .245 27.325) | Error / destructive color |
--pay-radius | 0.65rem | Border radius |
For dark mode, wrap the overrides in .pay-dark:
.pay-dark openhive-pay {
--pay-background: oklch(14.1% 0.005 285.823);
--pay-foreground: oklch(98.5% 0 0);
}
Usage examples
Standard
- Import
- CDN
<!-- Bundler: import the stylesheet once in your app entry point -->
<!-- <link rel="stylesheet" href="node_modules/@openhive-eu/payment/dist/styles.css"> -->
<!-- or via JS: import "@openhive-eu/payment/styles.css"; -->
<script type="module">
import "@openhive-eu/payment"; // registers <openhive-pay>
</script>
<openhive-pay
token="pk_xxx"
default-amount="5000"
default-reference="ORDER-12345"
product-name="Abonnement Premium"
customer-name="John Doe"
customer-email="john.doe@example.com"
locale="en"
></openhive-pay>
<!-- CSS is auto-injected — no stylesheet needed -->
<script src="https://cdn.openhive.eu/payment/index.min.js" defer></script>
<openhive-pay
token="pk_xxx"
api-url="https://api.openhive.eu"
default-amount="5000"
default-reference="ORDER-12345"
product-name="Abonnement Premium"
customer-name="John Doe"
customer-email="john.doe@example.com"
locale="en"
></openhive-pay>
Modal / dialog
- Import
- CDN
<button id="open-btn">Open Payment Modal</button>
<dialog id="payment-dialog">
<button id="close-btn">Close</button>
<openhive-pay
token="pk_xxx"
default-amount="5000"
default-reference="ORDER-12345"
product-name="Abonnement Premium"
customer-name="John Doe"
customer-email="john.doe@example.com"
locale="en"
></openhive-pay>
</dialog>
<script type="module">
import "@openhive-eu/payment"; // registers <openhive-pay>
const dialog = document.getElementById("payment-dialog");
document
.getElementById("open-btn")
.addEventListener("click", () => dialog.showModal());
document
.getElementById("close-btn")
.addEventListener("click", () => dialog.close());
</script>
<!-- CSS is auto-injected — no stylesheet needed -->
<script src="https://cdn.openhive.eu/payment/index.min.js" defer></script>
<button id="open-btn">Open Payment Modal</button>
<dialog id="payment-dialog">
<button id="close-btn">Close</button>
<openhive-pay
token="pk_xxx"
api-url="https://api.openhive.eu"
default-amount="5000"
default-reference="ORDER-12345"
product-name="Abonnement Premium"
customer-name="John Doe"
customer-email="john.doe@example.com"
locale="en"
></openhive-pay>
</dialog>
<script>
const dialog = document.getElementById("payment-dialog");
document
.getElementById("open-btn")
.addEventListener("click", () => dialog.showModal());
document
.getElementById("close-btn")
.addEventListener("click", () => dialog.close());
</script>
Custom payment methods
Override the payment client to supply custom payment methods or bypass the default fetching logic. See Get payment methods API.
- Import
- CDN
payClient is a JavaScript property, not an HTML attribute. It must be set via JS after the element is available.
<openhive-pay
id="pay-widget"
token="pk_xxx"
default-amount="5000"
default-reference="ORDER-12345"
product-name="Abonnement Premium"
customer-name="John Doe"
customer-email="john.doe@example.com"
locale="en"
></openhive-pay>
<script type="module">
import "@openhive-eu/payment"; // registers <openhive-pay>
/**
* @typedef {{ id: string, name: string, code: string, provider: string, description: string, logoUrl: string }} PaymentMethod
* @type {{ getPaymentMethods: () => Promise<PaymentMethod[]> }}
*/
const customPayClient = {
getPaymentMethods: async () => {
const response = await fetch("/api/payment-methods", {
headers: { Authorization: "Bearer <token>" },
});
if (!response.ok)
throw new Error(`HTTP error! Status: ${response.status}`);
return response.json();
},
};
const widget = document.getElementById("pay-widget");
widget.payClient = customPayClient;
</script>
Use pay-client-ref to name a window global — no timing issue, no bundler needed. Declare it before the CDN script tag.
<script>
window.myPayClient = {
getPaymentMethods: async () => {
const response = await fetch("/api/payment-methods", {
headers: { Authorization: "Bearer <token>" },
});
if (!response.ok)
throw new Error(`HTTP error! Status: ${response.status}`);
return response.json();
},
};
</script>
<!-- CSS is auto-injected — no stylesheet needed -->
<script src="https://cdn.openhive.eu/payment/index.min.js" defer></script>
<openhive-pay
pay-client-ref="myPayClient"
default-amount="5000"
default-reference="ORDER-12345"
product-name="Abonnement Premium"
locale="en"
></openhive-pay>
API
- Attributes
- JS properties
- Events
| Name | Type | Description |
|---|---|---|
token required | String | OpenHive token "pk_xxx" used to retrieve the payment methods configuration. |
default-reference | String | Pre-fills the reference field. Links the request to an order (e.g., "ORDER-1234"). |
default-amount | String | Pre-fills the amount field. Value is in cents as a string (e.g., "5000" = €50.00). |
read-only-amount | Boolean (presence) | Locks the amount field to default-amount. Set the attribute with an empty string to enable (e.g., read-only-amount=""). |
customer-name | String | Pre-fills the customer name. |
customer-email | String | Pre-fills the customer e-mail. |
customer-phone | String | Pre-fills the customer phone number. |
locale | String | UI language. Supported values: "fr" (default), "en". Controls all labels, error messages, and success screen text. |
api-url | String | Base URL of the payment API. Defaults to the OpenHive production endpoint. |
currency | String | ISO 4217 currency code (default: "EUR"). |
product-name | String | Product label shown on the Stripe checkout page and customer receipts. Falls back to default-reference if omitted. Has no effect on Fintecture. |
pay-client-ref | String | Name of a window global implementing { getPaymentMethods(): Promise<PaymentMethod[]> }. Takes priority over the default API client. Useful for CDN usage where setting a JS property has timing constraints. |
The following can only be set as JavaScript properties on the element instance (not as HTML attributes).
| Name | Type | Description |
|---|---|---|
payClient | Object | Inject a custom payment client to control how payment methods are fetched. If set after render, triggers a re-fetch. |
The object must implement a getPaymentMethods() method returning a Promise that resolves to an array of payment method objects:
| Property | Type | Description |
|---|---|---|
id | String | Unique identifier, e.g. "stripe_credit_card" |
name | String | Display name, e.g. "Credit card" |
code | String | Method code, e.g. "credit_card" |
provider | String | Provider slug: "stripe", "fintecture" |
description | String | Short description |
logoSvg | String | SVG logo markup as an inline string |
| Event | Detail type | Description |
|---|---|---|
request-to-pay | RequestToPay | Fired when the user submits the payment form. The payload is available in event.detail. |
close | — | Fired when the user closes the widget after a successful payment link submission. |
RequestToPay payload (event.detail)
| Field | Type | Description |
|---|---|---|
amount | Number | Amount in cents (e.g., 5000 = €50.00) |
currency | String | ISO 4217 currency code (e.g., "EUR") |
method | String | Payment method: "credit_card", "bank_transfer", "installments_3x" |
channel | String | Delivery channel: "email", "sms", "link" |
partner | String | Payment provider: "stripe", "fintecture" |
customer_contact | String | Customer email or phone number depending on the channel |
order_reference | String | Merchant order reference (e.g., "ORDER-1234") |
product_name | String | (optional) Product label forwarded to the backend |
metadata | Object | (optional) Key/value pairs of custom metadata |