payments
SKILL.md
Payments Expert - Stripe, PayPal, Connect
Comprehensive payment processing expertise for Stripe, PayPal, and marketplace payments.
Stripe Checkout (Quick Start)
import stripe
session = stripe.checkout.Session.create(
payment_method_types=['card'],
line_items=[{
'price_data': {
'currency': 'usd',
'product_data': {'name': 'Premium'},
'unit_amount': 2000, # $20.00
},
'quantity': 1,
}],
mode='payment', # or 'subscription'
success_url='https://example.com/success?session_id={CHECKOUT_SESSION_ID}',
cancel_url='https://example.com/cancel',
)
# Redirect to session.url
Webhook Handling
@app.route('/webhook', methods=['POST'])
def webhook():
event = stripe.Webhook.construct_event(
request.data,
request.headers.get('Stripe-Signature'),
webhook_secret
)
if event['type'] == 'checkout.session.completed':
session = event['data']['object']
await confirm_payment(session.id)
return 'Success', 200
Critical Events
| Event | Use Case |
|---|---|
checkout.session.completed |
Payment successful |
payment_intent.payment_failed |
Payment failed |
customer.subscription.updated |
Subscription changed |
account.updated |
Connect account status |
Stripe Connect (Marketplaces)
Charge Types
| Type | Who Creates | Webhook Location |
|---|---|---|
| Direct | Connected Account | Connect endpoint |
| Destination | Platform | Platform endpoint |
Direct Charge Webhook Setup
# /webhooks/stripe/connect - CRITICAL for Direct Charge!
@app.route('/webhooks/stripe/connect', methods=['POST'])
def connect_webhook():
event = stripe.webhooks.constructEvent(
request.data, sig, connect_webhook_secret
)
if event['type'] == 'checkout.session.completed':
# Direct Charge sessions complete here!
await handle_connect_checkout(event.data.object)
Critical Patterns
Dual Confirmation (Webhook + Frontend)
// Both webhook and frontend call this - idempotent!
async function confirmPayment(sessionId: string) {
const result = await db.update(orders)
.set({ status: 'paid' })
.where(and(
eq(orders.stripeSessionId, sessionId),
eq(orders.status, 'pending') // Only if pending!
));
if (result.changes === 0) return false; // Already processed
await decrementInventory(sessionId);
return true;
}
100% Promo Code Detection
# ✅ CORRECT - amount_total=0 + payment_status='paid'
def is_100_percent_promo(session):
return (
session.payment_status == 'paid' and
session.amount_total == 0 and
session.payment_intent is None
)
# ❌ WRONG - no_payment_required is different!
Web vs Native Browser Handling
// WebBrowser result types differ by platform!
switch (result.type) {
case 'dismiss': // Native: browser closed - NOW verify
await verifyPayment(sessionId);
break;
case 'opened': // Web: user still on Stripe page - DON'T verify yet!
Alert.alert('Complete payment in browser');
break;
}
Subscriptions
subscription = stripe.Subscription.create(
customer=customer_id,
items=[{'price': price_id}],
payment_behavior='default_incomplete',
expand=['latest_invoice.payment_intent'],
)
PayPal Integration
// PayPal SDK
paypal.Buttons({
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [{ amount: { value: '20.00' } }]
});
},
onApprove: async (data, actions) => {
const order = await actions.order.capture();
await verifyPayment(order.id);
}
}).render('#paypal-button');
Testing
TEST_CARDS = {
'success': '4242424242424242',
'declined': '4000000000000002',
'3d_secure': '4000002500003155',
}
Best Practices
- Always use webhooks - Don't rely on frontend only
- Idempotency - Handle duplicate events
- Verify signatures - Always validate webhooks
- Never store raw card data - Use Stripe Elements
- Implement SCA - 3D Secure for Europe
Related Skills
billing- Subscription managementcompliance- PCI compliance
Weekly Installs
2
Repository
anton-abyzov/specweaveGitHub Stars
82
First Seen
Feb 3, 2026
Installed on
opencode2
codex2
claude-code2
replit1
openclaw1
cursor1