> ## Documentation Index
> Fetch the complete documentation index at: https://docs.telnesstech.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Payment Processing

> Handle recurring billing, payment methods, invoicing, and payment failures using the Connect API

Implement comprehensive payment processing for telecommunications services including payment collection, stored payment methods, billing management, and payment failure handling. This use case covers the complete payment lifecycle from initial collection to ongoing billing.

## Prerequisites

Before you begin, ensure you have:

* **Order Management**: Understanding of order creation and pricing flows
* **Customer Management**: Active customers with subscription services
* **Payment Gateway Integration**: Access to payment processors (cards, bank transfers, digital wallets)
* **Billing System**: Understanding of billing cycles and pricing models
* **Compliance**: PCI DSS compliance for handling payment data

## Overview

Payment processing encompasses:

1. Payment session creation for secure payment collection
2. Payment profile management for stored payment methods
3. Payment processing and transaction handling
4. Payment failure management and retry logic
5. Billing and invoice management
6. Promotional pricing and discount handling

## Step-by-Step Implementation

### Step 1: Create Payment Sessions for Orders

Create secure payment sessions to collect payment for orders:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    // Create payment session for order
    const createOrderPaymentSession = async (orderId, paymentOptions = {}) => {
      const sessionData = {
        orderId: orderId,
        successUrl: paymentOptions.successUrl || `${window.location.origin}/payment/success`,
        cancelUrl: paymentOptions.cancelUrl || `${window.location.origin}/payment/cancel`,
        paymentMethods: paymentOptions.paymentMethods || ['card', 'bank_transfer'],
        locale: paymentOptions.locale || 'en',
        metadata: {
          source: 'customer_portal',
          timestamp: new Date().toISOString()
        }
      };

      const response = await fetch('https://connect.your-domain.com/api/v2/payment-sessions', {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(sessionData)
      });

      if (!response.ok) {
        const error = await response.json();
        throw new Error(`Payment session creation failed: ${error.message}`);
      }

      return await response.json();
    };

    // Monitor payment session status
    const checkPaymentSessionStatus = async (paymentSessionId) => {
      const response = await fetch(`https://connect.your-domain.com/api/v2/payment-sessions/${paymentSessionId}`, {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        }
      });

      const session = await response.json();

      return {
        status: session.status,
        paymentId: session.paymentId,
        orderId: session.orderId,
        amount: session.amount,
        currency: session.currency,
        completedAt: session.completedAt,
        failureReason: session.failureReason
      };
    };

    // Payment session component
    const PaymentSessionHandler = ({ orderId, onSuccess, onFailure }) => {
      const [paymentSession, setPaymentSession] = useState(null);
      const [loading, setLoading] = useState(false);

      const initiatePayment = async () => {
        setLoading(true);
        try {
          const session = await createOrderPaymentSession(orderId, {
            successUrl: `${window.location.origin}/orders/${orderId}/success`,
            cancelUrl: `${window.location.origin}/orders/${orderId}/cancel`
          });

          setPaymentSession(session);

          // Redirect to payment URL
          window.location.href = session.paymentUrl;
        } catch (error) {
          console.error('Payment session creation failed:', error);
          onFailure(error);
        } finally {
          setLoading(false);
        }
      };

      return (
        <div className="payment-session">
          <button onClick={initiatePayment} disabled={loading}>
            {loading ? 'Creating Payment Session...' : 'Pay Now'}
          </button>
        </div>
      );
    };
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    # Create payment session for order
    curl -X POST "https://connect.your-domain.com/api/v2/payment-sessions" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "orderId": "123e4567-e89b-12d3-a456-426614174000",
        "successUrl": "https://yourstore.com/payment/success",
        "cancelUrl": "https://yourstore.com/payment/cancel",
        "paymentMethods": ["card", "bank_transfer"]
      }'

    # Check payment session status
    curl -X GET "https://connect.your-domain.com/api/v2/payment-sessions/{paymentSessionId}" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json"
    ```
  </Tab>
</Tabs>

### Step 2: Manage Payment Profiles

Set up stored payment methods for recurring billing:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    // Create payment profile session for storing payment methods
    const createPaymentProfileSession = async (returnUrl, customerContext) => {
      const sessionData = {
        returnUrl: returnUrl,
        paymentMethods: ['card', 'bank_account'],
        metadata: {
          customerId: customerContext.customerId,
          source: 'billing_setup'
        }
      };

      const response = await fetch('https://connect.your-domain.com/api/v2/payment-profiles/sessions', {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(sessionData)
      });

      return await response.json();
    };

    // Get stored payment profiles
    const getPaymentProfiles = async () => {
      const response = await fetch('https://connect.your-domain.com/api/v2/payment-profiles', {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        }
      });

      return await response.json();
    };

    // Get specific payment profile
    const getPaymentProfile = async (paymentProfileId) => {
      const response = await fetch(`https://connect.your-domain.com/api/v2/payment-profiles/${paymentProfileId}`, {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        }
      });

      return await response.json();
    };
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    # Create payment profile session
    curl -X POST "https://connect.your-domain.com/api/v2/payment-profiles/sessions" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "returnUrl": "https://yourstore.com/billing/payment-methods",
        "paymentMethods": ["card", "bank_account"]
      }'

    # Get payment profiles
    curl -X GET "https://connect.your-domain.com/api/v2/payment-profiles" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json"
    ```
  </Tab>
</Tabs>

### Step 3: Process Payments

Handle payment processing and transaction management:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    // List payments with filtering
    const getPayments = async (filters = {}) => {
      const params = new URLSearchParams();

      if (filters.customerId) params.append('customerId', filters.customerId);
      if (filters.status) params.append('status', filters.status);
      if (filters.dateFrom) params.append('dateFrom', filters.dateFrom);
      if (filters.dateTo) params.append('dateTo', filters.dateTo);
      if (filters.limit) params.append('limit', filters.limit);
      if (filters.offset) params.append('offset', filters.offset);

      const response = await fetch(`https://connect.your-domain.com/api/v2/payments?${params}`, {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        }
      });

      return await response.json();
    };

    // Get specific payment details
    const getPaymentDetails = async (paymentId) => {
      const response = await fetch(`https://connect.your-domain.com/api/v2/payments/${paymentId}`, {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
          'X-API-Key': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
        }
      });

      return await response.json();
    };

    // Payment management component
    const PaymentManager = ({ customerId }) => {
      const [payments, setPayments] = useState([]);
      const [paymentProfiles, setPaymentProfiles] = useState([]);
      const [loading, setLoading] = useState(true);

      useEffect(() => {
        Promise.all([
          getPayments({ customerId, limit: 50 }),
          getPaymentProfiles()
        ]).then(([paymentsData, profilesData]) => {
          setPayments(paymentsData.items || []);
          setPaymentProfiles(profilesData.items || []);
          setLoading(false);
        });
      }, [customerId]);

      const handleAddPaymentMethod = async () => {
        try {
          const session = await createPaymentProfileSession(
            `${window.location.origin}/billing/payment-methods`,
            { customerId }
          );
          window.location.href = session.paymentUrl;
        } catch (error) {
          console.error('Failed to create payment profile session:', error);
        }
      };

      if (loading) return <div>Loading payment information...</div>;

      return (
        <div className="payment-manager">
          <h3>Payment Methods</h3>
          <div className="payment-profiles">
            {paymentProfiles.map(profile => (
              <div key={profile.paymentProfileId} className="payment-profile">
                <span>{profile.brand} •••• {profile.lastFour}</span>
                <span>Expires {profile.expiryMonth}/{profile.expiryYear}</span>
              </div>
            ))}
            <button onClick={handleAddPaymentMethod}>
              Add Payment Method
            </button>
          </div>

          <h3>Payment History</h3>
          <div className="payment-history">
            {payments.map(payment => (
              <div key={payment.paymentId} className="payment-item">
                <span>{payment.description}</span>
                <span>{payment.amount} {payment.currency}</span>
                <span className={`status ${payment.status}`}>
                  {payment.status}
                </span>
                <span>{new Date(payment.createdAt).toLocaleDateString()}</span>
              </div>
            ))}
          </div>
        </div>
      );
    };
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    # List payments
    curl -X GET "https://connect.your-domain.com/api/v2/payments?customerId={customerId}&limit=50" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json"

    # Get payment details
    curl -X GET "https://connect.your-domain.com/api/v2/payments/{paymentId}" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json"
    ```
  </Tab>
</Tabs>

## Handling Payment Failures and Retries

Implement robust payment failure handling with retry logic:

```javascript theme={null}
// Payment failure handler with exponential backoff
class PaymentRetryHandler {
  constructor(maxRetries = 3) {
    this.maxRetries = maxRetries;
    this.retryDelays = [24, 72, 168]; // Hours: 1 day, 3 days, 1 week
  }

  async handlePaymentFailure(paymentSessionId, failureReason) {
    console.log(`Payment failed for session ${paymentSessionId}: ${failureReason}`);

    // Get payment session details
    const session = await checkPaymentSessionStatus(paymentSessionId);

    // Categorize failure type
    const failureCategory = this.categorizeFailure(failureReason);

    switch (failureCategory) {
      case 'insufficient_funds':
        await this.scheduleRetry(paymentSessionId, 24); // Retry in 24 hours
        await this.notifyCustomer(session.customerId, 'insufficient_funds');
        break;

      case 'expired_card':
        await this.requestPaymentMethodUpdate(session.customerId);
        break;

      case 'fraud_suspected':
        await this.escalateToFraud(session);
        break;

      case 'technical_error':
        await this.scheduleRetry(paymentSessionId, 1); // Retry in 1 hour
        break;

      default:
        await this.escalateToSupport(session);
    }
  }

  categorizeFailure(reason) {
    const failureMap = {
      'insufficient_funds': 'insufficient_funds',
      'card_declined': 'insufficient_funds',
      'expired_card': 'expired_card',
      'invalid_cvc': 'expired_card',
      'fraud_suspected': 'fraud_suspected',
      'processing_error': 'technical_error',
      'network_error': 'technical_error'
    };

    return failureMap[reason] || 'unknown';
  }

  async scheduleRetry(paymentSessionId, delayHours) {
    // In production, this would schedule a background job
    setTimeout(async () => {
      try {
        // Create new payment session with same order
        const originalSession = await checkPaymentSessionStatus(paymentSessionId);
        const newSession = await createOrderPaymentSession(originalSession.orderId);

        // Notify customer of retry attempt
        await this.notifyCustomerRetry(originalSession.customerId, newSession.paymentUrl);
      } catch (error) {
        console.error('Payment retry failed:', error);
      }
    }, delayHours * 60 * 60 * 1000);
  }

  async notifyCustomer(customerId, failureType) {
    // Implement customer notification logic
    console.log(`Notifying customer ${customerId} about ${failureType}`);
  }

  async requestPaymentMethodUpdate(customerId) {
    // Create payment profile session for updating payment method
    const session = await createPaymentProfileSession(
      `${process.env.BASE_URL}/billing/update-payment`,
      { customerId }
    );

    // Send email with update link
    await this.notifyCustomer(customerId, 'payment_method_update_required');
  }
}
```

## Promotional Pricing and Discounts

Handle promotional codes and discount applications:

```javascript theme={null}
// Get promotion by promo code
const getPromotionByCode = async (promoCode) => {
  const response = await fetch(`https://connect.your-domain.com/api/v2/discounts/promotions/promo-code/${promoCode}`, {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
      'X-API-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    }
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Invalid promo code: ${error.message}`);
  }

  return await response.json();
};

// Apply promo code to order pricing
const applyPromoCodeToOrder = async (orderId, promoCode) => {
  try {
    // Validate promo code first
    const promotion = await getPromotionByCode(promoCode);

    // Calculate order price with promo code
    const pricingResponse = await fetch(`https://connect.your-domain.com/api/v2/orders/${orderId}/calculate-price`, {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
        'X-API-Key': 'YOUR_API_KEY',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        promoCode: promoCode
      })
    });

    const pricing = await pricingResponse.json();

    return {
      originalTotal: pricing.subtotal,
      discountAmount: pricing.discountAmount,
      finalTotal: pricing.total,
      promotion: promotion
    };
  } catch (error) {
    console.error('Failed to apply promo code:', error);
    throw error;
  }
};

// Promo code component
const PromoCodeInput = ({ orderId, onApplied, onError }) => {
  const [promoCode, setPromoCode] = useState('');
  const [loading, setLoading] = useState(false);
  const [applied, setApplied] = useState(null);

  const handleApply = async () => {
    if (!promoCode.trim()) return;

    setLoading(true);
    try {
      const result = await applyPromoCodeToOrder(orderId, promoCode);
      setApplied(result);
      onApplied(result);
    } catch (error) {
      onError(error.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="promo-code-input">
      <input
        type="text"
        placeholder="Enter promo code"
        value={promoCode}
        onChange={(e) => setPromoCode(e.target.value.toUpperCase())}
        disabled={loading || applied}
      />
      <button onClick={handleApply} disabled={loading || applied}>
        {loading ? 'Applying...' : 'Apply'}
      </button>

      {applied && (
        <div className="promo-applied">
          <p>✓ {applied.promotion.name} applied</p>
          <p>Discount: -{applied.discountAmount} {applied.promotion.currency}</p>
        </div>
      )}
    </div>
  );
};
```

## Next Steps

After implementing payment processing:

<Card title="Order fulfillment" icon="truck" href="/developer-guide/use-cases/order-fulfillment">
  Handle service provisioning after successful payment
</Card>

<Card title="Customer self-service" icon="user" href="/developer-guide/use-cases/self-management">
  Enable customers to manage their payment methods
</Card>

## Best Practices

### Security

* Never store raw payment card data - use tokenized payment profiles
* Implement PCI DSS compliance for card processing
* Use HTTPS for all payment-related communications
* Validate all payment webhooks and callbacks

### User Experience

* Provide clear payment status updates to customers
* Implement user-friendly error messages for payment failures
* Offer multiple payment methods when possible
* Save successful payment methods for future use

### Reliability

* Implement robust retry logic for failed payments
* Handle payment processor downtime gracefully
* Monitor payment success rates and failure patterns
* Set up alerts for payment processing issues

## Common Questions

**Q: How do I handle different currencies?**
A: The API supports multiple currencies. Specify the currency in payment sessions and ensure your payment processor supports the target currency.

**Q: Can I process refunds through the API?**
A: Refunds are typically handled through your payment processor's dashboard or API, then reflected in the Connect API payment records.

**Q: How do I implement recurring billing?**
A: Use stored payment profiles with scheduled payment sessions. The billing system can automatically create payment sessions for recurring charges.
