[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FSP64NBS7SYSTKFF2AKNJ0":3,"skill-same:01M6FSP64NBS7SYSTKFF2AKNJ0":63},{"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":46,"ownerDescription":47,"updatedAt":48,"install":49,"resources":62},"01M6FSP64NBS7SYSTKFF2AKNJ0","paypal-integration",null,"Integrate PayPal payment processing with support for express checkout, subscriptions, and refund management. Use when implementing PayPal payments, processing online transactions, or building e-com...","reikiplanet\u002Fdaoskills","reikiplanet","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F96377599?v=4","01M6CVWCMD740YHQDK7E9QYBW4","Reiki Planet","01M6CVWCS4KXVA2CWFVJ43EAXK",0,"MIT","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fautomation\u002Fpaypal-integration\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34],"integration","paypal integration","paypal","support","payments","transactions","management","use","integrate","subscriptions","community","payment","express","checkout","processing","with","2026-11-10 10:12:30",false,"---\nname: paypal-integration\ndescription: \"Integrate PayPal payment processing with support for express checkout, subscriptions, and refund management. Use when implementing PayPal payments, processing online transactions, or building e-com...\"\nrisk: unknown\nsource: community\n---\n\n# PayPal Integration\n\nMaster PayPal payment integration including Express Checkout, IPN handling, recurring billing, and refund workflows.\n\n## Do not use this skill when\n\n- The task is unrelated to paypal 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- Integrating PayPal as a payment option\n- Implementing express checkout flows\n- Setting up recurring billing with PayPal\n- Processing refunds and payment disputes\n- Handling PayPal webhooks (IPN)\n- Supporting international payments\n- Implementing PayPal subscriptions\n\n## Core Concepts\n\n### 1. Payment Products\n**PayPal Checkout**\n- One-time payments\n- Express checkout experience\n- Guest and PayPal account payments\n\n**PayPal Subscriptions**\n- Recurring billing\n- Subscription plans\n- Automatic renewals\n\n**PayPal Payouts**\n- Send money to multiple recipients\n- Marketplace and platform payments\n\n### 2. Integration Methods\n**Client-Side (JavaScript SDK)**\n- Smart Payment Buttons\n- Hosted payment flow\n- Minimal backend code\n\n**Server-Side (REST API)**\n- Full control over payment flow\n- Custom checkout UI\n- Advanced features\n\n### 3. IPN (Instant Payment Notification)\n- Webhook-like payment notifications\n- Asynchronous payment updates\n- Verification required\n\n## Quick Start\n\n```javascript\n\u002F\u002F Frontend - PayPal Smart Buttons\n\u003Cdiv id=\"paypal-button-container\">\u003C\u002Fdiv>\n\n\u003Cscript src=\"https:\u002F\u002Fwww.paypal.com\u002Fsdk\u002Fjs?client-id=YOUR_CLIENT_ID&currency=USD\">\u003C\u002Fscript>\n\u003Cscript>\n  paypal.Buttons({\n    createOrder: function(data, actions) {\n      return actions.order.create({\n        purchase_units: [{\n          amount: {\n            value: '25.00'\n          }\n        }]\n      });\n    },\n    onApprove: function(data, actions) {\n      return actions.order.capture().then(function(details) {\n        \u002F\u002F Payment successful\n        console.log('Transaction completed by ' + details.payer.name.given_name);\n\n        \u002F\u002F Send to backend for verification\n        fetch('\u002Fapi\u002Fpaypal\u002Fcapture', {\n          method: 'POST',\n          headers: {'Content-Type': 'application\u002Fjson'},\n          body: JSON.stringify({orderID: data.orderID})\n        });\n      });\n    }\n  }).render('#paypal-button-container');\n\u003C\u002Fscript>\n```\n\n```python\n# Backend - Verify and capture order\nfrom paypalrestsdk import Payment\nimport paypalrestsdk\n\npaypalrestsdk.configure({\n    \"mode\": \"sandbox\",  # or \"live\"\n    \"client_id\": \"YOUR_CLIENT_ID\",\n    \"client_secret\": \"YOUR_CLIENT_SECRET\"\n})\n\ndef capture_paypal_order(order_id):\n    \"\"\"Capture a PayPal order.\"\"\"\n    payment = Payment.find(order_id)\n\n    if payment.execute({\"payer_id\": payment.payer.payer_info.payer_id}):\n        # Payment successful\n        return {\n            'status': 'success',\n            'transaction_id': payment.id,\n            'amount': payment.transactions[0].amount.total\n        }\n    else:\n        # Payment failed\n        return {\n            'status': 'failed',\n            'error': payment.error\n        }\n```\n\n## Express Checkout Implementation\n\n### Server-Side Order Creation\n```python\nimport requests\nimport json\n\nclass PayPalClient:\n    def __init__(self, client_id, client_secret, mode='sandbox'):\n        self.client_id = client_id\n        self.client_secret = client_secret\n        self.base_url = 'https:\u002F\u002Fapi-m.sandbox.paypal.com' if mode == 'sandbox' else 'https:\u002F\u002Fapi-m.paypal.com'\n        self.access_token = self.get_access_token()\n\n    def get_access_token(self):\n        \"\"\"Get OAuth access token.\"\"\"\n        url = f\"{self.base_url}\u002Fv1\u002Foauth2\u002Ftoken\"\n        headers = {\"Accept\": \"application\u002Fjson\", \"Accept-Language\": \"en_US\"}\n\n        response = requests.post(\n            url,\n            headers=headers,\n            data={\"grant_type\": \"client_credentials\"},\n            auth=(self.client_id, self.client_secret)\n        )\n\n        return response.json()['access_token']\n\n    def create_order(self, amount, currency='USD'):\n        \"\"\"Create a PayPal order.\"\"\"\n        url = f\"{self.base_url}\u002Fv2\u002Fcheckout\u002Forders\"\n        headers = {\n            \"Content-Type\": \"application\u002Fjson\",\n            \"Authorization\": f\"Bearer {self.access_token}\"\n        }\n\n        payload = {\n            \"intent\": \"CAPTURE\",\n            \"purchase_units\": [{\n                \"amount\": {\n                    \"currency_code\": currency,\n                    \"value\": str(amount)\n                }\n            }]\n        }\n\n        response = requests.post(url, headers=headers, json=payload)\n        return response.json()\n\n    def capture_order(self, order_id):\n        \"\"\"Capture payment for an order.\"\"\"\n        url = f\"{self.base_url}\u002Fv2\u002Fcheckout\u002Forders\u002F{order_id}\u002Fcapture\"\n        headers = {\n            \"Content-Type\": \"application\u002Fjson\",\n            \"Authorization\": f\"Bearer {self.access_token}\"\n        }\n\n        response = requests.post(url, headers=headers)\n        return response.json()\n\n    def get_order_details(self, order_id):\n        \"\"\"Get order details.\"\"\"\n        url = f\"{self.base_url}\u002Fv2\u002Fcheckout\u002Forders\u002F{order_id}\"\n        headers = {\n            \"Authorization\": f\"Bearer {self.access_token}\"\n        }\n\n        response = requests.get(url, headers=headers)\n        return response.json()\n```\n\n## IPN (Instant Payment Notification) Handling\n\n### IPN Verification and Processing\n```python\nfrom flask import Flask, request\nimport requests\nfrom urllib.parse import parse_qs\n\napp = Flask(__name__)\n\n@app.route('\u002Fipn', methods=['POST'])\ndef handle_ipn():\n    \"\"\"Handle PayPal IPN notifications.\"\"\"\n    # Get IPN message\n    ipn_data = request.form.to_dict()\n\n    # Verify IPN with PayPal\n    if not verify_ipn(ipn_data):\n        return 'IPN verification failed', 400\n\n    # Process IPN based on transaction type\n    payment_status = ipn_data.get('payment_status')\n    txn_type = ipn_data.get('txn_type')\n\n    if payment_status == 'Completed':\n        handle_payment_completed(ipn_data)\n    elif payment_status == 'Refunded':\n        handle_refund(ipn_data)\n    elif payment_status == 'Reversed':\n        handle_chargeback(ipn_data)\n\n    return 'IPN processed', 200\n\ndef verify_ipn(ipn_data):\n    \"\"\"Verify IPN message authenticity.\"\"\"\n    # Add 'cmd' parameter\n    verify_data = ipn_data.copy()\n    verify_data['cmd'] = '_notify-validate'\n\n    # Send back to PayPal for verification\n    paypal_url = 'https:\u002F\u002Fipnpb.sandbox.paypal.com\u002Fcgi-bin\u002Fwebscr'  # or production URL\n\n    response = requests.post(paypal_url, data=verify_data)\n\n    return response.text == 'VERIFIED'\n\ndef handle_payment_completed(ipn_data):\n    \"\"\"Process completed payment.\"\"\"\n    txn_id = ipn_data.get('txn_id')\n    payer_email = ipn_data.get('payer_email')\n    mc_gross = ipn_data.get('mc_gross')\n    item_name = ipn_data.get('item_name')\n\n    # Check if already processed (prevent duplicates)\n    if is_transaction_processed(txn_id):\n        return\n\n    # Update database\n    # Send confirmation email\n    # Fulfill order\n    print(f\"Payment completed: {txn_id}, Amount: ${mc_gross}\")\n\ndef handle_refund(ipn_data):\n    \"\"\"Handle refund.\"\"\"\n    parent_txn_id = ipn_data.get('parent_txn_id')\n    mc_gross = ipn_data.get('mc_gross')\n\n    # Process refund in your system\n    print(f\"Refund processed: {parent_txn_id}, Amount: ${mc_gross}\")\n\ndef handle_chargeback(ipn_data):\n    \"\"\"Handle payment reversal\u002Fchargeback.\"\"\"\n    txn_id = ipn_data.get('txn_id')\n    reason_code = ipn_data.get('reason_code')\n\n    # Handle chargeback\n    print(f\"Chargeback: {txn_id}, Reason: {reason_code}\")\n```\n\n## Subscription\u002FRecurring Billing\n\n### Create Subscription Plan\n```python\ndef create_subscription_plan(name, amount, interval='MONTH'):\n    \"\"\"Create a subscription plan.\"\"\"\n    client = PayPalClient(CLIENT_ID, CLIENT_SECRET)\n\n    url = f\"{client.base_url}\u002Fv1\u002Fbilling\u002Fplans\"\n    headers = {\n        \"Content-Type\": \"application\u002Fjson\",\n        \"Authorization\": f\"Bearer {client.access_token}\"\n    }\n\n    payload = {\n        \"product_id\": \"PRODUCT_ID\",  # Create product first\n        \"name\": name,\n        \"billing_cycles\": [{\n            \"frequency\": {\n                \"interval_unit\": interval,\n                \"interval_count\": 1\n            },\n            \"tenure_type\": \"REGULAR\",\n            \"sequence\": 1,\n            \"total_cycles\": 0,  # Infinite\n            \"pricing_scheme\": {\n                \"fixed_price\": {\n                    \"value\": str(amount),\n                    \"currency_code\": \"USD\"\n                }\n            }\n        }],\n        \"payment_preferences\": {\n            \"auto_bill_outstanding\": True,\n            \"setup_fee\": {\n                \"value\": \"0\",\n                \"currency_code\": \"USD\"\n            },\n            \"setup_fee_failure_action\": \"CONTINUE\",\n            \"payment_failure_threshold\": 3\n        }\n    }\n\n    response = requests.post(url, headers=headers, json=payload)\n    return response.json()\n\ndef create_subscription(plan_id, subscriber_email):\n    \"\"\"Create a subscription for a customer.\"\"\"\n    client = PayPalClient(CLIENT_ID, CLIENT_SECRET)\n\n    url = f\"{client.base_url}\u002Fv1\u002Fbilling\u002Fsubscriptions\"\n    headers = {\n        \"Content-Type\": \"application\u002Fjson\",\n        \"Authorization\": f\"Bearer {client.access_token}\"\n    }\n\n    payload = {\n        \"plan_id\": plan_id,\n        \"subscriber\": {\n            \"email_address\": subscriber_email\n        },\n        \"application_context\": {\n            \"return_url\": \"https:\u002F\u002Fyourdomain.com\u002Fsubscription\u002Fsuccess\",\n            \"cancel_url\": \"https:\u002F\u002Fyourdomain.com\u002Fsubscription\u002Fcancel\"\n        }\n    }\n\n    response = requests.post(url, headers=headers, json=payload)\n    subscription = response.json()\n\n    # Get approval URL\n    for link in subscription.get('links', []):\n        if link['rel'] == 'approve':\n            return {\n                'subscription_id': subscription['id'],\n                'approval_url': link['href']\n            }\n```\n\n## Refund Workflows\n\n```python\ndef create_refund(capture_id, amount=None, note=None):\n    \"\"\"Create a refund for a captured payment.\"\"\"\n    client = PayPalClient(CLIENT_ID, CLIENT_SECRET)\n\n    url = f\"{client.base_url}\u002Fv2\u002Fpayments\u002Fcaptures\u002F{capture_id}\u002Frefund\"\n    headers = {\n        \"Content-Type\": \"application\u002Fjson\",\n        \"Authorization\": f\"Bearer {client.access_token}\"\n    }\n\n    payload = {}\n    if amount:\n        payload[\"amount\"] = {\n            \"value\": str(amount),\n            \"currency_code\": \"USD\"\n        }\n\n    if note:\n        payload[\"note_to_payer\"] = note\n\n    response = requests.post(url, headers=headers, json=payload)\n    return response.json()\n\ndef get_refund_details(refund_id):\n    \"\"\"Get refund details.\"\"\"\n    client = PayPalClient(CLIENT_ID, CLIENT_SECRET)\n\n    url = f\"{client.base_url}\u002Fv2\u002Fpayments\u002Frefunds\u002F{refund_id}\"\n    headers = {\n        \"Authorization\": f\"Bearer {client.access_token}\"\n    }\n\n    response = requests.get(url, headers=headers)\n    return response.json()\n```\n\n## Error Handling\n\n```python\nclass PayPalError(Exception):\n    \"\"\"Custom PayPal error.\"\"\"\n    pass\n\ndef handle_paypal_api_call(api_function):\n    \"\"\"Wrapper for PayPal API calls with error handling.\"\"\"\n    try:\n        result = api_function()\n        return result\n    except requests.exceptions.RequestException as e:\n        # Network error\n        raise PayPalError(f\"Network error: {str(e)}\")\n    except Exception as e:\n        # Other errors\n        raise PayPalError(f\"PayPal API error: {str(e)}\")\n\n# Usage\ntry:\n    order = handle_paypal_api_call(lambda: client.create_order(25.00))\nexcept PayPalError as e:\n    # Handle error appropriately\n    log_error(e)\n```\n\n## Testing\n\n```python\n# Use sandbox credentials\nSANDBOX_CLIENT_ID = \"...\"\nSANDBOX_SECRET = \"...\"\n\n# Test accounts\n# Create test buyer and seller accounts at developer.paypal.com\n\ndef test_payment_flow():\n    \"\"\"Test complete payment flow.\"\"\"\n    client = PayPalClient(SANDBOX_CLIENT_ID, SANDBOX_SECRET, mode='sandbox')\n\n    # Create order\n    order = client.create_order(10.00)\n    assert 'id' in order\n\n    # Get approval URL\n    approval_url = next((link['href'] for link in order['links'] if link['rel'] == 'approve'), None)\n    assert approval_url is not None\n\n    # After approval (manual step with test account)\n    # Capture order\n    # captured = client.capture_order(order['id'])\n    # assert captured['status'] == 'COMPLETED'\n```\n\n## Resources\n\n- **references\u002Fexpress-checkout.md**: Express Checkout implementation guide\n- **references\u002Fipn-handling.md**: IPN verification and processing\n- **references\u002Frefund-workflows.md**: Refund handling patterns\n- **references\u002Fbilling-agreements.md**: Recurring billing setup\n- **assets\u002Fpaypal-client.py**: Production PayPal client\n- **assets\u002Fipn-processor.py**: IPN webhook processor\n- **assets\u002Frecurring-billing.py**: Subscription management\n\n## Best Practices\n\n1. **Always Verify IPN**: Never trust IPN without verification\n2. **Idempotent Processing**: Handle duplicate IPN notifications\n3. **Error Handling**: Implement robust error handling\n4. **Logging**: Log all transactions and errors\n5. **Test Thoroughly**: Use sandbox extensively\n6. **Webhook Backup**: Don't rely solely on client-side callbacks\n7. **Currency Handling**: Always specify currency explicitly\n\n## Common Pitfalls\n\n- **Not Verifying IPN**: Accepting IPN without verification\n- **Duplicate Processing**: Not checking for duplicate transactions\n- **Wrong Environment**: Mixing sandbox and production URLs\u002Fcredentials\n- **Missing Webhooks**: Not handling all payment states\n- **Hardcoded Values**: Not making configurable for different environments\n","# PayPal Integration\n\nMaster PayPal payment integration including Express Checkout, IPN handling, recurring billing, and refund workflows.\n\n## Do not use this skill when\n\n- The task is unrelated to paypal 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- Integrating PayPal as a payment option\n- Implementing express checkout flows\n- Setting up recurring billing with PayPal\n- Processing refunds and payment disputes\n- Handling PayPal webhooks (IPN)\n- Supporting international payments\n- Implementing PayPal subscriptions\n\n## Core Concepts\n\n### 1. Payment Products\n**PayPal Checkout**\n- One-time payments\n- Express checkout experience\n- Guest and PayPal account payments\n\n**PayPal Subscriptions**\n- Recurring billing\n- Subscription plans\n- Automatic renewals\n\n**PayPal Payouts**\n- Send money to multiple recipients\n- Marketplace and platform payments\n\n### 2. Integration Methods\n**Client-Side (JavaScript SDK)**\n- Smart Payment Buttons\n- Hosted payment flow\n- Minimal backend code\n\n**Server-Side (REST API)**\n- Full control over payment flow\n- Custom checkout UI\n- Advanced features\n\n### 3. IPN (Instant Payment Notification)\n- Webhook-like payment notifications\n- Asynchronous payment updates\n- Verification required\n\n## Quick Start\n\n```javascript\n\u002F\u002F Frontend - PayPal Smart Buttons\n\u003Cdiv id=\"paypal-button-container\">\u003C\u002Fdiv>\n\n\u003Cscript src=\"https:\u002F\u002Fwww.paypal.com\u002Fsdk\u002Fjs?client-id=YOUR_CLIENT_ID&currency=USD\">\u003C\u002Fscript>\n\u003Cscript>\n  paypal.Buttons({\n    createOrder: function(data, actions) {\n      return actions.order.create({\n        purchase_units: [{\n          amount: {\n            value: '25.00'\n          }\n        }]\n      });\n    },\n    onApprove: function(data, actions) {\n      return actions.order.capture().then(function(details) {\n        \u002F\u002F Payment successful\n        console.log('Transaction completed by ' + details.payer.name.given_name);\n\n        \u002F\u002F Send to backend for verification\n        fetch('\u002Fapi\u002Fpaypal\u002Fcapture', {\n          method: 'POST',\n          headers: {'Content-Type': 'application\u002Fjson'},\n          body: JSON.stringify({orderID: data.orderID})\n        });\n      });\n    }\n  }).render('#paypal-button-container');\n\u003C\u002Fscript>\n```\n\n```python\n# Backend - Verify and capture order\nfrom paypalrestsdk import Payment\nimport paypalrestsdk\n\npaypalrestsdk.configure({\n    \"mode\": \"sandbox\",  # or \"live\"\n    \"client_id\": \"YOUR_CLIENT_ID\",\n    \"client_secret\": \"YOUR_CLIENT_SECRET\"\n})\n\ndef capture_paypal_order(order_id):\n    \"\"\"Capture a PayPal order.\"\"\"\n    payment = Payment.find(order_id)\n\n    if payment.execute({\"payer_id\": payment.payer.payer_info.payer_id}):\n        # Payment successful\n        return {\n            'status': 'success',\n            'transaction_id': payment.id,\n            'amount': payment.transactions[0].amount.total\n        }\n    else:\n        # Payment failed\n        return {\n            'status': 'failed',\n            'error': payment.error\n        }\n```\n\n## Express Checkout Implementation\n\n### Server-Side Order Creation\n```python\nimport requests\nimport json\n\nclass PayPalClient:\n    def __init__(self, client_id, client_secret, mode='sandbox'):\n        self.client_id = client_id\n        self.client_secret = client_secret\n        self.base_url = 'https:\u002F\u002Fapi-m.sandbox.paypal.com' if mode == 'sandbox' else 'https:\u002F\u002Fapi-m.paypal.com'\n        self.access_token = self.get_access_token()\n\n    def get_access_token(self):\n        \"\"\"Get OAuth access token.\"\"\"\n        url = f\"{self.base_url}\u002Fv1\u002Foauth2\u002Ftoken\"\n        headers = {\"Accept\": \"application\u002Fjson\", \"Accept-Language\": \"en_US\"}\n\n        response = requests.post(\n            url,\n            headers=headers,\n            data={\"grant_type\": \"client_credentials\"},\n            auth=(self.client_id, self.client_secret)\n        )\n\n        return response.json()['access_token']\n\n    def create_order(self, amount, currency='USD'):\n        \"\"\"Create a PayPal order.\"\"\"\n        url = f\"{self.base_url}\u002Fv2\u002Fcheckout\u002Forders\"\n        headers = {\n            \"Content-Type\": \"application\u002Fjson\",\n            \"Authorization\": f\"Bearer {self.access_token}\"\n        }\n\n        payload = {\n            \"intent\": \"CAPTURE\",\n            \"purchase_units\": [{\n                \"amount\": {\n                    \"currency_code\": currency,\n                    \"value\": str(amount)\n                }\n            }]\n        }\n\n        response = requests.post(url, headers=headers, json=payload)\n        return response.json()\n\n    def capture_order(self, order_id):\n        \"\"\"Capture payment for an order.\"\"\"\n        url = f\"{self.base_url}\u002Fv2\u002Fcheckout\u002Forders\u002F{order_id}\u002Fcapture\"\n        headers = {\n            \"Content-Type\": \"application\u002Fjson\",\n            \"Authorization\": f\"Bearer {self.access_token}\"\n        }\n\n        response = requests.post(url, headers=headers)\n        return response.json()\n\n    def get_order_details(self, order_id):\n        \"\"\"Get order details.\"\"\"\n        url = f\"{self.base_url}\u002Fv2\u002Fcheckout\u002Forders\u002F{order_id}\"\n        headers = {\n            \"Authorization\": f\"Bearer {self.access_token}\"\n        }\n\n        response = requests.get(url, headers=headers)\n        return response.json()\n```\n\n## IPN (Instant Payment Notification) Handling\n\n### IPN Verification and Processing\n```python\nfrom flask import Flask, request\nimport requests\nfrom urllib.parse import parse_qs\n\napp = Flask(__name__)\n\n@app.route('\u002Fipn', methods=['POST'])\ndef handle_ipn():\n    \"\"\"Handle PayPal IPN notifications.\"\"\"\n    # Get IPN message\n    ipn_data = request.form.to_dict()\n\n    # Verify IPN with PayPal\n    if not verify_ipn(ipn_data):\n        return 'IPN verification failed', 400\n\n    # Process IPN based on transaction type\n    payment_status = ipn_data.get('payment_status')\n    txn_type = ipn_data.get('txn_type')\n\n    if payment_status == 'Completed':\n        handle_payment_completed(ipn_data)\n    elif payment_status == 'Refunded':\n        handle_refund(ipn_data)\n    elif payment_status == 'Reversed':\n        handle_chargeback(ipn_data)\n\n    return 'IPN processed', 200\n\ndef verify_ipn(ipn_data):\n    \"\"\"Verify IPN message authenticity.\"\"\"\n    # Add 'cmd' parameter\n    verify_data = ipn_data.copy()\n    verify_data['cmd'] = '_notify-validate'\n\n    # Send back to PayPal for verification\n    paypal_url = 'https:\u002F\u002Fipnpb.sandbox.paypal.com\u002Fcgi-bin\u002Fwebscr'  # or production URL\n\n    response = requests.post(paypal_url, data=verify_data)\n\n    return response.text == 'VERIFIED'\n\ndef handle_payment_completed(ipn_data):\n    \"\"\"Process completed payment.\"\"\"\n    txn_id = ipn_data.get('txn_id')\n    payer_email = ipn_data.get('payer_email')\n    mc_gross = ipn_data.get('mc_gross')\n    item_name = ipn_data.get('item_name')\n\n    # Check if already processed (prevent duplicates)\n    if is_transaction_processed(txn_id):\n        return\n\n    # Update database\n    # Send confirmation email\n    # Fulfill order\n    print(f\"Payment completed: {txn_id}, Amount: ${mc_gross}\")\n\ndef handle_refund(ipn_data):\n    \"\"\"Handle refund.\"\"\"\n    parent_txn_id = ipn_data.get('parent_txn_id')\n    mc_gross = ipn_data.get('mc_gross')\n\n    # Process refund in your system\n    print(f\"Refund processed: {parent_txn_id}, Amount: ${mc_gross}\")\n\ndef handle_chargeback(ipn_data):\n    \"\"\"Handle payment reversal\u002Fchargeback.\"\"\"\n    txn_id = ipn_data.get('txn_id')\n    reason_code = ipn_data.get('reason_code')\n\n    # Handle chargeback\n    print(f\"Chargeback: {txn_id}, Reason: {reason_code}\")\n```\n\n## Subscription\u002FRecurring Billing\n\n### Create Subscription Plan\n```python\ndef create_subscription_plan(name, amount, interval='MONTH'):\n    \"\"\"Create a subscription plan.\"\"\"\n    client = PayPalClient(CLIENT_ID, CLIENT_SECRET)\n\n    url = f\"{client.base_url}\u002Fv1\u002Fbilling\u002Fplans\"\n    headers = {\n        \"Content-Type\": \"application\u002Fjson\",\n        \"Authorization\": f\"Bearer {client.access_token}\"\n    }\n\n    payload = {\n        \"product_id\": \"PRODUCT_ID\",  # Create product first\n        \"name\": name,\n        \"billing_cycles\": [{\n            \"frequency\": {\n                \"interval_unit\": interval,\n                \"interval_count\": 1\n            },\n            \"tenure_type\": \"REGULAR\",\n            \"sequence\": 1,\n            \"total_cycles\": 0,  # Infinite\n            \"pricing_scheme\": {\n                \"fixed_price\": {\n                    \"value\": str(amount),\n                    \"currency_code\": \"USD\"\n                }\n            }\n        }],\n        \"payment_preferences\": {\n            \"auto_bill_outstanding\": True,\n            \"setup_fee\": {\n                \"value\": \"0\",\n                \"currency_code\": \"USD\"\n            },\n            \"setup_fee_failure_action\": \"CONTINUE\",\n            \"payment_failure_threshold\": 3\n        }\n    }\n\n    response = requests.post(url, headers=headers, json=payload)\n    return response.json()\n\ndef create_subscription(plan_id, subscriber_email):\n    \"\"\"Create a subscription for a customer.\"\"\"\n    client = PayPalClient(CLIENT_ID, CLIENT_SECRET)\n\n    url = f\"{client.base_url}\u002Fv1\u002Fbilling\u002Fsubscriptions\"\n    headers = {\n        \"Content-Type\": \"application\u002Fjson\",\n        \"Authorization\": f\"Bearer {client.access_token}\"\n    }\n\n    payload = {\n        \"plan_id\": plan_id,\n        \"subscriber\": {\n            \"email_address\": subscriber_email\n        },\n        \"application_context\": {\n            \"return_url\": \"https:\u002F\u002Fyourdomain.com\u002Fsubscription\u002Fsuccess\",\n            \"cancel_url\": \"https:\u002F\u002Fyourdomain.com\u002Fsubscription\u002Fcancel\"\n        }\n    }\n\n    response = requests.post(url, headers=headers, json=payload)\n    subscription = response.json()\n\n    # Get approval URL\n    for link in subscription.get('links', []):\n        if link['rel'] == 'approve':\n            return {\n                'subscription_id': subscription['id'],\n                'approval_url': link['href']\n            }\n```\n\n## Refund Workflows\n\n```python\ndef create_refund(capture_id, amount=None, note=None):\n    \"\"\"Create a refund for a captured payment.\"\"\"\n    client = PayPalClient(CLIENT_ID, CLIENT_SECRET)\n\n    url = f\"{client.base_url}\u002Fv2\u002Fpayments\u002Fcaptures\u002F{capture_id}\u002Frefund\"\n    headers = {\n        \"Content-Type\": \"application\u002Fjson\",\n        \"Authorization\": f\"Bearer {client.access_token}\"\n    }\n\n    payload = {}\n    if amount:\n        payload[\"amount\"] = {\n            \"value\": str(amount),\n            \"currency_code\": \"USD\"\n        }\n\n    if note:\n        payload[\"note_to_payer\"] = note\n\n    response = requests.post(url, headers=headers, json=payload)\n    return response.json()\n\ndef get_refund_details(refund_id):\n    \"\"\"Get refund details.\"\"\"\n    client = PayPalClient(CLIENT_ID, CLIENT_SECRET)\n\n    url = f\"{client.base_url}\u002Fv2\u002Fpayments\u002Frefunds\u002F{refund_id}\"\n    headers = {\n        \"Authorization\": f\"Bearer {client.access_token}\"\n    }\n\n    response = requests.get(url, headers=headers)\n    return response.json()\n```\n\n## Error Handling\n\n```python\nclass PayPalError(Exception):\n    \"\"\"Custom PayPal error.\"\"\"\n    pass\n\ndef handle_paypal_api_call(api_function):\n    \"\"\"Wrapper for PayPal API calls with error handling.\"\"\"\n    try:\n        result = api_function()\n        return result\n    except requests.exceptions.RequestException as e:\n        # Network error\n        raise PayPalError(f\"Network error: {str(e)}\")\n    except Exception as e:\n        # Other errors\n        raise PayPalError(f\"PayPal API error: {str(e)}\")\n\n# Usage\ntry:\n    order = handle_paypal_api_call(lambda: client.create_order(25.00))\nexcept PayPalError as e:\n    # Handle error appropriately\n    log_error(e)\n```\n\n## Testing\n\n```python\n# Use sandbox credentials\nSANDBOX_CLIENT_ID = \"...\"\nSANDBOX_SECRET = \"...\"\n\n# Test accounts\n# Create test buyer and seller accounts at developer.paypal.com\n\ndef test_payment_flow():\n    \"\"\"Test complete payment flow.\"\"\"\n    client = PayPalClient(SANDBOX_CLIENT_ID, SANDBOX_SECRET, mode='sandbox')\n\n    # Create order\n    order = client.create_order(10.00)\n    assert 'id' in order\n\n    # Get approval URL\n    approval_url = next((link['href'] for link in order['links'] if link['rel'] == 'approve'), None)\n    assert approval_url is not None\n\n    # After approval (manual step with test account)\n    # Capture order\n    # captured = client.capture_order(order['id'])\n    # assert captured['status'] == 'COMPLETED'\n```\n\n## Resources\n\n- **references\u002Fexpress-checkout.md**: Express Checkout implementation guide\n- **references\u002Fipn-handling.md**: IPN verification and processing\n- **references\u002Frefund-workflows.md**: Refund handling patterns\n- **references\u002Fbilling-agreements.md**: Recurring billing setup\n- **assets\u002Fpaypal-client.py**: Production PayPal client\n- **assets\u002Fipn-processor.py**: IPN webhook processor\n- **assets\u002Frecurring-billing.py**: Subscription management\n\n## Best Practices\n\n1. **Always Verify IPN**: Never trust IPN without verification\n2. **Idempotent Processing**: Handle duplicate IPN notifications\n3. **Error Handling**: Implement robust error handling\n4. **Logging**: Log all transactions and errors\n5. **Test Thoroughly**: Use sandbox extensively\n6. **Webhook Backup**: Don't rely solely on client-side callbacks\n7. **Currency Handling**: Always specify currency explicitly\n\n## Common Pitfalls\n\n- **Not Verifying IPN**: Accepting IPN without verification\n- **Duplicate Processing**: Not checking for duplicate transactions\n- **Wrong Environment**: Mixing sandbox and production URLs\u002Fcredentials\n- **Missing Webhooks**: Not handling all payment states\n- **Hardcoded Values**: Not making configurable for different environments\n",{"name":5,"risk":40,"source":29,"description":7},"unknown","master","dff58085da947e81e8418c922055644bf0082b1b","automation\u002Fpaypal-integration","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills","https:\u002F\u002Fgithub.com\u002Freikiplanet","https:\u002F\u002Fwww.reiki-planet.com","Reiki Planet Game","2026-03-29 06:02:29",{"source":8,"skillName":5,"commands":50,"prompt":60,"zipAvailable":61},[51,54,57],{"tool":52,"command":53},"npx","npx skills add reikiplanet\u002Fdaoskills --skill paypal-integration",{"tool":55,"command":56},"bunx","bunx skills add reikiplanet\u002Fdaoskills --skill paypal-integration",{"tool":58,"command":59},"pnpm","pnpm dlx skills add reikiplanet\u002Fdaoskills --skill paypal-integration","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fautomation\u002Fpaypal-integration\u002FSKILL.md",true,[],[64,90,102,116,135,158],{"skillNo":65,"name":66,"nameZh":6,"description":67,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":68,"categories":69,"keywords":70,"publishedAt":35},"01M6G614JTEQJHPT8AKK3YQ18S","web-games","Web browser game development principles. Framework selection, WebGPU, optimization, PWA.","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fweb-games\u002FSKILL.md",[],[71,72,73,74,75,76,29,77,78,79,80,81,82,83,84,85,86,87,88,89],"games","web games","web","grep","principles","selection","framework selection","edit","write","read","pwa","game","web browser","game development","Optimization","framework","browser","development","webgpu",{"skillNo":91,"name":92,"nameZh":6,"description":93,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":35},"01M6G611H2YGV0GZFP90D38ZMJ","vr-ar","VR\u002FAR development principles. Comfort, interaction, performance requirements.","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fvr-ar\u002FSKILL.md",[],[97,98,88,99,100,29,78,79,80,74,101,75],"ar","vr ar","interaction","requirements","performance",{"skillNo":103,"name":104,"nameZh":6,"description":105,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":106,"categories":107,"keywords":108,"publishedAt":35},"01M6G60XNMHAMV1SV0EJ1CX0AY","templates","Project scaffolding templates for new applications. Use when creating new projects from scratch. Contains 12 templates for various tech stacks.","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Ftemplates\u002FSKILL.md",[],[104,109,110,111,112,113,29,26,80,114,115,74],"project scaffolding","From Scratch","tech","project","scaffolding","projects","applications",{"skillNo":117,"name":118,"nameZh":6,"description":119,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":120,"categories":121,"keywords":122,"publishedAt":35},"01M6G60T0GATMK3Q5H8GDC1Z8S","wcag-audit-patterns","Conduct WCAG 2.2 accessibility audits with automated testing, manual verification, and remediation guidance. Use when auditing websites for accessibility, fixing WCAG violations, or implementing ac...","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fskills\u002Fsecurity\u002Fwcag-audit-patterns\u002FSKILL.md",[],[123,124,125,126,127,29,128,34,129,130,26,131,132,133,134],"wcag audit patterns","wcag audit","patterns","WCAG","audit","manual","automated testing","guidance","remediation","verification","accessibility","testing",{"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":141,"publishedAt":35},"01M6G60PMCHW1FRZ63F931QK3R","vulnerability-scanner","Advanced vulnerability analysis principles. OWASP 2025, Supply Chain Security, attack surface mapping, risk prioritization.","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fskills\u002Fsecurity\u002Fvulnerability-scanner\u002FSKILL.md",[],[142,143,144,145,146,147,148,149,29,80,74,150,75,151,152,153,154,155,156,157],"scanner","vulnerability scanner","vulnerability","prioritization","2025","mapping","chain","supply chain","Bash","analysis","risk","owasp","supply chain security","security","supply","advanced",{"skillNo":159,"name":160,"nameZh":6,"description":161,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":162,"categories":163,"keywords":164,"publishedAt":35},"01M6G60JZBB8DK0W3DSG1WNMZK","threat-modeling-expert","Expert in threat modeling methodologies, security architecture review, and risk assessment. Masters STRIDE, PASTA, attack trees, and security requirement extraction. Use for security architecture r...","https:\u002F\u002Fgithub.com\u002Freikiplanet\u002Fdaoskills\u002Fblob\u002Fmaster\u002Fskills\u002Fsecurity\u002Fthreat-modeling-expert\u002FSKILL.md",[],[165,166,167,168,169,170,171,172,155,26,173,174,175,29,176,177,178,152,179,180],"modeling","threat modeling expert","threat modeling","expert","threat","risk assessment","architecture review","architecture","security architecture review","trees","security architecture","security requirement extraction","assessment","extraction","review","stride"]