Examples
Accept Payment Example
Complete example of accepting a payment using One2Pays API.
Overview
This example shows how to:
- Create a payment with required fields
- Handle the payment response with
nextAction - Redirect customer to payment page
- Handle webhook notifications
Complete Example
import crypto from 'crypto';
const API_KEY = process.env.PAYMENT_API_KEY!;
const API_SECRET = process.env.PAYMENT_API_SECRET!;
// Helper function to create HMAC signature
function createSignature(
timestamp: string,
body: string,
secret: string
): string {
// Signature format: HMAC-SHA256(timestamp + "." + rawBody, secretKey)
const message = `${timestamp}.${body}`;
return crypto
.createHmac('sha256', secret)
.update(message)
.digest('hex');
}
// Create payment
export async function createPayment(
orderId: string,
amount: string,
customerBankAccount: {
name: string;
number: string;
code: string;
}
) {
const method = 'POST';
const path = '/api/v1/payments';
const body = JSON.stringify({
amount, // Already a string like "1000.00"
currency: 'THB',
referenceId: `order-${orderId}`,
paymentMethod: 'promptpay',
customerBankAccountName: customerBankAccount.name,
customerBankAccountNumber: customerBankAccount.number,
customerBankCode: customerBankAccount.code,
description: `Payment for order #${orderId}`,
metadata: {
order_id: orderId,
},
idempotencyKey: `order-${orderId}-${Date.now()}`,
});
const timestamp = Date.now().toString(); // milliseconds
const signature = createSignature(timestamp, body, API_SECRET);
const response = await fetch(`https://api.example.com${path}`, {
method,
headers: {
'X-API-Key': API_KEY,
'X-Timestamp': timestamp,
'X-Signature': `sha256=${signature}`,
'Content-Type': 'application/json',
},
body,
});
const result = await response.json();
if (!result.success) {
throw new Error(result.error.message);
}
return result.data;
}
// Usage in API route (Next.js)
export async function POST(request: Request) {
try {
const { orderId, amount, customerBankAccount } = await request.json();
const payment = await createPayment(orderId, amount, customerBankAccount);
// Handle nextAction
if (payment.nextAction?.type === 'use_payment_app') {
return Response.json({
success: true,
paymentId: payment.id,
redirectUrl: payment.nextAction.paymentAppUrl,
});
} else if (payment.nextAction?.type === 'redirect') {
return Response.json({
success: true,
paymentId: payment.id,
redirectUrl: payment.nextAction.redirectUrl,
});
}
return Response.json({
success: true,
paymentId: payment.id,
status: payment.status,
});
} catch (error) {
return Response.json(
{ success: false, error: error instanceof Error ? error.message : 'Unknown error' },
{ status: 400 }
);
}
}Frontend Integration
'use client';
import { useState } from 'react';
export function PaymentButton({
orderId,
amount,
customerBankAccount
}: {
orderId: string;
amount: string;
customerBankAccount: {
name: string;
number: string;
code: string;
};
}) {
const [loading, setLoading] = useState(false);
const handlePayment = async () => {
setLoading(true);
try {
const response = await fetch('/api/payments/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
orderId,
amount,
customerBankAccount,
}),
});
const result = await response.json();
if (result.success && result.redirectUrl) {
window.location.href = result.redirectUrl;
} else {
alert('Payment creation failed');
}
} catch (error) {
console.error('Error:', error);
alert('An error occurred');
} finally {
setLoading(false);
}
};
return (
<button onClick={handlePayment} disabled={loading}>
{loading ? 'Processing...' : 'Pay Now'}
</button>
);
}