
Payment Gateway Integration
- 352 installs
- 202 repo stars
- Updated August 4, 2026
- secondsky/claude-skills
payment-gateway-integration is a Claude Code skill that integrates Stripe, PayPal, or Square checkout, subscriptions, webhooks, and PCI-aware patterns for developers adding payments to web applications.
About
payment-gateway-integration is an MIT-licensed secondsky/claude-skills plugin that implements secure payment processing for Stripe (Node.js PaymentIntents, subscriptions, refunds), PayPal (order capture, refunds, webhooks via references/paypal-integration.md), and Square-style flows with signature-verified webhooks and idempotency keys. It ships Node.js service examples, webhook handlers using express.raw for Stripe signatures, and a 9-item security checklist covering SDK-only usage, HTTPS routes, sandbox testing, and minimal card-data retention. Use payment-gateway-integration when adding checkout, recurring billing, refund handling, or dispute webhooks to a monetized SaaS or e-commerce API.
- payment-gateway-integration
Payment Gateway Integration by the numbers
- 352 all-time installs (skills.sh)
- +11 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #1,157 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/secondsky/claude-skills --skill payment-gateway-integrationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 352 |
|---|---|
| repo stars | ★ 202 |
| Last updated | August 4, 2026 |
| Repository | secondsky/claude-skills ↗ |
How do you integrate Stripe checkout and webhooks?
Use payment-gateway-integration for development tasks
Who is it for?
Full-stack developers adding Stripe, PayPal, or Square billing to Node.js APIs with subscriptions, refunds, and webhook verification.
Skip if: Teams only needing pricing strategy or tax compliance without gateway code—this skill implements payment processor integrations.
When should I use this skill?
User asks to add Stripe, PayPal, or Square checkout, subscriptions, webhooks, refunds, or PCI-compliant payment routes
What you get
Payment service code, webhook endpoints, subscription flows, and PCI security checklist completion
- Payment service module
- Webhook route handlers
- Security checklist sign-off
By the numbers
- Supports 3 payment gateways: Stripe, PayPal, and Square
- Includes a 9-item payment security checklist
Files
Payment Gateway Integration
Integrate secure payment processing with proper error handling and compliance.
Stripe Integration (Node.js)
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
class PaymentService {
async createPaymentIntent(amount, currency, customerId) {
return stripe.paymentIntents.create({
amount: Math.round(amount * 100), // Convert to cents
currency,
customer: customerId,
automatic_payment_methods: { enabled: true }
});
}
async createSubscription(customerId, priceId) {
return stripe.subscriptions.create({
customer: customerId,
items: [{ price: priceId }],
payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent']
});
}
async refund(paymentIntentId, amount = null) {
const params = { payment_intent: paymentIntentId };
if (amount) params.amount = Math.round(amount * 100);
return stripe.refunds.create(params);
}
}Webhook Handling
app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(req.body, sig, process.env.STRIPE_WEBHOOK_SECRET);
} catch (err) {
return res.status(400).send(`Webhook Error: ${err.message}`);
}
switch (event.type) {
case 'payment_intent.succeeded':
await handlePaymentSuccess(event.data.object);
break;
case 'invoice.payment_failed':
await handlePaymentFailed(event.data.object);
break;
}
res.json({ received: true });
});PayPal Integration
See references/paypal-integration.md for complete PayPal implementation with:
- Order creation and capture
- Refund processing
- Webhook handling
- Frontend SDK integration
- Success/cancel callbacks
Security Checklist
- [ ] Use official SDK only
- [ ] Verify webhook signatures
- [ ] Never log full card numbers
- [ ] Store minimal payment data
- [ ] Test in sandbox first
- [ ] HTTPS for all payment routes
- [ ] Handle all error cases
- [ ] Use idempotency keys
- [ ] Implement retry logic
Best Practices
Do:
- Use official SDK libraries
- Verify all webhook signatures
- Log transaction IDs (not card data)
- Test in sandbox environment
- Handle all payment states
- Implement proper error messages
Don't:
- Process raw card data directly
- Store sensitive payment info
- Hardcode API keys
- Skip webhook signature validation
- Ignore failed payment events
- Use test keys in production
PayPal Integration
Complete PayPal payment processing with Node.js.
const paypal = require('@paypal/checkout-server-sdk');
// PayPal environment setup
function environment() {
const clientId = process.env.PAYPAL_CLIENT_ID;
const clientSecret = process.env.PAYPAL_CLIENT_SECRET;
return process.env.NODE_ENV === 'production'
? new paypal.core.LiveEnvironment(clientId, clientSecret)
: new paypal.core.SandboxEnvironment(clientId, clientSecret);
}
const client = new paypal.core.PayPalHttpClient(environment());
class PayPalService {
/**
* Create a PayPal order
*/
async createOrder(amount, currency = 'USD', description = 'Purchase') {
const request = new paypal.orders.OrdersCreateRequest();
request.prefer('return=representation');
request.requestBody({
intent: 'CAPTURE',
purchase_units: [{
amount: {
currency_code: currency,
value: amount.toFixed(2)
},
description
}],
application_context: {
return_url: `${process.env.BASE_URL}/payment/success`,
cancel_url: `${process.env.BASE_URL}/payment/cancel`,
brand_name: 'Your Store',
landing_page: 'BILLING',
user_action: 'PAY_NOW'
}
});
const response = await client.execute(request);
return {
orderId: response.result.id,
approvalUrl: response.result.links.find(l => l.rel === 'approve').href
};
}
/**
* Capture a PayPal payment after user approval
*/
async capturePayment(orderId) {
const request = new paypal.orders.OrdersCaptureRequest(orderId);
request.requestBody({});
const response = await client.execute(request);
if (response.result.status !== 'COMPLETED') {
throw new Error(`Payment capture failed: ${response.result.status}`);
}
return {
transactionId: response.result.purchase_units[0].payments.captures[0].id,
status: response.result.status,
amount: response.result.purchase_units[0].payments.captures[0].amount
};
}
/**
* Refund a captured payment
*/
async refundPayment(captureId, amount = null) {
const request = new paypal.payments.CapturesRefundRequest(captureId);
const body = {};
if (amount) {
body.amount = {
currency_code: 'USD',
value: amount.toFixed(2)
};
}
request.requestBody(body);
const response = await client.execute(request);
return {
refundId: response.result.id,
status: response.result.status
};
}
/**
* Get order details
*/
async getOrder(orderId) {
const request = new paypal.orders.OrdersGetRequest(orderId);
const response = await client.execute(request);
return response.result;
}
}
module.exports = new PayPalService();Express Routes
const express = require('express');
const router = express.Router();
const paypal = require('./paypal-service');
// Create order
router.post('/create-order', async (req, res) => {
try {
const { amount, currency, description } = req.body;
const order = await paypal.createOrder(amount, currency, description);
// Store order in database
await db.orders.create({
paypalOrderId: order.orderId,
userId: req.user.id,
amount,
status: 'pending'
});
res.json(order);
} catch (error) {
console.error('Create order error:', error);
res.status(500).json({ error: 'Failed to create order' });
}
});
// Capture payment (called after user approves)
router.post('/capture/:orderId', async (req, res) => {
try {
const { orderId } = req.params;
const result = await paypal.capturePayment(orderId);
// Update order in database
await db.orders.update(
{ paypalOrderId: orderId },
{
status: 'completed',
transactionId: result.transactionId,
completedAt: new Date()
}
);
res.json(result);
} catch (error) {
console.error('Capture error:', error);
res.status(500).json({ error: 'Failed to capture payment' });
}
});
// Refund
router.post('/refund/:captureId', async (req, res) => {
try {
const { captureId } = req.params;
const { amount } = req.body;
const result = await paypal.refundPayment(captureId, amount);
res.json(result);
} catch (error) {
console.error('Refund error:', error);
res.status(500).json({ error: 'Failed to process refund' });
}
});
// Success callback
router.get('/success', async (req, res) => {
const { token } = req.query; // PayPal order ID
res.redirect(`/checkout/confirmation?orderId=${token}`);
});
// Cancel callback
router.get('/cancel', (req, res) => {
res.redirect('/checkout/cancelled');
});
module.exports = router;Webhook Handler
const crypto = require('crypto');
router.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
const webhookId = process.env.PAYPAL_WEBHOOK_ID;
// Verify webhook signature
const transmissionId = req.headers['paypal-transmission-id'];
const transmissionTime = req.headers['paypal-transmission-time'];
const certUrl = req.headers['paypal-cert-url'];
const transmissionSig = req.headers['paypal-transmission-sig'];
// In production, verify the webhook signature
// See PayPal documentation for full verification process
const event = JSON.parse(req.body);
switch (event.event_type) {
case 'PAYMENT.CAPTURE.COMPLETED':
await handleCaptureCompleted(event.resource);
break;
case 'PAYMENT.CAPTURE.REFUNDED':
await handleRefund(event.resource);
break;
case 'CHECKOUT.ORDER.APPROVED':
await handleOrderApproved(event.resource);
break;
default:
console.log('Unhandled event:', event.event_type);
}
res.status(200).send('OK');
});
async function handleCaptureCompleted(capture) {
await db.orders.update(
{ transactionId: capture.id },
{ status: 'completed' }
);
}Frontend Integration
<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID"></script>
<script>
paypal.Buttons({
createOrder: async () => {
const response = await fetch('/api/payment/create-order', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ amount: 99.99 })
});
const data = await response.json();
return data.orderId;
},
onApprove: async (data) => {
const response = await fetch(`/api/payment/capture/${data.orderID}`, {
method: 'POST'
});
const result = await response.json();
if (result.status === 'COMPLETED') {
window.location.href = '/checkout/success';
}
},
onError: (err) => {
console.error('PayPal error:', err);
alert('Payment failed. Please try again.');
}
}).render('#paypal-button-container');
</script>Dependencies
{
"@paypal/checkout-server-sdk": "^1.0.3"
}Related skills
How it compares
Use payment-gateway-integration for processor SDK and webhook implementation; use pricing or billing-architecture skills when defining plans, not wiring gateways.
FAQ
Which payment providers does payment-gateway-integration support?
payment-gateway-integration covers Stripe, PayPal, and Square patterns with Node.js examples for PaymentIntents, subscriptions, refunds, and webhooks. PayPal details live in references/paypal-integration.md for orders, captures, and frontend SDK callbacks.
What security practices does payment-gateway-integration require?
payment-gateway-integration enforces official SDK usage, webhook signature verification, idempotency keys, HTTPS routes, sandbox testing, and never logging full card numbers. Its checklist has 9 items including minimal payment-data storage and retry logic.