Your First Payment
A step-by-step walkthrough of creating and processing your first Pelago payment.
What We'll Build
A complete payment flow that:
- Creates a payment request
- Displays a QR code for the customer
- Handles the payment webhook
- Confirms the successful payment
Prerequisites
- Completed SDK installation (Quick Start)
- Sandbox environment configured (Sandbox Setup)
- A basic web server (Node.js/Express example below)
Full Example: Express.js Payment Server
import express from 'express';
import { PelagoClient } from '@pelago/sdk';
const app = express();
app.use(express.json());
// Initialize Pelago client
const pelago = new PelagoClient({
apiKey: process.env.PELAGO_API_KEY!,
apiSecret: process.env.PELAGO_API_SECRET!,
environment: 'sandbox'
});
// Store pending orders (use a database in production)
const orders = new Map<string, { status: string; amount: number }>();
// 1. Create a new order and payment
app.post('/api/checkout', async (req, res) => {
const { productId, email } = req.body;
// Create your order
const orderId = `order_${Date.now()}`;
const amount = 25.00; // Product price
orders.set(orderId, { status: 'pending', amount });
try {
// Create Pelago payment
const payment = await pelago.payments.create({
amount,
currency: 'USD',
cryptocurrency: 'USDC',
network: 'stellar-testnet',
merchantWallet: process.env.MERCHANT_WALLET!,
redirectUrl: `${process.env.APP_URL}/order/${orderId}/success`,
webhookUrl: `${process.env.APP_URL}/api/webhook`,
metadata: {
orderId,
customerEmail: email,
productId
}
});
res.json({
orderId,
paymentId: payment.id,
paymentUrl: payment.url,
qrCode: payment.qrCode,
expiresAt: payment.expiresAt
});
} catch (error) {
console.error('Payment creation failed:', error);
res.status(500).json({ error: 'Failed to create payment' });
}
});
// 2. Check payment/order status
app.get('/api/orders/:orderId', (req, res) => {
const order = orders.get(req.params.orderId);
if (!order) {
return res.status(404).json({ error: 'Order not found' });
}
res.json(order);
});
// 3. Handle Pelago webhooks
app.post('/api/webhook', async (req, res) => {
const signature = req.headers['x-pelago-signature'] as string;
// Verify the webhook signature
if (!pelago.webhooks.verify(req.body, signature)) {
console.warn('Invalid webhook signature');
return res.status(401).json({ error: 'Invalid signature' });
}
const event = req.body;
const { orderId } = event.data.metadata;
console.log(`Received webhook: ${event.type} for order ${orderId}`);
switch (event.type) {
case 'payment.completed':
// Update order status
const order = orders.get(orderId);
if (order) {
order.status = 'paid';
orders.set(orderId, order);
}
// Trigger fulfillment (send email, ship product, etc.)
console.log(`✅ Order ${orderId} paid successfully!`);
break;
case 'payment.failed':
const failedOrder = orders.get(orderId);
if (failedOrder) {
failedOrder.status = 'failed';
orders.set(orderId, failedOrder);
}
console.log(`❌ Order ${orderId} payment failed`);
break;
case 'payment.expired':
const expiredOrder = orders.get(orderId);
if (expiredOrder) {
expiredOrder.status = 'expired';
orders.set(orderId, expiredOrder);
}
console.log(`⏱️ Order ${orderId} payment expired`);
break;
}
// Always respond with 200 to acknowledge receipt
res.status(200).json({ received: true });
});
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Testing Your Integration
1. Start Your Server
# Set environment variables
export PELAGO_API_KEY=test_pk_xxxxx
export PELAGO_API_SECRET=test_sk_xxxxx
export MERCHANT_WALLET=GXXXXX...
export APP_URL=https://your-ngrok-url.ngrok.io
# Start the server
npx ts-node server.ts
2. Expose Webhooks with ngrok
ngrok http 3000
# Copy the https:// URL
3. Create a Test Order
curl -X POST http://localhost:3000/api/checkout \
-H "Content-Type: application/json" \
-d '{"productId": "prod_123", "email": "[email protected]"}'
Response:
{
"orderId": "order_1707401234567",
"paymentId": "pay_abc123",
"paymentUrl": "https://pay.sandbox.pelago.tech/pay_abc123",
"qrCode": "data:image/png;base64,...",
"expiresAt": "2025-02-08T22:30:00Z"
}
4. Complete the Payment
- Open the
paymentUrlin your browser - Connect your test wallet
- Approve the test USDC transfer
- Watch your webhook receive the
payment.completedevent
5. Verify the Order Status
curl http://localhost:3000/api/orders/order_1707401234567
{
"status": "paid",
"amount": 25.00
}
Payment Flow Visualization
Common Issues
Webhook Not Received
- Ensure your webhook URL is publicly accessible
- Check ngrok logs for incoming requests
- Verify webhook URL doesn't have typos
Payment Creation Fails
- Check API key environment variable
- Verify wallet address format
- Ensure you're using the correct network
Signature Verification Fails
- Use raw request body (not parsed)
- Ensure
x-pelago-signatureheader is present - Pass correct API secret to verify function
Next Steps
Now that you've processed your first payment: