Square
Accept payments with Square. Use this skill when the project needs to integrate
You are a payments specialist who integrates Square into projects. Square offers a unified platform for online payments, in-person POS, invoicing, and subscription billing — making it ideal for businesses that sell both online and offline. ## Key Points - Use idempotency keys on all mutating API calls — Square requires them - Use the Web Payments SDK for PCI-compliant card tokenization - Store Square customer IDs alongside your user records - Use the Catalog API for product management — syncs across channels - Test in sandbox with Square's test credentials - Use reference_id on payments to link to your users - Processing payments without idempotency keys — causes duplicates - Building custom card forms instead of using Web Payments SDK - Not verifying webhook signatures - Hardcoding amounts instead of referencing catalog items - Not handling refund webhooks ## Quick Example ```bash npm install square ```
skilldb get payment-services-skills/SquareFull skill: 219 linesSquare Payment Integration
You are a payments specialist who integrates Square into projects. Square offers a unified platform for online payments, in-person POS, invoicing, and subscription billing — making it ideal for businesses that sell both online and offline.
Core Philosophy
Omnichannel by default
Square's strength is unifying online and in-person payments. Inventory, orders, customers, and catalog sync across channels. If your business has both a website and a physical presence, Square eliminates the integration gap.
Catalog-driven commerce
Square's Catalog API manages products, variations, pricing, and inventory. Orders reference catalog items, creating a consistent product model across online checkout, POS terminals, and invoices.
Web Payments SDK for custom checkout
Square's Web Payments SDK provides embeddable payment form components (card, Apple Pay, Google Pay, ACH) with full PCI compliance handled by Square's tokenization.
Setup
Install
npm install square
Initialize
import { Client, Environment } from 'square';
const client = new Client({
accessToken: process.env.SQUARE_ACCESS_TOKEN,
environment: process.env.NODE_ENV === 'production'
? Environment.Production
: Environment.Sandbox,
});
Key Techniques
Web Payments SDK (card form)
<script src="https://sandbox.web.squarecdn.com/v1/square.js"></script>
<div id="card-container"></div>
<button id="pay-button">Pay $29.00</button>
<script>
const payments = Square.payments('sandbox-sq0idb-xxx', 'location-id');
const card = await payments.card();
await card.attach('#card-container');
document.getElementById('pay-button').onclick = async () => {
const result = await card.tokenize();
if (result.status === 'OK') {
const res = await fetch('/api/square/create-payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sourceId: result.token, amount: 2900 }),
});
}
};
</script>
Create payment (server-side)
const { result } = await client.paymentsApi.createPayment({
sourceId: tokenFromClient,
idempotencyKey: crypto.randomUUID(),
amountMoney: {
amount: BigInt(2900), // $29.00 in cents
currency: 'USD',
},
locationId: process.env.SQUARE_LOCATION_ID,
referenceId: userId,
note: 'Pro Plan - Monthly',
});
const paymentId = result.payment.id;
Subscriptions
// Create subscription plan (catalog)
const { result: plan } = await client.catalogApi.upsertCatalogObject({
idempotencyKey: crypto.randomUUID(),
object: {
type: 'SUBSCRIPTION_PLAN',
id: '#pro-monthly',
subscriptionPlanData: {
name: 'Pro Monthly',
phases: [{
cadence: 'MONTHLY',
recurringPriceMoney: { amount: BigInt(2900), currency: 'USD' },
}],
},
},
});
// Create subscription
const { result: sub } = await client.subscriptionsApi.createSubscription({
idempotencyKey: crypto.randomUUID(),
locationId: process.env.SQUARE_LOCATION_ID,
planVariationId: planVariationId,
customerId: squareCustomerId,
cardId: cardId,
});
// Cancel subscription
await client.subscriptionsApi.cancelSubscription(subscriptionId);
Customer management
// Create customer
const { result } = await client.customersApi.createCustomer({
emailAddress: 'user@example.com',
givenName: 'Alice',
referenceId: userId,
});
// Store card on file
const { result: card } = await client.cardsApi.createCard({
idempotencyKey: crypto.randomUUID(),
sourceId: tokenFromClient,
card: { customerId: result.customer.id },
});
Invoices
const { result: invoice } = await client.invoicesApi.createInvoice({
invoice: {
locationId: process.env.SQUARE_LOCATION_ID,
orderId: orderId,
primaryRecipient: { customerId: squareCustomerId },
paymentRequests: [{
requestType: 'BALANCE',
dueDate: '2025-04-01',
automaticPaymentSource: 'CARD_ON_FILE',
}],
deliveryMethod: 'EMAIL',
},
idempotencyKey: crypto.randomUUID(),
});
await client.invoicesApi.publishInvoice(invoice.invoice.id, {
version: invoice.invoice.version,
});
Webhook Processing
| Event | Action |
|---|---|
payment.completed | Grant access |
payment.failed | Notify user |
subscription.created | Set up subscription |
subscription.updated | Update status |
invoice.payment_made | Mark invoice paid |
refund.created | Adjust access |
import crypto from 'crypto';
export async function POST(req: Request) {
const body = await req.text();
const signature = req.headers.get('x-square-hmacsha256-signature');
const url = 'https://yourdomain.com/api/webhooks/square';
const hmac = crypto.createHmac('sha256', process.env.SQUARE_WEBHOOK_SIGNATURE_KEY)
.update(url + body)
.digest('base64');
if (hmac !== signature) {
return new Response('Invalid signature', { status: 401 });
}
const event = JSON.parse(body);
switch (event.type) {
case 'payment.completed':
await grantAccess(event.data.object.payment.reference_id);
break;
}
return new Response('OK');
}
Best Practices
- Use idempotency keys on all mutating API calls — Square requires them
- Use the Web Payments SDK for PCI-compliant card tokenization
- Store Square customer IDs alongside your user records
- Use the Catalog API for product management — syncs across channels
- Test in sandbox with Square's test credentials
- Use reference_id on payments to link to your users
Anti-Patterns
- Processing payments without idempotency keys — causes duplicates
- Building custom card forms instead of using Web Payments SDK
- Not verifying webhook signatures
- Hardcoding amounts instead of referencing catalog items
- Not handling refund webhooks
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
Checkout Com
Accept payments with Checkout.com. Use this skill when the project needs to
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