Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Master Stripe payment processing integration for robust, PCI-compliant payment flows including checkout, subscriptions, webhooks, and refunds.
.claude/skills/lingxling-stripe-integration/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✓→✗ | ▼ Worse | 148% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 69% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 93% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 177% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 493% | 0% |
Master Stripe payment processing integration for robust, PCI-compliant payment flows including checkout, subscriptions, webhooks, and refunds.
resources/implementation-playbook.md.Checkout Session (Hosted)
Payment Intents (Custom UI)
Setup Intents (Save Payment Methods)
Critical Events:
payment_intent.succeeded: Payment completedpayment_intent.payment_failed: Payment failedcustomer.subscription.updated: Subscription changedcustomer.subscription.deleted: Subscription canceledcharge.refunded: Refund processedinvoice.payment_succeeded: Subscription payment successfulComponents:
pythonimport stripe stripe.api_key = "sk_test_..." # Create a checkout session session = stripe.checkout.Session.create( payment_method_types=['card'], line_items=[{ 'price_data': { 'currency': 'usd', 'product_data': { 'name': 'Premium Subscription', }, 'unit_amount': 2000, # $20.00 'recurring': { 'interval': 'month', }, }, 'quantity': 1, }], mode='subscription', success_url='https://yourdomain.com/success?session_id={CHECKOUT_SESSION_ID}', cancel_url='https://yourdomain.com/cancel', ) # Redirect user to session.url print(session.url)
pythondef create_checkout_session(amount, currency='usd'): """Create a one-time payment checkout session.""" try: session = stripe.checkout.Session.create( payment_method_types=['card'], line_items=[{ 'price_data': { 'currency': currency, 'product_data': { 'name': 'Purchase', 'images': ['https://example.com/product.jpg'], }, 'unit_amount': amount, # Amount in cents }, 'quantity': 1, }], mode='payment', success_url='https://yourdomain.com/success?session_id={CHECKOUT_SESSION_ID}', cancel_url='https://yourdomain.com/cancel', metadata={ 'order_id': 'order_123', 'user_id': 'user_456' } ) return session except stripe.error.StripeError as e: # Handle error print(f"Stripe error: {e.user_message}") raise
pythondef create_payment_intent(amount, currency='usd', customer_id=None): """Create a payment intent for custom checkout UI.""" intent = stripe.PaymentIntent.create( amount=amount, currency=currency, customer=customer_id, automatic_payment_methods={ 'enabled': True, }, metadata={ 'integration_check': 'accept_a_payment' } ) return intent.client_secret # Send to frontend # Frontend (JavaScript) """ const stripe = Stripe('pk_test_...'); const elements = stripe.elements(); const cardElement = elements.create('card'); cardElement.mount('#card-element'); const {error, paymentIntent} = await stripe.confirmCardPayment( clientSecret, { payment_method: { card: cardElement, billing_details: { name: 'Customer Name' } } } ); if (error) { // Handle error } else if (paymentIntent.status === 'succeeded') { // Payment successful } """
pythondef create_subscription(customer_id, price_id): """Create a subscription for a customer.""" try: subscription = stripe.Subscription.create( customer=customer_id, items=[{'price': price_id}], payment_behavior='default_incomplete', payment_settings={'save_default_payment_method': 'on_subscription'}, expand=['latest_invoice.payment_intent'], ) return { 'subscription_id': subscription.id, 'client_secret': subscription.latest_invoice.payment_intent.client_secret } except stripe.error.StripeError as e: print(f"Subscription creation failed: {e}") raise
pythondef create_customer_portal_session(customer_id): """Create a portal session for customers to manage subscriptions.""" session = stripe.billing_portal.Session.create( customer=customer_id, return_url='https://yourdomain.com/account', ) return session.url # Redirect customer here
pythonfrom flask import Flask, request import stripe app = Flask(__name__) endpoint_secret = 'whsec_...' @app.route('/webhook', methods=['POST']) def webhook(): payload = request.data sig_header = request.headers.get('Stripe-Signature') try: event = stripe.Webhook.construct_event( payload, sig_header, endpoint_secret ) except ValueError: # Invalid payload return 'Invalid payload', 400 except stripe.error.SignatureVerificationError: # Invalid signature return 'Invalid signature', 400 # Handle the event if event['type'] == 'payment_intent.succeeded': payment_intent = event['data']['object'] handle_successful_payment(payment_intent) elif event['type'] == 'payment_intent.payment_failed': payment_intent = event['data']['object'] handle_failed_payment(payment_intent) elif event['type'] == 'customer.subscription.deleted': subscription = event['data']['object'] handle_subscription_canceled(subscription) return 'Success', 200 def handle_successful_payment(payment_intent): """Process successful payment.""" customer_id = payment_intent.get('customer') amount = payment_intent['amount'] metadata = payment_intent.get('metadata', {}) # Update your database # Send confirmation email # Fulfill order print(f"Payment succeeded: {payment_intent['id']}") def handle_failed_payment(payment_intent): """Handle failed payment.""" error = payment_intent.get('last_payment_error', {}) print(f"Payment failed: {error.get('message')}") # Notify customer # Update order status def handle_subscription_canceled(subscription): """Handle subscription cancellation.""" customer_id = subscription['customer'] # Update user access # Send cancellation email print(f"Subscription canceled: {subscription['id']}")
pythonimport hashlib import hmac def verify_webhook_signature(payload, signature, secret): """Manually verify webhook signature.""" expected_sig = hmac.new( secret.encode('utf-8'), payload, hashlib.sha256 ).hexdigest() return hmac.compare_digest(signature, expected_sig) def handle_webhook_idempotently(event_id, handler): """Ensure webhook is processed exactly once.""" # Check if event already processed if is_event_processed(event_id): return # Process event try: handler() mark_event_processed(event_id) except Exception as e: log_error(e) # Stripe will retry failed webhooks raise
pythondef create_customer(email, name, payment_method_id=None): """Create a Stripe customer.""" customer = stripe.Customer.create( email=email, name=name, payment_method=payment_method_id, invoice_settings={ 'default_payment_method': payment_method_id } if payment_method_id else None, metadata={ 'user_id': '12345' } ) return customer def attach_payment_method(customer_id, payment_method_id): """Attach a payment method to a customer.""" stripe.PaymentMethod.attach( payment_method_id, customer=customer_id ) # Set as default stripe.Customer.modify( customer_id, invoice_settings={ 'default_payment_method': payment_method_id } ) def list_customer_payment_methods(customer_id): """List all payment methods for a customer.""" payment_methods = stripe.PaymentMethod.list( customer=customer_id, type='card' ) return payment_methods.data
pythondef create_refund(payment_intent_id, amount=None, reason=None): """Create a refund.""" refund_params = { 'payment_intent': payment_intent_id } if amount: refund_params['amount'] = amount # Partial refund if reason: refund_params['reason'] = reason # 'duplicate', 'fraudulent', 'requested_by_customer' refund = stripe.Refund.create(**refund_params) return refund def handle_dispute(charge_id, evidence): """Update dispute with evidence.""" stripe.Dispute.modify( charge_id, evidence={ 'customer_name': evidence.get('customer_name'), 'customer_email_address': evidence.get('customer_email'), 'shipping_documentation': evidence.get('shipping_proof'), 'customer_communication': evidence.get('communication'), } )
python# Use test mode keys stripe.api_key = "sk_test_..." # Test card numbers TEST_CARDS = { 'success': '4242424242424242', 'declined': '4000000000000002', '3d_secure': '4000002500003155', 'insufficient_funds': '4000000000009995' } def test_payment_flow(): """Test complete payment flow.""" # Create test customer customer = stripe.Customer.create( email="test@example.com" ) # Create payment intent intent = stripe.PaymentIntent.create( amount=1000, currency='usd', customer=customer.id, payment_method_types=['card'] ) # Confirm with test card confirmed = stripe.PaymentIntent.confirm( intent.id, payment_method='pm_card_visa' # Test payment method ) assert confirmed.status == 'succeeded'
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 27,630 | 28,230 | +2% | 1 | 1 | 0% | 3,899 | 6,578 | +69% | 0 | 0 | — |
case-02 | pass→fail | 30,061 | 19,858 | -34% | 1 | 1 | 0% | 2,907 | 7,214 | +148% | 0 | 0 | — |
case-03 | pass→pass | 25,704 | 21,556 | -16% | 1 | 1 | 0% | 3,680 | 7,088 | +93% | 0 | 0 | — |
case-04 | pass→pass | 10,709 | 9,974 | -7% | 1 | 1 | 0% | 1,825 | 5,058 | +177% | 0 | 0 | — |
case-05 | pass→pass | 3,610 | 5,514 | +53% | 1 | 1 | 0% | 698 | 4,140 | +493% | 0 | 0 | — |
case-06 | pass→pass | 5,523 | 5,325 | -4% | 1 | 1 | 0% | 761 | 3,997 | +425% | 0 | 0 | — |
case-07 | pass→pass | 3,387 | 4,357 | +29% | 1 | 1 | 0% | 609 | 4,207 | +591% | 0 | 0 | — |
case-08 | pass→pass | 106,872 | 6,306 | -94% | 1 | 1 | 0% | 823 | 4,161 | +406% | 0 | 0 | — |
case-09 | pass→pass | 4,892 | 4,350 | -11% | 1 | 1 | 0% | 837 | 4,051 | +384% | 0 | 0 | — |
case-10 | pass→pass | 11,923 | 6,520 | -45% | 1 | 1 | 0% | 1,913 | 4,553 | +138% | 0 | 0 | — |
case-11 | pass→pass | 6,675 | 4,120 | -38% | 1 | 1 | 0% | 971 | 4,223 | +335% | 0 | 0 | — |
case-12 | pass→pass | 6,232 | 3,898 | -37% | 1 | 1 | 0% | 962 | 4,117 | +328% | 0 | 0 | — |
case-13 | pass→pass | 7,556 | 6,957 | -8% | 1 | 1 | 0% | 1,285 | 4,417 | +244% | 0 | 0 | — |
case-14 | pass→pass | 12,829 | 5,680 | -56% | 1 | 1 | 0% | 1,854 | 4,360 | +135% | 0 | 0 | — |
case-15 | pass→pass | 5,235 | 5,462 | +4% | 1 | 1 | 0% | 773 | 4,085 | +428% | 0 | 0 | — |
case-16 | pass→pass | 4,660 | 7,804 | +67% | 1 | 1 | 0% | 623 | 4,539 | +629% | 0 | 0 | — |
case-17 | pass→pass | 15,919 | 19,804 | +24% | 1 | 1 | 0% | 2,791 | 6,273 | +125% | 0 | 0 | — |
case-18 | pass→pass | 7,862 | 4,684 | -40% | 1 | 1 | 0% | 718 | 3,975 | +454% | 0 | 0 | — |
case-19 | pass→pass | 4,316 | 4,911 | +14% | 1 | 1 | 0% | 766 | 4,162 | +443% | 0 | 0 | — |
case-20 | pass→pass | 4,169 | 4,096 | -2% | 1 | 1 | 0% | 779 | 3,918 | +403% | 0 | 0 | — |
case-21 | pass→pass | 11,174 | 7,687 | -31% | 1 | 1 | 0% | 1,408 | 4,613 | +228% | 0 | 0 | — |
case-22 | pass→pass | 10,289 | 6,482 | -37% | 1 | 1 | 0% | 1,299 | 4,128 | +218% | 0 | 0 | — |
case-23 | pass→pass | 4,822 | 3,379 | -30% | 1 | 1 | 0% | 755 | 3,923 | +420% | 0 | 0 | — |
case-24 | pass→pass | 17,720 | 12,846 | -28% | 1 | 1 | 0% | 1,717 | 5,644 | +229% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 24 cases were attempted. The headline lift of -100 percentage points is the difference between those two pass rates over the 24 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Other measured skills in the registry, with their headline benchmark lift.