payment
SKILL.md
Payment Integration
Integrate payment processors securely.
When to use
- Payment gateway integration
- Subscription billing
- Checkout flows
- Webhook handling
- PCI compliance
Stripe integration
Setup
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
// Create payment intent
async function createPayment(amount, currency = "usd") {
const paymentIntent = await stripe.paymentIntents.create({
amount: amount * 100, // cents
currency,
automatic_payment_methods: { enabled: true },
metadata: { order_id: "order_123" },
});
return {
clientSecret: paymentIntent.client_secret,
id: paymentIntent.id,
};
}
Subscriptions
// Create subscription
async function createSubscription(customerId, priceId) {
const subscription = await stripe.subscriptions.create({
customer: customerId,
items: [{ price: priceId }],
payment_behavior: "default_incomplete",
expand: ["latest_invoice.payment_intent"],
});
return {
subscriptionId: subscription.id,
clientSecret: subscription.latest_invoice.payment_intent.client_secret,
};
}
// Cancel subscription
async function cancelSubscription(subscriptionId) {
return await stripe.subscriptions.update(subscriptionId, {
cancel_at_period_end: true,
});
}
Webhooks
import { buffer } from "micro";
export async function handleWebhook(req, res) {
const sig = req.headers["stripe-signature"];
const body = await buffer(req);
let event;
try {
event = stripe.webhooks.constructEvent(
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 "payment_intent.payment_failed":
await handlePaymentFailure(event.data.object);
break;
case "customer.subscription.deleted":
await handleSubscriptionCanceled(event.data.object);
break;
}
res.json({ received: true });
}
Database schema
CREATE TABLE payments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
stripe_payment_id VARCHAR(255) UNIQUE,
amount DECIMAL(10,2) NOT NULL,
currency VARCHAR(3) DEFAULT 'usd',
status VARCHAR(50) NOT NULL,
metadata JSONB,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE subscriptions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
stripe_subscription_id VARCHAR(255) UNIQUE,
stripe_customer_id VARCHAR(255),
plan VARCHAR(50) NOT NULL,
status VARCHAR(50) NOT NULL,
current_period_start TIMESTAMP,
current_period_end TIMESTAMP,
canceled_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_payments_user ON payments(user_id);
CREATE INDEX idx_subscriptions_user ON subscriptions(user_id);
Security checklist
- Never log full card numbers
- Use HTTPS everywhere
- Validate webhook signatures
- Implement idempotency keys
- Store only necessary data
- Use Stripe.js for card collection
- Handle errors gracefully
Examples
Input: "Add Stripe payments" Action: Set up Stripe, create payment intent endpoint, add webhook handler
Input: "Implement subscriptions" Action: Create subscription flow, handle lifecycle webhooks, add cancellation
Weekly Installs
5
Repository
htlin222/dotfilesInstalled on
claude-code4
windsurf3
antigravity3
gemini-cli3
trae2
opencode2