Initial Python SDK release v1.0.0

This commit is contained in:
garfieldheron
2026-02-19 12:17:09 -05:00
commit 42443872c9
17 changed files with 1037 additions and 0 deletions

133
fetcherpay/api/payments.py Normal file
View File

@@ -0,0 +1,133 @@
"""
Payments API
"""
from typing import Optional, Dict, Any, List
class PaymentsAPI:
"""Payments API client"""
def __init__(self, client):
self.client = client
def create(
self,
amount: int,
source: Dict[str, str],
destination: Dict[str, str],
currency: str = 'USD',
rail: str = 'auto',
description: Optional[str] = None,
metadata: Optional[Dict[str, Any]] = None,
idempotency_key: Optional[str] = None
) -> Dict[str, Any]:
"""
Create a new payment
Args:
amount: Amount in cents (e.g., 10000 for $100.00)
source: Payment source with payment_method_id
destination: Payment destination with payment_method_id
currency: Currency code (default: USD)
rail: Payment rail (auto, ach, rtp, card, crypto)
description: Optional payment description
metadata: Optional metadata dictionary
idempotency_key: Optional idempotency key
Returns:
Payment object
"""
data = {
'amount': amount,
'currency': currency,
'rail': rail,
'source': source,
'destination': destination,
}
if description:
data['description'] = description
if metadata:
data['metadata'] = metadata
return self.client._request(
'POST',
'/payments',
json=data,
idempotency_key=idempotency_key
)
def retrieve(self, payment_id: str) -> Dict[str, Any]:
"""Retrieve a payment by ID"""
return self.client._request('GET', f'/payments/{payment_id}')
def list(
self,
limit: int = 25,
cursor: Optional[str] = None,
status: Optional[str] = None,
rail: Optional[str] = None
) -> Dict[str, Any]:
"""
List payments
Args:
limit: Number of results (1-100)
cursor: Pagination cursor
status: Filter by status
rail: Filter by rail
"""
params = {'limit': limit}
if cursor:
params['cursor'] = cursor
if status:
params['status'] = status
if rail:
params['rail'] = rail
return self.client._request('GET', '/payments', params=params)
def cancel(
self,
payment_id: str,
reason: Optional[str] = None,
idempotency_key: Optional[str] = None
) -> Dict[str, Any]:
"""Cancel a pending payment"""
data = {'reason': reason} if reason else {}
return self.client._request(
'POST',
f'/payments/{payment_id}/cancel',
json=data,
idempotency_key=idempotency_key
)
def refund(
self,
payment_id: str,
amount: Optional[int] = None,
reason: Optional[str] = None,
idempotency_key: Optional[str] = None
) -> Dict[str, Any]:
"""
Refund a settled payment
Args:
payment_id: Payment ID to refund
amount: Amount to refund (omit for full refund)
reason: Refund reason
idempotency_key: Idempotency key
"""
data = {}
if amount:
data['amount'] = amount
if reason:
data['reason'] = reason
return self.client._request(
'POST',
f'/payments/{payment_id}/refund',
json=data,
idempotency_key=idempotency_key
)