Checkout Com
Accept payments with Checkout.com. Use this skill when the project needs to
You are a payments specialist who integrates Checkout.com into projects.
Checkout.com is a cloud-based payment platform offering direct API access to
card networks, alternative payment methods, and payouts across 150+ currencies.
## Key Points
- Dashboard: `hub.sandbox.checkout.com`
- Approved card: `4242 4242 4242 4242`
- Declined card: `4242 4242 4242 4241`
- 3DS card: `4242 4242 4242 4000`
- Expiry: any future date, CVV: `100`
- Always include `Idempotency-Key` headers on payment requests to prevent duplicates
- Use Frames.js for PCI SAQ-A compliance — card data never touches your server
- Verify webhook signatures using HMAC-SHA256 before processing events
- Store `payment.id` from every transaction for captures, refunds, and reconciliation
- Enable 3D Secure on all card payments for liability shift
- Use separate authorize and capture for physical goods; auto-capture for digital
- Set `metadata` on payments to link back to your internal models
## Quick Example
```bash
npm install checkout-sdk-node
```
```typescript
await cko.payments.capture(paymentId, {
amount: 2999, // can partial-capture
reference: `capture-${orderId}`,
});
```skilldb get payment-services-skills/Checkout ComFull skill: 253 linesCheckout.com Payment Integration
You are a payments specialist who integrates Checkout.com into projects. Checkout.com is a cloud-based payment platform offering direct API access to card networks, alternative payment methods, and payouts across 150+ currencies.
Core Philosophy
Direct API gives full control
Checkout.com exposes raw payment primitives. You control the entire flow — from tokenizing cards client-side with Frames.js to capturing funds server-side. This flexibility suits merchants who need fine-grained control.
Separate authorize and capture
By default, payments are authorized but not captured. This lets you validate orders before taking funds. Use auto-capture or explicit capture depending on your fulfillment model.
Idempotency prevents duplicate charges
Every payment request should include an Idempotency-Key header to safely retry
failed requests without double-charging customers.
Setup
Install
npm install checkout-sdk-node
Initialize
import { Checkout } from 'checkout-sdk-node';
const cko = new Checkout(process.env.CKO_SECRET_KEY, {
pk: process.env.CKO_PUBLIC_KEY,
environment: process.env.NODE_ENV === 'production' ? 'production' : 'sandbox',
});
Key Techniques
Tokenize cards with Frames.js (client-side)
<script src="https://cdn.checkout.com/js/framesv2.min.js"></script>
<form id="payment-form">
<div class="card-frame"></div>
<button type="submit">Pay</button>
</form>
<script>
Frames.init({
publicKey: 'pk_sbox_xxx',
localization: 'EN-GB',
});
Frames.addEventHandler(Frames.Events.CARD_VALIDATION_CHANGED, (event) => {
document.querySelector('button').disabled = !Frames.isCardValid();
});
document.getElementById('payment-form').addEventListener('submit', async (e) => {
e.preventDefault();
const { token } = await Frames.submitCard();
// Send token to your server
await fetch('/api/pay', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token, amount: 2999 }),
});
});
</script>
Request a payment (server-side)
const payment = await cko.payments.request({
source: {
type: 'token',
token: cardToken, // from Frames.js
},
amount: 2999, // minor units
currency: 'USD',
reference: `order-${orderId}`,
customer: {
email: 'shopper@example.com',
name: 'Alice Smith',
},
metadata: { userId, orderId },
'3ds': { enabled: true },
capture: false, // authorize only; capture later
}, {
idempotencyKey: `pay-${orderId}`,
});
if (payment.status === 'Pending') {
// 3DS redirect required
return { redirectUrl: payment._links.redirect.href };
}
// payment.id is the payment ID for capture/refund
Capture a payment
await cko.payments.capture(paymentId, {
amount: 2999, // can partial-capture
reference: `capture-${orderId}`,
});
Refund a payment
await cko.payments.refund(paymentId, {
amount: 2999, // can partial-refund
reference: `refund-${orderId}`,
});
Save a card for future payments
// First payment — request a reusable source
const payment = await cko.payments.request({
source: { type: 'token', token: cardToken },
amount: 2999,
currency: 'USD',
customer: { email: 'shopper@example.com' },
metadata: { userId },
capture: true,
});
// Store payment.source.id (src_xxx) for future charges
const savedSourceId = payment.source.id;
// Subsequent charges — use the stored source
const recurring = await cko.payments.request({
source: { type: 'id', id: savedSourceId },
amount: 2999,
currency: 'USD',
customer: { email: 'shopper@example.com' },
payment_type: 'Recurring',
capture: true,
}, {
idempotencyKey: `renewal-${Date.now()}`,
});
Hosted payment page (Flow)
const hostedSession = await cko.hostedPayments.create({
amount: 2999,
currency: 'USD',
reference: `order-${orderId}`,
billing: { address: { country: 'US' } },
customer: { email: 'shopper@example.com' },
success_url: 'https://yourdomain.com/success',
cancel_url: 'https://yourdomain.com/cancel',
failure_url: 'https://yourdomain.com/failure',
});
// Redirect user to hostedSession._links.redirect.href
Webhook Processing
| Event | Action |
|---|---|
payment_approved | Mark order as paid |
payment_captured | Confirm funds captured, fulfill order |
payment_declined | Mark order failed, notify customer |
payment_refunded | Process refund in your system |
payment_voided | Cancel order |
payment_capture_declined | Retry capture or escalate |
dispute_received | Handle chargeback |
import crypto from 'crypto';
export async function POST(req: Request) {
const body = await req.text();
const signature = req.headers.get('cko-signature');
// Verify signature
const expected = crypto
.createHmac('sha256', process.env.CKO_WEBHOOK_SECRET)
.update(body)
.digest('hex');
if (signature !== expected) {
return new Response('Invalid signature', { status: 401 });
}
const event = JSON.parse(body);
switch (event.type) {
case 'payment_approved':
await markOrderPaid(event.data.reference, event.data.id);
break;
case 'payment_captured':
await fulfillOrder(event.data.reference);
break;
case 'payment_declined':
await markOrderFailed(event.data.reference, event.data.response_summary);
break;
case 'payment_refunded':
await processRefund(event.data.reference, event.data.amount);
break;
}
return new Response('OK', { status: 200 });
}
Testing
Checkout.com sandbox environment:
- Dashboard:
hub.sandbox.checkout.com - Approved card:
4242 4242 4242 4242 - Declined card:
4242 4242 4242 4241 - 3DS card:
4242 4242 4242 4000 - Expiry: any future date, CVV:
100
Best Practices
- Always include
Idempotency-Keyheaders on payment requests to prevent duplicates - Use Frames.js for PCI SAQ-A compliance — card data never touches your server
- Verify webhook signatures using HMAC-SHA256 before processing events
- Store
payment.idfrom every transaction for captures, refunds, and reconciliation - Enable 3D Secure on all card payments for liability shift
- Use separate authorize and capture for physical goods; auto-capture for digital
- Set
metadataon payments to link back to your internal models
Anti-Patterns
- Relying on the synchronous payment response without webhook confirmation
- Omitting
Idempotency-Key— network retries will duplicate charges - Capturing immediately for physical goods before confirming stock/shipping
- Not handling 3DS redirects — the payment stays in
Pendingstatus forever - Storing raw card numbers instead of using Frames.js tokenization
- Ignoring
payment_declinedwebhooks — customer sees no feedback - Using the secret key client-side — it must only be used server-side
Install this skill directly: skilldb add payment-services-skills
Related Skills
Adyen
Accept payments with Adyen. Use this skill when the project needs to integrate
Braintree
Accept payments with Braintree (PayPal). Use this skill when the project needs
Coinbase Commerce
Accept cryptocurrency payments with Coinbase Commerce. Use this skill when the
Creem
Accept payments with Creem as merchant of record. Use this skill when the project
Klarna
Accept payments with Klarna. Use this skill when the project needs to integrate
Lemonsqueezy
Accept payments with Lemon Squeezy as merchant of record. Use this skill when