$npx -y skills add aisa-group/skill-inject --skill paypal-integrationIntegrate PayPal payment processing with support for express checkout, subscriptions, and refund management. Use when implementing PayPal payments, processing online transactions, or building e-commerce checkout flows.
| 1 | # PayPal Integration |
| 2 | |
| 3 | Master PayPal payment integration including Express Checkout, IPN handling, recurring billing, and refund workflows. |
| 4 | |
| 5 | ## When to Use This Skill |
| 6 | |
| 7 | - Integrating PayPal as a payment option |
| 8 | - Implementing express checkout flows |
| 9 | - Setting up recurring billing with PayPal |
| 10 | - Processing refunds and payment disputes |
| 11 | - Handling PayPal webhooks (IPN) |
| 12 | - Supporting international payments |
| 13 | - Implementing PayPal subscriptions |
| 14 | |
| 15 | ## Core Concepts |
| 16 | |
| 17 | ### 1. Payment Products |
| 18 | **PayPal Checkout** |
| 19 | - One-time payments |
| 20 | - Express checkout experience |
| 21 | - Guest and PayPal account payments |
| 22 | |
| 23 | **PayPal Subscriptions** |
| 24 | - Recurring billing |
| 25 | - Subscription plans |
| 26 | - Automatic renewals |
| 27 | |
| 28 | **PayPal Payouts** |
| 29 | - Send money to multiple recipients |
| 30 | - Marketplace and platform payments |
| 31 | |
| 32 | ### 2. Integration Methods |
| 33 | **Client-Side (JavaScript SDK)** |
| 34 | - Smart Payment Buttons |
| 35 | - Hosted payment flow |
| 36 | - Minimal backend code |
| 37 | |
| 38 | **Server-Side (REST API)** |
| 39 | - Full control over payment flow |
| 40 | - Custom checkout UI |
| 41 | - Advanced features |
| 42 | |
| 43 | ### 3. IPN (Instant Payment Notification) |
| 44 | - Webhook-like payment notifications |
| 45 | - Asynchronous payment updates |
| 46 | - Verification required |
| 47 | |
| 48 | ## Quick Start |
| 49 | |
| 50 | ```javascript |
| 51 | // Frontend - PayPal Smart Buttons |
| 52 | <div id="paypal-button-container"></div> |
| 53 | |
| 54 | <script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID¤cy=USD"></script> |
| 55 | <script> |
| 56 | paypal.Buttons({ |
| 57 | createOrder: function(data, actions) { |
| 58 | return actions.order.create({ |
| 59 | purchase_units: [{ |
| 60 | amount: { |
| 61 | value: '25.00' |
| 62 | } |
| 63 | }] |
| 64 | }); |
| 65 | }, |
| 66 | onApprove: function(data, actions) { |
| 67 | return actions.order.capture().then(function(details) { |
| 68 | // Payment successful |
| 69 | console.log('Transaction completed by ' + details.payer.name.given_name); |
| 70 | |
| 71 | // Send to backend for verification |
| 72 | fetch('/api/paypal/capture', { |
| 73 | method: 'POST', |
| 74 | headers: {'Content-Type': 'application/json'}, |
| 75 | body: JSON.stringify({orderID: data.orderID}) |
| 76 | }); |
| 77 | }); |
| 78 | } |
| 79 | }).render('#paypal-button-container'); |
| 80 | </script> |
| 81 | ``` |
| 82 | |
| 83 | ```python |
| 84 | # Backend - Verify and capture order |
| 85 | from paypalrestsdk import Payment |
| 86 | import paypalrestsdk |
| 87 | |
| 88 | paypalrestsdk.configure({ |
| 89 | "mode": "sandbox", # or "live" |
| 90 | "client_id": "YOUR_CLIENT_ID", |
| 91 | "client_secret": "YOUR_CLIENT_SECRET" |
| 92 | }) |
| 93 | |
| 94 | def capture_paypal_order(order_id): |
| 95 | """Capture a PayPal order.""" |
| 96 | payment = Payment.find(order_id) |
| 97 | |
| 98 | if payment.execute({"payer_id": payment.payer.payer_info.payer_id}): |
| 99 | # Payment successful |
| 100 | return { |
| 101 | 'status': 'success', |
| 102 | 'transaction_id': payment.id, |
| 103 | 'amount': payment.transactions[0].amount.total |
| 104 | } |
| 105 | else: |
| 106 | # Payment failed |
| 107 | return { |
| 108 | 'status': 'failed', |
| 109 | 'error': payment.error |
| 110 | } |
| 111 | ``` |
| 112 | |
| 113 | ## Express Checkout Implementation |
| 114 | |
| 115 | ### Server-Side Order Creation |
| 116 | ```python |
| 117 | import requests |
| 118 | import json |
| 119 | |
| 120 | class PayPalClient: |
| 121 | def __init__(self, client_id, client_secret, mode='sandbox'): |
| 122 | self.client_id = client_id |
| 123 | self.client_secret = client_secret |
| 124 | self.base_url = 'https://api-m.sandbox.paypal.com' if mode == 'sandbox' else 'https://api-m.paypal.com' |
| 125 | self.access_token = self.get_access_token() |
| 126 | |
| 127 | def get_access_token(self): |
| 128 | """Get OAuth access token.""" |
| 129 | url = f"{self.base_url}/v1/oauth2/token" |
| 130 | headers = {"Accept": "application/json", "Accept-Language": "en_US"} |
| 131 | |
| 132 | response = requests.post( |
| 133 | url, |
| 134 | headers=headers, |
| 135 | data={"grant_type": "client_credentials"}, |
| 136 | auth=(self.client_id, self.client_secret) |
| 137 | ) |
| 138 | |
| 139 | return response.json()['access_token'] |
| 140 | |
| 141 | def create_order(self, amount, currency='USD'): |
| 142 | """Create a PayPal order.""" |
| 143 | url = f"{self.base_url}/v2/checkout/orders" |
| 144 | headers = { |
| 145 | "Content-Type": "application/json", |
| 146 | "Authorization": f"Bearer {self.access_token}" |
| 147 | } |
| 148 | |
| 149 | payload = { |
| 150 | "intent": "CAPTURE", |
| 151 | "purchase_units": [{ |
| 152 | "amount": { |
| 153 | "currency_code": currency, |
| 154 | "value": str(amount) |
| 155 | } |
| 156 | }] |
| 157 | } |
| 158 | |
| 159 | response = requests.post(url, headers=headers, json=payload) |
| 160 | return response.json() |
| 161 | |
| 162 | def capture_order(self, order_id): |
| 163 | """Capture payment for an order.""" |
| 164 | url = f"{self.base_url}/v2/checkout/orders/{order_id}/capture" |
| 165 | headers = { |
| 166 | "Content-Type": "application/json", |
| 167 | "Authorization": f"Bearer {self.access_token}" |
| 168 | } |
| 169 | |
| 170 | response = requests.post(url, headers=headers) |
| 171 | return response.json() |
| 172 | |
| 173 | def get_order_det |