Skip to main content

A comprehensive Python SDK for PayPal Payments REST API v2 and Transaction Search API

Project description

PayPal Payments SDK for Python

A comprehensive Python SDK for PayPal Payments REST API v2, providing easy-to-use methods for handling authorizations, captures, and refunds.

Features

  • Complete API Coverage: Supports all PayPal Payments API v2 endpoints and Transaction Search API
  • Type Safety: Built with Pydantic for robust data validation
  • Error Handling: Comprehensive exception handling with specific error types
  • Authentication: Automatic OAuth token management
  • Environment Support: Easy configuration via environment variables
  • Context Manager: Clean resource management with context managers
  • Idempotency: Built-in support for request idempotency

Installation

  1. Clone the repository:

    git clone <repository-url>
    cd paypal-sdk
    
  2. Set up virtual environment:

    python -m venv .venv
    source .venv/bin/activate  # On Windows: .venv\Scripts\activate
    
  3. Install dependencies:

    pip install -r requirements.txt
    

Configuration

Environment Variables

Create a .env file in your project root:

# PayPal API Configuration
PAYPAL_CLIENT_ID=your_client_id_here
PAYPAL_CLIENT_SECRET=your_client_secret_here
PAYPAL_BASE_URL=https://api-m.sandbox.paypal.com
PAYPAL_MODE=sandbox  # or 'live'

# Optional: Request ID for idempotency
PAYPAL_REQUEST_ID=optional_request_id

Getting PayPal Credentials

  1. Go to PayPal Developer Portal
  2. Create a developer account
  3. Create a new app to get your Client ID and Client Secret
  4. Use sandbox credentials for testing, live credentials for production

Quick Start

from paypal_sdk import PayPalClient

# Initialize client
client = PayPalClient(
    client_id="your_client_id",
    client_secret="your_client_secret",
    mode="sandbox"  # Use "live" for production
)

# Get authorization details
auth = client.get_authorization("authorization_id")

# Create and process a capture
capture_request = client.create_capture_request(
    amount=client.create_money("USD", "10.99"),
    invoice_id="INVOICE-123"
)
capture = client.capture_authorization("authorization_id", capture_request)

# Process a refund
refund_request = client.create_refund_request(
    amount=client.create_money("USD", "5.00"),
    note_to_payer="Partial refund"
)
refund = client.refund_capture("capture_id", refund_request)

# Search for transactions
from datetime import datetime, timedelta
end_date = datetime.utcnow()
start_date = end_date - timedelta(days=30)
transactions = client.search_transactions(
    start_date=start_date,
    end_date=end_date,
    fields="transaction_info"
)

# Get account balances
balances = client.get_balances()

# Always close the client
client.close()

API Reference

Client Initialization

PayPalClient(
    client_id: Optional[str] = None,
    client_secret: Optional[str] = None,
    base_url: Optional[str] = None,
    mode: str = "sandbox",
    request_id: Optional[str] = None
)

Authorization Methods

Get Authorization Details

auth = client.get_authorization(authorization_id: str) -> Authorization

Capture Authorization

capture = client.capture_authorization(
    authorization_id: str,
    capture_request: CaptureRequest
) -> Capture

Reauthorize Authorization

reauth = client.reauthorize_authorization(
    authorization_id: str,
    reauthorize_request: ReauthorizeRequest
) -> Authorization

Void Authorization

voided_auth = client.void_authorization(authorization_id: str) -> Optional[Authorization]

Capture Methods

Get Capture Details

capture = client.get_capture(capture_id: str) -> Capture

Refund Capture

refund = client.refund_capture(
    capture_id: str,
    refund_request: Optional[RefundRequest] = None
) -> Refund

Refund Methods

Get Refund Details

refund = client.get_refund(refund_id: str) -> Refund

Convenience Methods

Create Request Objects

# Capture request
capture_request = client.create_capture_request(
    amount: Optional[Dict[str, str]] = None,
    invoice_id: Optional[str] = None,
    final_capture: bool = True,
    note_to_payer: Optional[str] = None,
    soft_descriptor: Optional[str] = None
) -> CaptureRequest

# Refund request
refund_request = client.create_refund_request(
    amount: Optional[Dict[str, str]] = None,
    custom_id: Optional[str] = None,
    invoice_id: Optional[str] = None,
    note_to_payer: Optional[str] = None
) -> RefundRequest

# Reauthorize request
reauth_request = client.create_reauthorize_request(
    amount: Dict[str, str]
) -> ReauthorizeRequest

# Money object
money = client.create_money(currency_code: str, value: str) -> Dict[str, str]

Data Models

The SDK includes comprehensive Pydantic models for all PayPal API data structures:

  • Authorization: Authorization entity with status and details
  • Capture: Capture entity with breakdown information
  • Refund: Refund entity with status and breakdown
  • Money: Currency and amount representation
  • ErrorResponse: Error response structure
  • And many more...

Error Handling

The SDK provides specific exception types for different error scenarios:

from paypal_sdk import (
    PayPalError,
    PayPalAuthenticationError,
    PayPalValidationError,
    PayPalNotFoundError,
    PayPalConflictError,
    PayPalUnprocessableEntityError,
    PayPalServerError,
    PayPalRateLimitError
)

try:
    auth = client.get_authorization("invalid_id")
except PayPalNotFoundError as e:
    print(f"Authorization not found: {e}")
except PayPalAuthenticationError as e:
    print(f"Authentication failed: {e}")
except PayPalError as e:
    print(f"PayPal error: {e}")

Examples

Basic Usage

# See examples/basic_usage.py for comprehensive examples

Environment Configuration

# Using environment variables
with PayPalClient() as client:
    auth = client.get_authorization("auth_id")
    # Client automatically closes

Full Refund

# Full refund (no amount specified)
refund = client.refund_capture("capture_id")

Partial Refund

# Partial refund
refund_request = client.create_refund_request(
    amount=client.create_money("USD", "5.00"),
    note_to_payer="Partial refund for defective item"
)
refund = client.refund_capture("capture_id", refund_request)

Reauthorization

# Reauthorize with new amount
reauth_request = client.create_reauthorize_request(
    client.create_money("USD", "15.99")
)
reauth = client.reauthorize_authorization("auth_id", reauth_request)

Transaction Search API

The SDK includes comprehensive support for PayPal's Transaction Search API, allowing you to search for transactions and retrieve account balances.

Search Transactions

from datetime import datetime, timedelta
from paypal_sdk import TransactionStatusEnum, PaymentInstrumentTypeEnum

# Search for transactions in the last 30 days
end_date = datetime.utcnow()
start_date = end_date - timedelta(days=30)

# Basic search
transactions = client.search_transactions(
    start_date=start_date,
    end_date=end_date,
    fields="transaction_info"
)

# Search with filters
successful_transactions = client.search_transactions(
    start_date=start_date,
    end_date=end_date,
    transaction_status=TransactionStatusEnum.S,  # Successful transactions only
    transaction_currency="USD",
    payment_instrument_type=PaymentInstrumentTypeEnum.CREDITCARD,
    fields="transaction_info,payer_info",
    page_size=10
)

# Search by amount range (in cents)
amount_filtered = client.search_transactions(
    start_date=start_date,
    end_date=end_date,
    transaction_amount="1000 TO 10000",  # $10.00 to $100.00
    transaction_currency="USD",
    fields="transaction_info"
)

# Access transaction details
for transaction in transactions.transaction_details:
    if transaction.transaction_info:
        info = transaction.transaction_info
        print(f"Transaction ID: {info.transaction_id}")
        print(f"Amount: {info.transaction_amount.value} {info.transaction_amount.currency_code}")
        print(f"Status: {info.transaction_status}")
        print(f"Date: {info.transaction_initiation_date}")

Get Account Balances

# Get current balances
balances = client.get_balances()

# Get balances for specific currency
usd_balances = client.get_balances(currency_code="USD")

# Get balances as of specific time
from datetime import datetime
as_of_time = datetime(2024, 1, 1, 12, 0, 0)
historical_balances = client.get_balances(as_of_time=as_of_time)

# Access balance information
for balance in balances.balances:
    print(f"Currency: {balance.currency}")
    print(f"Primary: {balance.primary}")
    if balance.total_balance:
        print(f"Total: {balance.total_balance.value} {balance.total_balance.currency_code}")
    if balance.available_balance:
        print(f"Available: {balance.available_balance.value} {balance.available_balance.currency_code}")
    if balance.withheld_balance:
        print(f"Withheld: {balance.withheld_balance.value} {balance.withheld_balance.currency_code}")

Transaction Status Codes

  • D: Denied
  • P: Pending
  • S: Success
  • V: Voided

Payment Instrument Types

  • CREDITCARD: Credit card transactions
  • DEBITCARD: Debit card transactions

Available Fields

You can specify which fields to include in the response:

  • transaction_info: Transaction details (default)
  • payer_info: Payer information
  • shipping_info: Shipping information
  • cart_info: Cart and item details
  • store_info: Store information
  • auction_info: Auction information
  • incentive_info: Incentive details
  • all: Include all fields

Best Practices

  1. Always close the client: Use context managers or explicitly call client.close()
  2. Handle errors appropriately: Catch specific exception types for better error handling
  3. Use environment variables: Store sensitive credentials in environment variables
  4. Test in sandbox: Always test in sandbox mode before going live
  5. Validate data: The SDK automatically validates data, but ensure your inputs are correct
  6. Use idempotency: Set request IDs for operations that should be idempotent

Development

Running Tests

# Install development dependencies
pip install -r requirements-dev.txt

# Run tests
pytest

Code Quality

# Run linting
flake8 paypal_sdk/

# Run type checking
mypy paypal_sdk/

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass
  6. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

For issues and questions:

Changelog

Version 1.1.0

  • Added Transaction Search API support
  • New models for transaction search and balances
  • Added search_transactions() method
  • Added get_balances() method
  • Added transaction status and payment instrument type enums
  • Comprehensive transaction search filtering options
  • Added transaction search example and tests

Version 1.0.0

  • Initial release
  • Complete PayPal Payments API v2 support
  • Pydantic models for type safety
  • Comprehensive error handling
  • OAuth token management
  • Environment variable support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

paypal_payments_sdk-1.1.0.tar.gz (20.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

paypal_payments_sdk-1.1.0-py3-none-any.whl (21.5 kB view details)

Uploaded Python 3

File details

Details for the file paypal_payments_sdk-1.1.0.tar.gz.

File metadata

  • Download URL: paypal_payments_sdk-1.1.0.tar.gz
  • Upload date:
  • Size: 20.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for paypal_payments_sdk-1.1.0.tar.gz
Algorithm Hash digest
SHA256 9f5ba4758a1222954260d615c9f6c1abdb5e13fd23ddf748688c46166b5f580e
MD5 cda83e3bec7edce86c2bfe02e43f3865
BLAKE2b-256 e4d2809d93d382bf24d4949c4eb549d1b07d8d391b94326e9f715f07f5f98e4c

See more details on using hashes here.

File details

Details for the file paypal_payments_sdk-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for paypal_payments_sdk-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4aad76b3b3a1c47b5ebcf9f5aeaf9905d90c0e7b95d2afc0d4bfbf7c80484a6a
MD5 97de1d49201a4b0f4f80c27bf1723047
BLAKE2b-256 38f3fefea50ac0566371623e4057728bb287a3c0470bca0bd19b78a3129e7e7f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page