Skip to main content

JavaScript Integration Examples

This guide provides complete JavaScript examples for integrating CryptoPay into your web applications.

Installation

Using npm (for HTTP client libraries)

# For Node.js projects, you can use popular HTTP clients
npm install axios
# or
npm install node-fetch

Using CDN (for browser projects)

<!-- No SDK needed - use native fetch() API available in all modern browsers -->

Basic Setup

Node.js/Express Example

const express = require('express');
const crypto = require('crypto');

const app = express();
app.use(express.json());

// Create payment endpoint
app.post('/create-payment', async (req, res) => {
try {
const { amount, currency, blockchain, productInfo } = req.body;

const response = await fetch('/api/payment-orders/', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.CRYPTOPAY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: amount.toString(),
currency: currency,
blockchain: blockchain,
order_info: JSON.stringify({
product: productInfo.product,
quantity: productInfo.quantity,
customer_id: req.user?.id
}),
nonce: Date.now() + Math.floor(Math.random() * 1000000),
webhook_url: `${process.env.BASE_URL}/webhooks/cryptopay`,
redirect_url: `${process.env.BASE_URL}/payment/success`
})
});

const paymentOrder = await response.json();

if (paymentOrder.success) {
res.json({
success: true,
payment_url: paymentOrder.data.payment_url,
order_id: paymentOrder.data.order_id
});
} else {
res.status(400).json({
success: false,
error: paymentOrder.error?.message || 'Payment creation failed'
});
}

} catch (error) {
console.error('Payment creation error:', error);
res.status(500).json({
success: false,
error: error.message
});
}
});

// Webhook handler
app.post('/webhooks/cryptopay', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-webhook-signature'];
const payload = req.body;

// Verify webhook signature
const expectedSignature = crypto
.createHmac('sha256', process.env.CRYPTOPAY_WEBHOOK_SECRET)
.update(payload, 'utf8')
.digest('hex');

if (signature !== expectedSignature) {
return res.status(401).send('Invalid signature');
}

const webhookData = JSON.parse(payload);
handleWebhook(webhookData);

res.status(200).send('OK');
});

async function handleWebhook(data) {
const { event, data: paymentData } = data;

switch (event) {
case 'payment.pending':
console.log('Payment pending:', paymentData.order_id);
// Update UI, send notification, etc.
break;

case 'payment.confirmed':
console.log('Payment confirmed:', paymentData.order_id);
// Fulfill order, update database, send confirmation
await fulfillOrder(paymentData);
break;

case 'payment.failed':
console.log('Payment failed:', paymentData.order_id);
// Handle failed payment
break;
}
}

async function fulfillOrder(paymentData) {
// Your order fulfillment logic here
const orderInfo = JSON.parse(paymentData.order_info);

// Update database
await db.orders.update(paymentData.order_id, {
status: 'paid',
transaction_hash: paymentData.transaction_hash,
paid_at: new Date()
});

// Send confirmation email
await sendConfirmationEmail(orderInfo.customer_id, paymentData);
}

app.listen(3000, () => {
console.log('Server running on port 3000');
});

Frontend Integration

React Component Example

import React, { useState } from 'react';

function PaymentComponent({ product, amount }) {
const [paymentUrl, setPaymentUrl] = useState(null);
const [loading, setLoading] = useState(false);
const [showModal, setShowModal] = useState(false);

const createPayment = async () => {
setLoading(true);

try {
const response = await fetch('/api/create-payment', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: amount,
currency: 'USDC',
blockchain: 'base',
productInfo: {
product: product.name,
quantity: 1
}
})
});

const result = await response.json();

if (result.success) {
setPaymentUrl(result.payment_url);
setShowModal(true);
} else {
alert('Payment creation failed: ' + result.error);
}
} catch (error) {
alert('Error creating payment: ' + error.message);
} finally {
setLoading(false);
}
};

const handlePaymentSuccess = (paymentData) => {
console.log('Payment successful:', paymentData);
setShowModal(false);
// Redirect to success page or update UI
window.location.href = '/payment/success';
};

const handlePaymentError = (error) => {
console.error('Payment error:', error);
alert('Payment failed: ' + error.message);
};

return (
<div className="payment-component">
<div className="product-info">
<h3>{product.name}</h3>
<p>Price: ${amount} USDC</p>
</div>

<button
onClick={createPayment}
disabled={loading}
className="pay-button"
>
{loading ? 'Creating Payment...' : 'Pay with Crypto'}
</button>

{showModal && (
<div className="payment-modal">
<div className="modal-content">
<span className="close" onClick={() => setShowModal(false)}>&times;</span>
<iframe
src={paymentUrl}
width="100%"
height="600"
title="CryptoPay Payment"
/>
</div>
</div>
)}
</div>
);
}

export default PaymentComponent;

Vanilla JavaScript Example

<!DOCTYPE html>
<html>
<head>
<title>CryptoPay Integration</title>
<!-- No external scripts needed - using native fetch API -->
</head>
<body>
<div id="payment-section">
<h2>Premium Plan - $29.99</h2>
<button id="pay-button">Pay with Crypto</button>
</div>

<div id="payment-modal" style="display: none;">
<div class="modal-content">
<span class="close">&times;</span>
<iframe id="payment-frame" width="100%" height="600"></iframe>
</div>
</div>

<script>
const payButton = document.getElementById('pay-button');
const modal = document.getElementById('payment-modal');
const paymentFrame = document.getElementById('payment-frame');
const closeBtn = document.querySelector('.close');

payButton.addEventListener('click', async () => {
try {
payButton.disabled = true;
payButton.textContent = 'Creating Payment...';

const response = await fetch('/api/create-payment', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 29.99,
currency: 'USDC',
blockchain: 'base',
productInfo: {
product: 'Premium Plan',
quantity: 1
}
})
});

const result = await response.json();

if (result.success) {
paymentFrame.src = result.payment_url;
modal.style.display = 'block';
} else {
alert('Payment creation failed: ' + result.error);
}
} catch (error) {
alert('Error: ' + error.message);
} finally {
payButton.disabled = false;
payButton.textContent = 'Pay with Crypto';
}
});

closeBtn.addEventListener('click', () => {
modal.style.display = 'none';
});

// Listen for payment completion messages
window.addEventListener('message', (event) => {
if (event.origin !== 'https://pay.cryptopay.com') return;

if (event.data.type === 'PAYMENT_SUCCESS') {
modal.style.display = 'none';
alert('Payment successful!');
window.location.href = '/success';
} else if (event.data.type === 'PAYMENT_ERROR') {
alert('Payment failed: ' + event.data.error);
}
});
</script>
</body>
</html>

Advanced Examples

Subscription Payments

// Create recurring payment setup
async function createSubscription(customerId, planId) {
const subscription = await cryptoPay.subscriptions.create({
customer_id: customerId,
plan_id: planId,
blockchain: 'base',
currency: 'USDC',
amount: '29.99',
interval: 'monthly',
webhook_url: `${process.env.BASE_URL}/webhooks/subscription`
});

return subscription;
}

// Handle subscription webhook
app.post('/webhooks/subscription', express.raw({type: 'application/json'}), (req, res) => {
const webhookData = JSON.parse(req.body);
const { event, data } = webhookData;

switch (event) {
case 'subscription.payment_succeeded':
// Extend subscription period
extendSubscription(data.customer_id, data.plan_id);
break;

case 'subscription.payment_failed':
// Handle failed payment, send reminder
handleFailedSubscriptionPayment(data);
break;

case 'subscription.cancelled':
// Handle subscription cancellation
cancelSubscription(data.subscription_id);
break;
}

res.status(200).send('OK');
});

Multi-Currency Support

// Get supported currencies for a blockchain
async function getSupportedCurrencies(blockchain) {
const currencies = await cryptoPay.blockchains.getCurrencies(blockchain);
return currencies;
}

// Create payment with currency selection
async function createPaymentWithCurrency(amount, selectedCurrency, blockchain) {
// Convert amount if needed
const convertedAmount = await convertCurrency(amount, 'USD', selectedCurrency);

const paymentOrder = await cryptoPay.paymentOrders.create({
amount: convertedAmount.toString(),
currency: selectedCurrency,
blockchain: blockchain,
order_info: JSON.stringify({
original_amount: amount,
original_currency: 'USD',
exchange_rate: convertedAmount / amount
}),
nonce: generateNonce()
});

return paymentOrder;
}

Error Handling

// Comprehensive error handling
async function createPaymentWithErrorHandling(paymentData) {
try {
const paymentOrder = await cryptoPay.paymentOrders.create(paymentData);
return { success: true, data: paymentOrder };

} catch (error) {
console.error('Payment creation error:', error);

// Handle specific error types
if (error.code === 'INSUFFICIENT_BALANCE') {
return {
success: false,
error: 'Insufficient balance in your account',
code: 'INSUFFICIENT_BALANCE'
};
} else if (error.code === 'INVALID_CURRENCY') {
return {
success: false,
error: 'Currency not supported on selected blockchain',
code: 'INVALID_CURRENCY'
};
} else if (error.code === 'RATE_LIMITED') {
return {
success: false,
error: 'Too many requests. Please try again later.',
code: 'RATE_LIMITED'
};
} else {
return {
success: false,
error: 'An unexpected error occurred',
code: 'UNKNOWN_ERROR'
};
}
}
}

Testing

Unit Tests with Jest

const CryptoPay = require('@cryptopay/sdk');
const { createPaymentOrder } = require('../src/payment-service');

// Mock the SDK
jest.mock('@cryptopay/sdk');

describe('Payment Service', () => {
let mockCryptoPay;

beforeEach(() => {
mockCryptoPay = {
paymentOrders: {
create: jest.fn()
}
};
CryptoPay.mockImplementation(() => mockCryptoPay);
});

test('should create payment order successfully', async () => {
const mockPaymentOrder = {
order_id: 'ORD-123',
payment_url: 'https://pay.cryptopay.com/order/ORD-123',
amount: '100.00',
currency: 'USDC'
};

mockCryptoPay.paymentOrders.create.mockResolvedValue(mockPaymentOrder);

const result = await createPaymentOrder({
amount: '100.00',
currency: 'USDC',
blockchain: 'base'
});

expect(result.success).toBe(true);
expect(result.data.order_id).toBe('ORD-123');
});

test('should handle payment creation errors', async () => {
mockCryptoPay.paymentOrders.create.mockRejectedValue(
new Error('Invalid currency')
);

const result = await createPaymentOrder({
amount: '100.00',
currency: 'INVALID',
blockchain: 'base'
});

expect(result.success).toBe(false);
expect(result.error).toContain('Invalid currency');
});
});

Best Practices

Security

// Always validate webhook signatures
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSignature, 'hex')
);
}

// Store sensitive data securely
const config = {
apiKey: process.env.CRYPTOPAY_API_KEY, // Never hardcode
webhookSecret: process.env.CRYPTOPAY_WEBHOOK_SECRET,
environment: process.env.NODE_ENV === 'production' ? 'production' : 'sandbox'
};

Performance

// Use connection pooling for database operations
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});

// Implement caching for frequently accessed data
const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 600 }); // 10 minutes

async function getCachedCurrencies(blockchain) {
const cacheKey = `currencies_${blockchain}`;
let currencies = cache.get(cacheKey);

if (!currencies) {
currencies = await cryptoPay.blockchains.getCurrencies(blockchain);
cache.set(cacheKey, currencies);
}

return currencies;
}

This JavaScript integration guide provides comprehensive examples for implementing CryptoPay in your applications. For more specific use cases or advanced features, check our API Reference or contact our support team.