[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M714QQRPJSPFSJ5B01WY0DEV":3,"skill-same:01M714QQRPJSPFSJ5B01WY0DEV":61},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":35,"linkOnly":36,"markdownContent":37,"markdownBody":38,"frontMatter":39,"refName":41,"commitSha":42,"skillDirectory":43,"forksCount":14,"repositoryHtmlUrl":44,"repositoryHomepageUrl":6,"ownerHtmlUrl":45,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":46,"install":47,"resources":60},"01M714QQRPJSPFSJ5B01WY0DEV","stripe-integration",null,"Master Stripe payment processing integration for robust, PCI-compliant payment flows including checkout, subscriptions, webhooks, and refunds.","sapsapshen\u002Fai-memory-router","sapsapshen","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F20347959?v=4","01M6XDQEF1DP50DKF37H81J3J5","shenmian","01M6XDQEJPE41Y3DT2763X8ZJN",0,"MIT","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fcopilot\u002Fstripe-integration\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34],"integration","stripe integration","stripe","refunds","webhooks","master","subscriptions","community","payment","checkout","processing","flows","for","unknown","pci","2026","2026-11-10 10:12:30",false,"---\nname: stripe-integration\ndescription: \"Master Stripe payment processing integration for robust, PCI-compliant payment flows including checkout, subscriptions, webhooks, and refunds.\"\nrisk: unknown\nsource: community\ndate_added: \"2026-02-27\"\n---\n\n# Stripe Integration\n\nMaster Stripe payment processing integration for robust, PCI-compliant payment flows including checkout, subscriptions, webhooks, and refunds.\n\n## Do not use this skill when\n\n- The task is unrelated to stripe integration\n- You need a different domain or tool outside this scope\n\n## Instructions\n\n- Clarify goals, constraints, and required inputs.\n- Apply relevant best practices and validate outcomes.\n- Provide actionable steps and verification.\n- If detailed examples are required, open `resources\u002Fimplementation-playbook.md`.\n\n## Use this skill when\n\n- Implementing payment processing in web\u002Fmobile applications\n- Setting up subscription billing systems\n- Handling one-time payments and recurring charges\n- Processing refunds and disputes\n- Managing customer payment methods\n- Implementing SCA (Strong Customer Authentication) for European payments\n- Building marketplace payment flows with Stripe Connect\n\n## Core Concepts\n\n### 1. Payment Flows\n**Checkout Session (Hosted)**\n- Stripe-hosted payment page\n- Minimal PCI compliance burden\n- Fastest implementation\n- Supports one-time and recurring payments\n\n**Payment Intents (Custom UI)**\n- Full control over payment UI\n- Requires Stripe.js for PCI compliance\n- More complex implementation\n- Better customization options\n\n**Setup Intents (Save Payment Methods)**\n- Collect payment method without charging\n- Used for subscriptions and future payments\n- Requires customer confirmation\n\n### 2. Webhooks\n**Critical Events:**\n- `payment_intent.succeeded`: Payment completed\n- `payment_intent.payment_failed`: Payment failed\n- `customer.subscription.updated`: Subscription changed\n- `customer.subscription.deleted`: Subscription canceled\n- `charge.refunded`: Refund processed\n- `invoice.payment_succeeded`: Subscription payment successful\n\n### 3. Subscriptions\n**Components:**\n- **Product**: What you're selling\n- **Price**: How much and how often\n- **Subscription**: Customer's recurring payment\n- **Invoice**: Generated for each billing cycle\n\n### 4. Customer Management\n- Create and manage customer records\n- Store multiple payment methods\n- Track customer metadata\n- Manage billing details\n\n## Quick Start\n\n```python\nimport stripe\n\nstripe.api_key = \"sk_test_...\"\n\n# Create a checkout session\nsession = stripe.checkout.Session.create(\n    payment_method_types=['card'],\n    line_items=[{\n        'price_data': {\n            'currency': 'usd',\n            'product_data': {\n                'name': 'Premium Subscription',\n            },\n            'unit_amount': 2000,  # $20.00\n            'recurring': {\n                'interval': 'month',\n            },\n        },\n        'quantity': 1,\n    }],\n    mode='subscription',\n    success_url='https:\u002F\u002Fyourdomain.com\u002Fsuccess?session_id={CHECKOUT_SESSION_ID}',\n    cancel_url='https:\u002F\u002Fyourdomain.com\u002Fcancel',\n)\n\n# Redirect user to session.url\nprint(session.url)\n```\n\n## Payment Implementation Patterns\n\n### Pattern 1: One-Time Payment (Hosted Checkout)\n```python\ndef create_checkout_session(amount, currency='usd'):\n    \"\"\"Create a one-time payment checkout session.\"\"\"\n    try:\n        session = stripe.checkout.Session.create(\n            payment_method_types=['card'],\n            line_items=[{\n                'price_data': {\n                    'currency': currency,\n                    'product_data': {\n                        'name': 'Purchase',\n                        'images': ['https:\u002F\u002Fexample.com\u002Fproduct.jpg'],\n                    },\n                    'unit_amount': amount,  # Amount in cents\n                },\n                'quantity': 1,\n            }],\n            mode='payment',\n            success_url='https:\u002F\u002Fyourdomain.com\u002Fsuccess?session_id={CHECKOUT_SESSION_ID}',\n            cancel_url='https:\u002F\u002Fyourdomain.com\u002Fcancel',\n            metadata={\n                'order_id': 'order_123',\n                'user_id': 'user_456'\n            }\n        )\n        return session\n    except stripe.error.StripeError as e:\n        # Handle error\n        print(f\"Stripe error: {e.user_message}\")\n        raise\n```\n\n### Pattern 2: Custom Payment Intent Flow\n```python\ndef create_payment_intent(amount, currency='usd', customer_id=None):\n    \"\"\"Create a payment intent for custom checkout UI.\"\"\"\n    intent = stripe.PaymentIntent.create(\n        amount=amount,\n        currency=currency,\n        customer=customer_id,\n        automatic_payment_methods={\n            'enabled': True,\n        },\n        metadata={\n            'integration_check': 'accept_a_payment'\n        }\n    )\n    return intent.client_secret  # Send to frontend\n\n# Frontend (JavaScript)\n\"\"\"\nconst stripe = Stripe('pk_test_...');\nconst elements = stripe.elements();\nconst cardElement = elements.create('card');\ncardElement.mount('#card-element');\n\nconst {error, paymentIntent} = await stripe.confirmCardPayment(\n    clientSecret,\n    {\n        payment_method: {\n            card: cardElement,\n            billing_details: {\n                name: 'Customer Name'\n            }\n        }\n    }\n);\n\nif (error) {\n    \u002F\u002F Handle error\n} else if (paymentIntent.status === 'succeeded') {\n    \u002F\u002F Payment successful\n}\n\"\"\"\n```\n\n### Pattern 3: Subscription Creation\n```python\ndef create_subscription(customer_id, price_id):\n    \"\"\"Create a subscription for a customer.\"\"\"\n    try:\n        subscription = stripe.Subscription.create(\n            customer=customer_id,\n            items=[{'price': price_id}],\n            payment_behavior='default_incomplete',\n            payment_settings={'save_default_payment_method': 'on_subscription'},\n            expand=['latest_invoice.payment_intent'],\n        )\n\n        return {\n            'subscription_id': subscription.id,\n            'client_secret': subscription.latest_invoice.payment_intent.client_secret\n        }\n    except stripe.error.StripeError as e:\n        print(f\"Subscription creation failed: {e}\")\n        raise\n```\n\n### Pattern 4: Customer Portal\n```python\ndef create_customer_portal_session(customer_id):\n    \"\"\"Create a portal session for customers to manage subscriptions.\"\"\"\n    session = stripe.billing_portal.Session.create(\n        customer=customer_id,\n        return_url='https:\u002F\u002Fyourdomain.com\u002Faccount',\n    )\n    return session.url  # Redirect customer here\n```\n\n## Webhook Handling\n\n### Secure Webhook Endpoint\n```python\nfrom flask import Flask, request\nimport stripe\n\napp = Flask(__name__)\n\nendpoint_secret = 'whsec_...'\n\n@app.route('\u002Fwebhook', methods=['POST'])\ndef webhook():\n    payload = request.data\n    sig_header = request.headers.get('Stripe-Signature')\n\n    try:\n        event = stripe.Webhook.construct_event(\n            payload, sig_header, endpoint_secret\n        )\n    except ValueError:\n        # Invalid payload\n        return 'Invalid payload', 400\n    except stripe.error.SignatureVerificationError:\n        # Invalid signature\n        return 'Invalid signature', 400\n\n    # Handle the event\n    if event['type'] == 'payment_intent.succeeded':\n        payment_intent = event['data']['object']\n        handle_successful_payment(payment_intent)\n    elif event['type'] == 'payment_intent.payment_failed':\n        payment_intent = event['data']['object']\n        handle_failed_payment(payment_intent)\n    elif event['type'] == 'customer.subscription.deleted':\n        subscription = event['data']['object']\n        handle_subscription_canceled(subscription)\n\n    return 'Success', 200\n\ndef handle_successful_payment(payment_intent):\n    \"\"\"Process successful payment.\"\"\"\n    customer_id = payment_intent.get('customer')\n    amount = payment_intent['amount']\n    metadata = payment_intent.get('metadata', {})\n\n    # Update your database\n    # Send confirmation email\n    # Fulfill order\n    print(f\"Payment succeeded: {payment_intent['id']}\")\n\ndef handle_failed_payment(payment_intent):\n    \"\"\"Handle failed payment.\"\"\"\n    error = payment_intent.get('last_payment_error', {})\n    print(f\"Payment failed: {error.get('message')}\")\n    # Notify customer\n    # Update order status\n\ndef handle_subscription_canceled(subscription):\n    \"\"\"Handle subscription cancellation.\"\"\"\n    customer_id = subscription['customer']\n    # Update user access\n    # Send cancellation email\n    print(f\"Subscription canceled: {subscription['id']}\")\n```\n\n### Webhook Best Practices\n```python\nimport hashlib\nimport hmac\n\ndef verify_webhook_signature(payload, signature, secret):\n    \"\"\"Manually verify webhook signature.\"\"\"\n    expected_sig = hmac.new(\n        secret.encode('utf-8'),\n        payload,\n        hashlib.sha256\n    ).hexdigest()\n\n    return hmac.compare_digest(signature, expected_sig)\n\ndef handle_webhook_idempotently(event_id, handler):\n    \"\"\"Ensure webhook is processed exactly once.\"\"\"\n    # Check if event already processed\n    if is_event_processed(event_id):\n        return\n\n    # Process event\n    try:\n        handler()\n        mark_event_processed(event_id)\n    except Exception as e:\n        log_error(e)\n        # Stripe will retry failed webhooks\n        raise\n```\n\n## Customer Management\n\n```python\ndef create_customer(email, name, payment_method_id=None):\n    \"\"\"Create a Stripe customer.\"\"\"\n    customer = stripe.Customer.create(\n        email=email,\n        name=name,\n        payment_method=payment_method_id,\n        invoice_settings={\n            'default_payment_method': payment_method_id\n        } if payment_method_id else None,\n        metadata={\n            'user_id': '12345'\n        }\n    )\n    return customer\n\ndef attach_payment_method(customer_id, payment_method_id):\n    \"\"\"Attach a payment method to a customer.\"\"\"\n    stripe.PaymentMethod.attach(\n        payment_method_id,\n        customer=customer_id\n    )\n\n    # Set as default\n    stripe.Customer.modify(\n        customer_id,\n        invoice_settings={\n            'default_payment_method': payment_method_id\n        }\n    )\n\ndef list_customer_payment_methods(customer_id):\n    \"\"\"List all payment methods for a customer.\"\"\"\n    payment_methods = stripe.PaymentMethod.list(\n        customer=customer_id,\n        type='card'\n    )\n    return payment_methods.data\n```\n\n## Refund Handling\n\n```python\ndef create_refund(payment_intent_id, amount=None, reason=None):\n    \"\"\"Create a refund.\"\"\"\n    refund_params = {\n        'payment_intent': payment_intent_id\n    }\n\n    if amount:\n        refund_params['amount'] = amount  # Partial refund\n\n    if reason:\n        refund_params['reason'] = reason  # 'duplicate', 'fraudulent', 'requested_by_customer'\n\n    refund = stripe.Refund.create(**refund_params)\n    return refund\n\ndef handle_dispute(charge_id, evidence):\n    \"\"\"Update dispute with evidence.\"\"\"\n    stripe.Dispute.modify(\n        charge_id,\n        evidence={\n            'customer_name': evidence.get('customer_name'),\n            'customer_email_address': evidence.get('customer_email'),\n            'shipping_documentation': evidence.get('shipping_proof'),\n            'customer_communication': evidence.get('communication'),\n        }\n    )\n```\n\n## Testing\n\n```python\n# Use test mode keys\nstripe.api_key = \"sk_test_...\"\n\n# Test card numbers\nTEST_CARDS = {\n    'success': '4242424242424242',\n    'declined': '4000000000000002',\n    '3d_secure': '4000002500003155',\n    'insufficient_funds': '4000000000009995'\n}\n\ndef test_payment_flow():\n    \"\"\"Test complete payment flow.\"\"\"\n    # Create test customer\n    customer = stripe.Customer.create(\n        email=\"test@example.com\"\n    )\n\n    # Create payment intent\n    intent = stripe.PaymentIntent.create(\n        amount=1000,\n        currency='usd',\n        customer=customer.id,\n        payment_method_types=['card']\n    )\n\n    # Confirm with test card\n    confirmed = stripe.PaymentIntent.confirm(\n        intent.id,\n        payment_method='pm_card_visa'  # Test payment method\n    )\n\n    assert confirmed.status == 'succeeded'\n```\n\n## Resources\n\n- **references\u002Fcheckout-flows.md**: Detailed checkout implementation\n- **references\u002Fwebhook-handling.md**: Webhook security and processing\n- **references\u002Fsubscription-management.md**: Subscription lifecycle\n- **references\u002Fcustomer-management.md**: Customer and payment method handling\n- **references\u002Finvoice-generation.md**: Invoicing and billing\n- **assets\u002Fstripe-client.py**: Production-ready Stripe client wrapper\n- **assets\u002Fwebhook-handler.py**: Complete webhook processor\n- **assets\u002Fcheckout-config.json**: Checkout configuration templates\n\n## Best Practices\n\n1. **Always Use Webhooks**: Don't rely solely on client-side confirmation\n2. **Idempotency**: Handle webhook events idempotently\n3. **Error Handling**: Gracefully handle all Stripe errors\n4. **Test Mode**: Thoroughly test with test keys before production\n5. **Metadata**: Use metadata to link Stripe objects to your database\n6. **Monitoring**: Track payment success rates and errors\n7. **PCI Compliance**: Never handle raw card data on your server\n8. **SCA Ready**: Implement 3D Secure for European payments\n\n## Common Pitfalls\n\n- **Not Verifying Webhooks**: Always verify webhook signatures\n- **Missing Webhook Events**: Handle all relevant webhook events\n- **Hardcoded Amounts**: Use cents\u002Fsmallest currency unit\n- **No Retry Logic**: Implement retries for API calls\n- **Ignoring Test Mode**: Test all edge cases with test cards\n","# Stripe Integration\n\nMaster Stripe payment processing integration for robust, PCI-compliant payment flows including checkout, subscriptions, webhooks, and refunds.\n\n## Do not use this skill when\n\n- The task is unrelated to stripe integration\n- You need a different domain or tool outside this scope\n\n## Instructions\n\n- Clarify goals, constraints, and required inputs.\n- Apply relevant best practices and validate outcomes.\n- Provide actionable steps and verification.\n- If detailed examples are required, open `resources\u002Fimplementation-playbook.md`.\n\n## Use this skill when\n\n- Implementing payment processing in web\u002Fmobile applications\n- Setting up subscription billing systems\n- Handling one-time payments and recurring charges\n- Processing refunds and disputes\n- Managing customer payment methods\n- Implementing SCA (Strong Customer Authentication) for European payments\n- Building marketplace payment flows with Stripe Connect\n\n## Core Concepts\n\n### 1. Payment Flows\n**Checkout Session (Hosted)**\n- Stripe-hosted payment page\n- Minimal PCI compliance burden\n- Fastest implementation\n- Supports one-time and recurring payments\n\n**Payment Intents (Custom UI)**\n- Full control over payment UI\n- Requires Stripe.js for PCI compliance\n- More complex implementation\n- Better customization options\n\n**Setup Intents (Save Payment Methods)**\n- Collect payment method without charging\n- Used for subscriptions and future payments\n- Requires customer confirmation\n\n### 2. Webhooks\n**Critical Events:**\n- `payment_intent.succeeded`: Payment completed\n- `payment_intent.payment_failed`: Payment failed\n- `customer.subscription.updated`: Subscription changed\n- `customer.subscription.deleted`: Subscription canceled\n- `charge.refunded`: Refund processed\n- `invoice.payment_succeeded`: Subscription payment successful\n\n### 3. Subscriptions\n**Components:**\n- **Product**: What you're selling\n- **Price**: How much and how often\n- **Subscription**: Customer's recurring payment\n- **Invoice**: Generated for each billing cycle\n\n### 4. Customer Management\n- Create and manage customer records\n- Store multiple payment methods\n- Track customer metadata\n- Manage billing details\n\n## Quick Start\n\n```python\nimport stripe\n\nstripe.api_key = \"sk_test_...\"\n\n# Create a checkout session\nsession = stripe.checkout.Session.create(\n    payment_method_types=['card'],\n    line_items=[{\n        'price_data': {\n            'currency': 'usd',\n            'product_data': {\n                'name': 'Premium Subscription',\n            },\n            'unit_amount': 2000,  # $20.00\n            'recurring': {\n                'interval': 'month',\n            },\n        },\n        'quantity': 1,\n    }],\n    mode='subscription',\n    success_url='https:\u002F\u002Fyourdomain.com\u002Fsuccess?session_id={CHECKOUT_SESSION_ID}',\n    cancel_url='https:\u002F\u002Fyourdomain.com\u002Fcancel',\n)\n\n# Redirect user to session.url\nprint(session.url)\n```\n\n## Payment Implementation Patterns\n\n### Pattern 1: One-Time Payment (Hosted Checkout)\n```python\ndef create_checkout_session(amount, currency='usd'):\n    \"\"\"Create a one-time payment checkout session.\"\"\"\n    try:\n        session = stripe.checkout.Session.create(\n            payment_method_types=['card'],\n            line_items=[{\n                'price_data': {\n                    'currency': currency,\n                    'product_data': {\n                        'name': 'Purchase',\n                        'images': ['https:\u002F\u002Fexample.com\u002Fproduct.jpg'],\n                    },\n                    'unit_amount': amount,  # Amount in cents\n                },\n                'quantity': 1,\n            }],\n            mode='payment',\n            success_url='https:\u002F\u002Fyourdomain.com\u002Fsuccess?session_id={CHECKOUT_SESSION_ID}',\n            cancel_url='https:\u002F\u002Fyourdomain.com\u002Fcancel',\n            metadata={\n                'order_id': 'order_123',\n                'user_id': 'user_456'\n            }\n        )\n        return session\n    except stripe.error.StripeError as e:\n        # Handle error\n        print(f\"Stripe error: {e.user_message}\")\n        raise\n```\n\n### Pattern 2: Custom Payment Intent Flow\n```python\ndef create_payment_intent(amount, currency='usd', customer_id=None):\n    \"\"\"Create a payment intent for custom checkout UI.\"\"\"\n    intent = stripe.PaymentIntent.create(\n        amount=amount,\n        currency=currency,\n        customer=customer_id,\n        automatic_payment_methods={\n            'enabled': True,\n        },\n        metadata={\n            'integration_check': 'accept_a_payment'\n        }\n    )\n    return intent.client_secret  # Send to frontend\n\n# Frontend (JavaScript)\n\"\"\"\nconst stripe = Stripe('pk_test_...');\nconst elements = stripe.elements();\nconst cardElement = elements.create('card');\ncardElement.mount('#card-element');\n\nconst {error, paymentIntent} = await stripe.confirmCardPayment(\n    clientSecret,\n    {\n        payment_method: {\n            card: cardElement,\n            billing_details: {\n                name: 'Customer Name'\n            }\n        }\n    }\n);\n\nif (error) {\n    \u002F\u002F Handle error\n} else if (paymentIntent.status === 'succeeded') {\n    \u002F\u002F Payment successful\n}\n\"\"\"\n```\n\n### Pattern 3: Subscription Creation\n```python\ndef create_subscription(customer_id, price_id):\n    \"\"\"Create a subscription for a customer.\"\"\"\n    try:\n        subscription = stripe.Subscription.create(\n            customer=customer_id,\n            items=[{'price': price_id}],\n            payment_behavior='default_incomplete',\n            payment_settings={'save_default_payment_method': 'on_subscription'},\n            expand=['latest_invoice.payment_intent'],\n        )\n\n        return {\n            'subscription_id': subscription.id,\n            'client_secret': subscription.latest_invoice.payment_intent.client_secret\n        }\n    except stripe.error.StripeError as e:\n        print(f\"Subscription creation failed: {e}\")\n        raise\n```\n\n### Pattern 4: Customer Portal\n```python\ndef create_customer_portal_session(customer_id):\n    \"\"\"Create a portal session for customers to manage subscriptions.\"\"\"\n    session = stripe.billing_portal.Session.create(\n        customer=customer_id,\n        return_url='https:\u002F\u002Fyourdomain.com\u002Faccount',\n    )\n    return session.url  # Redirect customer here\n```\n\n## Webhook Handling\n\n### Secure Webhook Endpoint\n```python\nfrom flask import Flask, request\nimport stripe\n\napp = Flask(__name__)\n\nendpoint_secret = 'whsec_...'\n\n@app.route('\u002Fwebhook', methods=['POST'])\ndef webhook():\n    payload = request.data\n    sig_header = request.headers.get('Stripe-Signature')\n\n    try:\n        event = stripe.Webhook.construct_event(\n            payload, sig_header, endpoint_secret\n        )\n    except ValueError:\n        # Invalid payload\n        return 'Invalid payload', 400\n    except stripe.error.SignatureVerificationError:\n        # Invalid signature\n        return 'Invalid signature', 400\n\n    # Handle the event\n    if event['type'] == 'payment_intent.succeeded':\n        payment_intent = event['data']['object']\n        handle_successful_payment(payment_intent)\n    elif event['type'] == 'payment_intent.payment_failed':\n        payment_intent = event['data']['object']\n        handle_failed_payment(payment_intent)\n    elif event['type'] == 'customer.subscription.deleted':\n        subscription = event['data']['object']\n        handle_subscription_canceled(subscription)\n\n    return 'Success', 200\n\ndef handle_successful_payment(payment_intent):\n    \"\"\"Process successful payment.\"\"\"\n    customer_id = payment_intent.get('customer')\n    amount = payment_intent['amount']\n    metadata = payment_intent.get('metadata', {})\n\n    # Update your database\n    # Send confirmation email\n    # Fulfill order\n    print(f\"Payment succeeded: {payment_intent['id']}\")\n\ndef handle_failed_payment(payment_intent):\n    \"\"\"Handle failed payment.\"\"\"\n    error = payment_intent.get('last_payment_error', {})\n    print(f\"Payment failed: {error.get('message')}\")\n    # Notify customer\n    # Update order status\n\ndef handle_subscription_canceled(subscription):\n    \"\"\"Handle subscription cancellation.\"\"\"\n    customer_id = subscription['customer']\n    # Update user access\n    # Send cancellation email\n    print(f\"Subscription canceled: {subscription['id']}\")\n```\n\n### Webhook Best Practices\n```python\nimport hashlib\nimport hmac\n\ndef verify_webhook_signature(payload, signature, secret):\n    \"\"\"Manually verify webhook signature.\"\"\"\n    expected_sig = hmac.new(\n        secret.encode('utf-8'),\n        payload,\n        hashlib.sha256\n    ).hexdigest()\n\n    return hmac.compare_digest(signature, expected_sig)\n\ndef handle_webhook_idempotently(event_id, handler):\n    \"\"\"Ensure webhook is processed exactly once.\"\"\"\n    # Check if event already processed\n    if is_event_processed(event_id):\n        return\n\n    # Process event\n    try:\n        handler()\n        mark_event_processed(event_id)\n    except Exception as e:\n        log_error(e)\n        # Stripe will retry failed webhooks\n        raise\n```\n\n## Customer Management\n\n```python\ndef create_customer(email, name, payment_method_id=None):\n    \"\"\"Create a Stripe customer.\"\"\"\n    customer = stripe.Customer.create(\n        email=email,\n        name=name,\n        payment_method=payment_method_id,\n        invoice_settings={\n            'default_payment_method': payment_method_id\n        } if payment_method_id else None,\n        metadata={\n            'user_id': '12345'\n        }\n    )\n    return customer\n\ndef attach_payment_method(customer_id, payment_method_id):\n    \"\"\"Attach a payment method to a customer.\"\"\"\n    stripe.PaymentMethod.attach(\n        payment_method_id,\n        customer=customer_id\n    )\n\n    # Set as default\n    stripe.Customer.modify(\n        customer_id,\n        invoice_settings={\n            'default_payment_method': payment_method_id\n        }\n    )\n\ndef list_customer_payment_methods(customer_id):\n    \"\"\"List all payment methods for a customer.\"\"\"\n    payment_methods = stripe.PaymentMethod.list(\n        customer=customer_id,\n        type='card'\n    )\n    return payment_methods.data\n```\n\n## Refund Handling\n\n```python\ndef create_refund(payment_intent_id, amount=None, reason=None):\n    \"\"\"Create a refund.\"\"\"\n    refund_params = {\n        'payment_intent': payment_intent_id\n    }\n\n    if amount:\n        refund_params['amount'] = amount  # Partial refund\n\n    if reason:\n        refund_params['reason'] = reason  # 'duplicate', 'fraudulent', 'requested_by_customer'\n\n    refund = stripe.Refund.create(**refund_params)\n    return refund\n\ndef handle_dispute(charge_id, evidence):\n    \"\"\"Update dispute with evidence.\"\"\"\n    stripe.Dispute.modify(\n        charge_id,\n        evidence={\n            'customer_name': evidence.get('customer_name'),\n            'customer_email_address': evidence.get('customer_email'),\n            'shipping_documentation': evidence.get('shipping_proof'),\n            'customer_communication': evidence.get('communication'),\n        }\n    )\n```\n\n## Testing\n\n```python\n# Use test mode keys\nstripe.api_key = \"sk_test_...\"\n\n# Test card numbers\nTEST_CARDS = {\n    'success': '4242424242424242',\n    'declined': '4000000000000002',\n    '3d_secure': '4000002500003155',\n    'insufficient_funds': '4000000000009995'\n}\n\ndef test_payment_flow():\n    \"\"\"Test complete payment flow.\"\"\"\n    # Create test customer\n    customer = stripe.Customer.create(\n        email=\"test@example.com\"\n    )\n\n    # Create payment intent\n    intent = stripe.PaymentIntent.create(\n        amount=1000,\n        currency='usd',\n        customer=customer.id,\n        payment_method_types=['card']\n    )\n\n    # Confirm with test card\n    confirmed = stripe.PaymentIntent.confirm(\n        intent.id,\n        payment_method='pm_card_visa'  # Test payment method\n    )\n\n    assert confirmed.status == 'succeeded'\n```\n\n## Resources\n\n- **references\u002Fcheckout-flows.md**: Detailed checkout implementation\n- **references\u002Fwebhook-handling.md**: Webhook security and processing\n- **references\u002Fsubscription-management.md**: Subscription lifecycle\n- **references\u002Fcustomer-management.md**: Customer and payment method handling\n- **references\u002Finvoice-generation.md**: Invoicing and billing\n- **assets\u002Fstripe-client.py**: Production-ready Stripe client wrapper\n- **assets\u002Fwebhook-handler.py**: Complete webhook processor\n- **assets\u002Fcheckout-config.json**: Checkout configuration templates\n\n## Best Practices\n\n1. **Always Use Webhooks**: Don't rely solely on client-side confirmation\n2. **Idempotency**: Handle webhook events idempotently\n3. **Error Handling**: Gracefully handle all Stripe errors\n4. **Test Mode**: Thoroughly test with test keys before production\n5. **Metadata**: Use metadata to link Stripe objects to your database\n6. **Monitoring**: Track payment success rates and errors\n7. **PCI Compliance**: Never handle raw card data on your server\n8. **SCA Ready**: Implement 3D Secure for European payments\n\n## Common Pitfalls\n\n- **Not Verifying Webhooks**: Always verify webhook signatures\n- **Missing Webhook Events**: Handle all relevant webhook events\n- **Hardcoded Amounts**: Use cents\u002Fsmallest currency unit\n- **No Retry Logic**: Implement retries for API calls\n- **Ignoring Test Mode**: Test all edge cases with test cards\n",{"name":5,"risk":32,"source":26,"date_added":40,"description":7},"2026-02-27","main","7a38d8e7073e61c16eda85681cb32fb68a8657a5","skills-store\u002Fcopilot\u002Fstripe-integration","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router","https:\u002F\u002Fgithub.com\u002Fsapsapshen","2026-04-14 21:12:12",{"source":8,"skillName":5,"commands":48,"prompt":58,"zipAvailable":59},[49,52,55],{"tool":50,"command":51},"npx","npx skills add sapsapshen\u002Fai-memory-router --skill stripe-integration",{"tool":53,"command":54},"bunx","bunx skills add sapsapshen\u002Fai-memory-router --skill stripe-integration",{"tool":56,"command":57},"pnpm","pnpm dlx skills add sapsapshen\u002Fai-memory-router --skill stripe-integration","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fcopilot\u002Fstripe-integration\u002FSKILL.md",true,[],[62,86,112,122,135,154],{"skillNo":63,"name":64,"nameZh":6,"description":65,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":66,"categories":67,"keywords":73,"publishedAt":35},"01M71ATQRKG48SH06FQ697T5G9","wechat-search","Search WeChat Official Account articles using OpenClaw's web search and fetch capabilities with compliance-focused design.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fwechat-search-release\u002FSKILL.md",[68],{"categoryNo":69,"categoryName":70,"taxonomyType":71,"taxonomyTypeDesc":72},"01JBSEEDCAT000000000000037","律师与法务","PROFESSION","适用职业",[74,75,76,77,78,79,80,81,82,83,84,85],"wechat search","wechat","search","capabilities","openclaw","design","web search","compliance","web","official","fetch","with",{"skillNo":87,"name":88,"nameZh":6,"description":89,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":92,"publishedAt":35},"01M71ATNAVGZB35PFYM2GC5N00","trend-tap","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend tap', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-tap\u002FSKILL.md",[],[93,94,95,96,97,98,76,99,100,101,102,103,104,105,106,107,108,109,110,111],"trend","trend tap","tap","api keys","Bash","time","trending","hacker","aggregator","do","when","brew","live","data","google","install","read","across","api",{"skillNo":113,"name":114,"nameZh":6,"description":115,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":118,"publishedAt":35},"01M71ATJ9AM5KM15AA8PS302EB","trend-radar","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend pulse', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-radar\u002FSKILL.md",[],[119,120,93,104,105,106,107,97,76,109,121,110,111,103,101,100,99,108,98,96],"trend radar","radar","pulse",{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":35},"01M71ATGF095N3EJM9G8SD0BB5","tech-news-daily","每日科技新闻汇——从全球多个 RSS 源抓取最新科技新闻，翻译（英→中）、去重、排版成每日简报。当用户询问科技新闻、科技新鲜事、每日科技、技术动态、Daily Tech News 或类似表达时触发此技能。","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftech-news-daily\u002FSKILL.md",[],[129,130,131,132,133,134],"news","tech","tech news daily","daily","rss","翻译",{"skillNo":136,"name":137,"nameZh":6,"description":138,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":139,"categories":140,"keywords":146,"publishedAt":35},"01M71ATFAEAMQ17M70NQNY7SR8","summarize","Summarize URLs or files with the summarize CLI (web, PDFs, images, audio, YouTube).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsummarize\u002FSKILL.md",[141],{"categoryNo":142,"categoryName":143,"taxonomyType":144,"taxonomyTypeDesc":145},"01JBSEEDCAT000000000000021","资料检索与研究","SCENARIO","使用场景",[137,82,147,148,149,85,104,150,151,152,95,153,108],"Audio","cli","youtube","images","https","files","pdfs",{"skillNo":155,"name":156,"nameZh":6,"description":157,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":158,"categories":159,"keywords":160,"publishedAt":35},"01M71ATDNS3R0M4H936PACQAWZ","sonoscli","Control Sonos speakers (discover\u002Fstatus\u002Fplay\u002Fvolume\u002Fgroup).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsonoscli\u002FSKILL.md",[],[156,161,162,163,108,164,151,165,166,167,168,169],"status","play","go","latest","github","discover","control","cmd","volume"]