---
title: "Technical Specifications"
space: "Integrations"
url: "https://integrations.frappe.cloud/integrations/payment-integration/payment-core/technical-specifications"
updated: "2026-07-30"
---

## System Requirements

- **Frappe Framework**: v15.0 or higher
- **Python**: 3.6 or higher
- **External Dependencies**: Gateway-specific SDKs (stripe, razorpay, braintree, etc.)

## Gateway-Specific Dependencies

```python
# Stripe
import stripe

# Razorpay
import razorpay

# Braintree
import braintree

# PayPal, PayTM, GoCardless, MPesa, Paymob use standard HTTP requests
from frappe.integrations.utils import make_get_request, make_post_request
```

## Security Features

- **Credential Storage**: Password fields with encryption at rest
- **API Token Management**: Secure secret key storage
- **Token Validation**: Integration request expiry handling
- **Guest Checkout**: Controlled guest access to payment processing
- **Webhook Validation**: Signature verification for callbacks
- **Sandbox/Production**: Environment separation

## Performance Considerations

- **Integration Request Logging**: Comprehensive transaction audit trail
- **Async Webhook Processing**: Background job queuing for subscription notifications
- **Currency Validation**: O(1) lookup in supported currencies tuple
- **Controller Caching**: Efficient gateway controller retrieval
- **Web Form Caching**: Optimized form rendering with payment fields

## Best Practices

### Payment Flow Implementation

```python
# 1. Always validate currency before processing
controller = get_payment_gateway_controller(payment_gateway)
try:
    controller.validate_transaction_currency(currency)
except Exception:
    frappe.throw(_("Currency not supported by gateway"))

# 2. Use integration requests for logging
integration_request = create_request_log(
    data=payment_details,
    service_name=gateway
)

# 3. Handle payment authorization callback
def on_payment_authorized(self, status):
    if status == "Completed":
        self.payment_status = "Paid"
        self.save()
    elif status == "Failed":
        frappe.log_error("Payment failed", f"{self.name} Payment Error")
```

### Error Handling

```python
# Gateway-level error handling
try:
    response = gateway.create_payment(data)
except GatewayError as e:
    frappe.log_error(str(e), "Gateway Payment Error")
    integration_request.db_set("error", str(e))
    return {"redirect_to": "payment-failed", "status": "Failed"}

# Integration request error handling
integration_request = create_request_log(data, service_name="Gateway")
try:
    result = process_payment(integration_request)
except Exception as e:
    integration_request.db_set("status", "Failed")
    integration_request.db_set("error", frappe.get_traceback())
```