[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-2fe2d48d-5b56-41c5-a5db-5d4cbc71aa25":3,"$fnVXObXlBOynF3FZGcSG6M80xuAFTt5cwbjyYvzus09o":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"2fe2d48d-5b56-41c5-a5db-5d4cbc71aa25","paypal-integration","精通PayPal支付集成，包括快速结账、IPN处理、周期性收费和退款流程。","cat_life_career","mod_other","sickn33,other","---\nname: paypal-integration\ndescription: \"Master PayPal payment integration including Express Checkout, IPN handling, recurring billing, and refund workflows.\"\nrisk: unknown\nsource: community\ndate_added: \"2026-02-27\"\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\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,197,1000,"2026-05-16 13:33:26",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"其他","other","mdi-page-next-outline","其他类型Skill",5,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"职场发展","career","mdi-briefcase-outline","面试准备、简历优化、职业规划",4,575,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"a02bc8e3-61b8-43f2-a78f-e1b8b6a50dfc","1.0.0","paypal-integration.zip",4693,"uploads\u002Fskills\u002F2fe2d48d-5b56-41c5-a5db-5d4cbc71aa25\u002Fpaypal-integration.zip","2aad628eb989d89169b584a904e3b664f9ef95c616801e9df083c21701ddf93c","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":14214}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]