Widget Integration
The DirectCryptoPay widget is a lightweight, embeddable payment component that works on any website. It handles wallet connection, chain/token selection, and transaction submission in a polished modal UI.
Quick Start
The fastest way to accept crypto payments is to load the widget via a script tag and initialize it with your Integration ID.
Step 1: Add the Script
<script src="https://widget-dev.directcryptopay.com/dcp-widget.umd.js"></script>
Step 2: Initialize
<script>
DirectCryptoPay.init({
integrationId: 'YOUR_INTEGRATION_ID'
});
</script>
Step 3: Trigger a Payment
<button onclick="DirectCryptoPay.pay({ amount: 49.99, currency: 'USD' })">
Pay $49.99 with Crypto
</button>
That is the complete integration. The widget handles everything else: wallet connection, chain selection, token conversion, transaction signing, and confirmation.
Integration ID: Create an integration in your DCP Dashboard > Integrations. The Integration ID encapsulates your merchant wallet, accepted chains, and token preferences.
Here is a full HTML page with the widget integrated:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Checkout - My Store</title>
<script src="https://widget-dev.directcryptopay.com/dcp-widget.umd.js"></script>
</head>
<body>
<h1>Complete Your Purchase</h1>
<p>Order Total: $49.99</p>
<button id="pay-button">Pay with Crypto</button>
<script>
// Initialize the widget
DirectCryptoPay.init({
integrationId: 'YOUR_INTEGRATION_ID'
});
// Attach payment to button
document.getElementById('pay-button').addEventListener('click', function() {
DirectCryptoPay.pay({
amount: 49.99,
currency: 'USD',
metadata: {
orderId: 'ORD-12345',
customerEmail: 'customer@example.com'
},
onSuccess: function(result) {
console.log('Payment successful:', result.txHash);
window.location.href = '/order-confirmation?tx=' + result.txHash;
},
onError: function(error) {
console.error('Payment failed:', error.message);
},
onClose: function() {
console.log('Widget closed by user');
}
});
});
</script>
</body>
</html>
Configuration Options
DirectCryptoPay.init(options)
Call this once when the page loads to configure the widget.
| Parameter | Type | Required | Description |
|---|---|---|---|
integrationId |
string |
Yes | Your integration ID from the DCP dashboard |
DirectCryptoPay.pay(options)
Call this to open the payment modal and start a payment.
| Parameter | Type | Required | Description |
|---|---|---|---|
amount |
number |
Yes | Payment amount in the specified currency |
currency |
string |
Yes | Currency code (e.g., "USD", "EUR") |
metadata |
object |
No | Custom key-value pairs attached to the payment |
onSuccess |
function |
No | Called when the transaction is signed and submitted |
onError |
function |
No | Called if the payment fails or is rejected |
onClose |
function |
No | Called when the user closes the widget |
Metadata
The metadata field accepts any JSON-serializable object. Use it to attach order IDs, customer emails, or any reference data you need in your webhook handler.
DirectCryptoPay.pay({
amount: 99.99,
currency: 'USD',
metadata: {
orderId: 'ORD-12345',
productName: 'Premium Plan',
customerEmail: 'user@example.com'
}
});
onSuccess does not mean the payment is confirmed. It means the customer signed the transaction and it was submitted to the blockchain. Final confirmation comes via the webhook. Never fulfill orders based solely on the onSuccess callback.
If you are using React, you can load the widget dynamically:
// components/CryptoPayButton.jsx
import { useEffect, useRef } from 'react';
export default function CryptoPayButton({ amount, currency, orderId }) {
const initialized = useRef(false);
useEffect(() => {
if (initialized.current) return;
const script = document.createElement('script');
script.src = 'https://widget-dev.directcryptopay.com/dcp-widget.umd.js';
script.onload = () => {
window.DirectCryptoPay.init({
integrationId: process.env.NEXT_PUBLIC_DCP_INTEGRATION_ID
});
initialized.current = true;
};
document.head.appendChild(script);
return () => {
document.head.removeChild(script);
};
}, []);
const handlePay = () => {
window.DirectCryptoPay.pay({
amount,
currency,
metadata: { orderId },
onSuccess: (result) => {
console.log('Transaction submitted:', result.txHash);
},
onError: (error) => {
console.error('Payment error:', error);
}
});
};
return (
<button onClick={handlePay}>
Pay ${amount} with Crypto
</button>
);
}
Usage in a page:
<CryptoPayButton amount={49.99} currency="USD" orderId="ORD-12345" />
Next.js (App Router) Integration
For Next.js with the App Router, create a client component:
// components/CryptoPayButton.tsx
'use client';
import { useEffect, useCallback } from 'react';
declare global {
interface Window {
DirectCryptoPay: {
init: (options: { integrationId: string }) => void;
pay: (options: any) => void;
};
}
}
interface Props {
amount: number;
currency: string;
orderId: string;
}
export default function CryptoPayButton({ amount, currency, orderId }: Props) {
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://widget-dev.directcryptopay.com/dcp-widget.umd.js';
script.async = true;
script.onload = () => {
window.DirectCryptoPay.init({
integrationId: process.env.NEXT_PUBLIC_DCP_INTEGRATION_ID!
});
};
document.head.appendChild(script);
}, []);
const handlePay = useCallback(() => {
window.DirectCryptoPay.pay({
amount,
currency,
metadata: { orderId },
onSuccess: (result: { txHash: string }) => {
window.location.href = `/success?tx=${result.txHash}`;
}
});
}, [amount, currency, orderId]);
return (
<button onClick={handlePay} className="bg-emerald-600 text-white px-6 py-3 rounded-lg">
Pay ${amount} with Crypto
</button>
);
}
Vanilla JavaScript (ES Module)
If you prefer ES module imports:
<script type="module">
import { init, pay } from 'https://widget-dev.directcryptopay.com/dcp-widget.es.js';
init({ integrationId: 'YOUR_INTEGRATION_ID' });
document.getElementById('pay-button').addEventListener('click', () => {
pay({
amount: 49.99,
currency: 'USD',
onSuccess: (result) => console.log('Success:', result)
});
});
</script>
Widget Customization
The widget modal inherits a clean dark theme by default. The following CSS custom properties can be overridden for basic customization:
/* Override widget theme (applied to the host page) */
:root {
--dcp-accent: #00d4aa; /* Primary accent color */
--dcp-bg: #0c1019; /* Modal background */
--dcp-text: #e8ecf4; /* Text color */
--dcp-border: #1a2236; /* Border color */
}
Widget Size: The widget renders as a centered modal overlay. It is fully responsive and adapts to mobile screens automatically.
- The widget is loaded from the DirectCryptoPay CDN with SRI (Subresource Integrity) hashes
- All payment verification is done server-side -- the widget cannot fake a successful payment
- Use webhooks to confirm payments before fulfilling orders
- The widget communicates with the DCP backend over HTTPS
Next Step: Set up Webhook Verification to receive server-side payment confirmations.