Introduction
Choosing the right payment gateway impacts your bottom line. With processing fees, feature differences, and integration complexity varying significantly, making an informed choice is critical.
Key Statistics:
- Average checkout abandonment: 70%
- Payment failures cost 3-5% of revenue
- Gateway downtime can cost $100K/hour
- 30% of users abandon if only one payment method offered
Comparison Matrix
| Feature | Stripe | Square | Adyen | Wise |
|---|---|---|---|---|
| Best For | Online SaaS | In-person + Online | Enterprise | International |
| US domestic | 2.9% + $0.30 | 2.6% + $0.10 | 2.9% + $0.30 | 0.5-1% |
| International | +1% | +1% | +0.5% | Mid-market rate |
| Setup Fee | Free | Free | Custom | Free |
| Monthly Fee | Free | Free | Custom | Free |
| API Quality | Excellent | Good | Good | Good |
| Payout Time | 2-7 days | Instant-2 days | Custom | 1-2 days |
Stripe Integration
Basic Checkout
#!/usr/bin/env python3
"""Stripe payment integration."""
import stripe
from flask import Flask, request, jsonify
app = Flask(__name__)
stripe.api_key = os.environ['STRIPE_SECRET_KEY']
@app.route('/create-checkout-session', methods=['POST'])
def create_checkout_session():
"""Create Stripe Checkout session."""
session = stripe.checkout.Session.create(
payment_method_types=['card'],
line_items=[{
'price_data': {
'currency': 'usd',
'product_data': {
'name': 'Premium Subscription',
'description': 'Monthly premium plan'
},
'unit_amount': 2999, # $29.99
'recurring': {
'interval': 'month'
}
},
'quantity': 1
}],
mode='subscription',
success_url='https://example.com/success',
cancel_url='https://example.com/cancel',
customer_email=request.json.get('email'),
metadata={
'user_id': request.json.get('user_id')
}
)
return jsonify({'session_id': session.id})
@app.route('/webhook', methods=['POST'])
def webhook():
"""Handle Stripe webhooks."""
payload = request.data
sig_header = request.headers.get('Stripe-Signature')
try:
event = stripe.Webhook.construct_event(
payload, sig_header, os.environ['STRIPE_WEBHOOK_SECRET']
)
except ValueError:
return 'Invalid payload', 400
except stripe.error.SignatureVerificationError:
return 'Invalid signature', 400
# Handle events
if event['type'] == 'checkout.session.completed':
session = event['data']['object']
handle_successful_payment(session)
elif event['type'] == 'customer.subscription.updated':
subscription = event['data']['object']
handle_subscription_update(subscription)
elif event['type'] == 'customer.subscription.deleted':
subscription = event['data']['object']
handle_subscription_cancelled(subscription)
return '', 200
Connect (Marketplaces)
# Stripe Connect for marketplaces
@app.route('/create-connected-account', methods=['POST'])
def create_connected_account():
"""Create connected account for seller."""
account = stripe.Account.create(
type='express',
country='US',
email=request.json.get('email'),
capabilities={
'card_payments': {'requested': True},
'transfers': {'requested': True}
}
)
return jsonify({'account_id': account.id})
@app.route('/create-account-link', methods=['POST'])
def create_account_link():
"""Create onboarding link for seller."""
account_link = stripe.AccountLink.create(
account=request.json.get('account_id'),
refresh_url='https://example.com/reauth',
return_url='https://example.com/return',
type='account_onboarding'
)
return jsonify({'url': account_link.url})
@app.route('/transfer-to-seller', methods=['POST'])
def transfer_to_seller():
"""Transfer payment to seller (minus platform fee)."""
transfer = stripe.Transfer.create(
amount=9500, # $95.00
currency='usd',
destination=request.json.get('seller_account_id'),
transfer_group='ORDER_123'
)
return jsonify({'transfer_id': transfer.id})
Square Integration
Point of Sale
#!/usr/bin/env python3
"""Square POS integration."""
import square
from square.client import Client
client = Client(
access_token=os.environ['SQUARE_ACCESS_TOKEN'],
environment='sandbox'
)
def create_payment_link():
"""Create payment link for online checkout."""
response = client.v1.payments.create_payment_link(
body={
"idempotency_key": "unique-key-123",
"order": {
"line_items": [
{
"name": "Premium Plan",
"quantity": "1",
"base_price_money": {
"amount": 2999,
"currency": "USD"
}
}
]
},
"checkout_options": {
"redirect_url": "https://example.com/success"
}
}
)
return response.body.payment_link.url
def process_pos_payment(source_id, amount):
"""Process payment from POS."""
response = client.payments.create(
body={
"source_id": source_id, # From Square POS SDK
"idempotency_key": "unique-key-456",
"amount_money": {
"amount": amount,
"currency": "USD"
},
"location_id": os.environ['SQUARE_LOCATION_ID']
}
)
return response.body.payment
Adyen Integration
#!/usr/bin/env python3
"""Adyen payment integration."""
from Adyen import Adyen
adyen = Adyen()
adyen.client.platform = "test"
adyen.client.api_key = os.environ['ADYEN_API_KEY']
def create_checkout_session():
"""Create Adyen checkout session."""
request = {
"merchantAccount": "YOUR_MERCHANT_ACCOUNT",
"amount": {
"currency": "USD",
"value": 2999
},
"returnUrl": "https://example.com/redirect",
"paymentMethod": {
"type": "scheme",
"encryptedCardNumber": "encrypted_card_number",
"encryptedExpiryMonth": "encrypted_expiry_month",
"encryptedExpiryYear": "encrypted_expiry_year",
"encryptedSecurityCode": "encrypted_cvc"
},
"shopperReference": "user_123"
}
result = adyen.checkout.payments_api.payments(request)
return result
def handle_webhook(notification):
"""Process Adyen webhook."""
notification_items = notification.get('notificationItems', [])
for item in notification_items:
notification_request = item.get('NotificationRequestItem')
if notification_request.get('eventCode') == 'AUTHORISATION':
if notification_request.get('success') == 'true':
handle_successful_payment(notification_request)
else:
handle_failed_payment(notification_request)
elif notification_request.get('eventCode') == 'REFUND':
handle_refund(notification_request)
Wise (International Payments)
#!/usr/bin/env python3
"""Wise (TransferWise) integration for international payments."""
import requests
from wise import Wise
wise = Wise(os.environ['WISE_API_KEY'])
def create_quote(source_currency, target_currency, amount):
"""Create exchange quote."""
quote = wise.create_quote(
source_currency=source_currency,
target_currency=target_currency,
amount=amount
)
return quote
def create_transfer(quote_id, recipient_id):
"""Create transfer to recipient."""
transfer = wise.create_transfer(
quote_id=quote_id,
target_account=recipient_id,
reference="Order #123"
)
return transfer
def get_requirements(country, currency):
"""Get field requirements for country/currency."""
requirements = wise.get_requirements(
country_code=country,
currency=currency
)
return requirements
def createRecipientProfile(details):
"""Create recipient profile for international transfer."""
recipient = wise.create_recipient(
profile_type='business',
details=details
)
return recipient
Decision Guide
When to Choose Each
| Scenario | Recommended Gateway |
|---|---|
| SaaS subscription | Stripe |
| E-commerce | Stripe or Square |
| In-person + online | Square |
| Enterprise/Marketplace | Adyen |
| International payments | Wise |
| Multi-currency | Stripe + Wise |
| Complex pricing | Adyen |
Comments