# Integration Examples

Complete integration examples and use case scenarios for the FarPay API. These examples demonstrate real-world implementations and best practices for common payment workflows.

## Quick Start Examples

### Basic API Setup

```javascript
// Configure API client
const FARPAY_API_BASE = 'https://api.farpay.io/v2';
const API_KEY = 'your-api-key-here';

const farpayClient = {
  async request(endpoint, options = {}) {
    const url = `${FARPAY_API_BASE}${endpoint}`;
    const response = await fetch(url, {
      headers: {
        'X-API-KEY': API_KEY,
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        ...options.headers
      },
      ...options
    });
    
    if (!response.ok) {
      throw new Error(`API Error: ${response.status} ${response.statusText}`);
    }
    
    return response.json();
  }
};
```

### Test API Connection

```javascript
// Test your API connection
async function testConnection() {
  try {
    const customers = await farpayClient.request('/customers');
    console.log('API connection successful!');
    console.log(`Found ${customers.length} customers`);
  } catch (error) {
    console.error('API connection failed:', error.message);
  }
}
```

## Customer Management Examples

### Create Customer with Complete Information

```javascript
async function createCustomer() {
  const customerData = {
    CustomerNumber: "CUST-001",
    Name: "John Smith",
    Email: "john.smith@example.com",
    Street: "Main Street 123",
    City: "Copenhagen",
    PostCode: "1000",
    Country: "Denmark",
    AttachPdfInvoice: false,
    Language: "English"
  };

  try {
    const customer = await farpayClient.request('/customers', {
      method: 'POST',
      body: JSON.stringify(customerData)
    });
    
    console.log('Customer created:', customer);
    return customer;
  } catch (error) {
    console.error('Failed to create customer:', error);
  }
}
```

### Update Customer Information

```javascript
async function updateCustomer(customerNumber, updates) {
  try {
    const customer = await farpayClient.request(`/customers/${customerNumber}`, {
      method: 'PUT',
      body: JSON.stringify({
        CustomerNumber: customerNumber,
        ...updates
      })
    });
    
    console.log('Customer updated:', customer);
    return customer;
  } catch (error) {
    console.error('Failed to update customer:', error);
  }
}

// Usage
updateCustomer("CUST-001", {
  Name: "John Smith Updated",
  Email: "john.updated@example.com",
  City: "Aarhus"
});
```

### Send Agreement Invitation

```javascript
async function sendAgreementInvitation(customerNumber, email, paymentType) {
  try {
    const response = await farpayClient.request(
      `/customers/${customerNumber}/agreementRequest?type=${paymentType}&email=${email}`
    );
    
    console.log('Agreement invitation sent');
    return response;
  } catch (error) {
    console.error('Failed to send invitation:', error);
  }
}

// Send card agreement invitation
sendAgreementInvitation("CUST-001", "john@example.com", "card");
```

## Order and Payment Flow Examples

### Create Payment Order

```javascript
async function createPaymentOrder(customerData, paymentData) {
  const orderData = {
    ExternalID: `ORDER-${Date.now()}`,
    AcceptUrl: "https://yourcompany.com/payment/success",
    CancelUrl: "https://yourcompany.com/payment/cancel",
    CallbackUrl: "https://yourcompany.com/payment/callback",
    Lang: "da",
    Agreement: 0, // No agreement required
    Customer: customerData,
    Payment: paymentData
  };

  try {
    const order = await farpayClient.request('/orders', {
      method: 'POST',
      body: JSON.stringify(orderData)
    });
    
    console.log('Order created:', order);
    console.log('Redirect customer to:', order.UserInputUrl);
    return order;
  } catch (error) {
    console.error('Failed to create order:', error);
  }
}

// Usage
const customer = {
  CustomerNumber: "CUST-001",
  CustomerName: "John Smith",
  CustomerEmail: "john@example.com"
};

const payment = {
  Amount: 99.95,
  Currency: "DKK",
  Description: "Monthly subscription",
  Reference: "SUB-001"
};

createPaymentOrder(customer, payment);
```

### Create Order with Agreement

```javascript
async function createAgreementOrder(customerData) {
  const orderData = {
    ExternalID: `AGREEMENT-${Date.now()}`,
    AcceptUrl: "https://yourcompany.com/agreement/success",
    CancelUrl: "https://yourcompany.com/agreement/cancel",
    CallbackUrl: "https://yourcompany.com/agreement/callback",
    Lang: "da",
    Agreement: 1, // Agreement required
    PaymentTypes: "card,mp", // Only cards and MobilePay
    Customer: customerData
  };

  try {
    const order = await farpayClient.request('/orders', {
      method: 'POST',
      body: JSON.stringify(orderData)
    });
    
    console.log('Agreement order created:', order);
    return order;
  } catch (error) {
    console.error('Failed to create agreement order:', error);
  }
}
```

### Monitor Order Status

```javascript
async function monitorOrder(token) {
  try {
    const order = await farpayClient.request(`/orders/${token}`);
    
    switch (order.Status) {
      case "New":
        console.log("Order created, waiting for customer action");
        break;
      case "PendingPayment":
        console.log("Payment received, processing...");
        break;
      case "Ok":
        console.log("Order completed successfully");
        break;
      case "Error":
        console.log("Order failed:", order.ErrorDescription);
        break;
      case "Canceled":
        console.log("Order was canceled");
        break;
      default:
        console.log("Order status:", order.Status);
    }
    
    return order;
  } catch (error) {
    console.error('Failed to get order status:', error);
  }
}
```

## Invoice Management Examples

### Create Invoice

```javascript
async function createInvoice(customerNumber, invoiceData) {
  const invoice = {
    CustomerNumber: customerNumber,
    InvoiceNumber: invoiceData.invoiceNumber,
    PaymentDueDate: invoiceData.dueDate,
    PaymentType: "MobilePayInvoice",
    InvoiceLines: invoiceData.lines
  };

  try {
    const result = await farpayClient.request('/invoices', {
      method: 'POST',
      body: JSON.stringify(invoice)
    });
    
    console.log('Invoice created:', result);
    return result;
  } catch (error) {
    console.error('Failed to create invoice:', error);
  }
}

// Usage
const invoiceData = {
  invoiceNumber: "INV-001",
  dueDate: "2023-02-15",
  lines: [
    {
      Description: "Basic subscription",
      Quantity: 1,
      UnitPrice: 99.00,
      TotalPrice: 99.00
    },
    {
      Description: "Premium add-on",
      Quantity: 1,
      UnitPrice: 26.00,
      TotalPrice: 26.00
    }
  ]
};

createInvoice("CUST-001", invoiceData);
```

### Get Invoices with Filtering

```javascript
async function getInvoices(filters = {}) {
  const params = new URLSearchParams();
  
  if (filters.fromDueDate) params.append('fromDueDate', filters.fromDueDate);
  if (filters.toDueDate) params.append('toDueDate', filters.toDueDate);
  if (filters.paymentStatus) params.append('paymentStatus', filters.paymentStatus);
  
  const queryString = params.toString();
  const endpoint = queryString ? `/invoices?${queryString}` : '/invoices';
  
  try {
    const invoices = await farpayClient.request(endpoint);
    console.log(`Found ${invoices.length} invoices`);
    return invoices;
  } catch (error) {
    console.error('Failed to get invoices:', error);
  }
}

// Get unpaid invoices from last month
const lastMonth = new Date();
lastMonth.setMonth(lastMonth.getMonth() - 1);

getInvoices({
  fromDueDate: lastMonth.toISOString().split('T')[0],
  paymentStatus: 100 // Not Paid
});
```

## Payment Tracking Examples

### Get Payment History

```javascript
async function getPaymentHistory(filters = {}) {
  const params = new URLSearchParams();
  
  if (filters.paymentDateFrom) params.append('paymentDateFrom', filters.paymentDateFrom);
  if (filters.paymentDateTo) params.append('paymentDateTo', filters.paymentDateTo);
  if (filters.invoiceID) params.append('invoiceID', filters.invoiceID);
  
  const queryString = params.toString();
  const endpoint = queryString ? `/payments?${queryString}` : '/payments';
  
  try {
    const payments = await farpayClient.request(endpoint);
    console.log(`Found ${payments.length} payments`);
    return payments;
  } catch (error) {
    console.error('Failed to get payments:', error);
  }
}

// Get payments from last 30 days
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

getPaymentHistory({
  paymentDateFrom: thirtyDaysAgo.toISOString().split('T')[0]
});
```

### Process Refund

```javascript
async function processRefund(paymentId, amount) {
  // Convert amount to minor units (cents)
  const minorUnits = Math.round(amount * 100);
  
  try {
    const refund = await farpayClient.request(`/payments/${paymentId}/refund/${minorUnits}`, {
      method: 'POST'
    });
    
    console.log('Refund processed:', refund);
    return refund;
  } catch (error) {
    console.error('Failed to process refund:', error);
  }
}

// Refund 50 DKK
processRefund(456, 50.00);
```

## Agreement Management Examples

### Create Bank Agreement

```javascript
async function createBankAgreement(customerNumber, bankData, agreementType) {
  const agreement = {
    BankRegNumber: bankData.regNumber,
    BankAccountNumber: bankData.accountNumber,
    Type: agreementType, // "BS" or "LS"
    CustomerNumber: customerNumber,
    PayerID: bankData.payerId
  };

  try {
    const result = await farpayClient.request('/agreements', {
      method: 'POST',
      body: JSON.stringify(agreement)
    });
    
    console.log('Agreement created:', result);
    return result;
  } catch (error) {
    console.error('Failed to create agreement:', error);
  }
}

// Create Betalingsservice agreement
const bankData = {
  regNumber: "1234",
  accountNumber: "12345678",
  payerId: "1234567890" // CPR number
};

createBankAgreement("CUST-001", bankData, "BS");
```

### Monitor Agreement Status

```javascript
async function monitorAgreements() {
  try {
    const agreements = await farpayClient.request('/agreements');
    
    const statusCounts = {
      Pending: 0,
      Ok: 0,
      Cancel: 0,
      Error: 0
    };
    
    agreements.forEach(agreement => {
      statusCounts[agreement.Status]++;
    });
    
    console.log('Agreement status summary:', statusCounts);
    
    // Check for pending agreements
    const pendingAgreements = agreements.filter(a => a.Status === 'Pending');
    if (pendingAgreements.length > 0) {
      console.log('Pending agreements:', pendingAgreements);
    }
    
    return agreements;
  } catch (error) {
    console.error('Failed to get agreements:', error);
  }
}
```

## File Upload Examples

### Upload Invoice File

```javascript
async function uploadInvoiceFile(filename, fileContent) {
  // Convert file to base64
  const base64Data = Buffer.from(fileContent).toString('base64');
  
  const delivery = {
    DeliveryType: "TransmissionReceipt",
    File: {
      Filename: filename,
      Data: base64Data
    }
  };

  try {
    const result = await farpayClient.request('/deliveries', {
      method: 'POST',
      body: JSON.stringify(delivery)
    });
    
    console.log('File uploaded:', result);
    return result;
  } catch (error) {
    console.error('Failed to upload file:', error);
  }
}

// Usage with file system
const fs = require('fs');
const fileContent = fs.readFileSync('invoices.xml');
uploadInvoiceFile('invoices.xml', fileContent);
```

### Monitor File Processing

```javascript
async function monitorFileProcessing(deliveryId) {
  try {
    const delivery = await farpayClient.request(`/deliveries/${deliveryId}`);
    
    switch (delivery.DeliveryStatus) {
      case "New":
        console.log("File uploaded, awaiting processing");
        break;
      case "Processing":
        console.log("File is being processed");
        break;
      case "Ok":
        console.log("File processed successfully");
        break;
      case "Error":
        console.log("Processing failed:", delivery.ErrorMessage);
        break;
    }
    
    return delivery;
  } catch (error) {
    console.error('Failed to get delivery status:', error);
  }
}
```

## Complete Integration Example

### Subscription Management System

```javascript
class SubscriptionManager {
  constructor() {
    this.apiClient = farpayClient;
  }

  async createSubscription(customerData, planData) {
    // 1. Create or update customer
    let customer = await this.ensureCustomer(customerData);
    
    // 2. Create agreement order
    const order = await this.createAgreementOrder(customer);
    
    // 3. Create initial invoice
    const invoice = await this.createInvoice(customer.CustomerNumber, {
      invoiceNumber: `INV-${Date.now()}`,
      dueDate: this.getNextMonthDate(),
      lines: [{
        Description: planData.name,
        Quantity: 1,
        UnitPrice: planData.price,
        TotalPrice: planData.price
      }]
    });
    
    return { customer, order, invoice };
  }

  async ensureCustomer(customerData) {
    try {
      // Try to get existing customer
      const customer = await this.apiClient.request(`/customers/${customerData.CustomerNumber}`);
      return customer;
    } catch (error) {
      // Customer doesn't exist, create new one
      return await this.apiClient.request('/customers', {
        method: 'POST',
        body: JSON.stringify(customerData)
      });
    }
  }

  async createAgreementOrder(customer) {
    const orderData = {
      ExternalID: `AGREEMENT-${Date.now()}`,
      AcceptUrl: "https://yourcompany.com/subscription/success",
      CancelUrl: "https://yourcompany.com/subscription/cancel",
      CallbackUrl: "https://yourcompany.com/subscription/callback",
      Lang: "da",
      Agreement: 1,
      PaymentTypes: "card,mp,bs",
      Customer: {
        CustomerNumber: customer.CustomerNumber,
        CustomerName: customer.Name,
        CustomerEmail: customer.Email
      }
    };

    return await this.apiClient.request('/orders', {
      method: 'POST',
      body: JSON.stringify(orderData)
    });
  }

  async createInvoice(customerNumber, invoiceData) {
    const invoice = {
      CustomerNumber: customerNumber,
      InvoiceNumber: invoiceData.invoiceNumber,
      PaymentDueDate: invoiceData.dueDate,
      PaymentType: "MobilePayInvoice",
      InvoiceLines: invoiceData.lines
    };

    return await this.apiClient.request('/invoices', {
      method: 'POST',
      body: JSON.stringify(invoice)
    });
  }

  getNextMonthDate() {
    const date = new Date();
    date.setMonth(date.getMonth() + 1);
    return date.toISOString().split('T')[0];
  }

  async monitorSubscription(customerNumber) {
    // Get customer with agreements
    const customer = await this.apiClient.request(`/customers/${customerNumber}`);
    
    // Get recent invoices
    const invoices = await this.apiClient.request(`/invoices?fromDueDate=${this.getLastMonthDate()}`);
    
    // Get recent payments
    const payments = await this.apiClient.request(`/payments?paymentDateFrom=${this.getLastMonthDate()}`);
    
    return {
      customer,
      agreements: customer.Agreements || [],
      invoices: invoices.filter(inv => inv.CustomerNumber === customerNumber),
      payments: payments.filter(pay => pay.CustomerNumber === customerNumber)
    };
  }

  getLastMonthDate() {
    const date = new Date();
    date.setMonth(date.getMonth() - 1);
    return date.toISOString().split('T')[0];
  }
}

// Usage
const subscriptionManager = new SubscriptionManager();

const customerData = {
  CustomerNumber: "CUST-001",
  Name: "John Smith",
  Email: "john@example.com",
  Street: "Main Street 123",
  City: "Copenhagen",
  PostCode: "1000",
  Country: "Denmark"
};

const planData = {
  name: "Premium Subscription",
  price: 99.95
};

subscriptionManager.createSubscription(customerData, planData)
  .then(result => {
    console.log('Subscription created:', result);
  })
  .catch(error => {
    console.error('Failed to create subscription:', error);
  });
```

## Error Handling Best Practices

### Comprehensive Error Handler

```javascript
class FarPayError extends Error {
  constructor(message, statusCode, details) {
    super(message);
    this.name = 'FarPayError';
    this.statusCode = statusCode;
    this.details = details;
  }
}

async function handleApiRequest(requestFn) {
  try {
    return await requestFn();
  } catch (error) {
    if (error.name === 'FarPayError') {
      // Handle known API errors
      switch (error.statusCode) {
        case 401:
          console.error('Authentication failed. Check your API key.');
          break;
        case 404:
          console.error('Resource not found:', error.details);
          break;
        case 400:
          console.error('Bad request:', error.details);
          break;
        default:
          console.error('API error:', error.message);
      }
    } else {
      // Handle network or other errors
      console.error('Request failed:', error.message);
    }
    throw error;
  }
}

// Usage
handleApiRequest(() => farpayClient.request('/customers'))
  .then(customers => {
    console.log('Success:', customers);
  })
  .catch(error => {
    // Error already handled above
  });
```

## Testing Examples

### Unit Tests

```javascript
// Using Jest for testing
describe('FarPay API Integration', () => {
  test('should create customer successfully', async () => {
    const customerData = {
      CustomerNumber: "TEST-001",
      Name: "Test Customer",
      Email: "test@example.com"
    };

    const customer = await farpayClient.request('/customers', {
      method: 'POST',
      body: JSON.stringify(customerData)
    });

    expect(customer.CustomerNumber).toBe("TEST-001");
    expect(customer.Name).toBe("Test Customer");
  });

  test('should handle duplicate customer error', async () => {
    const customerData = {
      CustomerNumber: "TEST-001",
      Name: "Test Customer",
      Email: "test@example.com"
    };

    await expect(
      farpayClient.request('/customers', {
        method: 'POST',
        body: JSON.stringify(customerData)
      })
    ).rejects.toThrow();
  });
});
```

## Related Resources

* [Authentication](authentication.md) - API setup and authentication
* [Customers](customers.md) - Customer management
* [Orders](orders.md) - Payment flows and orders
* [Invoices](invoices.md) - Invoice management
* [Payments](payments.md) - Payment tracking and refunds
* [Agreements](agreements.md) - Payment agreements
* [Deliveries](deliveries.md) - File uploads and batch processing