Accepting Payments

Learn how to accept cryptocurrency payments with BLAQPAY

Accepting Payments

This comprehensive guide covers everything you need to know about accepting cryptocurrency payments with BLAQPAY.

Payment Flow Overview

Here’s how a typical payment works:

  1. Customer initiates payment on your website/app
  2. Your server creates an order via our API
  3. Customer is redirected to BLAQPAY checkout
  4. Customer sends crypto to the provided address
  5. Payment is confirmed on the blockchain
  6. Webhook notification sent to your server
  7. You fulfill the order for your customer

Creating a Payment

Basic Payment

const order = await blaqpay.orders.create({
	amount: 99.99,
	currency: 'USD',
	crypto_currency: 'BTC',
	description: 'Premium Subscription',
	customer_email: 'customer@example.com'
});

Advanced Options

const order = await blaqpay.orders.create({
	// Required fields
	amount: 99.99,
	currency: 'USD',
	crypto_currency: 'BTC',

	// Customer information
	customer_email: 'customer@example.com',
	customer_name: 'John Doe',

	// Order details
	description: 'Premium Subscription - Annual',
	reference_id: 'order_12345', // Your internal ID

	// URLs
	return_url: 'https://yoursite.com/success',
	cancel_url: 'https://yoursite.com/cancel',
	webhook_url: 'https://yoursite.com/webhooks/blaqpay',

	// Metadata (optional custom data)
	metadata: {
		plan: 'premium',
		period: 'annual',
		user_id: '12345'
	},

	// Expiration
	expires_in: 3600 // 1 hour
});

Supported Cryptocurrencies

BLAQPAY supports 100+ cryptocurrencies. Popular options include:

  • Bitcoin (BTC)
  • Ethereum (ETH)
  • USDT (Tether - ERC20, TRC20, BEP20)
  • USDC (USD Coin)
  • BNB (Binance Coin)
  • Litecoin (LTC)
  • Dogecoin (DOGE)
  • And many more…

Let Customer Choose

Don’t specify crypto_currency to let customers choose:

const order = await blaqpay.orders.create({
	amount: 99.99,
	currency: 'USD',
	// crypto_currency not specified - customer chooses
	description: 'Premium Subscription'
});

Payment States

Orders go through several states:

pending → confirming → completed
   ↓           ↓
expired     failed
  • pending: Waiting for customer to send crypto
  • confirming: Transaction detected, waiting for confirmations
  • completed: Payment confirmed and successful
  • expired: Payment window expired
  • failed: Payment failed or was cancelled

Handling Payment Confirmation

Receive real-time notifications:

app.post('/webhooks/blaqpay', async (req, res) => {
	const event = req.body;

	// Verify signature
	const signature = req.headers['x-blaqpay-signature'];
	const isValid = blaqpay.webhooks.verify(
		JSON.stringify(event),
		signature,
		process.env.WEBHOOK_SECRET
	);

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

	switch (event.type) {
		case 'order.created':
			console.log('Order created:', event.data.id);
			break;

		case 'order.confirming':
			console.log('Payment detected:', event.data.id);
			break;

		case 'order.completed':
			// Payment successful! Fulfill the order
			await fulfillOrder(event.data);
			break;

		case 'order.failed':
			console.log('Payment failed:', event.data.id);
			break;
	}

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

Option 2: Polling

Poll the API to check payment status:

async function checkPaymentStatus(orderId) {
	const order = await blaqpay.orders.retrieve(orderId);

	if (order.status === 'completed') {
		// Payment successful
		await fulfillOrder(order);
	} else if (order.status === 'expired' || order.status === 'failed') {
		// Payment failed
		console.log('Payment not completed');
	} else {
		// Still pending, check again later
		setTimeout(() => checkPaymentStatus(orderId), 10000);
	}
}

Pricing and Currency Conversion

Fixed Crypto Amount

Charge a specific amount of cryptocurrency:

const order = await blaqpay.orders.create({
	crypto_amount: 0.001, // 0.001 BTC
	crypto_currency: 'BTC',
	description: 'Fixed crypto payment'
});

Fiat to Crypto Conversion

Charge in fiat, we handle conversion:

const order = await blaqpay.orders.create({
	amount: 100.0,
	currency: 'USD',
	crypto_currency: 'BTC',
	// We calculate the BTC amount automatically
	description: 'Fiat-based payment'
});

The crypto amount is locked when the order is created and remains valid for the expiration period.

Checkout Options

Hosted Checkout

Redirect customers to our hosted page:

// Create order
const order = await blaqpay.orders.create({ ... });

// Redirect to checkout
window.location.href = order.payment_url;

Embedded Checkout

Display checkout on your site:

<div id="blaqpay-checkout"></div>

<script>
	blaqpay.checkout({
		containerId: 'blaqpay-checkout',
		orderId: 'ord_1234567890',
		onSuccess: (order) => {
			window.location.href = '/success';
		},
		onCancel: () => {
			window.location.href = '/cancel';
		}
	});
</script>

QR Code

Generate QR codes for mobile payments:

const qrCode = await blaqpay.orders.getQRCode(orderId);
// Returns a data URL or SVG

Refunds

Issue full or partial refunds:

// Full refund
const refund = await blaqpay.refunds.create({
	order_id: 'ord_1234567890',
	reason: 'Customer request'
});

// Partial refund
const partialRefund = await blaqpay.refunds.create({
	order_id: 'ord_1234567890',
	amount: 50.0, // Refund $50 of $100 order
	reason: 'Partial refund'
});

Metadata and Custom Data

Store custom data with orders:

const order = await blaqpay.orders.create({
	amount: 99.99,
	currency: 'USD',
	metadata: {
		customer_id: '12345',
		subscription_id: 'sub_67890',
		plan: 'premium',
		referral_code: 'FRIEND10',
		custom_field: 'any data you need'
	}
});

// Metadata is returned in webhooks and API responses

Best Practices

1. Use Webhooks

Always use webhooks for payment confirmation. Don’t rely solely on return URLs as users might not return to your site.

2. Idempotency

Use idempotency keys to safely retry requests:

const order = await blaqpay.orders.create(
  { ... },
  {
    idempotencyKey: 'order_12345_' + Date.now()
  }
);

3. Set Expiration Times

Set reasonable expiration times:

const order = await blaqpay.orders.create({
	amount: 99.99,
	currency: 'USD',
	expires_in: 1800 // 30 minutes
});

4. Handle All States

Handle all possible order states in your application:

switch (order.status) {
	case 'pending':
		// Show "waiting for payment"
		break;
	case 'confirming':
		// Show "payment detected, confirming..."
		break;
	case 'completed':
		// Show "payment successful"
		break;
	case 'expired':
		// Show "payment expired, please try again"
		break;
	case 'failed':
		// Show "payment failed"
		break;
}

5. Verify Webhook Signatures

Always verify webhook signatures:

const isValid = blaqpay.webhooks.verify(payload, signature, webhookSecret);

if (!isValid) {
	throw new Error('Invalid webhook signature');
}

Testing

Test payments in sandbox mode:

// Use test API keys
const blaqpay = new BlaqPay('sk_test_...');

// Create test order
const order = await blaqpay.orders.create({
	amount: 1.0,
	currency: 'USD',
	crypto_currency: 'BTC'
});

// Test payments auto-complete after 1 minute

See our Testing Guide for more details.

Examples

E-commerce Checkout

// Shopping cart checkout
app.post('/checkout', async (req, res) => {
	const cart = req.body.cart;
	const total = calculateTotal(cart);

	const order = await blaqpay.orders.create({
		amount: total,
		currency: 'USD',
		description: `Order #${Date.now()}`,
		customer_email: req.body.email,
		metadata: {
			cart_items: JSON.stringify(cart),
			customer_id: req.user.id
		},
		return_url: `https://mystore.com/order-confirmation`,
		webhook_url: 'https://mystore.com/webhooks/payment'
	});

	res.json({ checkoutUrl: order.payment_url });
});

Subscription Payment

// Monthly subscription
async function chargeSubscription(subscription) {
	const order = await blaqpay.orders.create({
		amount: subscription.price,
		currency: 'USD',
		crypto_currency: 'USDT',
		description: `${subscription.plan} - Monthly`,
		customer_email: subscription.customer_email,
		metadata: {
			subscription_id: subscription.id,
			period_start: Date.now(),
			period_end: Date.now() + 30 * 24 * 60 * 60 * 1000
		}
	});

	// Send payment link to customer
	await sendEmail(subscription.customer_email, {
		subject: 'Subscription Payment',
		paymentLink: order.payment_url
	});
}

Next Steps

Need Help?

If you have questions about accepting payments: