Claude Agent Skill · by Wshobson

Paypal Integration

A solid PayPal integration guide that covers the essentials without getting lost in the weeds. Walks you through Express Checkout with their JavaScript SDK, ser

Install
Terminal · npx
$npx skills add https://github.com/wshobson/agents --skill paypal-integration
Works with Paperclip

How Paypal Integration fits into a Paperclip company.

Paypal Integration drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

E
E-Commerce EmpirePaired

Pre-configured AI company — 20 agents, 9 skills, one-time purchase.

$59$89
Explore pack
Source file
SKILL.md450 lines
Expand
---name: paypal-integrationdescription: Integrate 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.--- # PayPal Integration Master PayPal payment integration including Express Checkout, IPN handling, recurring billing, and refund workflows. ## When to Use This Skill - Integrating PayPal as a payment option- Implementing express checkout flows- Setting up recurring billing with PayPal- Processing refunds and payment disputes- Handling PayPal webhooks (IPN)- Supporting international payments- Implementing PayPal subscriptions ## Core Concepts ### 1. Payment Products **PayPal Checkout** - One-time payments- Express checkout experience- Guest and PayPal account payments **PayPal Subscriptions** - Recurring billing- Subscription plans- Automatic renewals **PayPal Payouts** - Send money to multiple recipients- Marketplace and platform payments ### 2. Integration Methods **Client-Side (JavaScript SDK)** - Smart Payment Buttons- Hosted payment flow- Minimal backend code **Server-Side (REST API)** - Full control over payment flow- Custom checkout UI- Advanced features ### 3. IPN (Instant Payment Notification) - Webhook-like payment notifications- Asynchronous payment updates- Verification required ## Quick Start ```javascript// Frontend - PayPal Smart Buttons<div id="paypal-button-container"></div> <script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&currency=USD"></script><script>  paypal.Buttons({    createOrder: function(data, actions) {      return actions.order.create({        purchase_units: [{          amount: {            value: '25.00'          }        }]      });    },    onApprove: function(data, actions) {      return actions.order.capture().then(function(details) {        // Payment successful        console.log('Transaction completed by ' + details.payer.name.given_name);         // Send to backend for verification        fetch('/api/paypal/capture', {          method: 'POST',          headers: {'Content-Type': 'application/json'},          body: JSON.stringify({orderID: data.orderID})        });      });    }  }).render('#paypal-button-container');</script>``` ```python# Backend - Verify and capture orderfrom paypalrestsdk import Paymentimport paypalrestsdk paypalrestsdk.configure({    "mode": "sandbox",  # or "live"    "client_id": "YOUR_CLIENT_ID",    "client_secret": "YOUR_CLIENT_SECRET"}) def capture_paypal_order(order_id):    """Capture a PayPal order."""    payment = Payment.find(order_id)     if payment.execute({"payer_id": payment.payer.payer_info.payer_id}):        # Payment successful        return {            'status': 'success',            'transaction_id': payment.id,            'amount': payment.transactions[0].amount.total        }    else:        # Payment failed        return {            'status': 'failed',            'error': payment.error        }``` ## Express Checkout Implementation ### Server-Side Order Creation ```pythonimport requestsimport json class PayPalClient:    def __init__(self, client_id, client_secret, mode='sandbox'):        self.client_id = client_id        self.client_secret = client_secret        self.base_url = 'https://api-m.sandbox.paypal.com' if mode == 'sandbox' else 'https://api-m.paypal.com'        self.access_token = self.get_access_token()     def get_access_token(self):        """Get OAuth access token."""        url = f"{self.base_url}/v1/oauth2/token"        headers = {"Accept": "application/json", "Accept-Language": "en_US"}         response = requests.post(            url,            headers=headers,            data={"grant_type": "client_credentials"},            auth=(self.client_id, self.client_secret)        )         return response.json()['access_token']     def create_order(self, amount, currency='USD'):        """Create a PayPal order."""        url = f"{self.base_url}/v2/checkout/orders"        headers = {            "Content-Type": "application/json",            "Authorization": f"Bearer {self.access_token}"        }         payload = {            "intent": "CAPTURE",            "purchase_units": [{                "amount": {                    "currency_code": currency,                    "value": str(amount)                }            }]        }         response = requests.post(url, headers=headers, json=payload)        return response.json()     def capture_order(self, order_id):        """Capture payment for an order."""        url = f"{self.base_url}/v2/checkout/orders/{order_id}/capture"        headers = {            "Content-Type": "application/json",            "Authorization": f"Bearer {self.access_token}"        }         response = requests.post(url, headers=headers)        return response.json()     def get_order_details(self, order_id):        """Get order details."""        url = f"{self.base_url}/v2/checkout/orders/{order_id}"        headers = {            "Authorization": f"Bearer {self.access_token}"        }         response = requests.get(url, headers=headers)        return response.json()``` ## IPN (Instant Payment Notification) Handling ### IPN Verification and Processing ```pythonfrom flask import Flask, requestimport requestsfrom urllib.parse import parse_qs app = Flask(__name__) @app.route('/ipn', methods=['POST'])def handle_ipn():    """Handle PayPal IPN notifications."""    # Get IPN message    ipn_data = request.form.to_dict()     # Verify IPN with PayPal    if not verify_ipn(ipn_data):        return 'IPN verification failed', 400     # Process IPN based on transaction type    payment_status = ipn_data.get('payment_status')    txn_type = ipn_data.get('txn_type')     if payment_status == 'Completed':        handle_payment_completed(ipn_data)    elif payment_status == 'Refunded':        handle_refund(ipn_data)    elif payment_status == 'Reversed':        handle_chargeback(ipn_data)     return 'IPN processed', 200 def verify_ipn(ipn_data):    """Verify IPN message authenticity."""    # Add 'cmd' parameter    verify_data = ipn_data.copy()    verify_data['cmd'] = '_notify-validate'     # Send back to PayPal for verification    paypal_url = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr'  # or production URL     response = requests.post(paypal_url, data=verify_data)     return response.text == 'VERIFIED' def handle_payment_completed(ipn_data):    """Process completed payment."""    txn_id = ipn_data.get('txn_id')    payer_email = ipn_data.get('payer_email')    mc_gross = ipn_data.get('mc_gross')    item_name = ipn_data.get('item_name')     # Check if already processed (prevent duplicates)    if is_transaction_processed(txn_id):        return     # Update database    # Send confirmation email    # Fulfill order    print(f"Payment completed: {txn_id}, Amount: ${mc_gross}") def handle_refund(ipn_data):    """Handle refund."""    parent_txn_id = ipn_data.get('parent_txn_id')    mc_gross = ipn_data.get('mc_gross')     # Process refund in your system    print(f"Refund processed: {parent_txn_id}, Amount: ${mc_gross}") def handle_chargeback(ipn_data):    """Handle payment reversal/chargeback."""    txn_id = ipn_data.get('txn_id')    reason_code = ipn_data.get('reason_code')     # Handle chargeback    print(f"Chargeback: {txn_id}, Reason: {reason_code}")``` ## Subscription/Recurring Billing ### Create Subscription Plan ```pythondef create_subscription_plan(name, amount, interval='MONTH'):    """Create a subscription plan."""    client = PayPalClient(CLIENT_ID, CLIENT_SECRET)     url = f"{client.base_url}/v1/billing/plans"    headers = {        "Content-Type": "application/json",        "Authorization": f"Bearer {client.access_token}"    }     payload = {        "product_id": "PRODUCT_ID",  # Create product first        "name": name,        "billing_cycles": [{            "frequency": {                "interval_unit": interval,                "interval_count": 1            },            "tenure_type": "REGULAR",            "sequence": 1,            "total_cycles": 0,  # Infinite            "pricing_scheme": {                "fixed_price": {                    "value": str(amount),                    "currency_code": "USD"                }            }        }],        "payment_preferences": {            "auto_bill_outstanding": True,            "setup_fee": {                "value": "0",                "currency_code": "USD"            },            "setup_fee_failure_action": "CONTINUE",            "payment_failure_threshold": 3        }    }     response = requests.post(url, headers=headers, json=payload)    return response.json() def create_subscription(plan_id, subscriber_email):    """Create a subscription for a customer."""    client = PayPalClient(CLIENT_ID, CLIENT_SECRET)     url = f"{client.base_url}/v1/billing/subscriptions"    headers = {        "Content-Type": "application/json",        "Authorization": f"Bearer {client.access_token}"    }     payload = {        "plan_id": plan_id,        "subscriber": {            "email_address": subscriber_email        },        "application_context": {            "return_url": "https://yourdomain.com/subscription/success",            "cancel_url": "https://yourdomain.com/subscription/cancel"        }    }     response = requests.post(url, headers=headers, json=payload)    subscription = response.json()     # Get approval URL    for link in subscription.get('links', []):        if link['rel'] == 'approve':            return {                'subscription_id': subscription['id'],                'approval_url': link['href']            }``` ## Refund Workflows ```pythondef create_refund(capture_id, amount=None, note=None):    """Create a refund for a captured payment."""    client = PayPalClient(CLIENT_ID, CLIENT_SECRET)     url = f"{client.base_url}/v2/payments/captures/{capture_id}/refund"    headers = {        "Content-Type": "application/json",        "Authorization": f"Bearer {client.access_token}"    }     payload = {}    if amount:        payload["amount"] = {            "value": str(amount),            "currency_code": "USD"        }     if note:        payload["note_to_payer"] = note     response = requests.post(url, headers=headers, json=payload)    return response.json() def get_refund_details(refund_id):    """Get refund details."""    client = PayPalClient(CLIENT_ID, CLIENT_SECRET)     url = f"{client.base_url}/v2/payments/refunds/{refund_id}"    headers = {        "Authorization": f"Bearer {client.access_token}"    }     response = requests.get(url, headers=headers)    return response.json()``` ## Error Handling ```pythonclass PayPalError(Exception):    """Custom PayPal error."""    pass def handle_paypal_api_call(api_function):    """Wrapper for PayPal API calls with error handling."""    try:        result = api_function()        return result    except requests.exceptions.RequestException as e:        # Network error        raise PayPalError(f"Network error: {str(e)}")    except Exception as e:        # Other errors        raise PayPalError(f"PayPal API error: {str(e)}") # Usagetry:    order = handle_paypal_api_call(lambda: client.create_order(25.00))except PayPalError as e:    # Handle error appropriately    log_error(e)``` ## Testing ```python# Use sandbox credentialsSANDBOX_CLIENT_ID = "..."SANDBOX_SECRET = "..." # Test accounts# Create test buyer and seller accounts at developer.paypal.com def test_payment_flow():    """Test complete payment flow."""    client = PayPalClient(SANDBOX_CLIENT_ID, SANDBOX_SECRET, mode='sandbox')     # Create order    order = client.create_order(10.00)    assert 'id' in order     # Get approval URL    approval_url = next((link['href'] for link in order['links'] if link['rel'] == 'approve'), None)    assert approval_url is not None     # After approval (manual step with test account)    # Capture order    # captured = client.capture_order(order['id'])    # assert captured['status'] == 'COMPLETED'```