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

# Complete Example

> End-to-end Payments Library integration in one page.

<Info>
  This page is part of the **Payments Library Guides**. Prefer direct API calls instead? See [REST API Guides](/guides/rest-api/charge).
</Info>

**Prerequisites:** [API key](/getting-started/generate-api-key), [Payment Gateway Account](/getting-started/add-payment-provider), and [eWallet Account](/guides/library/store-merchant-account) configured.

This page provides a complete working example showing how to integrate the Orchestra Payments Library from server to client.

<Card title="View on GitHub" icon="github" href="https://github.com/orchestra-solutions/payments-library-example">
  Clone the complete example project
</Card>

## Server-Side: Create Session

Your server creates a session with the Orchestra API and returns the token to the client.

<CodeGroup>
  ```javascript Node.js theme={null}
  const express = require('express');
  const app = express();

  // eWallet account IDs from environment variables
  const eWalletAccounts = {
    cardPay: process.env.EWALLET_CARDPAY_ACCOUNT_ID,
    googlePay: process.env.EWALLET_GOOGLEPAY_ACCOUNT_ID,
    applePay: process.env.EWALLET_APPLEPAY_ACCOUNT_ID,
    payPal: process.env.EWALLET_PAYPAL_ACCOUNT_ID,
  };

  // Build array of only the configured account IDs
  // Note: This helper is for the example's flexibility. In practice, you would
  // simply list your eWallet account names directly in the request, e.g.:
  // allowedeWalletAccountIds: ['my-cardpay-account', 'my-paypal-account']
  function getConfiguredEWalletAccountIds() {
    return Object.values(eWalletAccounts).filter(Boolean);
  }

  app.post('/api/create-session', async (req, res) => {
    const response = await fetch('https://api.orchestrasolutions.com/EWalletOperations', {
      method: 'POST',
      headers: {
        'X-Api-Key': process.env.ORCHESTRA_API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        operation: 'CHARGE',
        paymentGatewayAccountId: process.env.PAYMENT_GATEWAY_ACCOUNT_ID,
        allowedeWalletAccountIds: getConfiguredEWalletAccountIds(),
        allowedBrands: ['Visa', 'MasterCard', 'AMEX'],
        currencyCode: 'USD',
        countryCode: 'US',
        amount: 49.99,
        mode: 'TEST'
      })
    });

    const data = await response.json();
    res.json({ sessionToken: data.token });
  });

  app.listen(3000);
  ```

  ```python Python theme={null}
  from flask import Flask, jsonify
  import requests
  import os

  app = Flask(__name__)

  # eWallet account IDs from environment variables
  ewallet_accounts = {
      'cardPay': os.environ.get('EWALLET_CARDPAY_ACCOUNT_ID'),
      'googlePay': os.environ.get('EWALLET_GOOGLEPAY_ACCOUNT_ID'),
      'applePay': os.environ.get('EWALLET_APPLEPAY_ACCOUNT_ID'),
      'payPal': os.environ.get('EWALLET_PAYPAL_ACCOUNT_ID'),
  }

  # Build list of only the configured account IDs
  # Note: This helper is for the example's flexibility. In practice, you would
  # simply list your eWallet account names directly in the request, e.g.:
  # 'allowedeWalletAccountIds': ['my-cardpay-account', 'my-paypal-account']
  def get_configured_ewallet_account_ids():
      return [v for v in ewallet_accounts.values() if v]

  @app.route('/api/create-session', methods=['POST'])
  def create_session():
      response = requests.post(
          'https://api.orchestrasolutions.com/EWalletOperations',
          headers={
              'X-Api-Key': os.environ['ORCHESTRA_API_KEY'],
              'Content-Type': 'application/json'
          },
          json={
              'operation': 'CHARGE',
              'paymentGatewayAccountId': os.environ['PAYMENT_GATEWAY_ACCOUNT_ID'],
              'allowedeWalletAccountIds': get_configured_ewallet_account_ids(),
              'allowedBrands': ['Visa', 'MasterCard', 'AMEX'],
              'currencyCode': 'USD',
              'countryCode': 'US',
              'amount': 49.99,
              'mode': 'TEST'
          }
      )

      result = response.json()
      return jsonify({'sessionToken': result['token']})

  if __name__ == '__main__':
      app.run(port=3000)
  ```
</CodeGroup>

## Client-Side: HTML

Create container elements for each payment method you want to display:

```html theme={null}
<!DOCTYPE html>
<html>
<head>
  <title>Checkout</title>
</head>
<body>
  <h1>Complete Your Purchase</h1>
  <p>Total: $<span id="amount">49.99</span></p>

  <!-- Each payment method needs its own container -->
  <div id="card-button"></div>
  <div id="gpay-button"></div>
  <div id="applepay-button"></div>
  <div id="paypal-button"></div>

  <div id="result"></div>

  <script src="https://cdn.jsdelivr.net/npm/@orchestrasolutions/ewallet@latest/dist/index.js"></script>
  <script src="checkout.js"></script>
</body>
</html>
```

## Client-Side: JavaScript

Initialize the library and render payment buttons:

```javascript theme={null}
// checkout.js

let engine = null;

async function initPayment() {
  // 1. Get session token from your server
  const response = await fetch('/api/create-session', { method: 'POST' });
  const { sessionToken } = await response.json();

  // 2. Initialize the engine
  engine = new eWallet.Engine(sessionToken);

  // 3. Check which payment methods are available
  const available = await engine.checkAvailability();
  console.log('Available payment methods:', available);

  // 4. Build list of buttons to display
  const allButtons = [
    { name: 'CardPay', domEntitySelector: '#card-button' },
    { name: 'GooglePay', domEntitySelector: '#gpay-button' },
    { name: 'ApplePay', domEntitySelector: '#applepay-button' },
    { name: 'PayPal', domEntitySelector: '#paypal-button' }
  ];

  const buttons = allButtons.filter(btn => available.includes(btn.name));

  // 5. Render the buttons
  engine.payBy(buttons, handleResult, { color: 'Dark', text: 'Pay' });
}

async function handleResult(result) {
  const resultEl = document.getElementById('result');

  // User cancelled
  if (!result) {
    resultEl.textContent = 'Payment cancelled';
    return;
  }

  // Parse the result token
  const [data, success] = engine.parseResultToken(result.token);
  console.log('Payment result:', data);

  // Check if payment succeeded
  if (!data.clientSuccess) {
    resultEl.textContent = 'Payment failed: ' + (data.clientErrorMessage || 'Unknown error');
    return;
  }

  // Handle PSP charge results (CardPay, GooglePay, ApplePay)
  if (data.upgChargeResults) {
    if (data.upgChargeResults.operationResultCode === 'Success') {
      resultEl.innerHTML = `
        <strong>Payment successful!</strong><br>
        Gateway: ${data.upgChargeResults.gatewayName}<br>
        Reference: ${data.upgChargeResults.gatewayReference}<br>
        Amount: ${data.upgChargeResults.amount} ${data.upgChargeResults.currency}
      `;
    } else {
      resultEl.textContent = 'Payment declined: ' + (data.upgChargeResults.operationResultDescription || data.upgChargeResults.operationResultCode);
      return;
    }
  }

  // Handle direct charge results (PayPal, BankPay)
  if (data.directChargeResults) {
    if (data.directChargeResults.success) {
      resultEl.innerHTML = '<strong>Payment successful!</strong><br>Provider: PayPal';
    } else {
      resultEl.textContent = 'Payment failed: ' + data.directChargeResults.message;
      return;
    }
  }

  // Server-side validation (recommended for production)
  try {
    const validationResponse = await fetch('/api/validate-payment', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ resultToken: result.token })
    });

    if (validationResponse.ok) {
      const validationResult = await validationResponse.json();
      console.log('Server validation:', validationResult);
    }
  } catch (error) {
    console.warn('Could not reach server for validation:', error.message);
  }
}

// Start when page loads
document.addEventListener('DOMContentLoaded', initPayment);
```

## Server-Side: Validate Results

After a successful payment, validate the result token with Orchestra to confirm the payment:

<CodeGroup>
  ```javascript Node.js theme={null}
  app.post('/api/validate-payment', async (req, res) => {
    const { resultToken } = req.body;

    const response = await fetch('https://api.orchestrasolutions.com/EWalletOperations/validateResults', {
      method: 'POST',
      headers: {
        'X-Api-Key': process.env.ORCHESTRA_API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(resultToken)
    });

    const validationResult = await response.json();

    if (validationResult.failedUpgChargeResults?.length) {
      res.json({ success: false, error: validationResult.failedUpgChargeResults[0].operationResultDescription });
    } else if (validationResult.directChargeResults) {
      res.json({
        success: validationResult.directChargeResults.success,
        error: validationResult.directChargeResults.message,
        data: validationResult
      });
    } else if (validationResult.upgChargeResults || validationResult.tokenAndMaskedCardModel) {
      // Payment confirmed - fulfill the order
      res.json({ success: true, data: validationResult });
    }
  });
  ```

  ```python Python theme={null}
  @app.route('/api/validate-payment', methods=['POST'])
  def validate_payment():
      data = request.json
      result_token = data['resultToken']

      response = requests.post(
          'https://api.orchestrasolutions.com/EWalletOperations/validateResults',
          headers={
              'X-Api-Key': os.environ['ORCHESTRA_API_KEY'],
              'Content-Type': 'application/json'
          },
          data=json.dumps(result_token)
      )

      result = response.json()

      if result.get('failedUpgChargeResults'):
          return jsonify({
              'success': False,
              'error': result['failedUpgChargeResults'][0]['operationResultDescription']
          })
      elif result.get('directChargeResults'):
          return jsonify({
              'success': result['directChargeResults']['success'],
              'error': result['directChargeResults'].get('message'),
              'data': result
          })
      elif result.get('upgChargeResults') or result.get('tokenAndMaskedCardModel'):
          # Payment confirmed - fulfill the order
          return jsonify({'success': True, 'data': result})
  ```
</CodeGroup>

## Related

<CardGroup cols={2}>
  <Card title="Library Setup" icon="gear" href="/guides/library/setup">
    Installation and quick start
  </Card>

  <Card title="Library Reference" icon="book" href="/guides/library/reference">
    Full API reference
  </Card>

  <Card title="Start Session API" icon="code" href="/api-reference/ewalletoperations/start-an-ewallet-session">
    Session creation endpoint
  </Card>

  <Card title="Validate Results API" icon="check" href="/api-reference/ewalletoperations/validate-operation-results">
    Result validation endpoint
  </Card>
</CardGroup>
