Payment Flow Guide
This guide walks you through the complete payment flow from creating a payment order to receiving confirmation. Understanding this flow helps you provide the best experience for your customers.
Overview
The CryptoPay payment flow consists of these main steps:
- Create Payment Order - Generate a payment request
- Customer Payment - Customer sends cryptocurrency
- Detection - Our system detects the blockchain transaction
- Confirmation - Wait for required block confirmations
- Notification - Receive webhook notification
- Fulfillment - Complete the order
Step 1: Create Payment Order
Using the Dashboard
-
Navigate to Payments > Create Order
-
Fill in details:
- Amount:
100.00 - Currency:
USDC - Blockchain:
Base - Order Info: Product details in JSON format
- Expiration: Optional expiration time
- Amount:
-
Click Create Order to generate the payment link
Using the API
const order = await fetch('/api/payment-orders/', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: '100.00',
currency: 'USDC',
blockchain: 'base',
order_info: JSON.stringify({
product: 'Premium Plan',
customer_id: 'user_123',
quantity: 1
}),
nonce: Date.now() + Math.floor(Math.random() * 1000000),
webhook_url: 'https://your-site.com/webhooks/cryptopay'
})
});
const paymentOrder = await order.json();
console.log('Payment URL:', paymentOrder.data.payment_url);
Payment Order Response
{
"success": true,
"data": {
"id": 123,
"order_id": "ORD-abc123def456",
"amount": "100.00",
"currency": "USDC",
"blockchain": "base",
"status": "pending",
"receiving_address": "0x1234567890123456789012345678901234567890",
"payment_url": "https://pay.cryptopay.com/order/ORD-abc123def456",
"qr_code_url": "/qr/ORD-abc123def456",
"expires_at": "2024-01-01T12:00:00Z",
"created_at": "2024-01-01T10:00:00Z"
}
}
Step 2: Customer Payment
Payment Options
Customers can pay using:
1. Payment Page
- Direct them to
payment_url - Mobile-optimized interface
- Supports all major wallets
- QR code for mobile wallets
2. Direct Wallet Transfer
- Show the receiving address
- Display exact amount and token
- Include QR code for easy scanning
3. Embedded Widget
<iframe
src="https://pay.cryptopay.com/order/ORD-abc123def456"
width="400"
height="600"
frameborder="0">
</iframe>
Customer Experience
- Choose Wallet: MetaMask, Coinbase Wallet, etc.
- Connect Wallet: Authorize wallet connection
- Review Payment: Confirm amount, token, and recipient
- Send Transaction: Submit blockchain transaction
- Wait for Confirmation: Transaction processes on blockchain
Payment Instructions
Provide clear instructions to customers:
<div class="payment-instructions">
<h3>Complete Your Payment</h3>
<p>Send exactly <strong>100.00 USDC</strong> to:</p>
<code>0x1234567890123456789012345678901234567890</code>
<p>Network: <strong>Base</strong></p>
<p>⚠️ Only send USDC on Base network to this address</p>
</div>
Step 3: Payment Detection
How Detection Works
Our system continuously monitors blockchains for incoming transactions:
- Real-time Monitoring: We scan new blocks every few seconds
- Address Matching: Check if transactions match your wallet addresses
- Amount Verification: Verify the payment amount and token
- Initial Detection: Payment status changes to "processing"
Detection Timeline
| Blockchain | Detection Time | Block Time |
|---|---|---|
| Ethereum | 15-30 seconds | ~12 seconds |
| Base | 5-10 seconds | ~2 seconds |
| Polygon | 5-10 seconds | ~2 seconds |
| BSC | 10-15 seconds | ~3 seconds |
| Arbitrum | 2-5 seconds | ~0.25 seconds |
What We Check
- ✅ Correct Address: Payment sent to your wallet address
- ✅ Correct Token: Right cryptocurrency (USDC, ETH, etc.)
- ✅ Sufficient Amount: At least the required amount
- ✅ Valid Transaction: Transaction succeeded on blockchain
Step 4: Confirmation Process
Confirmation Requirements
Different confirmation thresholds based on your settings:
// Example confirmation thresholds
const confirmationSettings = {
'low_value': 1, // < $100
'medium_value': 6, // $100-$1000
'high_value': 12, // > $1000
'custom': 24 // Custom setting
};
Confirmation Timeline
Example: Base Network (2-second blocks, 12 confirmations)
- Block 1: Transaction included (0 confirmations)
- Block 2: 1 confirmation (2 seconds later)
- Block 6: 5 confirmations (10 seconds later)
- Block 12: 11 confirmations (22 seconds later)
- Block 13: 12 confirmations ✅ CONFIRMED (24 seconds later)
Status Updates
Payment status progresses through these stages:
- pending - Waiting for payment
- processing - Payment detected, waiting for confirmations
- confirmed - Required confirmations reached
- failed - Payment failed or insufficient
Step 5: Webhook Notifications
Webhook Events
You'll receive webhooks for each status change:
payment.pending - Initial detection
{
"event": "payment.pending",
"data": {
"order_id": "ORD-abc123def456",
"transaction_hash": "0xabcdef...",
"amount": "100.00",
"currency": "USDC",
"blockchain": "base",
"confirmations": 1,
"status": "processing"
}
}
payment.confirmed - Final confirmation
{
"event": "payment.confirmed",
"data": {
"order_id": "ORD-abc123def456",
"transaction_hash": "0xabcdef...",
"amount": "100.00",
"currency": "USDC",
"blockchain": "base",
"confirmations": 12,
"status": "confirmed",
"confirmed_at": "2024-01-01T10:15:00Z"
}
}
Webhook Handler Example
app.post('/webhooks/cryptopay', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-webhook-signature'];
const payload = req.body;
// Verify signature
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const webhookData = JSON.parse(payload);
const { event, data } = webhookData;
switch (event) {
case 'payment.pending':
// Update UI to show payment detected
updatePaymentStatus(data.order_id, 'processing');
notifyCustomer(data.order_id, 'Payment detected, waiting for confirmation');
break;
case 'payment.confirmed':
// Fulfill the order
fulfillOrder(data.order_id);
updatePaymentStatus(data.order_id, 'confirmed');
notifyCustomer(data.order_id, 'Payment confirmed! Order processing');
break;
case 'payment.failed':
// Handle failed payment
updatePaymentStatus(data.order_id, 'failed');
notifyCustomer(data.order_id, 'Payment failed: ' + data.reason);
break;
}
res.status(200).send('OK');
});
Step 6: Order Fulfillment
Fulfillment Process
Once payment is confirmed:
- Verify Payment: Double-check payment details
- Update Database: Mark order as paid
- Fulfill Order: Deliver product/service
- Send Confirmation: Email receipt to customer
- Update Analytics: Record successful payment
Example Fulfillment
async function fulfillOrder(orderId) {
try {
// Get order details
const order = await getOrderFromDatabase(orderId);
const orderInfo = JSON.parse(order.order_info);
// Update order status
await updateOrderStatus(orderId, 'paid');
// Fulfill based on product type
switch (orderInfo.product) {
case 'Premium Plan':
await activatePremiumSubscription(orderInfo.customer_id);
break;
case 'Digital Download':
await sendDownloadLink(orderInfo.customer_id, orderInfo.product_id);
break;
case 'Physical Product':
await createShippingLabel(orderInfo.customer_id, orderInfo.shipping_address);
break;
}
// Send confirmation email
await sendOrderConfirmation(orderInfo.customer_id, order);
console.log(`Order ${orderId} fulfilled successfully`);
} catch (error) {
console.error(`Error fulfilling order ${orderId}:`, error);
// Handle fulfillment errors
}
}
Payment Flow Monitoring
Dashboard Monitoring
Track payments in real-time through your dashboard:
- Live Feed: See payments as they happen
- Status Updates: Watch confirmations accumulate
- Transaction Details: View blockchain transaction info
- Customer Information: See payment source addresses
API Monitoring
Check payment status programmatically:
// Poll for payment updates
async function monitorPayment(orderId) {
const maxAttempts = 60; // 5 minutes with 5-second intervals
let attempts = 0;
while (attempts < maxAttempts) {
const response = await fetch(`/api/payment-orders/${orderId}/`, {
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
});
const order = await response.json();
if (order.data.status === 'confirmed') {
console.log('Payment confirmed!');
return order.data;
} else if (order.data.status === 'failed') {
console.log('Payment failed');
return order.data;
}
// Wait 5 seconds before next check
await new Promise(resolve => setTimeout(resolve, 5000));
attempts++;
}
console.log('Payment monitoring timeout');
return null;
}
Handling Edge Cases
Common Issues
1. Insufficient Amount
{
"event": "payment.failed",
"data": {
"reason": "insufficient_amount",
"expected_amount": "100.00",
"received_amount": "50.00"
}
}
2. Wrong Token
{
"event": "payment.failed",
"data": {
"reason": "invalid_token",
"expected_token": "USDC",
"received_token": "USDT"
}
}
3. Expired Order
{
"event": "order.expired",
"data": {
"order_id": "ORD-abc123def456",
"expired_at": "2024-01-01T12:00:00Z"
}
}
Recovery Actions
function handlePaymentIssue(webhookData) {
const { event, data } = webhookData;
switch (data.reason) {
case 'insufficient_amount':
// Contact customer about partial payment
sendPartialPaymentNotification(data.order_id, data);
break;
case 'invalid_token':
// Guide customer to send correct token
sendTokenCorrectionNotification(data.order_id, data);
break;
case 'expired':
// Offer to create new payment order
sendOrderRenewalNotification(data.order_id);
break;
}
}
Best Practices
Customer Communication
- Set Expectations: Explain confirmation times
- Provide Updates: Show payment progress
- Clear Instructions: Specify exact amount and token
- Support Contact: Offer help if issues arise
Error Handling
- Graceful Degradation: Handle API failures
- Retry Logic: Implement exponential backoff
- Logging: Record all payment events
- Monitoring: Alert on unusual patterns
Security
- Verify Webhooks: Always check HMAC signatures
- Validate Amounts: Confirm payment matches order
- Monitor Addresses: Watch for suspicious activity
- Secure Storage: Protect customer data
Next Steps
- Webhooks API - Configure notifications
- Dashboard Guide - Monitor payments
- FAQ - Resolve common issues
- API Reference - Technical details